Merge pull request #173 from wu-sheng/feature/3.0.1

Prepare for release 3.0.1
diff --git a/docker-compose.yml b/docker-compose.yml
index aae4559..fef0869 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -1,7 +1,7 @@
 version: '2.1'
 services:
   skywalking-webui:
-    image: sky-walking-ui:1.0
+    image: sky-walking-ui:3.0.1-2017
     expose:
       - "8080"
     ports:
@@ -12,12 +12,12 @@
       - COLLECTOR_SERVERS=skywalking-collector:7001
 
   skywalking-collector:
-    image: skywalking-collector:3.0-2017
+    image: skywalking-collector:3.0.1-2017
     expose:
-      - "7001"
+      - "12800"
       - "1000"
     ports:
-      - "7001:7001"
+      - "12800:12800"
     depends_on:
       es-server:
         condition: service_healthy
@@ -37,4 +37,4 @@
       test: ["CMD", "curl", "-f", "http://localhost:9200"]
       interval: 30s
       timeout: 10s
-      retries: 5
\ No newline at end of file
+      retries: 5
diff --git a/skywalking-application-toolkit/skywalking-toolkit-opentracing/src/main/java/com/a/eye/skywalking/toolkit/opentracing/SkyWalkingTracer.java b/skywalking-application-toolkit/skywalking-toolkit-opentracing/src/main/java/com/a/eye/skywalking/toolkit/opentracing/SkyWalkingTracer.java
index 6bcda06..def5873 100644
--- a/skywalking-application-toolkit/skywalking-toolkit-opentracing/src/main/java/com/a/eye/skywalking/toolkit/opentracing/SkyWalkingTracer.java
+++ b/skywalking-application-toolkit/skywalking-toolkit-opentracing/src/main/java/com/a/eye/skywalking/toolkit/opentracing/SkyWalkingTracer.java
@@ -6,6 +6,9 @@
 import io.opentracing.propagation.TextMap;
 
 import java.nio.ByteBuffer;
+import java.nio.charset.Charset;
+import java.util.Iterator;
+import java.util.Map;
 
 /**
  * All source code in SkyWalkingTracer acts like an NoopTracer.
@@ -15,10 +18,11 @@
  * Created by wusheng on 2016/12/20.
  */
 public class SkyWalkingTracer implements Tracer {
-    private static String TRACE_HEAD_NAME = "SW-TRACING-NAME";
+    private static String TRACE_HEAD_NAME = "sw3";
 
     public static Tracer INSTANCE = new SkyWalkingTracer();
 
+
     @Override
     public SpanBuilder buildSpan(String operationName) {
         return new SkyWalkingSpanBuilder(operationName);
@@ -27,15 +31,13 @@
     @Override
     public <C> void inject(SpanContext spanContext, Format<C> format, C carrier) {
         if (Format.Builtin.TEXT_MAP.equals(format) || Format.Builtin.HTTP_HEADERS.equals(format)) {
-            ((TextMap)carrier).put(TRACE_HEAD_NAME, formatCrossProcessPropagationContextData());
+            ((TextMap) carrier).put(TRACE_HEAD_NAME, formatInjectCrossProcessPropagationContextData());
         } else if (Format.Builtin.BINARY.equals(format)) {
             byte[] key = TRACE_HEAD_NAME.getBytes(ByteBufferContext.CHARSET);
-            byte[] value = formatCrossProcessPropagationContextData().getBytes(ByteBufferContext.CHARSET);
-            ((ByteBuffer)carrier).put(ByteBufferContext.ENTRY);
-            ((ByteBuffer)carrier).putInt(key.length);
-            ((ByteBuffer)carrier).putInt(value.length);
-            ((ByteBuffer)carrier).put(key);
-            ((ByteBuffer)carrier).put(value);
+            byte[] value = formatInjectCrossProcessPropagationContextData().getBytes(ByteBufferContext.CHARSET);
+            ((ByteBuffer) carrier).put(key);
+            ((ByteBuffer) carrier).putInt(value.length);
+            ((ByteBuffer) carrier).put(value);
         } else {
             throw new IllegalArgumentException("Unsupported format: " + format);
         }
@@ -44,13 +46,13 @@
     @Override
     public <C> SpanContext extract(Format<C> format, C carrier) {
         if (Format.Builtin.TEXT_MAP.equals(format) || Format.Builtin.HTTP_HEADERS.equals(format)) {
-            TextMap textMapCarrier = (TextMap)carrier;
-            extractCrossProcessPropagationContextData(textMapCarrier);
+            TextMap textMapCarrier = (TextMap) carrier;
+            formatExtractCrossProcessPropagationContextData(fetchContextData(textMapCarrier));
             return new TextMapContext(textMapCarrier);
         } else if (Format.Builtin.BINARY.equals(format)) {
-            ByteBuffer byteBufferCarrier = (ByteBuffer)carrier;
-            extractCrossProcessPropagationContextData(byteBufferCarrier);
-            return new ByteBufferContext((ByteBuffer)carrier);
+            ByteBuffer byteBufferCarrier = (ByteBuffer) carrier;
+            formatExtractCrossProcessPropagationContextData(fetchContextData(byteBufferCarrier));
+            return new ByteBufferContext((ByteBuffer) carrier);
         } else {
             throw new IllegalArgumentException("Unsupported format: " + format);
         }
@@ -58,28 +60,43 @@
 
     /**
      * set context data in toolkit-opentracing-activation
-     *
-     * @return
      */
-    private String formatCrossProcessPropagationContextData() {
+    private String formatInjectCrossProcessPropagationContextData() {
         return "";
     }
 
     /**
      * read context data in toolkit-opentracing-activation
-     *
-     * @param textMapCarrier
      */
-    private void extractCrossProcessPropagationContextData(TextMap textMapCarrier) {
-
+    private void formatExtractCrossProcessPropagationContextData(String contextData) {
     }
 
-    /**
-     * read context data in toolkit-opentracing-activation
-     *
-     * @param byteBufferCarrier
-     */
-    private void extractCrossProcessPropagationContextData(ByteBuffer byteBufferCarrier) {
+    private String fetchContextData(TextMap textMap) {
+        Iterator<Map.Entry<String, String>> iterator = textMap.iterator();
+        while (iterator.hasNext()) {
+            Map.Entry<String, String> entry = iterator.next();
+            if (TRACE_HEAD_NAME.equals(entry.getKey())) {
+                return entry.getValue();
+            }
+        }
 
+        return null;
+    }
+
+    private String fetchContextData(ByteBuffer byteBuffer) {
+        String contextDataStr = new String(byteBuffer.array(), Charset.forName("UTF-8"));
+        int index = contextDataStr.indexOf(TRACE_HEAD_NAME);
+        if (index == -1) {
+            return null;
+        }
+
+        try {
+            byteBuffer.position(index + TRACE_HEAD_NAME.getBytes().length);
+            byte[] contextDataBytes = new byte[byteBuffer.getInt()];
+            byteBuffer.get(contextDataBytes);
+            return new String(contextDataBytes, Charset.forName("UTF-8"));
+        } catch (Exception e) {
+            return null;
+        }
     }
 }
diff --git a/skywalking-collector/pom.xml b/skywalking-collector/pom.xml
index e695b28..8e09f8c 100644
--- a/skywalking-collector/pom.xml
+++ b/skywalking-collector/pom.xml
@@ -27,6 +27,17 @@
             <version>${akka.version}</version>
         </dependency>
         <dependency>
+            <groupId>com.typesafe.akka</groupId>
+            <artifactId>akka-slf4j_2.11</artifactId>
+            <version>${akka.version}</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.slf4j</groupId>
+                    <artifactId>slf4j-api</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
             <groupId>org.apache.logging.log4j</groupId>
             <artifactId>log4j-core</artifactId>
             <version>${log4j.version}</version>
@@ -37,6 +48,17 @@
             <version>${log4j.version}</version>
         </dependency>
         <dependency>
+            <groupId>org.apache.logging.log4j</groupId>
+            <artifactId>log4j-slf4j-impl</artifactId>
+            <version>${log4j.version}</version>
+            <scope>runtime</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.logging.log4j</groupId>
+            <artifactId>log4j-jcl</artifactId>
+            <version>${log4j.version}</version>
+        </dependency>
+        <dependency>
             <groupId>com.typesafe.akka</groupId>
             <artifactId>akka-testkit_2.11</artifactId>
             <version>${akka.version}</version>
diff --git a/skywalking-collector/skywalking-collector-cluster/src/main/java/com/a/eye/skywalking/collector/AkkaSystem.java b/skywalking-collector/skywalking-collector-cluster/src/main/java/com/a/eye/skywalking/collector/AkkaSystem.java
index 5c1252c..0b62746 100644
--- a/skywalking-collector/skywalking-collector-cluster/src/main/java/com/a/eye/skywalking/collector/AkkaSystem.java
+++ b/skywalking-collector/skywalking-collector-cluster/src/main/java/com/a/eye/skywalking/collector/AkkaSystem.java
@@ -6,6 +6,7 @@
 import com.a.eye.skywalking.collector.cluster.Const;
 import com.typesafe.config.Config;
 import com.typesafe.config.ConfigFactory;
+import org.apache.logging.log4j.Level;
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
 
@@ -17,9 +18,14 @@
     private Logger logger = LogManager.getFormatterLogger(AkkaSystem.class);
 
     public ActorSystem create() {
+        Level logLevel = logger.getLevel();
+
         final Config config = ConfigFactory.parseString("akka.remote.netty.tcp.HOSTNAME=" + ClusterConfig.Cluster.Current.HOSTNAME).
-            withFallback(ConfigFactory.parseString("akka.remote.netty.tcp.PORT=" + ClusterConfig.Cluster.Current.PORT)).
-            withFallback(ConfigFactory.load("application.conf"));
+                withFallback(ConfigFactory.parseString("akka.remote.netty.tcp.PORT=" + ClusterConfig.Cluster.Current.PORT)).
+                withFallback(ConfigFactory.parseString("akka.loggers=[\"akka.event.slf4j.Slf4jLogger\"]")).
+                withFallback(ConfigFactory.parseString("akka.loglevel=\"" + logLevel.name() + "\"")).
+
+                withFallback(ConfigFactory.load("application.conf"));
         if (!StringUtil.isEmpty(ClusterConfig.Cluster.SEED_NODES)) {
             config.withFallback(ConfigFactory.parseString("akka.cluster.seed-nodes=" + generateSeedNodes()));
         }
diff --git a/skywalking-collector/skywalking-collector-cluster/src/main/java/com/a/eye/skywalking/collector/actor/AbstractClusterWorker.java b/skywalking-collector/skywalking-collector-cluster/src/main/java/com/a/eye/skywalking/collector/actor/AbstractClusterWorker.java
index 5775bea..a7e5ddf 100644
--- a/skywalking-collector/skywalking-collector-cluster/src/main/java/com/a/eye/skywalking/collector/actor/AbstractClusterWorker.java
+++ b/skywalking-collector/skywalking-collector-cluster/src/main/java/com/a/eye/skywalking/collector/actor/AbstractClusterWorker.java
@@ -7,7 +7,7 @@
 import akka.cluster.MemberStatus;
 import com.a.eye.skywalking.collector.cluster.WorkerListenerMessage;
 import com.a.eye.skywalking.collector.cluster.WorkersListener;
-import org.apache.logging.log4j.LogManager;
+import com.a.eye.skywalking.collector.log.LogManager;
 import org.apache.logging.log4j.Logger;
 
 /**
@@ -52,7 +52,7 @@
     protected abstract void onWork(Object message) throws Exception;
 
     static class WorkerWithAkka extends UntypedActor {
-        private Logger logger = LogManager.getFormatterLogger(WorkerWithAkka.class);
+        private Logger logger = LogManager.INSTANCE.getFormatterLogger(WorkerWithAkka.class);
 
         private Cluster cluster;
         private final AbstractClusterWorker ownerWorker;
diff --git a/skywalking-collector/skywalking-collector-cluster/src/main/java/com/a/eye/skywalking/collector/actor/AbstractWorker.java b/skywalking-collector/skywalking-collector-cluster/src/main/java/com/a/eye/skywalking/collector/actor/AbstractWorker.java
index e5a5f8a..81d5774 100644
--- a/skywalking-collector/skywalking-collector-cluster/src/main/java/com/a/eye/skywalking/collector/actor/AbstractWorker.java
+++ b/skywalking-collector/skywalking-collector-cluster/src/main/java/com/a/eye/skywalking/collector/actor/AbstractWorker.java
@@ -1,9 +1,15 @@
 package com.a.eye.skywalking.collector.actor;
 
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
 /**
  * @author pengys5
  */
 public abstract class AbstractWorker {
+
+    private final Logger logger;
+
     private final LocalWorkerContext selfContext;
 
     private final Role role;
@@ -14,6 +20,11 @@
         this.role = role;
         this.clusterContext = clusterContext;
         this.selfContext = selfContext;
+        this.logger = LogManager.getFormatterLogger(role.roleName());
+    }
+
+    final public Logger logger() {
+        return logger;
     }
 
     public abstract void preStart() throws ProviderNotFoundException;
@@ -35,6 +46,6 @@
     }
 
     final protected void saveException(Exception e) {
-//        e.printStackTrace();
+        logger().error(e);
     }
 }
diff --git a/skywalking-collector/skywalking-collector-cluster/src/main/java/com/a/eye/skywalking/collector/actor/AbstractWorkerProvider.java b/skywalking-collector/skywalking-collector-cluster/src/main/java/com/a/eye/skywalking/collector/actor/AbstractWorkerProvider.java
index dfe72f3..945b06b 100644
--- a/skywalking-collector/skywalking-collector-cluster/src/main/java/com/a/eye/skywalking/collector/actor/AbstractWorkerProvider.java
+++ b/skywalking-collector/skywalking-collector-cluster/src/main/java/com/a/eye/skywalking/collector/actor/AbstractWorkerProvider.java
@@ -24,9 +24,6 @@
 
     final public WorkerRef create(
         AbstractWorker workerOwner) throws IllegalArgumentException, ProviderNotFoundException {
-        if (workerInstance(clusterContext) == null) {
-            throw new IllegalArgumentException("cannot get worker instance with nothing obtained from workerInstance()");
-        }
 
         if (workerOwner == null) {
             return onCreate(null);
diff --git a/skywalking-collector/skywalking-collector-cluster/src/main/java/com/a/eye/skywalking/collector/log/LogManager.java b/skywalking-collector/skywalking-collector-cluster/src/main/java/com/a/eye/skywalking/collector/log/LogManager.java
new file mode 100644
index 0000000..c374de5
--- /dev/null
+++ b/skywalking-collector/skywalking-collector-cluster/src/main/java/com/a/eye/skywalking/collector/log/LogManager.java
@@ -0,0 +1,14 @@
+package com.a.eye.skywalking.collector.log;
+
+import org.apache.logging.log4j.Logger;
+
+/**
+ * @author pengys5
+ */
+public enum LogManager {
+    INSTANCE;
+
+    public Logger getFormatterLogger(final Class<?> clazz) {
+        return org.apache.logging.log4j.LogManager.getFormatterLogger(clazz);
+    }
+}
diff --git a/skywalking-collector/skywalking-collector-cluster/src/test/java/com/a/eye/skywalking/collector/actor/AbstractClusterWorkerProviderTestCase.java b/skywalking-collector/skywalking-collector-cluster/src/test/java/com/a/eye/skywalking/collector/actor/AbstractClusterWorkerProviderTestCase.java
new file mode 100644
index 0000000..6b69272
--- /dev/null
+++ b/skywalking-collector/skywalking-collector-cluster/src/test/java/com/a/eye/skywalking/collector/actor/AbstractClusterWorkerProviderTestCase.java
@@ -0,0 +1,58 @@
+package com.a.eye.skywalking.collector.actor;
+
+import akka.actor.ActorSystem;
+import com.a.eye.skywalking.collector.actor.selector.RollingSelector;
+import com.a.eye.skywalking.collector.actor.selector.WorkerSelector;
+import com.a.eye.skywalking.collector.log.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.mockito.Mockito;
+import org.powermock.reflect.Whitebox;
+
+/**
+ * @author pengys5
+ */
+//@RunWith(PowerMockRunner.class)
+//@PrepareForTest({LogManager.class})
+public class AbstractClusterWorkerProviderTestCase {
+
+//    @Test
+    public void testOnCreate() throws ProviderNotFoundException {
+        LogManager logManager = Mockito.mock(LogManager.class);
+        Whitebox.setInternalState(LogManager.class, "INSTANCE", logManager);
+        Logger logger = Mockito.mock(Logger.class);
+        Mockito.when(logManager.getFormatterLogger(Mockito.any())).thenReturn(logger);
+
+        ActorSystem actorSystem = Mockito.mock(ActorSystem.class);
+        ClusterWorkerContext clusterWorkerContext = new ClusterWorkerContext(actorSystem);
+        Impl impl = new Impl();
+        impl.onCreate(null);
+    }
+
+    class Impl extends AbstractClusterWorkerProvider<AbstractClusterWorkerTestCase.Impl> {
+        @Override public Role role() {
+            return Role.INSTANCE;
+        }
+
+        @Override public AbstractClusterWorkerTestCase.Impl workerInstance(ClusterWorkerContext clusterContext) {
+            return new AbstractClusterWorkerTestCase.Impl(role(), clusterContext, new LocalWorkerContext());
+        }
+
+        @Override public int workerNum() {
+            return 0;
+        }
+    }
+
+    enum Role implements com.a.eye.skywalking.collector.actor.Role {
+        INSTANCE;
+
+        @Override
+        public String roleName() {
+            return AbstractClusterWorkerTestCase.Impl.class.getSimpleName();
+        }
+
+        @Override
+        public WorkerSelector workerSelector() {
+            return new RollingSelector();
+        }
+    }
+}
diff --git a/skywalking-collector/skywalking-collector-cluster/src/test/java/com/a/eye/skywalking/collector/actor/AbstractClusterWorkerTestCase.java b/skywalking-collector/skywalking-collector-cluster/src/test/java/com/a/eye/skywalking/collector/actor/AbstractClusterWorkerTestCase.java
index 968ff41..20d84eb 100644
--- a/skywalking-collector/skywalking-collector-cluster/src/test/java/com/a/eye/skywalking/collector/actor/AbstractClusterWorkerTestCase.java
+++ b/skywalking-collector/skywalking-collector-cluster/src/test/java/com/a/eye/skywalking/collector/actor/AbstractClusterWorkerTestCase.java
@@ -1,21 +1,101 @@
 package com.a.eye.skywalking.collector.actor;
 
+import akka.actor.Address;
+import akka.cluster.ClusterEvent;
+import akka.cluster.Member;
+import com.a.eye.skywalking.collector.actor.selector.RollingSelector;
+import com.a.eye.skywalking.collector.actor.selector.WorkerSelector;
+import org.apache.logging.log4j.Logger;
+import org.junit.Before;
 import org.junit.Test;
-import org.mockito.Mockito;
+import org.junit.runner.RunWith;
 import org.powermock.api.mockito.PowerMockito;
+import org.powermock.core.classloader.annotations.PowerMockIgnore;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import org.powermock.reflect.Whitebox;
+
+import static org.mockito.Mockito.CALLS_REAL_METHODS;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
 
 /**
  * @author pengys5
  */
+@RunWith(PowerMockRunner.class)
+@PrepareForTest({ClusterEvent.MemberUp.class, Address.class})
+@PowerMockIgnore({"javax.management.*"})
 public class AbstractClusterWorkerTestCase {
 
+    private AbstractClusterWorker.WorkerWithAkka workerWithAkka = mock(AbstractClusterWorker.WorkerWithAkka.class, CALLS_REAL_METHODS);
+    private AbstractClusterWorker worker = PowerMockito.spy(new Impl(WorkerRole.INSTANCE, null, null));
+
+    @Before
+    public void init(){
+        Logger logger = mock(Logger.class);
+        Whitebox.setInternalState(workerWithAkka, "logger", logger);
+        Whitebox.setInternalState(workerWithAkka, "ownerWorker", worker);
+    }
+
     @Test
     public void testAllocateJob() throws Exception {
-        AbstractClusterWorker worker = PowerMockito.mock(AbstractClusterWorker.class);
 
         String jobStr = "TestJob";
         worker.allocateJob(jobStr);
 
-        Mockito.verify(worker).onWork(jobStr);
+        verify(worker).onWork(jobStr);
+    }
+
+    @Test
+    public void testMemberUp() throws Throwable {
+        ClusterEvent.MemberUp memberUp = mock(ClusterEvent.MemberUp.class);
+
+        Address address = mock(Address.class);
+        when(address.toString()).thenReturn("address");
+
+        Member member = mock(Member.class);
+        when(member.address()).thenReturn(address);
+
+        when(memberUp.member()).thenReturn(member);
+
+        workerWithAkka.onReceive(memberUp);
+
+        verify(workerWithAkka).register(member);
+    }
+
+    @Test
+    public void testMessage() throws Throwable {
+        String message = "test";
+        workerWithAkka.onReceive(message);
+
+        verify(worker).allocateJob(message);
+    }
+
+    static class Impl extends AbstractClusterWorker {
+        @Override public void preStart() throws ProviderNotFoundException {
+        }
+
+        public Impl(Role role, ClusterWorkerContext clusterContext, LocalWorkerContext selfContext) {
+            super(role, clusterContext, selfContext);
+        }
+
+        @Override protected void onWork(Object message) throws Exception {
+
+        }
+    }
+
+    public enum WorkerRole implements Role {
+        INSTANCE;
+
+        @Override
+        public String roleName() {
+            return Impl.class.getSimpleName();
+        }
+
+        @Override
+        public WorkerSelector workerSelector() {
+            return new RollingSelector();
+        }
     }
 }
diff --git a/skywalking-collector/skywalking-collector-cluster/src/test/java/com/a/eye/skywalking/collector/actor/AbstractWorkerProviderTestCase.java b/skywalking-collector/skywalking-collector-cluster/src/test/java/com/a/eye/skywalking/collector/actor/AbstractWorkerProviderTestCase.java
index 5ff6ca5..eeb974f 100644
--- a/skywalking-collector/skywalking-collector-cluster/src/test/java/com/a/eye/skywalking/collector/actor/AbstractWorkerProviderTestCase.java
+++ b/skywalking-collector/skywalking-collector-cluster/src/test/java/com/a/eye/skywalking/collector/actor/AbstractWorkerProviderTestCase.java
@@ -6,6 +6,7 @@
 import static org.powermock.api.mockito.PowerMockito.*;
 
 import org.mockito.Mockito;
+import org.powermock.core.classloader.annotations.PowerMockIgnore;
 import org.powermock.core.classloader.annotations.PrepareForTest;
 import org.powermock.modules.junit4.PowerMockRunner;
 
@@ -14,6 +15,7 @@
  */
 @RunWith(PowerMockRunner.class)
 @PrepareForTest({AbstractWorker.class})
+@PowerMockIgnore({"javax.management.*"})
 public class AbstractWorkerProviderTestCase {
 
     @Test(expected = IllegalArgumentException.class)
diff --git a/skywalking-collector/skywalking-collector-cluster/src/test/java/com/a/eye/skywalking/collector/actor/selector/AbstractHashMessageTestCase.java b/skywalking-collector/skywalking-collector-cluster/src/test/java/com/a/eye/skywalking/collector/actor/selector/AbstractHashMessageTestCase.java
new file mode 100644
index 0000000..f3a66c9
--- /dev/null
+++ b/skywalking-collector/skywalking-collector-cluster/src/test/java/com/a/eye/skywalking/collector/actor/selector/AbstractHashMessageTestCase.java
@@ -0,0 +1,24 @@
+package com.a.eye.skywalking.collector.actor.selector;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * @author pengys5
+ */
+public class AbstractHashMessageTestCase {
+
+    @Test
+    public void testGetHashCode() {
+        String key = "key";
+
+        Impl impl = new Impl(key);
+        Assert.assertEquals(key.hashCode(), impl.getHashCode());
+    }
+
+    class Impl extends AbstractHashMessage {
+        public Impl(String key) {
+            super(key);
+        }
+    }
+}
diff --git a/skywalking-collector/skywalking-collector-cluster/src/test/java/com/a/eye/skywalking/collector/actor/selector/HashCodeSelectorTestCase.java b/skywalking-collector/skywalking-collector-cluster/src/test/java/com/a/eye/skywalking/collector/actor/selector/HashCodeSelectorTestCase.java
index 13cfda8..9a71c6b 100644
--- a/skywalking-collector/skywalking-collector-cluster/src/test/java/com/a/eye/skywalking/collector/actor/selector/HashCodeSelectorTestCase.java
+++ b/skywalking-collector/skywalking-collector-cluster/src/test/java/com/a/eye/skywalking/collector/actor/selector/HashCodeSelectorTestCase.java
@@ -46,4 +46,10 @@
         WorkerRef select_3 = selector.select(members, message_3);
         Assert.assertEquals(workerRef_3.hashCode(), select_3.hashCode());
     }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testSelectError() {
+        HashCodeSelector selector = new HashCodeSelector();
+        selector.select(null, new Object());
+    }
 }
diff --git a/skywalking-collector/skywalking-collector-cluster/src/test/java/com/a/eye/skywalking/collector/log/MockLog.java b/skywalking-collector/skywalking-collector-cluster/src/test/java/com/a/eye/skywalking/collector/log/MockLog.java
new file mode 100644
index 0000000..313fa04
--- /dev/null
+++ b/skywalking-collector/skywalking-collector-cluster/src/test/java/com/a/eye/skywalking/collector/log/MockLog.java
@@ -0,0 +1,18 @@
+package com.a.eye.skywalking.collector.log;
+
+import org.apache.logging.log4j.Logger;
+import org.mockito.Mockito;
+import org.powermock.api.mockito.PowerMockito;
+
+/**
+ * @author pengys5
+ */
+public class MockLog {
+
+    public Logger mockito() {
+        LogManager logManager = PowerMockito.mock(LogManager.class);
+        Logger logger = Mockito.mock(Logger.class);
+        Mockito.when(logManager.getFormatterLogger(Mockito.any())).thenReturn(logger);
+        return logger;
+    }
+}
diff --git a/skywalking-collector/skywalking-collector-cluster/src/test/resources/application.conf b/skywalking-collector/skywalking-collector-cluster/src/test/resources/application.conf
deleted file mode 100644
index 63ff452..0000000
--- a/skywalking-collector/skywalking-collector-cluster/src/test/resources/application.conf
+++ /dev/null
@@ -1,37 +0,0 @@
-akka {
-  actor {
-    provider = "akka.cluster.ClusterActorRefProvider"
-
-    serializers {
-      java = "akka.serialization.JavaSerializer"
-      proto = "akka.remote.serialization.ProtobufSerializer"
-//      data = "com.a.eye.skywalking.collector.worker.TraceSegmentSerializer"
-//      json = "com.a.eye.skywalking.collector.commons.serializer.JsonSerializer"
-    }
-
-    serialization-bindings {
-      "java.lang.String" = java
-      "com.google.protobuf.Message" = proto
-//      "com.a.eye.skywalking.messages.ISerializable" = data
-//      "com.google.gson.JsonObject" = json
-      //      "java.io.Serializable" = none
-    }
-
-    //    serialize-messages = on
-    warn-about-java-serializer-usage = on
-  }
-
-  remote {
-    log-remote-lifecycle-events = off
-
-    netty.tcp {
-      hostname = "127.0.0.1"
-      port = 1000
-    }
-  }
-
-  cluster {
-    auto-down-unreachable-after = off
-    metrics.enabled = off
-  }
-}
\ No newline at end of file
diff --git a/skywalking-collector/skywalking-collector-cluster/src/test/resources/log4j2.xml b/skywalking-collector/skywalking-collector-cluster/src/test/resources/log4j2.xml
index e6e23fe..cc2fe77 100644
--- a/skywalking-collector/skywalking-collector-cluster/src/test/resources/log4j2.xml
+++ b/skywalking-collector/skywalking-collector-cluster/src/test/resources/log4j2.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<Configuration status="debug">
+<Configuration status="error">
     <Appenders>
         <Console name="Console" target="SYSTEM_OUT">
             <PatternLayout charset="UTF-8" pattern="[%d{yyyy-MM-dd HH:mm:ss:SSS}] [%p] - %l - %m%n"/>
diff --git a/skywalking-collector/skywalking-collector-worker/docker/Dockerfile b/skywalking-collector/skywalking-collector-worker/docker/Dockerfile
index b6025fd..d9d2505 100644
--- a/skywalking-collector/skywalking-collector-worker/docker/Dockerfile
+++ b/skywalking-collector/skywalking-collector-worker/docker/Dockerfile
@@ -9,7 +9,7 @@
     ES_INDEX_SHARDS_NUMBER=2 \
     ES_INDEX_REPLICAS_NUMBER=0 \
     HTTP_HOST_NAME=127.0.0.1 \
-    HTTP_PORT=7001 \
+    HTTP_PORT=12800 \
     HTTP_CONTEXT_PATH=/
 
 ADD skywalking-collector.tar.gz /usr/local
diff --git a/skywalking-collector/skywalking-collector-worker/pom.xml b/skywalking-collector/skywalking-collector-worker/pom.xml
index 5e4ee97..9c2a207 100644
--- a/skywalking-collector/skywalking-collector-worker/pom.xml
+++ b/skywalking-collector/skywalking-collector-worker/pom.xml
@@ -51,11 +51,6 @@
             <version>${project.version}</version>
             <scope>test</scope>
         </dependency>
-        <dependency>
-            <groupId>org.jetbrains</groupId>
-            <artifactId>annotations</artifactId>
-            <version>RELEASE</version>
-        </dependency>
     </dependencies>
 
     <build>
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/AnalysisMember.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/AnalysisMember.java
index ef821a8..a529181 100644
--- a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/AnalysisMember.java
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/AnalysisMember.java
@@ -2,6 +2,7 @@
 
 import com.a.eye.skywalking.collector.actor.*;
 import com.a.eye.skywalking.collector.queue.EndOfBatchCommand;
+import com.a.eye.skywalking.collector.worker.config.CacheSizeConfig;
 
 /**
  * @author pengys5
@@ -12,6 +13,8 @@
         super(role, clusterContext, selfContext);
     }
 
+    private int messageNum;
+
     public abstract void analyse(Object message) throws Exception;
 
     @Override
@@ -23,11 +26,17 @@
         if (message instanceof EndOfBatchCommand) {
             aggregation();
         } else {
+            messageNum++;
             try {
                 analyse(message);
             } catch (Exception e) {
                 saveException(e);
             }
+
+            if (messageNum >= CacheSizeConfig.Cache.Analysis.SIZE) {
+                aggregation();
+                messageNum = 0;
+            }
         }
     }
 
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/CollectorBootStartUp.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/CollectorBootStartUp.java
index daaccf4..5d56361 100644
--- a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/CollectorBootStartUp.java
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/CollectorBootStartUp.java
@@ -5,6 +5,7 @@
 import com.a.eye.skywalking.collector.worker.httpserver.HttpServer;
 import com.a.eye.skywalking.collector.worker.storage.EsClient;
 import com.a.eye.skywalking.collector.worker.storage.IndexCreator;
+import com.a.eye.skywalking.collector.worker.storage.PersistenceTimer;
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
 
@@ -20,6 +21,7 @@
         collectorSystem.boot();
         EsClient.INSTANCE.boot();
         IndexCreator.INSTANCE.create();
+        PersistenceTimer.INSTANCE.boot();
         HttpServer.INSTANCE.boot((ClusterWorkerContext)collectorSystem.getClusterContext());
     }
 }
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/JoinAndSplitAnalysisMember.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/JoinAndSplitAnalysisMember.java
new file mode 100644
index 0000000..92f6129
--- /dev/null
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/JoinAndSplitAnalysisMember.java
@@ -0,0 +1,41 @@
+package com.a.eye.skywalking.collector.worker;
+
+import com.a.eye.skywalking.collector.actor.ClusterWorkerContext;
+import com.a.eye.skywalking.collector.actor.LocalWorkerContext;
+import com.a.eye.skywalking.collector.actor.Role;
+import com.a.eye.skywalking.collector.actor.WorkerRefs;
+import com.a.eye.skywalking.collector.worker.storage.JoinAndSplitAnalysisData;
+
+/**
+ * @author pengys5
+ */
+public abstract class JoinAndSplitAnalysisMember extends AnalysisMember {
+    private JoinAndSplitAnalysisData joinAndSplitAnalysisData;
+
+    public JoinAndSplitAnalysisMember(Role role, ClusterWorkerContext clusterContext, LocalWorkerContext selfContext) {
+        super(role, clusterContext, selfContext);
+        joinAndSplitAnalysisData = new JoinAndSplitAnalysisData();
+    }
+
+    private JoinAndSplitAnalysisData getJoinAndSplitAnalysisData() {
+        return joinAndSplitAnalysisData;
+    }
+
+    final protected void set(String id, String attributeName, String value) throws Exception {
+        getJoinAndSplitAnalysisData().getOrCreate(id).set(attributeName, value);
+    }
+
+    @Override
+    final protected void aggregation() throws Exception {
+        getJoinAndSplitAnalysisData().asMap().forEach((key, value) -> {
+            try {
+                aggWorkRefs().tell(value);
+            } catch (Exception e) {
+                logger().error(e);
+            }
+        });
+        getJoinAndSplitAnalysisData().asMap().clear();
+    }
+
+    protected abstract WorkerRefs aggWorkRefs();
+}
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/JoinAndSplitPersistenceMember.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/JoinAndSplitPersistenceMember.java
new file mode 100644
index 0000000..81b9f27
--- /dev/null
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/JoinAndSplitPersistenceMember.java
@@ -0,0 +1,58 @@
+package com.a.eye.skywalking.collector.worker;
+
+import com.a.eye.skywalking.collector.actor.ClusterWorkerContext;
+import com.a.eye.skywalking.collector.actor.LocalWorkerContext;
+import com.a.eye.skywalking.collector.actor.Role;
+import com.a.eye.skywalking.collector.worker.storage.EsClient;
+import com.a.eye.skywalking.collector.worker.storage.JoinAndSplitData;
+import com.a.eye.skywalking.collector.worker.storage.JoinAndSplitPersistenceData;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.elasticsearch.action.index.IndexRequestBuilder;
+import org.elasticsearch.client.Client;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author pengys5
+ */
+public abstract class JoinAndSplitPersistenceMember extends PersistenceMember<JoinAndSplitPersistenceData, JoinAndSplitData> {
+
+    private Logger logger = LogManager.getFormatterLogger(JoinAndSplitPersistenceMember.class);
+
+    protected JoinAndSplitPersistenceMember(Role role, ClusterWorkerContext clusterContext, LocalWorkerContext selfContext) {
+        super(role, clusterContext, selfContext);
+    }
+
+    @Override
+    public JoinAndSplitPersistenceData initializeData() {
+        return new JoinAndSplitPersistenceData();
+    }
+
+    @Override
+    final public void analyse(Object message) throws Exception {
+        if (message instanceof JoinAndSplitData) {
+            JoinAndSplitData joinAndSplitData = (JoinAndSplitData) message;
+            JoinAndSplitPersistenceData data = getPersistenceData();
+            data.hold();
+            data.getOrCreate(joinAndSplitData.getId()).merge(joinAndSplitData);
+            data.release();
+        } else {
+            logger.error("unhandled message, message instance must JoinAndSplitData, but is %s", message.getClass().toString());
+        }
+    }
+
+    @Override
+    final protected void prepareIndex(List<IndexRequestBuilder> builderList) {
+        Map<String, JoinAndSplitData> lastData = getPersistenceData().getLast().asMap();
+        extractData(lastData);
+
+        Client client = EsClient.INSTANCE.getClient();
+        lastData.forEach((key, value) -> {
+            IndexRequestBuilder builder = client.prepareIndex(esIndex(), esType(), key).setSource(value.asMap());
+            builderList.add(builder);
+        });
+        lastData.clear();
+    }
+}
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/MergeAnalysisMember.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/MergeAnalysisMember.java
deleted file mode 100644
index 9864a5e..0000000
--- a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/MergeAnalysisMember.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package com.a.eye.skywalking.collector.worker;
-
-import com.a.eye.skywalking.collector.actor.ClusterWorkerContext;
-import com.a.eye.skywalking.collector.actor.LocalWorkerContext;
-import com.a.eye.skywalking.collector.actor.Role;
-import com.a.eye.skywalking.collector.worker.config.CacheSizeConfig;
-import com.a.eye.skywalking.collector.worker.storage.MergeData;
-import com.a.eye.skywalking.collector.worker.storage.MergePersistenceData;
-
-/**
- * @author pengys5
- */
-public abstract class MergeAnalysisMember extends AnalysisMember {
-
-    private MergePersistenceData persistenceData;
-
-    protected MergeAnalysisMember(Role role, ClusterWorkerContext clusterContext, LocalWorkerContext selfContext) {
-        super(role, clusterContext, selfContext);
-        persistenceData = new MergePersistenceData();
-    }
-
-    private MergePersistenceData getPersistenceData() {
-        return persistenceData;
-    }
-
-    final protected void setMergeData(String id, String column, String value) throws Exception {
-        getPersistenceData().getElseCreate(id).setMergeData(column, value);
-        if (getPersistenceData().size() >= CacheSizeConfig.Cache.Analysis.SIZE) {
-            aggregation();
-        }
-    }
-
-    final public MergeData pushOne() {
-        if (getPersistenceData().iterator().hasNext()) {
-            return getPersistenceData().pushOne();
-        }
-        return null;
-    }
-}
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/MergePersistenceMember.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/MergePersistenceMember.java
deleted file mode 100644
index f6d7ebf..0000000
--- a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/MergePersistenceMember.java
+++ /dev/null
@@ -1,95 +0,0 @@
-package com.a.eye.skywalking.collector.worker;
-
-import com.a.eye.skywalking.collector.actor.ClusterWorkerContext;
-import com.a.eye.skywalking.collector.actor.LocalWorkerContext;
-import com.a.eye.skywalking.collector.actor.Role;
-import com.a.eye.skywalking.collector.worker.config.CacheSizeConfig;
-import com.a.eye.skywalking.collector.worker.storage.EsClient;
-import com.a.eye.skywalking.collector.worker.storage.MergeData;
-import com.a.eye.skywalking.collector.worker.storage.MergePersistenceData;
-import org.apache.logging.log4j.LogManager;
-import org.apache.logging.log4j.Logger;
-import org.elasticsearch.action.bulk.BulkRequestBuilder;
-import org.elasticsearch.action.bulk.BulkResponse;
-import org.elasticsearch.action.get.GetResponse;
-import org.elasticsearch.action.get.MultiGetItemResponse;
-import org.elasticsearch.action.get.MultiGetRequestBuilder;
-import org.elasticsearch.action.get.MultiGetResponse;
-import org.elasticsearch.client.Client;
-
-import java.util.Iterator;
-import java.util.Map;
-
-/**
- * @author pengys5
- */
-public abstract class MergePersistenceMember extends PersistenceMember {
-
-    private Logger logger = LogManager.getFormatterLogger(MergePersistenceMember.class);
-
-    private MergePersistenceData persistenceData;
-
-    protected MergePersistenceMember(Role role, ClusterWorkerContext clusterContext, LocalWorkerContext selfContext) {
-        super(role, clusterContext, selfContext);
-        persistenceData = new MergePersistenceData();
-    }
-
-    private MergePersistenceData getPersistenceData() {
-        return persistenceData;
-    }
-
-    @Override final public void analyse(Object message) throws Exception {
-        if (message instanceof MergeData) {
-            MergeData mergeData = (MergeData)message;
-            getPersistenceData().getElseCreate(mergeData.getId()).merge(mergeData);
-            if (getPersistenceData().size() >= CacheSizeConfig.Cache.Persistence.SIZE) {
-                persistence();
-            }
-        } else {
-            logger.error("message unhandled");
-        }
-    }
-
-    final protected void persistence() {
-        MultiGetResponse multiGetResponse = searchFromEs();
-        for (MultiGetItemResponse itemResponse : multiGetResponse) {
-            GetResponse response = itemResponse.getResponse();
-            if (response != null && response.isExists()) {
-                getPersistenceData().getElseCreate(response.getId()).merge(response.getSource());
-            }
-        }
-
-        boolean success = saveToEs();
-        if (success) {
-            getPersistenceData().clear();
-        }
-    }
-
-    private MultiGetResponse searchFromEs() {
-        Client client = EsClient.INSTANCE.getClient();
-        MultiGetRequestBuilder multiGetRequestBuilder = client.prepareMultiGet();
-
-        Iterator<Map.Entry<String, MergeData>> iterator = getPersistenceData().iterator();
-
-        while (iterator.hasNext()) {
-            multiGetRequestBuilder.add(esIndex(), esType(), iterator.next().getKey());
-        }
-
-        return multiGetRequestBuilder.get();
-    }
-
-    private boolean saveToEs() {
-        Client client = EsClient.INSTANCE.getClient();
-        BulkRequestBuilder bulkRequest = client.prepareBulk();
-        logger.debug("persistenceData SIZE: %s", getPersistenceData().size());
-
-        Iterator<Map.Entry<String, MergeData>> iterator = getPersistenceData().iterator();
-        while (iterator.hasNext()) {
-            MergeData mergeData = iterator.next().getValue();
-            bulkRequest.add(client.prepareIndex(esIndex(), esType(), mergeData.getId()).setSource(mergeData.toMap()));
-        }
-
-        BulkResponse bulkResponse = bulkRequest.execute().actionGet();
-        return !bulkResponse.hasFailures();
-    }
-}
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/MetricAnalysisMember.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/MetricAnalysisMember.java
index 4a63a5e..51d1e64 100644
--- a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/MetricAnalysisMember.java
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/MetricAnalysisMember.java
@@ -3,32 +3,38 @@
 import com.a.eye.skywalking.collector.actor.ClusterWorkerContext;
 import com.a.eye.skywalking.collector.actor.LocalWorkerContext;
 import com.a.eye.skywalking.collector.actor.Role;
-import com.a.eye.skywalking.collector.worker.config.CacheSizeConfig;
-import com.a.eye.skywalking.collector.worker.storage.MetricData;
-import com.a.eye.skywalking.collector.worker.storage.MetricPersistenceData;
+import com.a.eye.skywalking.collector.actor.WorkerRefs;
+import com.a.eye.skywalking.collector.worker.storage.MetricAnalysisData;
 
 /**
  * @author pengys5
  */
 public abstract class MetricAnalysisMember extends AnalysisMember {
-
-    private MetricPersistenceData persistenceData = new MetricPersistenceData();
+    private MetricAnalysisData metricAnalysisData = new MetricAnalysisData();
 
     public MetricAnalysisMember(Role role, ClusterWorkerContext clusterContext, LocalWorkerContext selfContext) {
         super(role, clusterContext, selfContext);
     }
 
-    final protected void setMetric(String id, String column, Long value) throws Exception {
-        persistenceData.getElseCreate(id).setMetric(column, value);
-        if (persistenceData.size() >= CacheSizeConfig.Cache.Persistence.SIZE) {
-            aggregation();
-        }
+    final protected void set(String id, String metricName, Long value) throws Exception {
+        getMetricAnalysisData().getOrCreate(id).set(metricName, value);
     }
 
-    final public MetricData pushOne() {
-        if (persistenceData.iterator().hasNext()) {
-            return persistenceData.pushOne();
-        }
-        return null;
+    private MetricAnalysisData getMetricAnalysisData() {
+        return metricAnalysisData;
     }
+
+    @Override
+    final protected void aggregation() throws Exception {
+        getMetricAnalysisData().asMap().forEach((key, value) -> {
+            try {
+                aggWorkRefs().tell(value);
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        });
+        getMetricAnalysisData().asMap().clear();
+    }
+
+    protected abstract WorkerRefs aggWorkRefs();
 }
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/MetricPersistenceMember.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/MetricPersistenceMember.java
index 2089848..520b100 100644
--- a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/MetricPersistenceMember.java
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/MetricPersistenceMember.java
@@ -3,89 +3,55 @@
 import com.a.eye.skywalking.collector.actor.ClusterWorkerContext;
 import com.a.eye.skywalking.collector.actor.LocalWorkerContext;
 import com.a.eye.skywalking.collector.actor.Role;
-import com.a.eye.skywalking.collector.worker.config.CacheSizeConfig;
 import com.a.eye.skywalking.collector.worker.storage.EsClient;
 import com.a.eye.skywalking.collector.worker.storage.MetricData;
 import com.a.eye.skywalking.collector.worker.storage.MetricPersistenceData;
+import java.util.List;
+import java.util.Map;
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
-import org.elasticsearch.action.bulk.BulkRequestBuilder;
-import org.elasticsearch.action.bulk.BulkResponse;
-import org.elasticsearch.action.get.GetResponse;
-import org.elasticsearch.action.get.MultiGetItemResponse;
-import org.elasticsearch.action.get.MultiGetRequestBuilder;
-import org.elasticsearch.action.get.MultiGetResponse;
+import org.elasticsearch.action.index.IndexRequestBuilder;
 import org.elasticsearch.client.Client;
 
-import java.util.Iterator;
-import java.util.Map;
-
 /**
  * @author pengys5
  */
-public abstract class MetricPersistenceMember extends PersistenceMember {
+public abstract class MetricPersistenceMember extends PersistenceMember<MetricPersistenceData, MetricData> {
 
     private Logger logger = LogManager.getFormatterLogger(MetricPersistenceMember.class);
 
-    private MetricPersistenceData persistenceData = new MetricPersistenceData();
-
     public MetricPersistenceMember(Role role, ClusterWorkerContext clusterContext, LocalWorkerContext selfContext) {
         super(role, clusterContext, selfContext);
     }
 
-    @Override final public void analyse(Object message) throws Exception {
+    @Override
+    public MetricPersistenceData initializeData() {
+        return new MetricPersistenceData();
+    }
+
+    @Override
+    final public void analyse(Object message) throws Exception {
         if (message instanceof MetricData) {
-            MetricData metricData = (MetricData)message;
-            persistenceData.getElseCreate(metricData.getId()).merge(metricData);
-            if (persistenceData.size() >= CacheSizeConfig.Cache.Persistence.SIZE) {
-                persistence();
-            }
+            MetricData metricData = (MetricData) message;
+            MetricPersistenceData data = getPersistenceData();
+            data.hold();
+            data.getOrCreate(metricData.getId()).merge(metricData);
+            data.release();
         } else {
-            logger.error("message unhandled");
+            logger.error("unhandled message, message instance must MetricData, but is %s", message.getClass().toString());
         }
     }
 
-    final protected void persistence() {
-        MultiGetResponse multiGetResponse = searchFromEs();
-        for (MultiGetItemResponse itemResponse : multiGetResponse) {
-            GetResponse response = itemResponse.getResponse();
-            if (response != null && response.isExists()) {
-                persistenceData.getElseCreate(response.getId()).merge(response.getSource());
-            }
-        }
+    @Override
+    final protected void prepareIndex(List<IndexRequestBuilder> builderList) {
+        Map<String, MetricData> lastData = getPersistenceData().getLast().asMap();
+        extractData(lastData);
 
-        boolean success = saveToEs();
-        if (success) {
-            persistenceData.clear();
-        }
-    }
-
-    private MultiGetResponse searchFromEs() {
         Client client = EsClient.INSTANCE.getClient();
-        MultiGetRequestBuilder multiGetRequestBuilder = client.prepareMultiGet();
-
-        Iterator<Map.Entry<String, MetricData>> iterator = persistenceData.iterator();
-
-        while (iterator.hasNext()) {
-            multiGetRequestBuilder.add(esIndex(), esType(), iterator.next().getKey());
-        }
-
-        MultiGetResponse multiGetResponse = multiGetRequestBuilder.get();
-        return multiGetResponse;
+        lastData.forEach((key, value) -> {
+            IndexRequestBuilder builder = client.prepareIndex(esIndex(), esType(), key).setSource(value.asMap());
+            builderList.add(builder);
+        });
+        lastData.clear();
     }
-
-    private boolean saveToEs() {
-        Client client = EsClient.INSTANCE.getClient();
-        BulkRequestBuilder bulkRequest = client.prepareBulk();
-        logger.debug("persistenceData SIZE: %s", persistenceData.size());
-
-        Iterator<Map.Entry<String, MetricData>> iterator = persistenceData.iterator();
-        while (iterator.hasNext()) {
-            MetricData metricData = iterator.next().getValue();
-            bulkRequest.add(client.prepareIndex(esIndex(), esType(), metricData.getId()).setSource(metricData.toMap()));
-        }
-
-        BulkResponse bulkResponse = bulkRequest.execute().actionGet();
-        return !bulkResponse.hasFailures();
-    }
-}
+}
\ No newline at end of file
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/PersistenceMember.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/PersistenceMember.java
index 4a28178..ffe16dd 100644
--- a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/PersistenceMember.java
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/PersistenceMember.java
@@ -1,19 +1,38 @@
 package com.a.eye.skywalking.collector.worker;
 
 import com.a.eye.skywalking.collector.actor.*;
-import com.a.eye.skywalking.collector.queue.EndOfBatchCommand;
+import com.a.eye.skywalking.collector.worker.storage.*;
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
+import org.elasticsearch.action.get.GetResponse;
+import org.elasticsearch.action.get.MultiGetItemResponse;
+import org.elasticsearch.action.get.MultiGetRequestBuilder;
+import org.elasticsearch.action.get.MultiGetResponse;
+import org.elasticsearch.action.index.IndexRequestBuilder;
+import org.elasticsearch.client.Client;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
 
 /**
  * @author pengys5
  */
-public abstract class PersistenceMember extends AbstractLocalAsyncWorker {
+public abstract class PersistenceMember<T extends Window & PersistenceData, D extends Data> extends AbstractLocalSyncWorker {
 
     private Logger logger = LogManager.getFormatterLogger(PersistenceMember.class);
 
     public PersistenceMember(Role role, ClusterWorkerContext clusterContext, LocalWorkerContext selfContext) {
         super(role, clusterContext, selfContext);
+        persistenceData = initializeData();
+    }
+
+    private T persistenceData;
+
+    public abstract T initializeData();
+
+    protected T getPersistenceData() {
+        return persistenceData;
     }
 
     public abstract String esIndex();
@@ -22,17 +41,76 @@
 
     public abstract void analyse(Object message) throws Exception;
 
-    @Override final public void preStart() throws ProviderNotFoundException {
+    @Override
+    final public void preStart() throws ProviderNotFoundException {
 
     }
 
-    @Override final protected void onWork(Object message) throws Exception {
-        if (message instanceof EndOfBatchCommand) {
-            persistence();
+    @Override
+    protected void onWork(Object request, Object response) throws Exception {
+        if (request instanceof FlushAndSwitch) {
+            persistenceData.switchPointer();
+            while (persistenceData.getLast().isHolding()) {
+                Thread.sleep(10);
+            }
+
+            if (response instanceof LinkedList) {
+                prepareIndex((LinkedList) response);
+            } else {
+                logger.error("unhandled response, response instance must LinkedList, but is %s", response.getClass().toString());
+            }
+
         } else {
-            analyse(message);
+            analyse(request);
         }
     }
 
-    protected abstract void persistence();
+    private MultiGetResponse searchFromEs(Map<String, D> dataMap) {
+        Client client = EsClient.INSTANCE.getClient();
+        MultiGetRequestBuilder multiGetRequestBuilder = client.prepareMultiGet();
+
+        HasDataFlag flag = new HasDataFlag();
+        dataMap.forEach((key, value) -> {
+            multiGetRequestBuilder.add(esIndex(), esType(), value.getId());
+            flag.doTagHasData();
+        });
+
+        if (flag.isHasData()) {
+            return multiGetRequestBuilder.get();
+        } else {
+            return null;
+        }
+    }
+
+    final void extractData(Map<String, D> dataMap) {
+        MultiGetResponse multiGetResponse = searchFromEs(dataMap);
+        if (multiGetResponse != null) {
+            for (MultiGetItemResponse itemResponse : multiGetResponse) {
+                GetResponse response = itemResponse.getResponse();
+                if (response != null && response.isExists()) {
+                    if (dataMap.containsKey(response.getId())) {
+                        dataMap.get(response.getId()).merge(response.getSource());
+                    }
+                }
+            }
+        }
+    }
+
+    protected abstract void prepareIndex(List<IndexRequestBuilder> builderList);
+
+    class HasDataFlag {
+        private boolean hasData;
+
+        HasDataFlag() {
+            hasData = false;
+        }
+
+        boolean isHasData() {
+            return hasData;
+        }
+
+        void doTagHasData() {
+            this.hasData = true;
+        }
+    }
 }
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/RecordAnalysisMember.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/RecordAnalysisMember.java
index 1e52670..137b969 100644
--- a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/RecordAnalysisMember.java
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/RecordAnalysisMember.java
@@ -3,33 +3,43 @@
 import com.a.eye.skywalking.collector.actor.ClusterWorkerContext;
 import com.a.eye.skywalking.collector.actor.LocalWorkerContext;
 import com.a.eye.skywalking.collector.actor.Role;
-import com.a.eye.skywalking.collector.worker.config.CacheSizeConfig;
-import com.a.eye.skywalking.collector.worker.storage.RecordData;
-import com.a.eye.skywalking.collector.worker.storage.RecordPersistenceData;
+import com.a.eye.skywalking.collector.actor.WorkerRefs;
+import com.a.eye.skywalking.collector.worker.storage.RecordAnalysisData;
 import com.google.gson.JsonObject;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
 
 /**
  * @author pengys5
  */
 public abstract class RecordAnalysisMember extends AnalysisMember {
 
-    private RecordPersistenceData persistenceData = new RecordPersistenceData();
+    private Logger logger = LogManager.getFormatterLogger(RecordAnalysisMember.class);
+
+    private RecordAnalysisData recordAnalysisData = new RecordAnalysisData();
 
     public RecordAnalysisMember(Role role, ClusterWorkerContext clusterContext, LocalWorkerContext selfContext) {
         super(role, clusterContext, selfContext);
     }
 
-    final public void setRecord(String id, JsonObject record) throws Exception {
-        persistenceData.getElseCreate(id).setRecord(record);
-        if (persistenceData.size() >= CacheSizeConfig.Cache.Analysis.SIZE) {
-            aggregation();
-        }
+    final public void set(String id, JsonObject record) throws Exception {
+        getRecordAnalysisData().getOrCreate(id).set(record);
     }
 
-    final public RecordData pushOne() {
-        if (persistenceData.hasNext()) {
-            return persistenceData.pushOne();
-        }
-        return null;
+    private RecordAnalysisData getRecordAnalysisData() {
+        return recordAnalysisData;
     }
+
+    @Override final protected void aggregation() throws Exception {
+        getRecordAnalysisData().asMap().forEach((key, value) -> {
+            try {
+                aggWorkRefs().tell(value);
+            } catch (Exception e) {
+                logger.error(e);
+            }
+        });
+        getRecordAnalysisData().asMap().clear();
+    }
+
+    protected abstract WorkerRefs aggWorkRefs();
 }
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/RecordPersistenceMember.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/RecordPersistenceMember.java
index 42a9195..ec0f560 100644
--- a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/RecordPersistenceMember.java
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/RecordPersistenceMember.java
@@ -3,75 +3,52 @@
 import com.a.eye.skywalking.collector.actor.ClusterWorkerContext;
 import com.a.eye.skywalking.collector.actor.LocalWorkerContext;
 import com.a.eye.skywalking.collector.actor.Role;
-import com.a.eye.skywalking.collector.worker.config.CacheSizeConfig;
 import com.a.eye.skywalking.collector.worker.storage.EsClient;
 import com.a.eye.skywalking.collector.worker.storage.RecordData;
 import com.a.eye.skywalking.collector.worker.storage.RecordPersistenceData;
-import org.apache.logging.log4j.LogManager;
-import org.apache.logging.log4j.Logger;
-import org.elasticsearch.action.bulk.BulkRequestBuilder;
-import org.elasticsearch.action.bulk.BulkResponse;
-import org.elasticsearch.client.Client;
-
-import java.util.Iterator;
+import java.util.List;
 import java.util.Map;
+import org.elasticsearch.action.index.IndexRequestBuilder;
+import org.elasticsearch.client.Client;
 
 /**
  * @author pengys5
  */
-public abstract class RecordPersistenceMember extends PersistenceMember {
-
-    private Logger logger = LogManager.getFormatterLogger(RecordPersistenceMember.class);
-
-    private RecordPersistenceData persistenceData;
+public abstract class RecordPersistenceMember extends PersistenceMember<RecordPersistenceData, RecordData> {
 
     public RecordPersistenceMember(Role role, ClusterWorkerContext clusterContext, LocalWorkerContext selfContext) {
         super(role, clusterContext, selfContext);
-        persistenceData = new RecordPersistenceData();
     }
 
-    private RecordPersistenceData getPersistenceData() {
-        return this.persistenceData;
+    @Override
+    final public RecordPersistenceData initializeData() {
+        return new RecordPersistenceData();
     }
 
     @Override
     public void analyse(Object message) throws Exception {
         if (message instanceof RecordData) {
-            RecordData recordData = (RecordData)message;
-            logger.debug("setRecord: id: %s, data: %s", recordData.getId(), recordData.getRecord());
-            getPersistenceData().getElseCreate(recordData.getId()).setRecord(recordData.getRecord());
-            if (getPersistenceData().size() >= CacheSizeConfig.Cache.Persistence.SIZE) {
-                persistence();
-            }
+            RecordData recordData = (RecordData) message;
+            logger().debug("set: id: %s, data: %s", recordData.getId(), recordData.get());
+            RecordPersistenceData data = getPersistenceData();
+            data.hold();
+            data.getOrCreate(recordData.getId()).set(recordData.get());
+            data.release();
         } else {
-            logger.error("message unhandled");
+            logger().error("message unhandled");
         }
     }
 
-    protected void persistence() {
-        boolean success = saveToEs();
-        if (success) {
-            getPersistenceData().clear();
-        }
-    }
+    @Override
+    final protected void prepareIndex(List<IndexRequestBuilder> builderList) {
+        Map<String, RecordData> lastData = getPersistenceData().getLast().asMap();
+        extractData(lastData);
 
-    private boolean saveToEs() {
         Client client = EsClient.INSTANCE.getClient();
-        BulkRequestBuilder bulkRequest = client.prepareBulk();
-        logger.debug("persistenceData SIZE: %s", getPersistenceData().size());
-
-        Iterator<Map.Entry<String, RecordData>> iterator = getPersistenceData().iterator();
-
-        while (iterator.hasNext()) {
-            Map.Entry<String, RecordData> recordData = iterator.next();
-            logger.debug("saveToEs: key: %s, data: %s", recordData.getKey(), recordData.getValue().getRecord().toString());
-            bulkRequest.add(client.prepareIndex(esIndex(), esType(), recordData.getKey()).setSource(recordData.getValue().getRecord().toString()));
-        }
-
-        BulkResponse bulkResponse = bulkRequest.execute().actionGet();
-        if (bulkResponse.hasFailures()) {
-            logger.error(bulkResponse.buildFailureMessage());
-        }
-        return !bulkResponse.hasFailures();
+        lastData.forEach((key, value) -> {
+            IndexRequestBuilder builder = client.prepareIndex(esIndex(), esType(), key).setSource(value.get().toString());
+            builderList.add(builder);
+        });
+        lastData.clear();
     }
 }
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/config/CacheSizeConfig.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/config/CacheSizeConfig.java
index 69fb26e..5fc4426 100644
--- a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/config/CacheSizeConfig.java
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/config/CacheSizeConfig.java
@@ -7,11 +7,11 @@
 
     public static class Cache {
         public static class Analysis {
-            public static int SIZE = 1000;
+            public static int SIZE = 1024;
         }
 
         public static class Persistence {
-            public static int SIZE = 1000;
+            public static int SIZE = 5000;
         }
     }
 }
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/config/EsConfig.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/config/EsConfig.java
index d4dc24a..0c8c133 100644
--- a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/config/EsConfig.java
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/config/EsConfig.java
@@ -15,6 +15,12 @@
             }
         }
 
+        public static class Persistence {
+            public static class Timer {
+                public static Integer VALUE = 3;
+            }
+        }
+
         public static class Index {
 
             public static class Initialize {
@@ -28,6 +34,40 @@
             public static class Replicas {
                 public static String NUMBER = "";
             }
+
+            public static class RefreshInterval {
+                public static class GlobalTraceIndex {
+                    public static Integer VALUE = 1;
+                }
+
+                public static class NodeCompIndex {
+                    public static Integer VALUE = 1;
+                }
+
+                public static class NodeMappingIndex {
+                    public static Integer VALUE = 1;
+                }
+
+                public static class NodeRefIndex {
+                    public static Integer VALUE = 1;
+                }
+
+                public static class NodeRefResSumIndex {
+                    public static Integer VALUE = 1;
+                }
+
+                public static class SegmentCostIndex {
+                    public static Integer VALUE = 10;
+                }
+
+                public static class SegmentExceptionIndex {
+                    public static Integer VALUE = 10;
+                }
+
+                public static class SegmentIndex {
+                    public static Integer VALUE = 10;
+                }
+            }
         }
     }
 
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/config/WorkerConfig.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/config/WorkerConfig.java
index 004cdc6..c0603a0 100644
--- a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/config/WorkerConfig.java
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/config/WorkerConfig.java
@@ -8,61 +8,57 @@
     public static class WorkerNum {
         public static class Node {
             public static class NodeCompAgg {
-                public static int VALUE = 10;
+                public static int VALUE = 2;
             }
 
             public static class NodeMappingDayAgg {
-                public static int VALUE = 10;
+                public static int VALUE = 2;
             }
 
             public static class NodeMappingHourAgg {
-                public static int VALUE = 10;
+                public static int VALUE = 2;
             }
 
             public static class NodeMappingMinuteAgg {
-                public static int VALUE = 10;
+                public static int VALUE = 2;
             }
         }
 
         public static class NodeRef {
             public static class NodeRefDayAgg {
-                public static int VALUE = 10;
+                public static int VALUE = 2;
             }
 
             public static class NodeRefHourAgg {
-                public static int VALUE = 10;
+                public static int VALUE = 2;
             }
 
             public static class NodeRefMinuteAgg {
-                public static int VALUE = 10;
+                public static int VALUE = 2;
             }
 
             public static class NodeRefResSumDayAgg {
-                public static int VALUE = 10;
+                public static int VALUE = 2;
             }
 
             public static class NodeRefResSumHourAgg {
-                public static int VALUE = 10;
+                public static int VALUE = 2;
             }
 
             public static class NodeRefResSumMinuteAgg {
-                public static int VALUE = 10;
+                public static int VALUE = 2;
             }
         }
 
         public static class GlobalTrace {
             public static class GlobalTraceAgg {
-                public static int VALUE = 10;
+                public static int VALUE = 2;
             }
         }
     }
 
     public static class Queue {
         public static class GlobalTrace {
-            public static class GlobalTraceSave {
-                public static int SIZE = 1024;
-            }
-
             public static class GlobalTraceAnalysis {
                 public static int SIZE = 1024;
             }
@@ -70,19 +66,19 @@
 
         public static class Segment {
             public static class SegmentPost {
+                public static int SIZE = 4096;
+            }
+
+            public static class SegmentAnalysis {
                 public static int SIZE = 1024;
             }
 
-            public static class SegmentCostSave {
-                public static int SIZE = 1024;
+            public static class SegmentCostAnalysis {
+                public static int SIZE = 4096;
             }
 
-            public static class SegmentSave {
-                public static int SIZE = 1024;
-            }
-
-            public static class SegmentExceptionSave {
-                public static int SIZE = 1024;
+            public static class SegmentExceptionAnalysis {
+                public static int SIZE = 4096;
             }
         }
 
@@ -102,22 +98,6 @@
             public static class NodeMappingMinuteAnalysis {
                 public static int SIZE = 1024;
             }
-
-            public static class NodeCompSave {
-                public static int SIZE = 1024;
-            }
-
-            public static class NodeMappingDaySave {
-                public static int SIZE = 1024;
-            }
-
-            public static class NodeMappingHourSave {
-                public static int SIZE = 1024;
-            }
-
-            public static class NodeMappingMinuteSave {
-                public static int SIZE = 1024;
-            }
         }
 
         public static class NodeRef {
@@ -133,30 +113,6 @@
                 public static int SIZE = 1024;
             }
 
-            public static class NodeRefDaySave {
-                public static int SIZE = 1024;
-            }
-
-            public static class NodeRefHourSave {
-                public static int SIZE = 1024;
-            }
-
-            public static class NodeRefMinuteSave {
-                public static int SIZE = 1024;
-            }
-
-            public static class NodeRefResSumDaySave {
-                public static int SIZE = 1024;
-            }
-
-            public static class NodeRefResSumHourSave {
-                public static int SIZE = 1024;
-            }
-
-            public static class NodeRefResSumMinuteSave {
-                public static int SIZE = 1024;
-            }
-
             public static class NodeRefResSumDayAnalysis {
                 public static int SIZE = 1024;
             }
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/globaltrace/GlobalTraceGetWithGlobalId.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/globaltrace/GlobalTraceGetWithGlobalId.java
index c3e07f2..6bf9a5a 100644
--- a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/globaltrace/GlobalTraceGetWithGlobalId.java
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/globaltrace/GlobalTraceGetWithGlobalId.java
@@ -46,8 +46,6 @@
     }
 
     public static class Factory extends AbstractGetProvider<GlobalTraceGetWithGlobalId> {
-        public static Factory INSTANCE = new Factory();
-
         @Override
         public Role role() {
             return WorkerRole.INSTANCE;
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/globaltrace/GlobalTraceIndex.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/globaltrace/GlobalTraceIndex.java
index 37d3b95..760fa55 100644
--- a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/globaltrace/GlobalTraceIndex.java
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/globaltrace/GlobalTraceIndex.java
@@ -1,5 +1,6 @@
 package com.a.eye.skywalking.collector.worker.globaltrace;
 
+import com.a.eye.skywalking.collector.worker.config.EsConfig;
 import com.a.eye.skywalking.collector.worker.storage.AbstractIndex;
 import org.elasticsearch.common.xcontent.XContentBuilder;
 import org.elasticsearch.common.xcontent.XContentFactory;
@@ -25,13 +26,17 @@
     }
 
     @Override
+    public int refreshInterval() {
+        return EsConfig.Es.Index.RefreshInterval.GlobalTraceIndex.VALUE;
+    }
+
+    @Override
     public XContentBuilder createMappingBuilder() throws IOException {
         XContentBuilder mappingBuilder = XContentFactory.jsonBuilder()
             .startObject()
             .startObject("properties")
             .startObject(SUB_SEG_IDS)
-            .field("type", "text")
-            .field("index", "not_analyzed")
+            .field("type", "keyword")
             .endObject()
             .endObject()
             .endObject();
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/globaltrace/analysis/GlobalTraceAnalysis.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/globaltrace/analysis/GlobalTraceAnalysis.java
index ae88d48..27a72d1 100644
--- a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/globaltrace/analysis/GlobalTraceAnalysis.java
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/globaltrace/analysis/GlobalTraceAnalysis.java
@@ -1,26 +1,27 @@
 package com.a.eye.skywalking.collector.worker.globaltrace.analysis;
 
-import com.a.eye.skywalking.collector.actor.AbstractLocalAsyncWorkerProvider;
-import com.a.eye.skywalking.collector.actor.ClusterWorkerContext;
-import com.a.eye.skywalking.collector.actor.LocalWorkerContext;
+import com.a.eye.skywalking.collector.actor.*;
 import com.a.eye.skywalking.collector.actor.selector.RollingSelector;
 import com.a.eye.skywalking.collector.actor.selector.WorkerSelector;
-import com.a.eye.skywalking.collector.worker.MergeAnalysisMember;
+import com.a.eye.skywalking.collector.worker.JoinAndSplitAnalysisMember;
 import com.a.eye.skywalking.collector.worker.config.WorkerConfig;
 import com.a.eye.skywalking.collector.worker.globaltrace.GlobalTraceIndex;
 import com.a.eye.skywalking.collector.worker.globaltrace.persistence.GlobalTraceAgg;
 import com.a.eye.skywalking.collector.worker.segment.SegmentPost;
-import com.a.eye.skywalking.collector.worker.storage.MergeData;
+import com.a.eye.skywalking.collector.worker.segment.entity.GlobalTraceId;
+import com.a.eye.skywalking.collector.worker.segment.entity.Segment;
 import com.a.eye.skywalking.collector.worker.tools.CollectionTools;
-import com.a.eye.skywalking.trace.TraceId.DistributedTraceId;
-import com.a.eye.skywalking.trace.TraceSegment;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
 
 import java.util.List;
 
 /**
  * @author pengys5
  */
-public class GlobalTraceAnalysis extends MergeAnalysisMember {
+public class GlobalTraceAnalysis extends JoinAndSplitAnalysisMember {
+
+    private Logger logger = LogManager.getFormatterLogger(GlobalTraceAnalysis.class);
 
     GlobalTraceAnalysis(Role role, ClusterWorkerContext clusterContext, LocalWorkerContext selfContext) {
         super(role, clusterContext, selfContext);
@@ -29,30 +30,32 @@
     @Override
     public void analyse(Object message) throws Exception {
         if (message instanceof SegmentPost.SegmentWithTimeSlice) {
-            SegmentPost.SegmentWithTimeSlice segmentWithTimeSlice = (SegmentPost.SegmentWithTimeSlice)message;
-            TraceSegment segment = segmentWithTimeSlice.getTraceSegment();
+            SegmentPost.SegmentWithTimeSlice segmentWithTimeSlice = (SegmentPost.SegmentWithTimeSlice) message;
+            Segment segment = segmentWithTimeSlice.getSegment();
             String subSegmentId = segment.getTraceSegmentId();
-            List<DistributedTraceId> globalTraceIdList = segment.getRelatedGlobalTraces();
+            List<GlobalTraceId> globalTraceIdList = segment.getRelatedGlobalTraces();
             if (CollectionTools.isNotEmpty(globalTraceIdList)) {
-                for (DistributedTraceId disTraceId : globalTraceIdList) {
+                for (GlobalTraceId disTraceId : globalTraceIdList) {
                     String traceId = disTraceId.get();
-                    setMergeData(traceId, GlobalTraceIndex.SUB_SEG_IDS, subSegmentId);
+                    set(traceId, GlobalTraceIndex.SUB_SEG_IDS, subSegmentId);
                 }
             }
+        } else {
+            logger.error("unhandled message, message instance must SegmentPost.SegmentWithTimeSlice, but is %s", message.getClass().toString());
         }
     }
 
     @Override
-    protected void aggregation() throws Exception {
-        MergeData oneRecord;
-        while ((oneRecord = pushOne()) != null) {
-            getClusterContext().lookup(GlobalTraceAgg.Role.INSTANCE).tell(oneRecord);
+    protected WorkerRefs aggWorkRefs() {
+        try {
+            return getClusterContext().lookup(GlobalTraceAgg.Role.INSTANCE);
+        } catch (WorkerNotFoundException e) {
+            logger.error("The role of %s worker not found", GlobalTraceAgg.Role.INSTANCE.roleName());
         }
+        return null;
     }
 
     public static class Factory extends AbstractLocalAsyncWorkerProvider<GlobalTraceAnalysis> {
-        public static Factory INSTANCE = new Factory();
-
         @Override
         public Role role() {
             return Role.INSTANCE;
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/globaltrace/persistence/GlobalTraceAgg.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/globaltrace/persistence/GlobalTraceAgg.java
index d658e93..5335b20 100644
--- a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/globaltrace/persistence/GlobalTraceAgg.java
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/globaltrace/persistence/GlobalTraceAgg.java
@@ -4,7 +4,7 @@
 import com.a.eye.skywalking.collector.actor.selector.HashCodeSelector;
 import com.a.eye.skywalking.collector.actor.selector.WorkerSelector;
 import com.a.eye.skywalking.collector.worker.config.WorkerConfig;
-import com.a.eye.skywalking.collector.worker.storage.MergeData;
+import com.a.eye.skywalking.collector.worker.storage.JoinAndSplitData;
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
 
@@ -27,16 +27,14 @@
 
     @Override
     protected void onWork(Object message) throws Exception {
-        if (message instanceof MergeData) {
+        if (message instanceof JoinAndSplitData) {
             getSelfContext().lookup(GlobalTraceSave.Role.INSTANCE).tell(message);
         } else {
-            logger.error("message unhandled");
+            logger.error("unhandled message, message instance must JoinAndSplitData, but is %s", message.getClass().toString());
         }
     }
 
     public static class Factory extends AbstractClusterWorkerProvider<GlobalTraceAgg> {
-        public static Factory INSTANCE = new Factory();
-
         @Override
         public Role role() {
             return Role.INSTANCE;
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/globaltrace/persistence/GlobalTraceSave.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/globaltrace/persistence/GlobalTraceSave.java
index 5691efb..e5d91a3 100644
--- a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/globaltrace/persistence/GlobalTraceSave.java
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/globaltrace/persistence/GlobalTraceSave.java
@@ -1,21 +1,21 @@
 package com.a.eye.skywalking.collector.worker.globaltrace.persistence;
 
-import com.a.eye.skywalking.collector.actor.AbstractLocalAsyncWorkerProvider;
+import com.a.eye.skywalking.collector.actor.AbstractLocalSyncWorkerProvider;
 import com.a.eye.skywalking.collector.actor.ClusterWorkerContext;
 import com.a.eye.skywalking.collector.actor.LocalWorkerContext;
 import com.a.eye.skywalking.collector.actor.selector.HashCodeSelector;
 import com.a.eye.skywalking.collector.actor.selector.WorkerSelector;
-import com.a.eye.skywalking.collector.worker.MergePersistenceMember;
-import com.a.eye.skywalking.collector.worker.config.WorkerConfig;
+import com.a.eye.skywalking.collector.worker.JoinAndSplitPersistenceMember;
 import com.a.eye.skywalking.collector.worker.globaltrace.GlobalTraceIndex;
+import com.a.eye.skywalking.collector.worker.storage.PersistenceWorkerListener;
 
 /**
  * @author pengys5
  */
-public class GlobalTraceSave extends MergePersistenceMember {
+public class GlobalTraceSave extends JoinAndSplitPersistenceMember {
 
     GlobalTraceSave(com.a.eye.skywalking.collector.actor.Role role, ClusterWorkerContext clusterContext,
-        LocalWorkerContext selfContext) {
+                    LocalWorkerContext selfContext) {
         super(role, clusterContext, selfContext);
     }
 
@@ -29,22 +29,17 @@
         return GlobalTraceIndex.TYPE_RECORD;
     }
 
-    public static class Factory extends AbstractLocalAsyncWorkerProvider<GlobalTraceSave> {
-        public static Factory INSTANCE = new Factory();
-
+    public static class Factory extends AbstractLocalSyncWorkerProvider<GlobalTraceSave> {
         @Override
         public Role role() {
             return Role.INSTANCE;
         }
 
         @Override
-        public int queueSize() {
-            return WorkerConfig.Queue.GlobalTrace.GlobalTraceSave.SIZE;
-        }
-
-        @Override
         public GlobalTraceSave workerInstance(ClusterWorkerContext clusterContext) {
-            return new GlobalTraceSave(role(), clusterContext, new LocalWorkerContext());
+            GlobalTraceSave worker = new GlobalTraceSave(role(), clusterContext, new LocalWorkerContext());
+            PersistenceWorkerListener.INSTANCE.register(worker);
+            return worker;
         }
     }
 
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/globaltrace/persistence/GlobalTraceSearchWithGlobalId.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/globaltrace/persistence/GlobalTraceSearchWithGlobalId.java
index b4928c6..62a4442 100644
--- a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/globaltrace/persistence/GlobalTraceSearchWithGlobalId.java
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/globaltrace/persistence/GlobalTraceSearchWithGlobalId.java
@@ -6,14 +6,10 @@
 import com.a.eye.skywalking.collector.actor.selector.WorkerSelector;
 import com.a.eye.skywalking.collector.worker.globaltrace.GlobalTraceIndex;
 import com.a.eye.skywalking.collector.worker.segment.SegmentIndex;
-import com.a.eye.skywalking.collector.worker.segment.logic.Segment;
-import com.a.eye.skywalking.collector.worker.segment.logic.SegmentDeserialize;
-import com.a.eye.skywalking.collector.worker.segment.logic.SpanView;
+import com.a.eye.skywalking.collector.worker.segment.entity.*;
 import com.a.eye.skywalking.collector.worker.storage.GetResponseFromEs;
-import com.a.eye.skywalking.collector.worker.storage.MergeData;
+import com.a.eye.skywalking.collector.worker.storage.JoinAndSplitData;
 import com.a.eye.skywalking.collector.worker.tools.CollectionTools;
-import com.a.eye.skywalking.trace.Span;
-import com.a.eye.skywalking.trace.TraceSegmentRef;
 import com.google.gson.Gson;
 import com.google.gson.JsonObject;
 import org.apache.logging.log4j.LogManager;
@@ -32,7 +28,7 @@
 
     private Gson gson = new Gson();
 
-    GlobalTraceSearchWithGlobalId(Role role, ClusterWorkerContext clusterContext, LocalWorkerContext selfContext) {
+    public GlobalTraceSearchWithGlobalId(Role role, ClusterWorkerContext clusterContext, LocalWorkerContext selfContext) {
         super(role, clusterContext, selfContext);
     }
 
@@ -45,14 +41,14 @@
             logger.debug("globalTraceObj: %s", globalTraceObj);
 
             String subSegIdsStr = globalTraceObj.get(GlobalTraceIndex.SUB_SEG_IDS).getAsString();
-            String[] subSegIds = subSegIdsStr.split(MergeData.SPLIT);
+            String[] subSegIds = subSegIdsStr.split(JoinAndSplitData.SPLIT);
 
             List<SpanView> spanViewList = new ArrayList<>();
             for (String subSegId : subSegIds) {
                 logger.debug("subSegId: %s", subSegId);
                 String segmentSource = GetResponseFromEs.INSTANCE.get(SegmentIndex.INDEX, SegmentIndex.TYPE_RECORD, subSegId).getSourceAsString();
                 logger.debug("segmentSource: %s", segmentSource);
-                Segment segment = SegmentDeserialize.INSTANCE.deserializeFromES(segmentSource);
+                Segment segment = SegmentDeserialize.INSTANCE.deserializeSingle(segmentSource);
                 String segmentId = segment.getTraceSegmentId();
                 List<TraceSegmentRef> refsList = segment.getRefs();
 
@@ -64,6 +60,8 @@
 
             JsonObject responseObj = (JsonObject)response;
             responseObj.addProperty("result", buildTree(spanViewList));
+        } else {
+            logger.error("unhandled message, message instance must String, but is %s", request.getClass().toString());
         }
     }
 
@@ -157,8 +155,6 @@
     }
 
     public static class Factory extends AbstractLocalSyncWorkerProvider<GlobalTraceSearchWithGlobalId> {
-        public static Factory INSTANCE = new Factory();
-
         @Override
         public Role role() {
             return WorkerRole.INSTANCE;
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/httpserver/AbstractGet.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/httpserver/AbstractGet.java
index 0e08109..b7bb77a 100644
--- a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/httpserver/AbstractGet.java
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/httpserver/AbstractGet.java
@@ -18,12 +18,12 @@
         super(role, clusterContext, selfContext);
     }
 
-    @Override final public void onWork(Object request, Object response) throws Exception {
+    @Override
+    final public void onWork(Object request, Object response) throws Exception {
         Map<String, String[]> parameterMap = (Map<String, String[]>)request;
         try {
             onSearch(parameterMap, (JsonObject)response);
         } catch (Exception e) {
-            e.printStackTrace();
             ((JsonObject)response).addProperty("isSuccess", false);
             ((JsonObject)response).addProperty("reason", e.getMessage());
         }
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/httpserver/AbstractPost.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/httpserver/AbstractPost.java
index b344cdb..90c945b 100644
--- a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/httpserver/AbstractPost.java
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/httpserver/AbstractPost.java
@@ -1,15 +1,20 @@
 package com.a.eye.skywalking.collector.worker.httpserver;
 
-import com.a.eye.skywalking.collector.actor.*;
+import com.a.eye.skywalking.collector.actor.AbstractLocalAsyncWorker;
+import com.a.eye.skywalking.collector.actor.ClusterWorkerContext;
+import com.a.eye.skywalking.collector.actor.LocalAsyncWorkerRef;
+import com.a.eye.skywalking.collector.actor.LocalWorkerContext;
+import com.a.eye.skywalking.collector.actor.Role;
+import com.a.eye.skywalking.collector.worker.segment.entity.Segment;
 import com.google.gson.JsonObject;
-import org.apache.logging.log4j.LogManager;
-import org.apache.logging.log4j.Logger;
-
+import com.google.gson.stream.JsonReader;
+import java.io.BufferedReader;
+import java.io.IOException;
 import javax.servlet.ServletException;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
-import java.io.BufferedReader;
-import java.io.IOException;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
 
 /**
  * @author pengys5
@@ -17,25 +22,20 @@
 
 public abstract class AbstractPost extends AbstractLocalAsyncWorker {
 
-    private Logger logger = LogManager.getFormatterLogger(AbstractPost.class);
-
     public AbstractPost(Role role, ClusterWorkerContext clusterContext, LocalWorkerContext selfContext) {
         super(role, clusterContext, selfContext);
     }
 
-    @Override final public void onWork(Object request) throws Exception {
-        if (request instanceof String) {
-            onReceive((String)request);
-        } else {
-            logger.error("unhandled request, request instance must String, but is %s", request.getClass().toString());
-            saveException(new IllegalArgumentException("request instance must String"));
-        }
+    @Override final public void onWork(Object message) throws Exception {
+        onReceive(message);
     }
 
-    protected abstract void onReceive(String reqJsonStr) throws Exception;
+    protected abstract void onReceive(Object message) throws Exception;
 
     static class PostWithHttpServlet extends AbstractHttpServlet {
 
+        private Logger logger = LogManager.getFormatterLogger(PostWithHttpServlet.class);
+
         private final LocalAsyncWorkerRef ownerWorkerRef;
 
         PostWithHttpServlet(LocalAsyncWorkerRef ownerWorkerRef) {
@@ -47,17 +47,29 @@
             JsonObject resJson = new JsonObject();
             try {
                 BufferedReader bufferedReader = request.getReader();
-                StringBuilder dataStr = new StringBuilder();
-                String tmpStr;
-                while ((tmpStr = bufferedReader.readLine()) != null) {
-                    dataStr.append(tmpStr);
-                }
-                ownerWorkerRef.tell(dataStr.toString());
+                streamReader(bufferedReader);
                 reply(response, resJson, HttpServletResponse.SC_OK);
             } catch (Exception e) {
+                logger.error(e);
                 resJson.addProperty("error", e.getMessage());
                 reply(response, resJson, HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
             }
         }
+
+        private void streamReader(BufferedReader bufferedReader) throws Exception {
+            try (JsonReader reader = new JsonReader(bufferedReader)) {
+                readSegmentArray(reader);
+            }
+        }
+
+        private void readSegmentArray(JsonReader reader) throws Exception {
+            reader.beginArray();
+            while (reader.hasNext()) {
+                Segment segment = new Segment();
+                segment.deserialize(reader);
+                ownerWorkerRef.tell(segment);
+            }
+            reader.endArray();
+        }
     }
 }
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/node/NodeCompIndex.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/node/NodeCompIndex.java
index 69f795b..3c99955 100644
--- a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/node/NodeCompIndex.java
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/node/NodeCompIndex.java
@@ -1,5 +1,6 @@
 package com.a.eye.skywalking.collector.worker.node;
 
+import com.a.eye.skywalking.collector.worker.config.EsConfig;
 import com.a.eye.skywalking.collector.worker.storage.AbstractIndex;
 import org.elasticsearch.common.xcontent.XContentBuilder;
 import org.elasticsearch.common.xcontent.XContentFactory;
@@ -26,24 +27,26 @@
     }
 
     @Override
+    public int refreshInterval() {
+        return EsConfig.Es.Index.RefreshInterval.NodeCompIndex.VALUE;
+    }
+
+    @Override
     public XContentBuilder createMappingBuilder() throws IOException {
         XContentBuilder mappingBuilder = XContentFactory.jsonBuilder()
-            .startObject()
-            .startObject("properties")
-            .startObject(NAME)
-            .field("type", "string")
-            .field("index", "not_analyzed")
-            .endObject()
-            .startObject(PEERS)
-            .field("type", "string")
-            .field("index", "not_analyzed")
-            .endObject()
-            .startObject(AGG_COLUMN)
-            .field("type", "string")
-            .field("index", "not_analyzed")
-            .endObject()
-            .endObject()
-            .endObject();
+                .startObject()
+                .startObject("properties")
+                .startObject(NAME)
+                .field("type", "keyword")
+                .endObject()
+                .startObject(PEERS)
+                .field("type", "keyword")
+                .endObject()
+                .startObject(AGG_COLUMN)
+                .field("type", "keyword")
+                .endObject()
+                .endObject()
+                .endObject();
         return mappingBuilder;
     }
 }
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/node/NodeMappingIndex.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/node/NodeMappingIndex.java
index ea9a9c5..32e901a 100644
--- a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/node/NodeMappingIndex.java
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/node/NodeMappingIndex.java
@@ -1,5 +1,6 @@
 package com.a.eye.skywalking.collector.worker.node;
 
+import com.a.eye.skywalking.collector.worker.config.EsConfig;
 import com.a.eye.skywalking.collector.worker.storage.AbstractIndex;
 import org.elasticsearch.common.xcontent.XContentBuilder;
 import org.elasticsearch.common.xcontent.XContentFactory;
@@ -26,28 +27,33 @@
     }
 
     @Override
+    public int refreshInterval() {
+        return EsConfig.Es.Index.RefreshInterval.NodeMappingIndex.VALUE;
+    }
+
+    @Override
     public XContentBuilder createMappingBuilder() throws IOException {
         XContentBuilder mappingBuilder = XContentFactory.jsonBuilder()
-            .startObject()
-            .startObject("properties")
-            .startObject(CODE)
-            .field("type", "string")
-            .field("index", "not_analyzed")
-            .endObject()
-            .startObject(PEERS)
-            .field("type", "string")
-            .field("index", "not_analyzed")
-            .endObject()
-            .startObject(AGG_COLUMN)
-            .field("type", "string")
-            .field("index", "not_analyzed")
-            .endObject()
-            .startObject(TIME_SLICE)
-            .field("type", "long")
-            .field("index", "not_analyzed")
-            .endObject()
-            .endObject()
-            .endObject();
+                .startObject()
+                .startObject("properties")
+                .startObject(CODE)
+                .field("type", "string")
+                .field("index", "not_analyzed")
+                .endObject()
+                .startObject(PEERS)
+                .field("type", "string")
+                .field("index", "not_analyzed")
+                .endObject()
+                .startObject(AGG_COLUMN)
+                .field("type", "string")
+                .field("index", "not_analyzed")
+                .endObject()
+                .startObject(TIME_SLICE)
+                .field("type", "long")
+                .field("index", "not_analyzed")
+                .endObject()
+                .endObject()
+                .endObject();
         return mappingBuilder;
     }
 }
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/node/analysis/AbstractNodeCompAnalysis.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/node/analysis/AbstractNodeCompAnalysis.java
index c21daad..81c1558 100644
--- a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/node/analysis/AbstractNodeCompAnalysis.java
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/node/analysis/AbstractNodeCompAnalysis.java
@@ -4,12 +4,12 @@
 import com.a.eye.skywalking.collector.actor.LocalWorkerContext;
 import com.a.eye.skywalking.collector.worker.RecordAnalysisMember;
 import com.a.eye.skywalking.collector.worker.node.NodeCompIndex;
+import com.a.eye.skywalking.collector.worker.segment.entity.Segment;
+import com.a.eye.skywalking.collector.worker.segment.entity.Span;
+import com.a.eye.skywalking.collector.worker.segment.entity.tag.Tags;
 import com.a.eye.skywalking.collector.worker.tools.ClientSpanIsLeafTools;
 import com.a.eye.skywalking.collector.worker.tools.CollectionTools;
 import com.a.eye.skywalking.collector.worker.tools.SpanPeersTools;
-import com.a.eye.skywalking.trace.Span;
-import com.a.eye.skywalking.trace.TraceSegment;
-import com.a.eye.skywalking.trace.tag.Tags;
 import com.google.gson.JsonObject;
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
@@ -28,7 +28,7 @@
         super(role, clusterContext, selfContext);
     }
 
-    void analyseSpans(TraceSegment segment) throws Exception {
+    final void analyseSpans(Segment segment) throws Exception {
         List<Span> spanList = segment.getSpans();
         logger.debug("node analysis span isNotEmpty %s", CollectionTools.isNotEmpty(spanList));
 
@@ -43,7 +43,7 @@
                     compJsonObj.addProperty(NodeCompIndex.PEERS, peers);
                     compJsonObj.addProperty(NodeCompIndex.NAME, Tags.COMPONENT.get(span));
 
-                    setRecord(peers, compJsonObj);
+                    set(peers, compJsonObj);
                 } else if (Tags.SPAN_KIND_SERVER.equals(kind) && span.getParentSpanId() == -1) {
                     String peers = segment.getApplicationCode();
 
@@ -51,9 +51,7 @@
                     compJsonObj.addProperty(NodeCompIndex.PEERS, peers);
                     compJsonObj.addProperty(NodeCompIndex.NAME, Tags.COMPONENT.get(span));
 
-                    setRecord(peers, compJsonObj);
-                } else {
-                    logger.error("The span kind value is incorrect which segment record id is %s, the value must client or server", segment.getTraceSegmentId());
+                    set(peers, compJsonObj);
                 }
             }
         }
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/node/analysis/AbstractNodeMappingAnalysis.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/node/analysis/AbstractNodeMappingAnalysis.java
index 05ad012..59c43b4 100644
--- a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/node/analysis/AbstractNodeMappingAnalysis.java
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/node/analysis/AbstractNodeMappingAnalysis.java
@@ -5,9 +5,9 @@
 import com.a.eye.skywalking.collector.worker.Const;
 import com.a.eye.skywalking.collector.worker.RecordAnalysisMember;
 import com.a.eye.skywalking.collector.worker.node.NodeMappingIndex;
+import com.a.eye.skywalking.collector.worker.segment.entity.Segment;
+import com.a.eye.skywalking.collector.worker.segment.entity.TraceSegmentRef;
 import com.a.eye.skywalking.collector.worker.tools.CollectionTools;
-import com.a.eye.skywalking.trace.TraceSegment;
-import com.a.eye.skywalking.trace.TraceSegmentRef;
 import com.google.gson.JsonObject;
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
@@ -26,7 +26,7 @@
         super(role, clusterContext, selfContext);
     }
 
-    void analyseRefs(TraceSegment segment, long timeSlice) throws Exception {
+    final void analyseRefs(Segment segment, long timeSlice) throws Exception {
         List<TraceSegmentRef> segmentRefList = segment.getRefs();
         logger.debug("node mapping analysis refs isNotEmpty %s", CollectionTools.isNotEmpty(segmentRefList));
 
@@ -42,7 +42,7 @@
                 nodeMappingJsonObj.addProperty(NodeMappingIndex.TIME_SLICE, timeSlice);
 
                 String id = timeSlice + Const.ID_SPLIT + code + Const.ID_SPLIT + peers;
-                setRecord(id, nodeMappingJsonObj);
+                set(id, nodeMappingJsonObj);
             }
         }
     }
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/node/analysis/NodeCompAnalysis.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/node/analysis/NodeCompAnalysis.java
index 1d3acb6..edffd90 100644
--- a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/node/analysis/NodeCompAnalysis.java
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/node/analysis/NodeCompAnalysis.java
@@ -1,46 +1,49 @@
 package com.a.eye.skywalking.collector.worker.node.analysis;
 
-import com.a.eye.skywalking.collector.actor.AbstractLocalAsyncWorkerProvider;
-import com.a.eye.skywalking.collector.actor.ClusterWorkerContext;
-import com.a.eye.skywalking.collector.actor.LocalWorkerContext;
+import com.a.eye.skywalking.collector.actor.*;
 import com.a.eye.skywalking.collector.actor.selector.RollingSelector;
 import com.a.eye.skywalking.collector.actor.selector.WorkerSelector;
 import com.a.eye.skywalking.collector.worker.config.WorkerConfig;
 import com.a.eye.skywalking.collector.worker.node.persistence.NodeCompAgg;
 import com.a.eye.skywalking.collector.worker.segment.SegmentPost;
-import com.a.eye.skywalking.collector.worker.storage.RecordData;
-import com.a.eye.skywalking.trace.TraceSegment;
+import com.a.eye.skywalking.collector.worker.segment.entity.Segment;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
 
 /**
  * @author pengys5
  */
 public class NodeCompAnalysis extends AbstractNodeCompAnalysis {
 
+    private Logger logger = LogManager.getFormatterLogger(NodeCompAnalysis.class);
+
     NodeCompAnalysis(com.a.eye.skywalking.collector.actor.Role role, ClusterWorkerContext clusterContext,
-        LocalWorkerContext selfContext) {
+                     LocalWorkerContext selfContext) {
         super(role, clusterContext, selfContext);
     }
 
     @Override
     public void analyse(Object message) throws Exception {
         if (message instanceof SegmentPost.SegmentWithTimeSlice) {
-            SegmentPost.SegmentWithTimeSlice segmentWithTimeSlice = (SegmentPost.SegmentWithTimeSlice)message;
-            TraceSegment segment = segmentWithTimeSlice.getTraceSegment();
+            SegmentPost.SegmentWithTimeSlice segmentWithTimeSlice = (SegmentPost.SegmentWithTimeSlice) message;
+            Segment segment = segmentWithTimeSlice.getSegment();
             analyseSpans(segment);
+        } else {
+            logger.error("unhandled message, message instance must SegmentPost.SegmentWithTimeSlice, but is %s", message.getClass().toString());
         }
     }
 
     @Override
-    protected void aggregation() throws Exception {
-        RecordData oneRecord;
-        while ((oneRecord = pushOne()) != null) {
-            getClusterContext().lookup(NodeCompAgg.Role.INSTANCE).tell(oneRecord);
+    protected WorkerRefs aggWorkRefs() {
+        try {
+            return getClusterContext().lookup(NodeCompAgg.Role.INSTANCE);
+        } catch (WorkerNotFoundException e) {
+            logger.error("The role of %s worker not found", NodeCompAgg.Role.INSTANCE.roleName());
         }
+        return null;
     }
 
     public static class Factory extends AbstractLocalAsyncWorkerProvider<NodeCompAnalysis> {
-        public static Factory INSTANCE = new Factory();
-
         @Override
         public Role role() {
             return Role.INSTANCE;
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/node/analysis/NodeMappingDayAnalysis.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/node/analysis/NodeMappingDayAnalysis.java
index 9a93871..c997a72 100644
--- a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/node/analysis/NodeMappingDayAnalysis.java
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/node/analysis/NodeMappingDayAnalysis.java
@@ -1,46 +1,49 @@
 package com.a.eye.skywalking.collector.worker.node.analysis;
 
-import com.a.eye.skywalking.collector.actor.AbstractLocalAsyncWorkerProvider;
-import com.a.eye.skywalking.collector.actor.ClusterWorkerContext;
-import com.a.eye.skywalking.collector.actor.LocalWorkerContext;
+import com.a.eye.skywalking.collector.actor.*;
 import com.a.eye.skywalking.collector.actor.selector.RollingSelector;
 import com.a.eye.skywalking.collector.actor.selector.WorkerSelector;
 import com.a.eye.skywalking.collector.worker.config.WorkerConfig;
 import com.a.eye.skywalking.collector.worker.node.persistence.NodeMappingDayAgg;
 import com.a.eye.skywalking.collector.worker.segment.SegmentPost;
-import com.a.eye.skywalking.collector.worker.storage.RecordData;
-import com.a.eye.skywalking.trace.TraceSegment;
+import com.a.eye.skywalking.collector.worker.segment.entity.Segment;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
 
 /**
  * @author pengys5
  */
 public class NodeMappingDayAnalysis extends AbstractNodeMappingAnalysis {
 
+    private Logger logger = LogManager.getFormatterLogger(NodeMappingDayAnalysis.class);
+
     public NodeMappingDayAnalysis(com.a.eye.skywalking.collector.actor.Role role, ClusterWorkerContext clusterContext,
-        LocalWorkerContext selfContext) {
+                                  LocalWorkerContext selfContext) {
         super(role, clusterContext, selfContext);
     }
 
     @Override
     public void analyse(Object message) throws Exception {
         if (message instanceof SegmentPost.SegmentWithTimeSlice) {
-            SegmentPost.SegmentWithTimeSlice segmentWithTimeSlice = (SegmentPost.SegmentWithTimeSlice)message;
-            TraceSegment segment = segmentWithTimeSlice.getTraceSegment();
+            SegmentPost.SegmentWithTimeSlice segmentWithTimeSlice = (SegmentPost.SegmentWithTimeSlice) message;
+            Segment segment = segmentWithTimeSlice.getSegment();
             analyseRefs(segment, segmentWithTimeSlice.getDay());
+        } else {
+            logger.error("unhandled message, message instance must SegmentPost.SegmentWithTimeSlice, but is %s", message.getClass().toString());
         }
     }
 
     @Override
-    protected void aggregation() throws Exception {
-        RecordData oneRecord;
-        while ((oneRecord = pushOne()) != null) {
-            getClusterContext().lookup(NodeMappingDayAgg.Role.INSTANCE).tell(oneRecord);
+    protected WorkerRefs aggWorkRefs() {
+        try {
+            return getClusterContext().lookup(NodeMappingDayAgg.Role.INSTANCE);
+        } catch (WorkerNotFoundException e) {
+            logger.error("The role of %s worker not found", NodeMappingDayAgg.Role.INSTANCE.roleName());
         }
+        return null;
     }
 
     public static class Factory extends AbstractLocalAsyncWorkerProvider<NodeMappingDayAnalysis> {
-        public static Factory INSTANCE = new Factory();
-
         @Override
         public Role role() {
             return Role.INSTANCE;
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/node/analysis/NodeMappingHourAnalysis.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/node/analysis/NodeMappingHourAnalysis.java
index 7e7744e..176b716 100644
--- a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/node/analysis/NodeMappingHourAnalysis.java
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/node/analysis/NodeMappingHourAnalysis.java
@@ -1,46 +1,49 @@
 package com.a.eye.skywalking.collector.worker.node.analysis;
 
-import com.a.eye.skywalking.collector.actor.AbstractLocalAsyncWorkerProvider;
-import com.a.eye.skywalking.collector.actor.ClusterWorkerContext;
-import com.a.eye.skywalking.collector.actor.LocalWorkerContext;
+import com.a.eye.skywalking.collector.actor.*;
 import com.a.eye.skywalking.collector.actor.selector.RollingSelector;
 import com.a.eye.skywalking.collector.actor.selector.WorkerSelector;
 import com.a.eye.skywalking.collector.worker.config.WorkerConfig;
 import com.a.eye.skywalking.collector.worker.node.persistence.NodeMappingHourAgg;
 import com.a.eye.skywalking.collector.worker.segment.SegmentPost;
-import com.a.eye.skywalking.collector.worker.storage.RecordData;
-import com.a.eye.skywalking.trace.TraceSegment;
+import com.a.eye.skywalking.collector.worker.segment.entity.Segment;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
 
 /**
  * @author pengys5
  */
 public class NodeMappingHourAnalysis extends AbstractNodeMappingAnalysis {
 
+    private Logger logger = LogManager.getFormatterLogger(NodeMappingHourAnalysis.class);
+
     NodeMappingHourAnalysis(com.a.eye.skywalking.collector.actor.Role role, ClusterWorkerContext clusterContext,
-        LocalWorkerContext selfContext) {
+                            LocalWorkerContext selfContext) {
         super(role, clusterContext, selfContext);
     }
 
     @Override
     public void analyse(Object message) throws Exception {
         if (message instanceof SegmentPost.SegmentWithTimeSlice) {
-            SegmentPost.SegmentWithTimeSlice segmentWithTimeSlice = (SegmentPost.SegmentWithTimeSlice)message;
-            TraceSegment segment = segmentWithTimeSlice.getTraceSegment();
+            SegmentPost.SegmentWithTimeSlice segmentWithTimeSlice = (SegmentPost.SegmentWithTimeSlice) message;
+            Segment segment = segmentWithTimeSlice.getSegment();
             analyseRefs(segment, segmentWithTimeSlice.getHour());
+        } else {
+            logger.error("unhandled message, message instance must SegmentPost.SegmentWithTimeSlice, but is %s", message.getClass().toString());
         }
     }
 
     @Override
-    protected void aggregation() throws Exception {
-        RecordData oneRecord;
-        while ((oneRecord = pushOne()) != null) {
-            getClusterContext().lookup(NodeMappingHourAgg.Role.INSTANCE).tell(oneRecord);
+    protected WorkerRefs aggWorkRefs() {
+        try {
+            return getClusterContext().lookup(NodeMappingHourAgg.Role.INSTANCE);
+        } catch (WorkerNotFoundException e) {
+            logger.error("The role of %s worker not found", NodeMappingHourAgg.Role.INSTANCE.roleName());
         }
+        return null;
     }
-
+    
     public static class Factory extends AbstractLocalAsyncWorkerProvider<NodeMappingHourAnalysis> {
-        public static Factory INSTANCE = new Factory();
-
         @Override
         public Role role() {
             return Role.INSTANCE;
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/node/analysis/NodeMappingMinuteAnalysis.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/node/analysis/NodeMappingMinuteAnalysis.java
index 08db84a..c60b683 100644
--- a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/node/analysis/NodeMappingMinuteAnalysis.java
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/node/analysis/NodeMappingMinuteAnalysis.java
@@ -1,46 +1,49 @@
 package com.a.eye.skywalking.collector.worker.node.analysis;
 
-import com.a.eye.skywalking.collector.actor.AbstractLocalAsyncWorkerProvider;
-import com.a.eye.skywalking.collector.actor.ClusterWorkerContext;
-import com.a.eye.skywalking.collector.actor.LocalWorkerContext;
+import com.a.eye.skywalking.collector.actor.*;
 import com.a.eye.skywalking.collector.actor.selector.RollingSelector;
 import com.a.eye.skywalking.collector.actor.selector.WorkerSelector;
 import com.a.eye.skywalking.collector.worker.config.WorkerConfig;
 import com.a.eye.skywalking.collector.worker.node.persistence.NodeMappingMinuteAgg;
 import com.a.eye.skywalking.collector.worker.segment.SegmentPost;
-import com.a.eye.skywalking.collector.worker.storage.RecordData;
-import com.a.eye.skywalking.trace.TraceSegment;
+import com.a.eye.skywalking.collector.worker.segment.entity.Segment;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
 
 /**
  * @author pengys5
  */
 public class NodeMappingMinuteAnalysis extends AbstractNodeMappingAnalysis {
 
+    private Logger logger = LogManager.getFormatterLogger(NodeMappingMinuteAnalysis.class);
+
     NodeMappingMinuteAnalysis(com.a.eye.skywalking.collector.actor.Role role, ClusterWorkerContext clusterContext,
-        LocalWorkerContext selfContext) {
+                              LocalWorkerContext selfContext) {
         super(role, clusterContext, selfContext);
     }
 
     @Override
     public void analyse(Object message) throws Exception {
         if (message instanceof SegmentPost.SegmentWithTimeSlice) {
-            SegmentPost.SegmentWithTimeSlice segmentWithTimeSlice = (SegmentPost.SegmentWithTimeSlice)message;
-            TraceSegment segment = segmentWithTimeSlice.getTraceSegment();
+            SegmentPost.SegmentWithTimeSlice segmentWithTimeSlice = (SegmentPost.SegmentWithTimeSlice) message;
+            Segment segment = segmentWithTimeSlice.getSegment();
             analyseRefs(segment, segmentWithTimeSlice.getMinute());
+        } else {
+            logger.error("unhandled message, message instance must SegmentPost.SegmentWithTimeSlice, but is %s", message.getClass().toString());
         }
     }
 
     @Override
-    protected void aggregation() throws Exception {
-        RecordData oneRecord;
-        while ((oneRecord = pushOne()) != null) {
-            getClusterContext().lookup(NodeMappingMinuteAgg.Role.INSTANCE).tell(oneRecord);
+    protected WorkerRefs aggWorkRefs() {
+        try {
+            return getClusterContext().lookup(NodeMappingMinuteAgg.Role.INSTANCE);
+        } catch (WorkerNotFoundException e) {
+            logger.error("The role of %s worker not found", NodeMappingMinuteAgg.Role.INSTANCE.roleName());
         }
+        return null;
     }
-
+    
     public static class Factory extends AbstractLocalAsyncWorkerProvider<NodeMappingMinuteAnalysis> {
-        public static Factory INSTANCE = new Factory();
-
         @Override
         public Role role() {
             return Role.INSTANCE;
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/node/persistence/NodeCompAgg.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/node/persistence/NodeCompAgg.java
index 3806168..ea34b10 100644
--- a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/node/persistence/NodeCompAgg.java
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/node/persistence/NodeCompAgg.java
@@ -5,12 +5,16 @@
 import com.a.eye.skywalking.collector.actor.selector.WorkerSelector;
 import com.a.eye.skywalking.collector.worker.config.WorkerConfig;
 import com.a.eye.skywalking.collector.worker.storage.RecordData;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
 
 /**
  * @author pengys5
  */
 public class NodeCompAgg extends AbstractClusterWorker {
 
+    private Logger logger = LogManager.getFormatterLogger(NodeCompAgg.class);
+
     NodeCompAgg(com.a.eye.skywalking.collector.actor.Role role, ClusterWorkerContext clusterContext,
         LocalWorkerContext selfContext) {
         super(role, clusterContext, selfContext);
@@ -25,13 +29,12 @@
     protected void onWork(Object message) throws Exception {
         if (message instanceof RecordData) {
             getSelfContext().lookup(NodeCompSave.Role.INSTANCE).tell(message);
-        } else
-            throw new IllegalArgumentException("message instance must RecordData");
+        } else {
+            logger.error("unhandled message, message instance must RecordData, but is %s", message.getClass().toString());
+        }
     }
 
     public static class Factory extends AbstractClusterWorkerProvider<NodeCompAgg> {
-        public static Factory INSTANCE = new Factory();
-
         @Override
         public Role role() {
             return Role.INSTANCE;
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/node/persistence/NodeCompLoad.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/node/persistence/NodeCompLoad.java
index 61fa081..8c3819d 100644
--- a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/node/persistence/NodeCompLoad.java
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/node/persistence/NodeCompLoad.java
@@ -49,8 +49,6 @@
     }
 
     public static class Factory extends AbstractLocalSyncWorkerProvider<NodeCompLoad> {
-        public static Factory INSTANCE = new Factory();
-
         @Override
         public Role role() {
             return WorkerRole.INSTANCE;
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/node/persistence/NodeCompSave.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/node/persistence/NodeCompSave.java
index a048af4..fd6b6fb 100644
--- a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/node/persistence/NodeCompSave.java
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/node/persistence/NodeCompSave.java
@@ -1,13 +1,13 @@
 package com.a.eye.skywalking.collector.worker.node.persistence;
 
-import com.a.eye.skywalking.collector.actor.AbstractLocalAsyncWorkerProvider;
+import com.a.eye.skywalking.collector.actor.AbstractLocalSyncWorkerProvider;
 import com.a.eye.skywalking.collector.actor.ClusterWorkerContext;
 import com.a.eye.skywalking.collector.actor.LocalWorkerContext;
 import com.a.eye.skywalking.collector.actor.selector.HashCodeSelector;
 import com.a.eye.skywalking.collector.actor.selector.WorkerSelector;
 import com.a.eye.skywalking.collector.worker.RecordPersistenceMember;
-import com.a.eye.skywalking.collector.worker.config.WorkerConfig;
 import com.a.eye.skywalking.collector.worker.node.NodeCompIndex;
+import com.a.eye.skywalking.collector.worker.storage.PersistenceWorkerListener;
 
 /**
  * @author pengys5
@@ -15,7 +15,7 @@
 public class NodeCompSave extends RecordPersistenceMember {
 
     NodeCompSave(com.a.eye.skywalking.collector.actor.Role role, ClusterWorkerContext clusterContext,
-        LocalWorkerContext selfContext) {
+                 LocalWorkerContext selfContext) {
         super(role, clusterContext, selfContext);
     }
 
@@ -29,9 +29,7 @@
         return NodeCompIndex.TYPE_RECORD;
     }
 
-    public static class Factory extends AbstractLocalAsyncWorkerProvider<NodeCompSave> {
-        public static Factory INSTANCE = new Factory();
-
+    public static class Factory extends AbstractLocalSyncWorkerProvider<NodeCompSave> {
         @Override
         public Role role() {
             return Role.INSTANCE;
@@ -39,12 +37,9 @@
 
         @Override
         public NodeCompSave workerInstance(ClusterWorkerContext clusterContext) {
-            return new NodeCompSave(role(), clusterContext, new LocalWorkerContext());
-        }
-
-        @Override
-        public int queueSize() {
-            return WorkerConfig.Queue.Node.NodeCompSave.SIZE;
+            NodeCompSave worker = new NodeCompSave(role(), clusterContext, new LocalWorkerContext());
+            PersistenceWorkerListener.INSTANCE.register(worker);
+            return worker;
         }
     }
 
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/node/persistence/NodeMappingDayAgg.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/node/persistence/NodeMappingDayAgg.java
index 61c2ec2..9e4e74f 100644
--- a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/node/persistence/NodeMappingDayAgg.java
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/node/persistence/NodeMappingDayAgg.java
@@ -5,12 +5,16 @@
 import com.a.eye.skywalking.collector.actor.selector.WorkerSelector;
 import com.a.eye.skywalking.collector.worker.config.WorkerConfig;
 import com.a.eye.skywalking.collector.worker.storage.RecordData;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
 
 /**
  * @author pengys5
  */
 public class NodeMappingDayAgg extends AbstractClusterWorker {
 
+    private Logger logger = LogManager.getFormatterLogger(NodeMappingDayAgg.class);
+
     NodeMappingDayAgg(com.a.eye.skywalking.collector.actor.Role role, ClusterWorkerContext clusterContext,
         LocalWorkerContext selfContext) {
         super(role, clusterContext, selfContext);
@@ -26,13 +30,11 @@
         if (message instanceof RecordData) {
             getSelfContext().lookup(NodeMappingDaySave.Role.INSTANCE).tell(message);
         } else {
-            throw new IllegalArgumentException("message instance must RecordData");
+            logger.error("unhandled message, message instance must RecordData, but is %s", message.getClass().toString());
         }
     }
 
     public static class Factory extends AbstractClusterWorkerProvider<NodeMappingDayAgg> {
-        public static Factory INSTANCE = new Factory();
-
         @Override
         public Role role() {
             return Role.INSTANCE;
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/node/persistence/NodeMappingDaySave.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/node/persistence/NodeMappingDaySave.java
index 7cf9e34..6c06bfd 100644
--- a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/node/persistence/NodeMappingDaySave.java
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/node/persistence/NodeMappingDaySave.java
@@ -1,13 +1,13 @@
 package com.a.eye.skywalking.collector.worker.node.persistence;
 
-import com.a.eye.skywalking.collector.actor.AbstractLocalAsyncWorkerProvider;
+import com.a.eye.skywalking.collector.actor.AbstractLocalSyncWorkerProvider;
 import com.a.eye.skywalking.collector.actor.ClusterWorkerContext;
 import com.a.eye.skywalking.collector.actor.LocalWorkerContext;
 import com.a.eye.skywalking.collector.actor.selector.HashCodeSelector;
 import com.a.eye.skywalking.collector.actor.selector.WorkerSelector;
 import com.a.eye.skywalking.collector.worker.RecordPersistenceMember;
-import com.a.eye.skywalking.collector.worker.config.WorkerConfig;
 import com.a.eye.skywalking.collector.worker.node.NodeMappingIndex;
+import com.a.eye.skywalking.collector.worker.storage.PersistenceWorkerListener;
 
 /**
  * @author pengys5
@@ -15,7 +15,7 @@
 public class NodeMappingDaySave extends RecordPersistenceMember {
 
     NodeMappingDaySave(com.a.eye.skywalking.collector.actor.Role role, ClusterWorkerContext clusterContext,
-        LocalWorkerContext selfContext) {
+                       LocalWorkerContext selfContext) {
         super(role, clusterContext, selfContext);
     }
 
@@ -29,9 +29,7 @@
         return NodeMappingIndex.TYPE_DAY;
     }
 
-    public static class Factory extends AbstractLocalAsyncWorkerProvider<NodeMappingDaySave> {
-        public static Factory INSTANCE = new Factory();
-
+    public static class Factory extends AbstractLocalSyncWorkerProvider<NodeMappingDaySave> {
         @Override
         public Role role() {
             return Role.INSTANCE;
@@ -39,12 +37,9 @@
 
         @Override
         public NodeMappingDaySave workerInstance(ClusterWorkerContext clusterContext) {
-            return new NodeMappingDaySave(role(), clusterContext, new LocalWorkerContext());
-        }
-
-        @Override
-        public int queueSize() {
-            return WorkerConfig.Queue.Node.NodeMappingDaySave.SIZE;
+            NodeMappingDaySave worker = new NodeMappingDaySave(role(), clusterContext, new LocalWorkerContext());
+            PersistenceWorkerListener.INSTANCE.register(worker);
+            return worker;
         }
     }
 
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/node/persistence/NodeMappingHourAgg.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/node/persistence/NodeMappingHourAgg.java
index 4f0cb3c..ec87db5 100644
--- a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/node/persistence/NodeMappingHourAgg.java
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/node/persistence/NodeMappingHourAgg.java
@@ -5,12 +5,16 @@
 import com.a.eye.skywalking.collector.actor.selector.WorkerSelector;
 import com.a.eye.skywalking.collector.worker.config.WorkerConfig;
 import com.a.eye.skywalking.collector.worker.storage.RecordData;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
 
 /**
  * @author pengys5
  */
 public class NodeMappingHourAgg extends AbstractClusterWorker {
 
+    private Logger logger = LogManager.getFormatterLogger(NodeMappingHourAgg.class);
+
     NodeMappingHourAgg(com.a.eye.skywalking.collector.actor.Role role, ClusterWorkerContext clusterContext,
         LocalWorkerContext selfContext) {
         super(role, clusterContext, selfContext);
@@ -26,13 +30,11 @@
         if (message instanceof RecordData) {
             getSelfContext().lookup(NodeMappingHourSave.Role.INSTANCE).tell(message);
         } else {
-            throw new IllegalArgumentException("message instance must RecordData");
+            logger.error("unhandled message, message instance must RecordData, but is %s", message.getClass().toString());
         }
     }
 
     public static class Factory extends AbstractClusterWorkerProvider<NodeMappingHourAgg> {
-        public static Factory INSTANCE = new Factory();
-
         @Override
         public Role role() {
             return Role.INSTANCE;
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/node/persistence/NodeMappingHourSave.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/node/persistence/NodeMappingHourSave.java
index e5c9953..5dfbdc3 100644
--- a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/node/persistence/NodeMappingHourSave.java
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/node/persistence/NodeMappingHourSave.java
@@ -1,13 +1,13 @@
 package com.a.eye.skywalking.collector.worker.node.persistence;
 
-import com.a.eye.skywalking.collector.actor.AbstractLocalAsyncWorkerProvider;
+import com.a.eye.skywalking.collector.actor.AbstractLocalSyncWorkerProvider;
 import com.a.eye.skywalking.collector.actor.ClusterWorkerContext;
 import com.a.eye.skywalking.collector.actor.LocalWorkerContext;
 import com.a.eye.skywalking.collector.actor.selector.HashCodeSelector;
 import com.a.eye.skywalking.collector.actor.selector.WorkerSelector;
 import com.a.eye.skywalking.collector.worker.RecordPersistenceMember;
-import com.a.eye.skywalking.collector.worker.config.WorkerConfig;
 import com.a.eye.skywalking.collector.worker.node.NodeMappingIndex;
+import com.a.eye.skywalking.collector.worker.storage.PersistenceWorkerListener;
 
 /**
  * @author pengys5
@@ -15,7 +15,7 @@
 public class NodeMappingHourSave extends RecordPersistenceMember {
 
     NodeMappingHourSave(com.a.eye.skywalking.collector.actor.Role role, ClusterWorkerContext clusterContext,
-        LocalWorkerContext selfContext) {
+                        LocalWorkerContext selfContext) {
         super(role, clusterContext, selfContext);
     }
 
@@ -29,9 +29,7 @@
         return NodeMappingIndex.TYPE_HOUR;
     }
 
-    public static class Factory extends AbstractLocalAsyncWorkerProvider<NodeMappingHourSave> {
-        public static Factory INSTANCE = new Factory();
-
+    public static class Factory extends AbstractLocalSyncWorkerProvider<NodeMappingHourSave> {
         @Override
         public Role role() {
             return Role.INSTANCE;
@@ -39,12 +37,9 @@
 
         @Override
         public NodeMappingHourSave workerInstance(ClusterWorkerContext clusterContext) {
-            return new NodeMappingHourSave(role(), clusterContext, new LocalWorkerContext());
-        }
-
-        @Override
-        public int queueSize() {
-            return WorkerConfig.Queue.Node.NodeMappingHourSave.SIZE;
+            NodeMappingHourSave worker = new NodeMappingHourSave(role(), clusterContext, new LocalWorkerContext());
+            PersistenceWorkerListener.INSTANCE.register(worker);
+            return worker;
         }
     }
 
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/node/persistence/NodeMappingMinuteAgg.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/node/persistence/NodeMappingMinuteAgg.java
index 99fff3d..422ba5c 100644
--- a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/node/persistence/NodeMappingMinuteAgg.java
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/node/persistence/NodeMappingMinuteAgg.java
@@ -5,12 +5,16 @@
 import com.a.eye.skywalking.collector.actor.selector.WorkerSelector;
 import com.a.eye.skywalking.collector.worker.config.WorkerConfig;
 import com.a.eye.skywalking.collector.worker.storage.RecordData;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
 
 /**
  * @author pengys5
  */
 public class NodeMappingMinuteAgg extends AbstractClusterWorker {
 
+    private Logger logger = LogManager.getFormatterLogger(NodeMappingMinuteAgg.class);
+
     NodeMappingMinuteAgg(com.a.eye.skywalking.collector.actor.Role role, ClusterWorkerContext clusterContext,
         LocalWorkerContext selfContext) {
         super(role, clusterContext, selfContext);
@@ -26,13 +30,11 @@
         if (message instanceof RecordData) {
             getSelfContext().lookup(NodeMappingMinuteSave.Role.INSTANCE).tell(message);
         } else {
-            throw new IllegalArgumentException("message instance must RecordData");
+            logger.error("unhandled message, message instance must RecordData, but is %s", message.getClass().toString());
         }
     }
 
     public static class Factory extends AbstractClusterWorkerProvider<NodeMappingMinuteAgg> {
-        public static Factory INSTANCE = new Factory();
-
         @Override
         public Role role() {
             return Role.INSTANCE;
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/node/persistence/NodeMappingMinuteSave.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/node/persistence/NodeMappingMinuteSave.java
index 6b75aee..ca55a8d 100644
--- a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/node/persistence/NodeMappingMinuteSave.java
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/node/persistence/NodeMappingMinuteSave.java
@@ -1,13 +1,13 @@
 package com.a.eye.skywalking.collector.worker.node.persistence;
 
-import com.a.eye.skywalking.collector.actor.AbstractLocalAsyncWorkerProvider;
+import com.a.eye.skywalking.collector.actor.AbstractLocalSyncWorkerProvider;
 import com.a.eye.skywalking.collector.actor.ClusterWorkerContext;
 import com.a.eye.skywalking.collector.actor.LocalWorkerContext;
 import com.a.eye.skywalking.collector.actor.selector.HashCodeSelector;
 import com.a.eye.skywalking.collector.actor.selector.WorkerSelector;
 import com.a.eye.skywalking.collector.worker.RecordPersistenceMember;
-import com.a.eye.skywalking.collector.worker.config.WorkerConfig;
 import com.a.eye.skywalking.collector.worker.node.NodeMappingIndex;
+import com.a.eye.skywalking.collector.worker.storage.PersistenceWorkerListener;
 
 /**
  * @author pengys5
@@ -15,7 +15,7 @@
 public class NodeMappingMinuteSave extends RecordPersistenceMember {
 
     NodeMappingMinuteSave(com.a.eye.skywalking.collector.actor.Role role, ClusterWorkerContext clusterContext,
-        LocalWorkerContext selfContext) {
+                          LocalWorkerContext selfContext) {
         super(role, clusterContext, selfContext);
     }
 
@@ -29,9 +29,7 @@
         return NodeMappingIndex.TYPE_MINUTE;
     }
 
-    public static class Factory extends AbstractLocalAsyncWorkerProvider<NodeMappingMinuteSave> {
-        public static Factory INSTANCE = new Factory();
-
+    public static class Factory extends AbstractLocalSyncWorkerProvider<NodeMappingMinuteSave> {
         @Override
         public Role role() {
             return Role.INSTANCE;
@@ -39,12 +37,9 @@
 
         @Override
         public NodeMappingMinuteSave workerInstance(ClusterWorkerContext clusterContext) {
-            return new NodeMappingMinuteSave(role(), clusterContext, new LocalWorkerContext());
-        }
-
-        @Override
-        public int queueSize() {
-            return WorkerConfig.Queue.Node.NodeMappingMinuteSave.SIZE;
+            NodeMappingMinuteSave worker = new NodeMappingMinuteSave(role(), clusterContext, new LocalWorkerContext());
+            PersistenceWorkerListener.INSTANCE.register(worker);
+            return worker;
         }
     }
 
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/node/persistence/NodeMappingSearchWithTimeSlice.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/node/persistence/NodeMappingSearchWithTimeSlice.java
index e36b8ca..5103a72 100644
--- a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/node/persistence/NodeMappingSearchWithTimeSlice.java
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/node/persistence/NodeMappingSearchWithTimeSlice.java
@@ -62,7 +62,7 @@
             JsonObject resJsonObj = (JsonObject)response;
             resJsonObj.add(Const.RESULT, nodeMappingArray);
         } else {
-            throw new IllegalArgumentException("message instance must be RequestEntity");
+            logger.error("unhandled message, message instance must NodeMappingSearchWithTimeSlice.RequestEntity, but is %s", request.getClass().toString());
         }
     }
 
@@ -73,8 +73,6 @@
     }
 
     public static class Factory extends AbstractLocalSyncWorkerProvider<NodeMappingSearchWithTimeSlice> {
-        public static Factory INSTANCE = new Factory();
-
         @Override
         public Role role() {
             return WorkerRole.INSTANCE;
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/NodeRefIndex.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/NodeRefIndex.java
index 59066a1..1c268b2 100644
--- a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/NodeRefIndex.java
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/NodeRefIndex.java
@@ -1,5 +1,6 @@
 package com.a.eye.skywalking.collector.worker.noderef;
 
+import com.a.eye.skywalking.collector.worker.config.EsConfig;
 import com.a.eye.skywalking.collector.worker.storage.AbstractIndex;
 import org.elasticsearch.common.xcontent.XContentBuilder;
 import org.elasticsearch.common.xcontent.XContentFactory;
@@ -27,29 +28,31 @@
     }
 
     @Override
+    public int refreshInterval() {
+        return EsConfig.Es.Index.RefreshInterval.NodeRefIndex.VALUE;
+    }
+
+    @Override
     public XContentBuilder createMappingBuilder() throws IOException {
         XContentBuilder mappingBuilder = XContentFactory.jsonBuilder()
             .startObject()
             .startObject("properties")
             .startObject(FRONT)
-            .field("type", "string")
-            .field("index", "not_analyzed")
+            .field("type", "keyword")
             .endObject()
             .startObject(FRONT_IS_REAL_CODE)
             .field("type", "boolean")
             .field("index", "not_analyzed")
             .endObject()
             .startObject(BEHIND)
-            .field("type", "string")
-            .field("index", "not_analyzed")
+            .field("type", "keyword")
             .endObject()
             .startObject(BEHIND_IS_REAL_CODE)
             .field("type", "boolean")
             .field("index", "not_analyzed")
             .endObject()
             .startObject(AGG_COLUMN)
-            .field("type", "string")
-            .field("index", "not_analyzed")
+            .field("type", "keyword")
             .endObject()
             .startObject(TIME_SLICE)
             .field("type", "long")
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/NodeRefResSumGetGroupWithTimeSlice.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/NodeRefResSumGetGroupWithTimeSlice.java
index 957748b..9cb7940 100644
--- a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/NodeRefResSumGetGroupWithTimeSlice.java
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/NodeRefResSumGetGroupWithTimeSlice.java
@@ -61,8 +61,6 @@
     }
 
     public static class Factory extends AbstractGetProvider<NodeRefResSumGetGroupWithTimeSlice> {
-        public static Factory INSTANCE = new Factory();
-
         @Override
         public Role role() {
             return WorkerRole.INSTANCE;
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/NodeRefResSumIndex.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/NodeRefResSumIndex.java
index a1b47c4..796deb1 100644
--- a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/NodeRefResSumIndex.java
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/NodeRefResSumIndex.java
@@ -1,5 +1,6 @@
 package com.a.eye.skywalking.collector.worker.noderef;
 
+import com.a.eye.skywalking.collector.worker.config.EsConfig;
 import com.a.eye.skywalking.collector.worker.storage.AbstractIndex;
 import org.elasticsearch.common.xcontent.XContentBuilder;
 import org.elasticsearch.common.xcontent.XContentFactory;
@@ -29,44 +30,48 @@
     }
 
     @Override
+    public int refreshInterval() {
+        return EsConfig.Es.Index.RefreshInterval.NodeRefResSumIndex.VALUE;
+    }
+
+    @Override
     public XContentBuilder createMappingBuilder() throws IOException {
         XContentBuilder mappingBuilder = XContentFactory.jsonBuilder()
-            .startObject()
-            .startObject("properties")
-            .startObject(ONE_SECOND_LESS)
-            .field("type", "long")
-            .field("index", "not_analyzed")
-            .endObject()
-            .startObject(THREE_SECOND_LESS)
-            .field("type", "long")
-            .field("index", "not_analyzed")
-            .endObject()
-            .startObject(FIVE_SECOND_LESS)
-            .field("type", "long")
-            .field("index", "not_analyzed")
-            .endObject()
-            .startObject(FIVE_SECOND_GREATER)
-            .field("type", "long")
-            .field("index", "not_analyzed")
-            .endObject()
-            .startObject(ERROR)
-            .field("type", "long")
-            .field("index", "not_analyzed")
-            .endObject()
-            .startObject(SUMMARY)
-            .field("type", "long")
-            .field("index", "not_analyzed")
-            .endObject()
-            .startObject(AGG_COLUMN)
-            .field("type", "string")
-            .field("index", "not_analyzed")
-            .endObject()
-            .startObject(TIME_SLICE)
-            .field("type", "long")
-            .field("index", "not_analyzed")
-            .endObject()
-            .endObject()
-            .endObject();
+                .startObject()
+                .startObject("properties")
+                .startObject(ONE_SECOND_LESS)
+                .field("type", "long")
+                .field("index", "not_analyzed")
+                .endObject()
+                .startObject(THREE_SECOND_LESS)
+                .field("type", "long")
+                .field("index", "not_analyzed")
+                .endObject()
+                .startObject(FIVE_SECOND_LESS)
+                .field("type", "long")
+                .field("index", "not_analyzed")
+                .endObject()
+                .startObject(FIVE_SECOND_GREATER)
+                .field("type", "long")
+                .field("index", "not_analyzed")
+                .endObject()
+                .startObject(ERROR)
+                .field("type", "long")
+                .field("index", "not_analyzed")
+                .endObject()
+                .startObject(SUMMARY)
+                .field("type", "long")
+                .field("index", "not_analyzed")
+                .endObject()
+                .startObject(AGG_COLUMN)
+                .field("type", "keyword")
+                .endObject()
+                .startObject(TIME_SLICE)
+                .field("type", "long")
+                .field("index", "not_analyzed")
+                .endObject()
+                .endObject()
+                .endObject();
         return mappingBuilder;
     }
 }
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/analysis/AbstractNodeRefAnalysis.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/analysis/AbstractNodeRefAnalysis.java
index 49abfe6..2fd6b5b 100644
--- a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/analysis/AbstractNodeRefAnalysis.java
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/analysis/AbstractNodeRefAnalysis.java
@@ -5,12 +5,12 @@
 import com.a.eye.skywalking.collector.worker.Const;
 import com.a.eye.skywalking.collector.worker.RecordAnalysisMember;
 import com.a.eye.skywalking.collector.worker.noderef.NodeRefIndex;
+import com.a.eye.skywalking.collector.worker.segment.entity.Segment;
+import com.a.eye.skywalking.collector.worker.segment.entity.Span;
+import com.a.eye.skywalking.collector.worker.segment.entity.tag.Tags;
 import com.a.eye.skywalking.collector.worker.tools.ClientSpanIsLeafTools;
 import com.a.eye.skywalking.collector.worker.tools.CollectionTools;
 import com.a.eye.skywalking.collector.worker.tools.SpanPeersTools;
-import com.a.eye.skywalking.trace.Span;
-import com.a.eye.skywalking.trace.TraceSegment;
-import com.a.eye.skywalking.trace.tag.Tags;
 import com.google.gson.JsonObject;
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
@@ -25,12 +25,12 @@
     private Logger logger = LogManager.getFormatterLogger(AbstractNodeRefAnalysis.class);
 
     AbstractNodeRefAnalysis(com.a.eye.skywalking.collector.actor.Role role, ClusterWorkerContext clusterContext,
-        LocalWorkerContext selfContext) {
+                            LocalWorkerContext selfContext) {
         super(role, clusterContext, selfContext);
     }
 
-    final void analyseNodeRef(TraceSegment segment, long timeSlice, long minute, long hour, long day,
-        int second) throws Exception {
+    final void analyseNodeRef(Segment segment, long timeSlice, long minute, long hour, long day,
+                              int second) throws Exception {
         List<Span> spanList = segment.getSpans();
         if (CollectionTools.isNotEmpty(spanList)) {
             for (Span span : spanList) {
@@ -49,7 +49,7 @@
 
                     String id = timeSlice + Const.ID_SPLIT + front + Const.ID_SPLIT + behind;
                     logger.debug("dag node ref: %s", dataJsonObj.toString());
-                    setRecord(id, dataJsonObj);
+                    set(id, dataJsonObj);
                     buildNodeRefResRecordData(id, span, minute, hour, day, second);
                 } else if (Tags.SPAN_KIND_SERVER.equals(Tags.SPAN_KIND.get(span))) {
                     if (span.getParentSpanId() == -1 && CollectionTools.isEmpty(segment.getRefs())) {
@@ -60,7 +60,7 @@
                         dataJsonObj.addProperty(NodeRefIndex.FRONT, front);
 
                         String id = timeSlice + Const.ID_SPLIT + front + Const.ID_SPLIT + behind;
-                        setRecord(id, dataJsonObj);
+                        set(id, dataJsonObj);
                         buildNodeRefResRecordData(id, span, minute, hour, day, second);
                     }
                 }
@@ -69,7 +69,7 @@
     }
 
     private void buildNodeRefResRecordData(String nodeRefId, Span span, long minute, long hour, long day,
-        int second) throws Exception {
+                                           int second) throws Exception {
         AbstractNodeRefResSumAnalysis.NodeRefResRecord refResRecord = new AbstractNodeRefResSumAnalysis.NodeRefResRecord(minute, hour, day, second);
         refResRecord.setStartTime(span.getStartTime());
         refResRecord.setEndTime(span.getEndTime());
@@ -79,5 +79,5 @@
     }
 
     protected abstract void sendToResSumAnalysis(
-        AbstractNodeRefResSumAnalysis.NodeRefResRecord refResRecord) throws Exception;
+            AbstractNodeRefResSumAnalysis.NodeRefResRecord refResRecord) throws Exception;
 }
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/analysis/AbstractNodeRefResSumAnalysis.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/analysis/AbstractNodeRefResSumAnalysis.java
index d006883..ac57873 100644
--- a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/analysis/AbstractNodeRefResSumAnalysis.java
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/analysis/AbstractNodeRefResSumAnalysis.java
@@ -22,23 +22,23 @@
         boolean isError = nodeRefRes.isError;
         long cost = endTime - startTime;
 
-        setMetric(nodeRefRes.nodeRefId, NodeRefResSumIndex.ONE_SECOND_LESS, 0L);
-        setMetric(nodeRefRes.nodeRefId, NodeRefResSumIndex.THREE_SECOND_LESS, 0L);
-        setMetric(nodeRefRes.nodeRefId, NodeRefResSumIndex.FIVE_SECOND_LESS, 0L);
-        setMetric(nodeRefRes.nodeRefId, NodeRefResSumIndex.FIVE_SECOND_GREATER, 0L);
-        setMetric(nodeRefRes.nodeRefId, NodeRefResSumIndex.ERROR, 0L);
+        set(nodeRefRes.nodeRefId, NodeRefResSumIndex.ONE_SECOND_LESS, 0L);
+        set(nodeRefRes.nodeRefId, NodeRefResSumIndex.THREE_SECOND_LESS, 0L);
+        set(nodeRefRes.nodeRefId, NodeRefResSumIndex.FIVE_SECOND_LESS, 0L);
+        set(nodeRefRes.nodeRefId, NodeRefResSumIndex.FIVE_SECOND_GREATER, 0L);
+        set(nodeRefRes.nodeRefId, NodeRefResSumIndex.ERROR, 0L);
         if (cost <= 1000 && !isError) {
-            setMetric(nodeRefRes.nodeRefId, NodeRefResSumIndex.ONE_SECOND_LESS, 1L);
+            set(nodeRefRes.nodeRefId, NodeRefResSumIndex.ONE_SECOND_LESS, 1L);
         } else if (1000 < cost && cost <= 3000 && !isError) {
-            setMetric(nodeRefRes.nodeRefId, NodeRefResSumIndex.THREE_SECOND_LESS, 1L);
+            set(nodeRefRes.nodeRefId, NodeRefResSumIndex.THREE_SECOND_LESS, 1L);
         } else if (3000 < cost && cost <= 5000 && !isError) {
-            setMetric(nodeRefRes.nodeRefId, NodeRefResSumIndex.FIVE_SECOND_LESS, 1L);
+            set(nodeRefRes.nodeRefId, NodeRefResSumIndex.FIVE_SECOND_LESS, 1L);
         } else if (5000 < cost && !isError) {
-            setMetric(nodeRefRes.nodeRefId, NodeRefResSumIndex.FIVE_SECOND_GREATER, 1L);
+            set(nodeRefRes.nodeRefId, NodeRefResSumIndex.FIVE_SECOND_GREATER, 1L);
         } else {
-            setMetric(nodeRefRes.nodeRefId, NodeRefResSumIndex.ERROR, 1L);
+            set(nodeRefRes.nodeRefId, NodeRefResSumIndex.ERROR, 1L);
         }
-        setMetric(nodeRefRes.nodeRefId, NodeRefResSumIndex.SUMMARY, 1L);
+        set(nodeRefRes.nodeRefId, NodeRefResSumIndex.SUMMARY, 1L);
     }
 
     public static class NodeRefResRecord extends AbstractTimeSlice {
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/analysis/NodeRefDayAnalysis.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/analysis/NodeRefDayAnalysis.java
index 2774526..1107a0d 100644
--- a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/analysis/NodeRefDayAnalysis.java
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/analysis/NodeRefDayAnalysis.java
@@ -1,24 +1,24 @@
 package com.a.eye.skywalking.collector.worker.noderef.analysis;
 
-import com.a.eye.skywalking.collector.actor.AbstractLocalAsyncWorkerProvider;
-import com.a.eye.skywalking.collector.actor.ClusterWorkerContext;
-import com.a.eye.skywalking.collector.actor.LocalWorkerContext;
-import com.a.eye.skywalking.collector.actor.ProviderNotFoundException;
+import com.a.eye.skywalking.collector.actor.*;
 import com.a.eye.skywalking.collector.actor.selector.RollingSelector;
 import com.a.eye.skywalking.collector.actor.selector.WorkerSelector;
 import com.a.eye.skywalking.collector.worker.config.WorkerConfig;
 import com.a.eye.skywalking.collector.worker.noderef.persistence.NodeRefDayAgg;
 import com.a.eye.skywalking.collector.worker.segment.SegmentPost;
-import com.a.eye.skywalking.collector.worker.storage.RecordData;
-import com.a.eye.skywalking.trace.TraceSegment;
+import com.a.eye.skywalking.collector.worker.segment.entity.Segment;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
 
 /**
  * @author pengys5
  */
 public class NodeRefDayAnalysis extends AbstractNodeRefAnalysis {
 
+    private Logger logger = LogManager.getFormatterLogger(NodeRefDayAnalysis.class);
+
     protected NodeRefDayAnalysis(com.a.eye.skywalking.collector.actor.Role role, ClusterWorkerContext clusterContext,
-        LocalWorkerContext selfContext) {
+                                 LocalWorkerContext selfContext) {
         super(role, clusterContext, selfContext);
     }
 
@@ -31,14 +31,16 @@
     @Override
     public void analyse(Object message) throws Exception {
         if (message instanceof SegmentPost.SegmentWithTimeSlice) {
-            SegmentPost.SegmentWithTimeSlice segmentWithTimeSlice = (SegmentPost.SegmentWithTimeSlice)message;
-            TraceSegment segment = segmentWithTimeSlice.getTraceSegment();
+            SegmentPost.SegmentWithTimeSlice segmentWithTimeSlice = (SegmentPost.SegmentWithTimeSlice) message;
+            Segment segment = segmentWithTimeSlice.getSegment();
 
             long minute = segmentWithTimeSlice.getMinute();
             long hour = segmentWithTimeSlice.getHour();
             long day = segmentWithTimeSlice.getDay();
             int second = segmentWithTimeSlice.getSecond();
             analyseNodeRef(segment, segmentWithTimeSlice.getDay(), minute, hour, day, second);
+        } else {
+            logger.error("unhandled message, message instance must SegmentPost.SegmentWithTimeSlice, but is %s", message.getClass().toString());
         }
     }
 
@@ -48,17 +50,16 @@
     }
 
     @Override
-    protected void aggregation() throws Exception {
-        RecordData oneRecord;
-        while ((oneRecord = pushOne()) != null) {
-            getClusterContext().lookup(NodeRefDayAgg.Role.INSTANCE).tell(oneRecord);
+    protected WorkerRefs aggWorkRefs() {
+        try {
+            return getClusterContext().lookup(NodeRefDayAgg.Role.INSTANCE);
+        } catch (WorkerNotFoundException e) {
+            logger.error("The role of %s worker not found", NodeRefDayAgg.Role.INSTANCE.roleName());
         }
+        return null;
     }
 
     public static class Factory extends AbstractLocalAsyncWorkerProvider<NodeRefDayAnalysis> {
-
-        public static Factory INSTANCE = new Factory();
-
         @Override
         public Role role() {
             return Role.INSTANCE;
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/analysis/NodeRefHourAnalysis.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/analysis/NodeRefHourAnalysis.java
index cbf573c..a39bc86 100644
--- a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/analysis/NodeRefHourAnalysis.java
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/analysis/NodeRefHourAnalysis.java
@@ -1,24 +1,24 @@
 package com.a.eye.skywalking.collector.worker.noderef.analysis;
 
-import com.a.eye.skywalking.collector.actor.AbstractLocalAsyncWorkerProvider;
-import com.a.eye.skywalking.collector.actor.ClusterWorkerContext;
-import com.a.eye.skywalking.collector.actor.LocalWorkerContext;
-import com.a.eye.skywalking.collector.actor.ProviderNotFoundException;
+import com.a.eye.skywalking.collector.actor.*;
 import com.a.eye.skywalking.collector.actor.selector.RollingSelector;
 import com.a.eye.skywalking.collector.actor.selector.WorkerSelector;
 import com.a.eye.skywalking.collector.worker.config.WorkerConfig;
 import com.a.eye.skywalking.collector.worker.noderef.persistence.NodeRefHourAgg;
 import com.a.eye.skywalking.collector.worker.segment.SegmentPost;
-import com.a.eye.skywalking.collector.worker.storage.RecordData;
-import com.a.eye.skywalking.trace.TraceSegment;
+import com.a.eye.skywalking.collector.worker.segment.entity.Segment;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
 
 /**
  * @author pengys5
  */
 public class NodeRefHourAnalysis extends AbstractNodeRefAnalysis {
 
+    private Logger logger = LogManager.getFormatterLogger(NodeRefHourAnalysis.class);
+
     protected NodeRefHourAnalysis(com.a.eye.skywalking.collector.actor.Role role, ClusterWorkerContext clusterContext,
-        LocalWorkerContext selfContext) {
+                                  LocalWorkerContext selfContext) {
         super(role, clusterContext, selfContext);
     }
 
@@ -31,14 +31,16 @@
     @Override
     public void analyse(Object message) throws Exception {
         if (message instanceof SegmentPost.SegmentWithTimeSlice) {
-            SegmentPost.SegmentWithTimeSlice segmentWithTimeSlice = (SegmentPost.SegmentWithTimeSlice)message;
-            TraceSegment segment = segmentWithTimeSlice.getTraceSegment();
+            SegmentPost.SegmentWithTimeSlice segmentWithTimeSlice = (SegmentPost.SegmentWithTimeSlice) message;
+            Segment segment = segmentWithTimeSlice.getSegment();
 
             long minute = segmentWithTimeSlice.getMinute();
             long hour = segmentWithTimeSlice.getHour();
             long day = segmentWithTimeSlice.getDay();
             int second = segmentWithTimeSlice.getSecond();
             analyseNodeRef(segment, segmentWithTimeSlice.getHour(), minute, hour, day, second);
+        } else {
+            logger.error("unhandled message, message instance must SegmentPost.SegmentWithTimeSlice, but is %s", message.getClass().toString());
         }
     }
 
@@ -48,17 +50,16 @@
     }
 
     @Override
-    protected void aggregation() throws Exception {
-        RecordData oneRecord;
-        while ((oneRecord = pushOne()) != null) {
-            getClusterContext().lookup(NodeRefHourAgg.Role.INSTANCE).tell(oneRecord);
+    protected WorkerRefs aggWorkRefs() {
+        try {
+            return getClusterContext().lookup(NodeRefHourAgg.Role.INSTANCE);
+        } catch (WorkerNotFoundException e) {
+            logger.error("The role of %s worker not found", NodeRefHourAgg.Role.INSTANCE.roleName());
         }
+        return null;
     }
 
     public static class Factory extends AbstractLocalAsyncWorkerProvider<NodeRefHourAnalysis> {
-
-        public static Factory INSTANCE = new Factory();
-
         @Override
         public Role role() {
             return Role.INSTANCE;
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/analysis/NodeRefMinuteAnalysis.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/analysis/NodeRefMinuteAnalysis.java
index 57754a1..58943b1 100644
--- a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/analysis/NodeRefMinuteAnalysis.java
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/analysis/NodeRefMinuteAnalysis.java
@@ -1,24 +1,24 @@
 package com.a.eye.skywalking.collector.worker.noderef.analysis;
 
-import com.a.eye.skywalking.collector.actor.AbstractLocalAsyncWorkerProvider;
-import com.a.eye.skywalking.collector.actor.ClusterWorkerContext;
-import com.a.eye.skywalking.collector.actor.LocalWorkerContext;
-import com.a.eye.skywalking.collector.actor.ProviderNotFoundException;
+import com.a.eye.skywalking.collector.actor.*;
 import com.a.eye.skywalking.collector.actor.selector.RollingSelector;
 import com.a.eye.skywalking.collector.actor.selector.WorkerSelector;
 import com.a.eye.skywalking.collector.worker.config.WorkerConfig;
 import com.a.eye.skywalking.collector.worker.noderef.persistence.NodeRefMinuteAgg;
 import com.a.eye.skywalking.collector.worker.segment.SegmentPost;
-import com.a.eye.skywalking.collector.worker.storage.RecordData;
-import com.a.eye.skywalking.trace.TraceSegment;
+import com.a.eye.skywalking.collector.worker.segment.entity.Segment;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
 
 /**
  * @author pengys5
  */
 public class NodeRefMinuteAnalysis extends AbstractNodeRefAnalysis {
 
+    private Logger logger = LogManager.getFormatterLogger(NodeRefMinuteAnalysis.class);
+
     protected NodeRefMinuteAnalysis(com.a.eye.skywalking.collector.actor.Role role, ClusterWorkerContext clusterContext,
-        LocalWorkerContext selfContext) {
+                                    LocalWorkerContext selfContext) {
         super(role, clusterContext, selfContext);
     }
 
@@ -31,13 +31,15 @@
     @Override
     public void analyse(Object message) throws Exception {
         if (message instanceof SegmentPost.SegmentWithTimeSlice) {
-            SegmentPost.SegmentWithTimeSlice segmentWithTimeSlice = (SegmentPost.SegmentWithTimeSlice)message;
-            TraceSegment segment = segmentWithTimeSlice.getTraceSegment();
+            SegmentPost.SegmentWithTimeSlice segmentWithTimeSlice = (SegmentPost.SegmentWithTimeSlice) message;
+            Segment segment = segmentWithTimeSlice.getSegment();
             long minute = segmentWithTimeSlice.getMinute();
             long hour = segmentWithTimeSlice.getHour();
             long day = segmentWithTimeSlice.getDay();
             int second = segmentWithTimeSlice.getSecond();
             analyseNodeRef(segment, segmentWithTimeSlice.getMinute(), minute, hour, day, second);
+        } else {
+            logger.error("unhandled message, message instance must SegmentPost.SegmentWithTimeSlice, but is %s", message.getClass().toString());
         }
     }
 
@@ -47,17 +49,16 @@
     }
 
     @Override
-    protected void aggregation() throws Exception {
-        RecordData oneRecord;
-        while ((oneRecord = pushOne()) != null) {
-            getClusterContext().lookup(NodeRefMinuteAgg.Role.INSTANCE).tell(oneRecord);
+    protected WorkerRefs aggWorkRefs() {
+        try {
+            return getClusterContext().lookup(NodeRefMinuteAgg.Role.INSTANCE);
+        } catch (WorkerNotFoundException e) {
+            logger.error("The role of %s worker not found", NodeRefMinuteAgg.Role.INSTANCE.roleName());
         }
+        return null;
     }
 
     public static class Factory extends AbstractLocalAsyncWorkerProvider<NodeRefMinuteAnalysis> {
-
-        public static Factory INSTANCE = new Factory();
-
         @Override
         public Role role() {
             return Role.INSTANCE;
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/analysis/NodeRefResSumDayAnalysis.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/analysis/NodeRefResSumDayAnalysis.java
index bf049b2..8aaea75 100644
--- a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/analysis/NodeRefResSumDayAnalysis.java
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/analysis/NodeRefResSumDayAnalysis.java
@@ -1,43 +1,46 @@
 package com.a.eye.skywalking.collector.worker.noderef.analysis;
 
-import com.a.eye.skywalking.collector.actor.AbstractLocalAsyncWorkerProvider;
-import com.a.eye.skywalking.collector.actor.ClusterWorkerContext;
-import com.a.eye.skywalking.collector.actor.LocalWorkerContext;
+import com.a.eye.skywalking.collector.actor.*;
 import com.a.eye.skywalking.collector.actor.selector.RollingSelector;
 import com.a.eye.skywalking.collector.actor.selector.WorkerSelector;
 import com.a.eye.skywalking.collector.worker.config.WorkerConfig;
 import com.a.eye.skywalking.collector.worker.noderef.persistence.NodeRefResSumDayAgg;
-import com.a.eye.skywalking.collector.worker.storage.MetricData;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
 
 /**
  * @author pengys5
  */
 public class NodeRefResSumDayAnalysis extends AbstractNodeRefResSumAnalysis {
 
+    private Logger logger = LogManager.getFormatterLogger(NodeRefResSumDayAnalysis.class);
+
     NodeRefResSumDayAnalysis(com.a.eye.skywalking.collector.actor.Role role, ClusterWorkerContext clusterContext,
-        LocalWorkerContext selfContext) {
+                             LocalWorkerContext selfContext) {
         super(role, clusterContext, selfContext);
     }
 
     @Override
     public void analyse(Object message) throws Exception {
         if (message instanceof NodeRefResRecord) {
-            NodeRefResRecord refResRecord = (NodeRefResRecord)message;
+            NodeRefResRecord refResRecord = (NodeRefResRecord) message;
             analyseResSum(refResRecord);
+        } else {
+            logger.error("unhandled message, message instance must NodeRefResRecord, but is %s", message.getClass().toString());
         }
     }
 
     @Override
-    protected void aggregation() throws Exception {
-        MetricData oneMetric;
-        while ((oneMetric = pushOne()) != null) {
-            getClusterContext().lookup(NodeRefResSumDayAgg.Role.INSTANCE).tell(oneMetric);
+    protected WorkerRefs aggWorkRefs() {
+        try {
+            return getClusterContext().lookup(NodeRefResSumDayAgg.Role.INSTANCE);
+        } catch (WorkerNotFoundException e) {
+            logger.error("The role of %s worker not found", NodeRefResSumDayAgg.Role.INSTANCE.roleName());
         }
+        return null;
     }
 
     public static class Factory extends AbstractLocalAsyncWorkerProvider<NodeRefResSumDayAnalysis> {
-        public static Factory INSTANCE = new Factory();
-
         @Override
         public Role role() {
             return Role.INSTANCE;
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/analysis/NodeRefResSumHourAnalysis.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/analysis/NodeRefResSumHourAnalysis.java
index b234183..d2442a7 100644
--- a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/analysis/NodeRefResSumHourAnalysis.java
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/analysis/NodeRefResSumHourAnalysis.java
@@ -1,43 +1,46 @@
 package com.a.eye.skywalking.collector.worker.noderef.analysis;
 
-import com.a.eye.skywalking.collector.actor.AbstractLocalAsyncWorkerProvider;
-import com.a.eye.skywalking.collector.actor.ClusterWorkerContext;
-import com.a.eye.skywalking.collector.actor.LocalWorkerContext;
+import com.a.eye.skywalking.collector.actor.*;
 import com.a.eye.skywalking.collector.actor.selector.RollingSelector;
 import com.a.eye.skywalking.collector.actor.selector.WorkerSelector;
 import com.a.eye.skywalking.collector.worker.config.WorkerConfig;
 import com.a.eye.skywalking.collector.worker.noderef.persistence.NodeRefResSumHourAgg;
-import com.a.eye.skywalking.collector.worker.storage.MetricData;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
 
 /**
  * @author pengys5
  */
 public class NodeRefResSumHourAnalysis extends AbstractNodeRefResSumAnalysis {
 
+    private Logger logger = LogManager.getFormatterLogger(NodeRefResSumHourAnalysis.class);
+
     NodeRefResSumHourAnalysis(com.a.eye.skywalking.collector.actor.Role role, ClusterWorkerContext clusterContext,
-        LocalWorkerContext selfContext) {
+                              LocalWorkerContext selfContext) {
         super(role, clusterContext, selfContext);
     }
 
     @Override
     public void analyse(Object message) throws Exception {
         if (message instanceof NodeRefResRecord) {
-            NodeRefResRecord refResRecord = (NodeRefResRecord)message;
+            NodeRefResRecord refResRecord = (NodeRefResRecord) message;
             analyseResSum(refResRecord);
+        } else {
+            logger.error("unhandled message, message instance must NodeRefResRecord, but is %s", message.getClass().toString());
         }
     }
 
     @Override
-    protected void aggregation() throws Exception {
-        MetricData oneMetric;
-        while ((oneMetric = pushOne()) != null) {
-            getClusterContext().lookup(NodeRefResSumHourAgg.Role.INSTANCE).tell(oneMetric);
+    protected WorkerRefs aggWorkRefs() {
+        try {
+            return getClusterContext().lookup(NodeRefResSumHourAgg.Role.INSTANCE);
+        } catch (WorkerNotFoundException e) {
+            logger.error("The role of %s worker not found", NodeRefResSumHourAgg.Role.INSTANCE.roleName());
         }
+        return null;
     }
 
     public static class Factory extends AbstractLocalAsyncWorkerProvider<NodeRefResSumHourAnalysis> {
-        public static Factory INSTANCE = new Factory();
-
         @Override
         public Role role() {
             return Role.INSTANCE;
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/analysis/NodeRefResSumMinuteAnalysis.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/analysis/NodeRefResSumMinuteAnalysis.java
index 810827b..c88062c 100644
--- a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/analysis/NodeRefResSumMinuteAnalysis.java
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/analysis/NodeRefResSumMinuteAnalysis.java
@@ -1,43 +1,46 @@
 package com.a.eye.skywalking.collector.worker.noderef.analysis;
 
-import com.a.eye.skywalking.collector.actor.AbstractLocalAsyncWorkerProvider;
-import com.a.eye.skywalking.collector.actor.ClusterWorkerContext;
-import com.a.eye.skywalking.collector.actor.LocalWorkerContext;
+import com.a.eye.skywalking.collector.actor.*;
 import com.a.eye.skywalking.collector.actor.selector.RollingSelector;
 import com.a.eye.skywalking.collector.actor.selector.WorkerSelector;
 import com.a.eye.skywalking.collector.worker.config.WorkerConfig;
 import com.a.eye.skywalking.collector.worker.noderef.persistence.NodeRefResSumMinuteAgg;
-import com.a.eye.skywalking.collector.worker.storage.MetricData;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
 
 /**
  * @author pengys5
  */
 public class NodeRefResSumMinuteAnalysis extends AbstractNodeRefResSumAnalysis {
 
+    private Logger logger = LogManager.getFormatterLogger(NodeRefResSumMinuteAnalysis.class);
+
     NodeRefResSumMinuteAnalysis(com.a.eye.skywalking.collector.actor.Role role, ClusterWorkerContext clusterContext,
-        LocalWorkerContext selfContext) {
+                                LocalWorkerContext selfContext) {
         super(role, clusterContext, selfContext);
     }
 
     @Override
     public void analyse(Object message) throws Exception {
         if (message instanceof NodeRefResRecord) {
-            NodeRefResRecord refResRecord = (NodeRefResRecord)message;
+            NodeRefResRecord refResRecord = (NodeRefResRecord) message;
             analyseResSum(refResRecord);
+        } else {
+            logger.error("unhandled message, message instance must NodeRefResRecord, but is %s", message.getClass().toString());
         }
     }
 
     @Override
-    protected void aggregation() throws Exception {
-        MetricData oneMetric;
-        while ((oneMetric = pushOne()) != null) {
-            getClusterContext().lookup(NodeRefResSumMinuteAgg.Role.INSTANCE).tell(oneMetric);
+    protected WorkerRefs aggWorkRefs() {
+        try {
+            return getClusterContext().lookup(NodeRefResSumMinuteAgg.Role.INSTANCE);
+        } catch (WorkerNotFoundException e) {
+            logger.error("The role of %s worker not found", NodeRefResSumMinuteAgg.Role.INSTANCE.roleName());
         }
+        return null;
     }
 
     public static class Factory extends AbstractLocalAsyncWorkerProvider<NodeRefResSumMinuteAnalysis> {
-        public static Factory INSTANCE = new Factory();
-
         @Override
         public Role role() {
             return Role.INSTANCE;
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefDayAgg.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefDayAgg.java
index da585f7..c9ad8c6 100644
--- a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefDayAgg.java
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefDayAgg.java
@@ -30,13 +30,11 @@
         if (message instanceof RecordData) {
             getSelfContext().lookup(NodeRefDaySave.Role.INSTANCE).tell(message);
         } else {
-            logger.error("message unhandled");
+            logger.error("unhandled message, message instance must RecordData, but is %s", message.getClass().toString());
         }
     }
 
     public static class Factory extends AbstractClusterWorkerProvider<NodeRefDayAgg> {
-        public static Factory INSTANCE = new Factory();
-
         @Override
         public Role role() {
             return Role.INSTANCE;
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefDaySave.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefDaySave.java
index b2dac0d..ac47083 100644
--- a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefDaySave.java
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefDaySave.java
@@ -1,13 +1,13 @@
 package com.a.eye.skywalking.collector.worker.noderef.persistence;
 
-import com.a.eye.skywalking.collector.actor.AbstractLocalAsyncWorkerProvider;
+import com.a.eye.skywalking.collector.actor.AbstractLocalSyncWorkerProvider;
 import com.a.eye.skywalking.collector.actor.ClusterWorkerContext;
 import com.a.eye.skywalking.collector.actor.LocalWorkerContext;
 import com.a.eye.skywalking.collector.actor.selector.HashCodeSelector;
 import com.a.eye.skywalking.collector.actor.selector.WorkerSelector;
 import com.a.eye.skywalking.collector.worker.RecordPersistenceMember;
-import com.a.eye.skywalking.collector.worker.config.WorkerConfig;
 import com.a.eye.skywalking.collector.worker.noderef.NodeRefIndex;
+import com.a.eye.skywalking.collector.worker.storage.PersistenceWorkerListener;
 
 /**
  * @author pengys5
@@ -15,7 +15,7 @@
 public class NodeRefDaySave extends RecordPersistenceMember {
 
     NodeRefDaySave(com.a.eye.skywalking.collector.actor.Role role, ClusterWorkerContext clusterContext,
-        LocalWorkerContext selfContext) {
+                   LocalWorkerContext selfContext) {
         super(role, clusterContext, selfContext);
     }
 
@@ -29,10 +29,7 @@
         return NodeRefIndex.TYPE_DAY;
     }
 
-    public static class Factory extends AbstractLocalAsyncWorkerProvider<NodeRefDaySave> {
-
-        public static Factory INSTANCE = new Factory();
-
+    public static class Factory extends AbstractLocalSyncWorkerProvider<NodeRefDaySave> {
         @Override
         public Role role() {
             return Role.INSTANCE;
@@ -40,12 +37,9 @@
 
         @Override
         public NodeRefDaySave workerInstance(ClusterWorkerContext clusterContext) {
-            return new NodeRefDaySave(role(), clusterContext, new LocalWorkerContext());
-        }
-
-        @Override
-        public int queueSize() {
-            return WorkerConfig.Queue.NodeRef.NodeRefDaySave.SIZE;
+            NodeRefDaySave worker = new NodeRefDaySave(role(), clusterContext, new LocalWorkerContext());
+            PersistenceWorkerListener.INSTANCE.register(worker);
+            return worker;
         }
     }
 
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefHourAgg.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefHourAgg.java
index edda638..a567412 100644
--- a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefHourAgg.java
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefHourAgg.java
@@ -30,13 +30,11 @@
         if (message instanceof RecordData) {
             getSelfContext().lookup(NodeRefHourSave.Role.INSTANCE).tell(message);
         } else {
-            logger.error("message unhandled");
+            logger.error("unhandled message, message instance must RecordData, but is %s", message.getClass().toString());
         }
     }
 
     public static class Factory extends AbstractClusterWorkerProvider<NodeRefHourAgg> {
-        public static Factory INSTANCE = new Factory();
-
         @Override
         public Role role() {
             return Role.INSTANCE;
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefHourSave.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefHourSave.java
index 8b237e1..736a473 100644
--- a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefHourSave.java
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefHourSave.java
@@ -1,13 +1,13 @@
 package com.a.eye.skywalking.collector.worker.noderef.persistence;
 
-import com.a.eye.skywalking.collector.actor.AbstractLocalAsyncWorkerProvider;
+import com.a.eye.skywalking.collector.actor.AbstractLocalSyncWorkerProvider;
 import com.a.eye.skywalking.collector.actor.ClusterWorkerContext;
 import com.a.eye.skywalking.collector.actor.LocalWorkerContext;
 import com.a.eye.skywalking.collector.actor.selector.HashCodeSelector;
 import com.a.eye.skywalking.collector.actor.selector.WorkerSelector;
 import com.a.eye.skywalking.collector.worker.RecordPersistenceMember;
-import com.a.eye.skywalking.collector.worker.config.WorkerConfig;
 import com.a.eye.skywalking.collector.worker.noderef.NodeRefIndex;
+import com.a.eye.skywalking.collector.worker.storage.PersistenceWorkerListener;
 
 /**
  * @author pengys5
@@ -15,7 +15,7 @@
 public class NodeRefHourSave extends RecordPersistenceMember {
 
     NodeRefHourSave(com.a.eye.skywalking.collector.actor.Role role, ClusterWorkerContext clusterContext,
-        LocalWorkerContext selfContext) {
+                    LocalWorkerContext selfContext) {
         super(role, clusterContext, selfContext);
     }
 
@@ -29,10 +29,7 @@
         return NodeRefIndex.TYPE_HOUR;
     }
 
-    public static class Factory extends AbstractLocalAsyncWorkerProvider<NodeRefHourSave> {
-
-        public static Factory INSTANCE = new Factory();
-
+    public static class Factory extends AbstractLocalSyncWorkerProvider<NodeRefHourSave> {
         @Override
         public Role role() {
             return Role.INSTANCE;
@@ -40,12 +37,9 @@
 
         @Override
         public NodeRefHourSave workerInstance(ClusterWorkerContext clusterContext) {
-            return new NodeRefHourSave(role(), clusterContext, new LocalWorkerContext());
-        }
-
-        @Override
-        public int queueSize() {
-            return WorkerConfig.Queue.NodeRef.NodeRefHourSave.SIZE;
+            NodeRefHourSave worker = new NodeRefHourSave(role(), clusterContext, new LocalWorkerContext());
+            PersistenceWorkerListener.INSTANCE.register(worker);
+            return worker;
         }
     }
 
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefMinuteAgg.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefMinuteAgg.java
index fe4db00..2070ebf 100644
--- a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefMinuteAgg.java
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefMinuteAgg.java
@@ -30,13 +30,11 @@
         if (message instanceof RecordData) {
             getSelfContext().lookup(NodeRefMinuteSave.Role.INSTANCE).tell(message);
         } else {
-            logger.error("message unhandled");
+            logger.error("unhandled message, message instance must RecordData, but is %s", message.getClass().toString());
         }
     }
 
     public static class Factory extends AbstractClusterWorkerProvider<NodeRefMinuteAgg> {
-        public static Factory INSTANCE = new Factory();
-
         @Override
         public Role role() {
             return Role.INSTANCE;
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefMinuteSave.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefMinuteSave.java
index f1fcba2..3c04054 100644
--- a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefMinuteSave.java
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefMinuteSave.java
@@ -1,13 +1,13 @@
 package com.a.eye.skywalking.collector.worker.noderef.persistence;
 
-import com.a.eye.skywalking.collector.actor.AbstractLocalAsyncWorkerProvider;
+import com.a.eye.skywalking.collector.actor.AbstractLocalSyncWorkerProvider;
 import com.a.eye.skywalking.collector.actor.ClusterWorkerContext;
 import com.a.eye.skywalking.collector.actor.LocalWorkerContext;
 import com.a.eye.skywalking.collector.actor.selector.HashCodeSelector;
 import com.a.eye.skywalking.collector.actor.selector.WorkerSelector;
 import com.a.eye.skywalking.collector.worker.RecordPersistenceMember;
-import com.a.eye.skywalking.collector.worker.config.WorkerConfig;
 import com.a.eye.skywalking.collector.worker.noderef.NodeRefIndex;
+import com.a.eye.skywalking.collector.worker.storage.PersistenceWorkerListener;
 
 /**
  * @author pengys5
@@ -15,7 +15,7 @@
 public class NodeRefMinuteSave extends RecordPersistenceMember {
 
     NodeRefMinuteSave(com.a.eye.skywalking.collector.actor.Role role, ClusterWorkerContext clusterContext,
-        LocalWorkerContext selfContext) {
+                      LocalWorkerContext selfContext) {
         super(role, clusterContext, selfContext);
     }
 
@@ -29,10 +29,7 @@
         return NodeRefIndex.TYPE_MINUTE;
     }
 
-    public static class Factory extends AbstractLocalAsyncWorkerProvider<NodeRefMinuteSave> {
-
-        public static Factory INSTANCE = new Factory();
-
+    public static class Factory extends AbstractLocalSyncWorkerProvider<NodeRefMinuteSave> {
         @Override
         public Role role() {
             return Role.INSTANCE;
@@ -40,12 +37,9 @@
 
         @Override
         public NodeRefMinuteSave workerInstance(ClusterWorkerContext clusterContext) {
-            return new NodeRefMinuteSave(role(), clusterContext, new LocalWorkerContext());
-        }
-
-        @Override
-        public int queueSize() {
-            return WorkerConfig.Queue.NodeRef.NodeRefMinuteSave.SIZE;
+            NodeRefMinuteSave worker = new NodeRefMinuteSave(role(), clusterContext, new LocalWorkerContext());
+            PersistenceWorkerListener.INSTANCE.register(worker);
+            return worker;
         }
     }
 
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefResSumDayAgg.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefResSumDayAgg.java
index 2147ab5..ec76fb7 100644
--- a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefResSumDayAgg.java
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefResSumDayAgg.java
@@ -30,13 +30,11 @@
         if (message instanceof MetricData) {
             getSelfContext().lookup(NodeRefResSumDaySave.Role.INSTANCE).tell(message);
         } else {
-            logger.error("message unhandled");
+            logger.error("unhandled message, message instance must MetricData, but is %s", message.getClass().toString());
         }
     }
 
     public static class Factory extends AbstractClusterWorkerProvider<NodeRefResSumDayAgg> {
-        public static Factory INSTANCE = new Factory();
-
         @Override
         public Role role() {
             return Role.INSTANCE;
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefResSumDaySave.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefResSumDaySave.java
index f39a33a..074b41d 100644
--- a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefResSumDaySave.java
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefResSumDaySave.java
@@ -1,13 +1,13 @@
 package com.a.eye.skywalking.collector.worker.noderef.persistence;
 
-import com.a.eye.skywalking.collector.actor.AbstractLocalAsyncWorkerProvider;
+import com.a.eye.skywalking.collector.actor.AbstractLocalSyncWorkerProvider;
 import com.a.eye.skywalking.collector.actor.ClusterWorkerContext;
 import com.a.eye.skywalking.collector.actor.LocalWorkerContext;
 import com.a.eye.skywalking.collector.actor.selector.HashCodeSelector;
 import com.a.eye.skywalking.collector.actor.selector.WorkerSelector;
 import com.a.eye.skywalking.collector.worker.MetricPersistenceMember;
-import com.a.eye.skywalking.collector.worker.config.WorkerConfig;
 import com.a.eye.skywalking.collector.worker.noderef.NodeRefResSumIndex;
+import com.a.eye.skywalking.collector.worker.storage.PersistenceWorkerListener;
 
 /**
  * @author pengys5
@@ -15,7 +15,7 @@
 public class NodeRefResSumDaySave extends MetricPersistenceMember {
 
     NodeRefResSumDaySave(com.a.eye.skywalking.collector.actor.Role role, ClusterWorkerContext clusterContext,
-        LocalWorkerContext selfContext) {
+                         LocalWorkerContext selfContext) {
         super(role, clusterContext, selfContext);
     }
 
@@ -29,9 +29,7 @@
         return NodeRefResSumIndex.TYPE_DAY;
     }
 
-    public static class Factory extends AbstractLocalAsyncWorkerProvider<NodeRefResSumDaySave> {
-        public static Factory INSTANCE = new Factory();
-
+    public static class Factory extends AbstractLocalSyncWorkerProvider<NodeRefResSumDaySave> {
         @Override
         public Role role() {
             return Role.INSTANCE;
@@ -39,12 +37,9 @@
 
         @Override
         public NodeRefResSumDaySave workerInstance(ClusterWorkerContext clusterContext) {
-            return new NodeRefResSumDaySave(role(), clusterContext, new LocalWorkerContext());
-        }
-
-        @Override
-        public int queueSize() {
-            return WorkerConfig.Queue.NodeRef.NodeRefResSumDaySave.SIZE;
+            NodeRefResSumDaySave worker = new NodeRefResSumDaySave(role(), clusterContext, new LocalWorkerContext());
+            PersistenceWorkerListener.INSTANCE.register(worker);
+            return worker;
         }
     }
 
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefResSumGroupWithTimeSlice.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefResSumGroupWithTimeSlice.java
index c62eaad..defc826 100644
--- a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefResSumGroupWithTimeSlice.java
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefResSumGroupWithTimeSlice.java
@@ -80,7 +80,7 @@
             JsonObject resJsonObj = (JsonObject)response;
             resJsonObj.add("result", nodeRefResSumArray);
         } else {
-            throw new IllegalArgumentException("message instance must be RequestEntity");
+            logger.error("unhandled message, message instance must NodeRefResSumGroupWithTimeSlice.RequestEntity, but is %s", request.getClass().toString());
         }
     }
 
@@ -91,8 +91,6 @@
     }
 
     public static class Factory extends AbstractLocalSyncWorkerProvider<NodeRefResSumGroupWithTimeSlice> {
-        public static Factory INSTANCE = new Factory();
-
         @Override
         public Role role() {
             return WorkerRole.INSTANCE;
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefResSumHourAgg.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefResSumHourAgg.java
index 4ec8b6d..8799b42 100644
--- a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefResSumHourAgg.java
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefResSumHourAgg.java
@@ -30,13 +30,11 @@
         if (message instanceof MetricData) {
             getSelfContext().lookup(NodeRefResSumHourSave.Role.INSTANCE).tell(message);
         } else {
-            logger.error("message unhandled");
+            logger.error("unhandled message, message instance must MetricData, but is %s", message.getClass().toString());
         }
     }
 
     public static class Factory extends AbstractClusterWorkerProvider<NodeRefResSumHourAgg> {
-        public static Factory INSTANCE = new Factory();
-
         @Override
         public Role role() {
             return Role.INSTANCE;
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefResSumHourSave.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefResSumHourSave.java
index f4e58ef..776a511 100644
--- a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefResSumHourSave.java
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefResSumHourSave.java
@@ -1,13 +1,13 @@
 package com.a.eye.skywalking.collector.worker.noderef.persistence;
 
-import com.a.eye.skywalking.collector.actor.AbstractLocalAsyncWorkerProvider;
+import com.a.eye.skywalking.collector.actor.AbstractLocalSyncWorkerProvider;
 import com.a.eye.skywalking.collector.actor.ClusterWorkerContext;
 import com.a.eye.skywalking.collector.actor.LocalWorkerContext;
 import com.a.eye.skywalking.collector.actor.selector.HashCodeSelector;
 import com.a.eye.skywalking.collector.actor.selector.WorkerSelector;
 import com.a.eye.skywalking.collector.worker.MetricPersistenceMember;
-import com.a.eye.skywalking.collector.worker.config.WorkerConfig;
 import com.a.eye.skywalking.collector.worker.noderef.NodeRefResSumIndex;
+import com.a.eye.skywalking.collector.worker.storage.PersistenceWorkerListener;
 
 /**
  * @author pengys5
@@ -15,7 +15,7 @@
 public class NodeRefResSumHourSave extends MetricPersistenceMember {
 
     NodeRefResSumHourSave(com.a.eye.skywalking.collector.actor.Role role, ClusterWorkerContext clusterContext,
-        LocalWorkerContext selfContext) {
+                          LocalWorkerContext selfContext) {
         super(role, clusterContext, selfContext);
     }
 
@@ -29,9 +29,7 @@
         return NodeRefResSumIndex.TYPE_HOUR;
     }
 
-    public static class Factory extends AbstractLocalAsyncWorkerProvider<NodeRefResSumHourSave> {
-        public static Factory INSTANCE = new Factory();
-
+    public static class Factory extends AbstractLocalSyncWorkerProvider<NodeRefResSumHourSave> {
         @Override
         public Role role() {
             return Role.INSTANCE;
@@ -39,12 +37,9 @@
 
         @Override
         public NodeRefResSumHourSave workerInstance(ClusterWorkerContext clusterContext) {
-            return new NodeRefResSumHourSave(role(), clusterContext, new LocalWorkerContext());
-        }
-
-        @Override
-        public int queueSize() {
-            return WorkerConfig.Queue.NodeRef.NodeRefResSumHourSave.SIZE;
+            NodeRefResSumHourSave worker = new NodeRefResSumHourSave(role(), clusterContext, new LocalWorkerContext());
+            PersistenceWorkerListener.INSTANCE.register(worker);
+            return worker;
         }
     }
 
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefResSumMinuteAgg.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefResSumMinuteAgg.java
index 6b0b948..244edb5 100644
--- a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefResSumMinuteAgg.java
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefResSumMinuteAgg.java
@@ -30,13 +30,11 @@
         if (message instanceof MetricData) {
             getSelfContext().lookup(NodeRefResSumMinuteSave.Role.INSTANCE).tell(message);
         } else {
-            logger.error("message unhandled");
+            logger.error("unhandled message, message instance must MetricData, but is %s", message.getClass().toString());
         }
     }
 
     public static class Factory extends AbstractClusterWorkerProvider<NodeRefResSumMinuteAgg> {
-        public static Factory INSTANCE = new Factory();
-
         @Override
         public Role role() {
             return Role.INSTANCE;
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefResSumMinuteSave.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefResSumMinuteSave.java
index 0cead78..040b20c 100644
--- a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefResSumMinuteSave.java
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefResSumMinuteSave.java
@@ -1,13 +1,13 @@
 package com.a.eye.skywalking.collector.worker.noderef.persistence;
 
-import com.a.eye.skywalking.collector.actor.AbstractLocalAsyncWorkerProvider;
+import com.a.eye.skywalking.collector.actor.AbstractLocalSyncWorkerProvider;
 import com.a.eye.skywalking.collector.actor.ClusterWorkerContext;
 import com.a.eye.skywalking.collector.actor.LocalWorkerContext;
 import com.a.eye.skywalking.collector.actor.selector.HashCodeSelector;
 import com.a.eye.skywalking.collector.actor.selector.WorkerSelector;
 import com.a.eye.skywalking.collector.worker.MetricPersistenceMember;
-import com.a.eye.skywalking.collector.worker.config.WorkerConfig;
 import com.a.eye.skywalking.collector.worker.noderef.NodeRefResSumIndex;
+import com.a.eye.skywalking.collector.worker.storage.PersistenceWorkerListener;
 
 /**
  * @author pengys5
@@ -15,7 +15,7 @@
 public class NodeRefResSumMinuteSave extends MetricPersistenceMember {
 
     NodeRefResSumMinuteSave(com.a.eye.skywalking.collector.actor.Role role, ClusterWorkerContext clusterContext,
-        LocalWorkerContext selfContext) {
+                            LocalWorkerContext selfContext) {
         super(role, clusterContext, selfContext);
     }
 
@@ -29,9 +29,7 @@
         return NodeRefResSumIndex.TYPE_MINUTE;
     }
 
-    public static class Factory extends AbstractLocalAsyncWorkerProvider<NodeRefResSumMinuteSave> {
-        public static Factory INSTANCE = new Factory();
-
+    public static class Factory extends AbstractLocalSyncWorkerProvider<NodeRefResSumMinuteSave> {
         @Override
         public Role role() {
             return Role.INSTANCE;
@@ -39,12 +37,9 @@
 
         @Override
         public NodeRefResSumMinuteSave workerInstance(ClusterWorkerContext clusterContext) {
-            return new NodeRefResSumMinuteSave(role(), clusterContext, new LocalWorkerContext());
-        }
-
-        @Override
-        public int queueSize() {
-            return WorkerConfig.Queue.NodeRef.NodeRefResSumMinuteSave.SIZE;
+            NodeRefResSumMinuteSave worker = new NodeRefResSumMinuteSave(role(), clusterContext, new LocalWorkerContext());
+            PersistenceWorkerListener.INSTANCE.register(worker);
+            return worker;
         }
     }
 
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefResSumSearchWithTimeSlice.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefResSumSearchWithTimeSlice.java
index 0fa7c19..c26b9a5 100644
--- a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefResSumSearchWithTimeSlice.java
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefResSumSearchWithTimeSlice.java
@@ -91,7 +91,7 @@
             JsonObject resJsonObj = (JsonObject)response;
             resJsonObj.add("result", nodeRefResSumArray);
         } else {
-            throw new IllegalArgumentException("message instance must be RequestEntity");
+            logger.error("unhandled message, message instance must NodeRefResSumSearchWithTimeSlice.RequestEntity, but is %s", request.getClass().toString());
         }
     }
 
@@ -102,8 +102,6 @@
     }
 
     public static class Factory extends AbstractLocalSyncWorkerProvider<NodeRefResSumSearchWithTimeSlice> {
-        public static Factory INSTANCE = new Factory();
-
         @Override
         public Role role() {
             return WorkerRole.INSTANCE;
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefSearchWithTimeSlice.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefSearchWithTimeSlice.java
index c6f2728..f1027c6 100644
--- a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefSearchWithTimeSlice.java
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefSearchWithTimeSlice.java
@@ -63,7 +63,7 @@
             JsonObject resJsonObj = (JsonObject)response;
             resJsonObj.add("result", nodeRefArray);
         } else {
-            throw new IllegalArgumentException("message instance must be RequestEntity");
+            logger.error("unhandled message, message instance must NodeRefSearchWithTimeSlice.RequestEntity, but is %s", request.getClass().toString());
         }
     }
 
@@ -74,8 +74,6 @@
     }
 
     public static class Factory extends AbstractLocalSyncWorkerProvider<NodeRefSearchWithTimeSlice> {
-        public static Factory INSTANCE = new Factory();
-
         @Override
         public Role role() {
             return WorkerRole.INSTANCE;
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/SegmentCostIndex.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/SegmentCostIndex.java
index a8e74ef..823b43f 100644
--- a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/SegmentCostIndex.java
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/SegmentCostIndex.java
@@ -1,5 +1,6 @@
 package com.a.eye.skywalking.collector.worker.segment;
 
+import com.a.eye.skywalking.collector.worker.config.EsConfig;
 import com.a.eye.skywalking.collector.worker.storage.AbstractIndex;
 import org.elasticsearch.common.xcontent.XContentBuilder;
 import org.elasticsearch.common.xcontent.XContentFactory;
@@ -29,31 +30,34 @@
     }
 
     @Override
+    public int refreshInterval() {
+        return EsConfig.Es.Index.RefreshInterval.SegmentCostIndex.VALUE;
+    }
+
+    @Override
     public XContentBuilder createMappingBuilder() throws IOException {
         return XContentFactory.jsonBuilder()
-            .startObject()
-            .startObject("properties")
-            .startObject(SEG_ID)
-            .field("type", "string")
-            .field("index", "not_analyzed")
-            .endObject()
-            .startObject(START_TIME)
-            .field("type", "long")
-            .field("index", "not_analyzed")
-            .endObject()
-            .startObject(END_TIME)
-            .field("type", "long")
-            .field("index", "not_analyzed")
-            .endObject()
-            .startObject(OPERATION_NAME)
-            .field("type", "string")
-            .field("index", "not_analyzed")
-            .endObject()
-            .startObject(COST)
-            .field("type", "long")
-            .field("index", "not_analyzed")
-            .endObject()
-            .endObject()
-            .endObject();
+                .startObject()
+                .startObject("properties")
+                .startObject(SEG_ID)
+                .field("type", "keyword")
+                .endObject()
+                .startObject(START_TIME)
+                .field("type", "long")
+                .field("index", "not_analyzed")
+                .endObject()
+                .startObject(END_TIME)
+                .field("type", "long")
+                .field("index", "not_analyzed")
+                .endObject()
+                .startObject(OPERATION_NAME)
+                .field("type", "keyword")
+                .endObject()
+                .startObject(COST)
+                .field("type", "long")
+                .field("index", "not_analyzed")
+                .endObject()
+                .endObject()
+                .endObject();
     }
 }
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/SegmentExceptionIndex.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/SegmentExceptionIndex.java
index 65efbd7..54b199a 100644
--- a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/SegmentExceptionIndex.java
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/SegmentExceptionIndex.java
@@ -1,5 +1,6 @@
 package com.a.eye.skywalking.collector.worker.segment;
 
+import com.a.eye.skywalking.collector.worker.config.EsConfig;
 import com.a.eye.skywalking.collector.worker.storage.AbstractIndex;
 import org.elasticsearch.common.xcontent.XContentBuilder;
 import org.elasticsearch.common.xcontent.XContentFactory;
@@ -26,24 +27,27 @@
     }
 
     @Override
+    public int refreshInterval() {
+        return EsConfig.Es.Index.RefreshInterval.SegmentExceptionIndex.VALUE;
+    }
+
+    @Override
     public XContentBuilder createMappingBuilder() throws IOException {
         XContentBuilder mappingBuilder = XContentFactory.jsonBuilder()
-            .startObject()
-            .startObject("properties")
-            .startObject(SEG_ID)
-            .field("type", "string")
-            .field("index", "not_analyzed")
-            .endObject()
-            .startObject(IS_ERROR)
-            .field("type", "boolean")
-            .field("index", "not_analyzed")
-            .endObject()
-            .startObject(ERROR_KIND)
-            .field("type", "string")
-            .field("index", "not_analyzed")
-            .endObject()
-            .endObject()
-            .endObject();
+                .startObject()
+                .startObject("properties")
+                .startObject(SEG_ID)
+                .field("type", "keyword")
+                .endObject()
+                .startObject(IS_ERROR)
+                .field("type", "boolean")
+                .field("index", "not_analyzed")
+                .endObject()
+                .startObject(ERROR_KIND)
+                .field("type", "keyword")
+                .endObject()
+                .endObject()
+                .endObject();
         return mappingBuilder;
     }
 }
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/SegmentIndex.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/SegmentIndex.java
index 83cb3fd..56a3a99 100644
--- a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/SegmentIndex.java
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/SegmentIndex.java
@@ -1,5 +1,6 @@
 package com.a.eye.skywalking.collector.worker.segment;
 
+import com.a.eye.skywalking.collector.worker.config.EsConfig;
 import com.a.eye.skywalking.collector.worker.storage.AbstractIndex;
 import org.elasticsearch.common.xcontent.XContentBuilder;
 import org.elasticsearch.common.xcontent.XContentFactory;
@@ -24,39 +25,42 @@
     }
 
     @Override
+    public int refreshInterval() {
+        return EsConfig.Es.Index.RefreshInterval.SegmentIndex.VALUE;
+    }
+
+    @Override
     public XContentBuilder createMappingBuilder() throws IOException {
         return XContentFactory.jsonBuilder()
-            .startObject()
-            .startObject("properties")
-            .startObject("traceSegmentId")
-            .field("type", "string")
-            .field("index", "not_analyzed")
-            .endObject()
-            .startObject("startTime")
-            .field("type", "date")
-            .field("index", "not_analyzed")
-            .endObject()
-            .startObject("endTime")
-            .field("type", "date")
-            .field("index", "not_analyzed")
-            .endObject()
-            .startObject("applicationCode")
-            .field("type", "string")
-            .field("index", "not_analyzed")
-            .endObject()
-            .startObject("minute")
-            .field("type", "long")
-            .field("index", "not_analyzed")
-            .endObject()
-            .startObject("hour")
-            .field("type", "long")
-            .field("index", "not_analyzed")
-            .endObject()
-            .startObject("day")
-            .field("type", "long")
-            .field("index", "not_analyzed")
-            .endObject()
-            .endObject()
-            .endObject();
+                .startObject()
+                .startObject("properties")
+                .startObject("traceSegmentId")
+                .field("type", "keyword")
+                .endObject()
+                .startObject("startTime")
+                .field("type", "date")
+                .field("index", "not_analyzed")
+                .endObject()
+                .startObject("endTime")
+                .field("type", "date")
+                .field("index", "not_analyzed")
+                .endObject()
+                .startObject("applicationCode")
+                .field("type", "keyword")
+                .endObject()
+                .startObject("minute")
+                .field("type", "long")
+                .field("index", "not_analyzed")
+                .endObject()
+                .startObject("hour")
+                .field("type", "long")
+                .field("index", "not_analyzed")
+                .endObject()
+                .startObject("day")
+                .field("type", "long")
+                .field("index", "not_analyzed")
+                .endObject()
+                .endObject()
+                .endObject();
     }
 }
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/SegmentPost.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/SegmentPost.java
index 79a90d9..3802bc4 100644
--- a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/SegmentPost.java
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/SegmentPost.java
@@ -11,82 +11,75 @@
 import com.a.eye.skywalking.collector.worker.globaltrace.analysis.GlobalTraceAnalysis;
 import com.a.eye.skywalking.collector.worker.httpserver.AbstractPost;
 import com.a.eye.skywalking.collector.worker.httpserver.AbstractPostProvider;
-import com.a.eye.skywalking.collector.worker.node.analysis.*;
+import com.a.eye.skywalking.collector.worker.node.analysis.NodeCompAnalysis;
+import com.a.eye.skywalking.collector.worker.node.analysis.NodeMappingDayAnalysis;
+import com.a.eye.skywalking.collector.worker.node.analysis.NodeMappingHourAnalysis;
+import com.a.eye.skywalking.collector.worker.node.analysis.NodeMappingMinuteAnalysis;
 import com.a.eye.skywalking.collector.worker.noderef.analysis.NodeRefDayAnalysis;
 import com.a.eye.skywalking.collector.worker.noderef.analysis.NodeRefHourAnalysis;
 import com.a.eye.skywalking.collector.worker.noderef.analysis.NodeRefMinuteAnalysis;
-import com.a.eye.skywalking.collector.worker.segment.persistence.SegmentCostSave;
-import com.a.eye.skywalking.collector.worker.segment.persistence.SegmentExceptionSave;
-import com.a.eye.skywalking.collector.worker.segment.persistence.SegmentSave;
+import com.a.eye.skywalking.collector.worker.segment.analysis.SegmentAnalysis;
+import com.a.eye.skywalking.collector.worker.segment.analysis.SegmentCostAnalysis;
+import com.a.eye.skywalking.collector.worker.segment.analysis.SegmentExceptionAnalysis;
+import com.a.eye.skywalking.collector.worker.segment.entity.Segment;
 import com.a.eye.skywalking.collector.worker.storage.AbstractTimeSlice;
 import com.a.eye.skywalking.collector.worker.tools.DateTools;
-import com.a.eye.skywalking.trace.SegmentsMessage;
-import com.a.eye.skywalking.trace.TraceSegment;
-import com.google.gson.Gson;
-import com.google.gson.JsonObject;
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
 
-import java.util.List;
-
 /**
  * @author pengys5
  */
 public class SegmentPost extends AbstractPost {
     private static final Logger logger = LogManager.getFormatterLogger(SegmentPost.class);
 
-    private Gson gson;
-
     public SegmentPost(Role role, ClusterWorkerContext clusterContext, LocalWorkerContext selfContext) {
         super(role, clusterContext, selfContext);
-        gson = new Gson();
     }
 
     @Override
     public void preStart() throws ProviderNotFoundException {
         getClusterContext().findProvider(GlobalTraceAnalysis.Role.INSTANCE).create(this);
 
-        getClusterContext().findProvider(NodeCompAnalysis.Role.INSTANCE).create(this);
-
-        getClusterContext().findProvider(SegmentSave.Role.INSTANCE).create(this);
-        getClusterContext().findProvider(SegmentCostSave.Role.INSTANCE).create(this);
-        getClusterContext().findProvider(SegmentExceptionSave.Role.INSTANCE).create(this);
+        getClusterContext().findProvider(SegmentAnalysis.Role.INSTANCE).create(this);
+        getClusterContext().findProvider(SegmentCostAnalysis.Role.INSTANCE).create(this);
+        getClusterContext().findProvider(SegmentExceptionAnalysis.Role.INSTANCE).create(this);
 
         getClusterContext().findProvider(NodeRefMinuteAnalysis.Role.INSTANCE).create(this);
         getClusterContext().findProvider(NodeRefHourAnalysis.Role.INSTANCE).create(this);
         getClusterContext().findProvider(NodeRefDayAnalysis.Role.INSTANCE).create(this);
 
+        getClusterContext().findProvider(NodeCompAnalysis.Role.INSTANCE).create(this);
+
         getClusterContext().findProvider(NodeMappingDayAnalysis.Role.INSTANCE).create(this);
         getClusterContext().findProvider(NodeMappingHourAnalysis.Role.INSTANCE).create(this);
         getClusterContext().findProvider(NodeMappingMinuteAnalysis.Role.INSTANCE).create(this);
     }
 
     @Override
-    protected void onReceive(String reqJsonStr) throws Exception {
-        SegmentsMessage segmentsMessage = gson.fromJson(reqJsonStr, SegmentsMessage.class);
-        List<TraceSegment> segmentList = segmentsMessage.getSegments();
-        for (TraceSegment newSegment : segmentList) {
+    protected void onReceive(Object message) throws Exception {
+        if (message instanceof Segment) {
+            Segment segment = (Segment) message;
             try {
-                validateData(newSegment);
+                validateData(segment);
             } catch (IllegalArgumentException e) {
-                continue;
+                return;
             }
 
-            logger.debug("receive message instanceof TraceSegment, traceSegmentId is %s", newSegment.getTraceSegmentId());
+            logger.debug("receive message instanceof TraceSegment, traceSegmentId is %s", segment.getTraceSegmentId());
 
-            long minuteSlice = DateTools.getMinuteSlice(newSegment.getStartTime());
-            long hourSlice = DateTools.getHourSlice(newSegment.getStartTime());
-            long daySlice = DateTools.getDaySlice(newSegment.getStartTime());
-            int second = DateTools.getSecond(newSegment.getStartTime());
+            long minuteSlice = DateTools.getMinuteSlice(segment.getStartTime());
+            long hourSlice = DateTools.getHourSlice(segment.getStartTime());
+            long daySlice = DateTools.getDaySlice(segment.getStartTime());
+            int second = DateTools.getSecond(segment.getStartTime());
             logger.debug("minuteSlice: %s, hourSlice: %s, daySlice: %s, second:%s", minuteSlice, hourSlice, daySlice, second);
 
-            SegmentWithTimeSlice segmentWithTimeSlice = new SegmentWithTimeSlice(newSegment, minuteSlice, hourSlice, daySlice, second);
-            String newSegmentJsonStr = gson.toJson(newSegment);
-            tellSegmentSave(newSegmentJsonStr, daySlice, hourSlice, minuteSlice);
+            SegmentWithTimeSlice segmentWithTimeSlice = new SegmentWithTimeSlice(segment, minuteSlice, hourSlice, daySlice, second);
+            getSelfContext().lookup(SegmentAnalysis.Role.INSTANCE).tell(segment);
 
-            getSelfContext().lookup(SegmentCostSave.Role.INSTANCE).tell(segmentWithTimeSlice);
+            getSelfContext().lookup(SegmentCostAnalysis.Role.INSTANCE).tell(segmentWithTimeSlice);
             getSelfContext().lookup(GlobalTraceAnalysis.Role.INSTANCE).tell(segmentWithTimeSlice);
-            getSelfContext().lookup(SegmentExceptionSave.Role.INSTANCE).tell(segmentWithTimeSlice);
+            getSelfContext().lookup(SegmentExceptionAnalysis.Role.INSTANCE).tell(segmentWithTimeSlice);
 
             getSelfContext().lookup(NodeCompAnalysis.Role.INSTANCE).tell(segmentWithTimeSlice);
 
@@ -95,14 +88,6 @@
         }
     }
 
-    private void tellSegmentSave(String newSegmentJsonStr, long day, long hour, long minute) throws Exception {
-        JsonObject newSegmentJson = gson.fromJson(newSegmentJsonStr, JsonObject.class);
-        newSegmentJson.addProperty("minute", minute);
-        newSegmentJson.addProperty("hour", hour);
-        newSegmentJson.addProperty("day", day);
-        getSelfContext().lookup(SegmentSave.Role.INSTANCE).tell(newSegmentJson);
-    }
-
     private void tellNodeRef(SegmentWithTimeSlice segmentWithTimeSlice) throws Exception {
         getSelfContext().lookup(NodeRefMinuteAnalysis.Role.INSTANCE).tell(segmentWithTimeSlice);
         getSelfContext().lookup(NodeRefHourAnalysis.Role.INSTANCE).tell(segmentWithTimeSlice);
@@ -115,18 +100,16 @@
         getSelfContext().lookup(NodeMappingDayAnalysis.Role.INSTANCE).tell(segmentWithTimeSlice);
     }
 
-    private void validateData(TraceSegment newSegment) {
-        if (StringUtil.isEmpty(newSegment.getTraceSegmentId())) {
+    private void validateData(Segment segment) {
+        if (StringUtil.isEmpty(segment.getTraceSegmentId())) {
             throw new IllegalArgumentException("traceSegmentId required");
         }
-        if (0 == newSegment.getStartTime()) {
+        if (0 == segment.getStartTime()) {
             throw new IllegalArgumentException("startTime required");
         }
     }
 
     public static class Factory extends AbstractPostProvider<SegmentPost> {
-        public static Factory INSTANCE = new Factory();
-
         @Override
         public String servletPath() {
             return "/segments";
@@ -163,15 +146,15 @@
     }
 
     public static class SegmentWithTimeSlice extends AbstractTimeSlice {
-        private final TraceSegment traceSegment;
+        private final Segment segment;
 
-        public SegmentWithTimeSlice(TraceSegment traceSegment, long minute, long hour, long day, int second) {
+        public SegmentWithTimeSlice(Segment segment, long minute, long hour, long day, int second) {
             super(minute, hour, day, second);
-            this.traceSegment = traceSegment;
+            this.segment = segment;
         }
 
-        public TraceSegment getTraceSegment() {
-            return traceSegment;
+        public Segment getSegment() {
+            return segment;
         }
     }
 }
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/SegmentTopGetWithGlobalTraceId.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/SegmentTopGetWithGlobalTraceId.java
index d7f0d49..1162381 100644
--- a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/SegmentTopGetWithGlobalTraceId.java
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/SegmentTopGetWithGlobalTraceId.java
@@ -62,8 +62,6 @@
     }
 
     public static class Factory extends AbstractGetProvider<SegmentTopGetWithGlobalTraceId> {
-        public static Factory INSTANCE = new Factory();
-
         @Override
         public Role role() {
             return WorkerRole.INSTANCE;
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/SegmentTopGetWithTimeSlice.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/SegmentTopGetWithTimeSlice.java
index 1448fc2..0ff5fd4 100644
--- a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/SegmentTopGetWithTimeSlice.java
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/SegmentTopGetWithTimeSlice.java
@@ -86,8 +86,6 @@
     }
 
     public static class Factory extends AbstractGetProvider<SegmentTopGetWithTimeSlice> {
-        public static Factory INSTANCE = new Factory();
-
         @Override
         public Role role() {
             return WorkerRole.INSTANCE;
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/analysis/SegmentAnalysis.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/analysis/SegmentAnalysis.java
new file mode 100644
index 0000000..4027fb4
--- /dev/null
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/analysis/SegmentAnalysis.java
@@ -0,0 +1,74 @@
+package com.a.eye.skywalking.collector.worker.segment.analysis;
+
+import com.a.eye.skywalking.collector.actor.*;
+import com.a.eye.skywalking.collector.actor.selector.RollingSelector;
+import com.a.eye.skywalking.collector.actor.selector.WorkerSelector;
+import com.a.eye.skywalking.collector.worker.RecordAnalysisMember;
+import com.a.eye.skywalking.collector.worker.config.WorkerConfig;
+import com.a.eye.skywalking.collector.worker.segment.entity.Segment;
+import com.a.eye.skywalking.collector.worker.segment.persistence.SegmentSave;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
+/**
+ * @author pengys5
+ */
+public class SegmentAnalysis extends RecordAnalysisMember {
+
+    private Logger logger = LogManager.getFormatterLogger(SegmentAnalysis.class);
+
+    SegmentAnalysis(Role role, ClusterWorkerContext clusterContext, LocalWorkerContext selfContext) {
+        super(role, clusterContext, selfContext);
+    }
+
+    @Override
+    public void preStart() throws ProviderNotFoundException {
+        getClusterContext().findProvider(SegmentSave.Role.INSTANCE).create(this);
+    }
+
+    @Override
+    public void analyse(Object message) throws Exception {
+        if (message instanceof Segment) {
+            Segment segment = (Segment) message;
+            getSelfContext().lookup(SegmentSave.Role.INSTANCE).tell(segment);
+        } else {
+            logger.error("unhandled message, message instance must Segment, but is %s", message.getClass().toString());
+        }
+    }
+
+    @Override
+    protected WorkerRefs aggWorkRefs() {
+        return null;
+    }
+
+    public static class Factory extends AbstractLocalAsyncWorkerProvider<SegmentAnalysis> {
+        @Override
+        public Role role() {
+            return SegmentAnalysis.Role.INSTANCE;
+        }
+
+        @Override
+        public SegmentAnalysis workerInstance(ClusterWorkerContext clusterContext) {
+            return new SegmentAnalysis(role(), clusterContext, new LocalWorkerContext());
+        }
+
+        @Override
+        public int queueSize() {
+            return WorkerConfig.Queue.Segment.SegmentAnalysis.SIZE;
+        }
+    }
+
+    public enum Role implements com.a.eye.skywalking.collector.actor.Role {
+        INSTANCE;
+
+        @Override
+        public String roleName() {
+            return SegmentAnalysis.class.getSimpleName();
+        }
+
+        @Override
+        public WorkerSelector workerSelector() {
+            return new RollingSelector();
+        }
+    }
+}
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/analysis/SegmentCostAnalysis.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/analysis/SegmentCostAnalysis.java
new file mode 100644
index 0000000..85c01dd
--- /dev/null
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/analysis/SegmentCostAnalysis.java
@@ -0,0 +1,106 @@
+package com.a.eye.skywalking.collector.worker.segment.analysis;
+
+import com.a.eye.skywalking.collector.actor.*;
+import com.a.eye.skywalking.collector.actor.selector.RollingSelector;
+import com.a.eye.skywalking.collector.actor.selector.WorkerSelector;
+import com.a.eye.skywalking.collector.worker.RecordAnalysisMember;
+import com.a.eye.skywalking.collector.worker.config.WorkerConfig;
+import com.a.eye.skywalking.collector.worker.segment.SegmentCostIndex;
+import com.a.eye.skywalking.collector.worker.segment.SegmentPost;
+import com.a.eye.skywalking.collector.worker.segment.entity.Segment;
+import com.a.eye.skywalking.collector.worker.segment.entity.Span;
+import com.a.eye.skywalking.collector.worker.segment.persistence.SegmentCostSave;
+import com.a.eye.skywalking.collector.worker.tools.CollectionTools;
+import com.google.gson.JsonObject;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
+/**
+ * @author pengys5
+ */
+public class SegmentCostAnalysis extends RecordAnalysisMember {
+
+    private Logger logger = LogManager.getFormatterLogger(SegmentCostAnalysis.class);
+
+    SegmentCostAnalysis(Role role, ClusterWorkerContext clusterContext, LocalWorkerContext selfContext) {
+        super(role, clusterContext, selfContext);
+    }
+
+    @Override
+    public void preStart() throws ProviderNotFoundException {
+        getClusterContext().findProvider(SegmentCostSave.Role.INSTANCE).create(this);
+    }
+
+    @Override
+    public void analyse(Object message) throws Exception {
+        if (message instanceof SegmentPost.SegmentWithTimeSlice) {
+            SegmentPost.SegmentWithTimeSlice segmentWithTimeSlice = (SegmentPost.SegmentWithTimeSlice) message;
+            Segment segment = segmentWithTimeSlice.getSegment();
+
+            if (CollectionTools.isNotEmpty(segment.getSpans())) {
+                for (Span span : segment.getSpans()) {
+                    if (span.getParentSpanId() == -1) {
+                        JsonObject dataJsonObj = new JsonObject();
+                        dataJsonObj.addProperty(SegmentCostIndex.SEG_ID, segment.getTraceSegmentId());
+                        dataJsonObj.addProperty(SegmentCostIndex.START_TIME, span.getStartTime());
+                        dataJsonObj.addProperty(SegmentCostIndex.END_TIME, span.getEndTime());
+                        dataJsonObj.addProperty(SegmentCostIndex.OPERATION_NAME, span.getOperationName());
+                        dataJsonObj.addProperty(SegmentCostIndex.TIME_SLICE, segmentWithTimeSlice.getMinute());
+
+                        long startTime = span.getStartTime();
+                        long endTime = span.getEndTime();
+                        long cost = endTime - startTime;
+                        if (cost == 0) {
+                            cost = 1;
+                        }
+                        dataJsonObj.addProperty(SegmentCostIndex.COST, cost);
+                        set(segment.getTraceSegmentId(), dataJsonObj);
+                    }
+                }
+            }
+        } else {
+            logger.error("unhandled message, message instance must SegmentPost.SegmentWithTimeSlice, but is %s", message.getClass().toString());
+        }
+    }
+
+    @Override
+    protected WorkerRefs aggWorkRefs() {
+        try {
+            return getSelfContext().lookup(SegmentCostSave.Role.INSTANCE);
+        } catch (WorkerNotFoundException e) {
+            logger.error("The role of %s worker not found", SegmentCostSave.Role.INSTANCE.roleName());
+        }
+        return null;
+    }
+
+    public static class Factory extends AbstractLocalAsyncWorkerProvider<SegmentCostAnalysis> {
+        @Override
+        public Role role() {
+            return SegmentCostAnalysis.Role.INSTANCE;
+        }
+
+        @Override
+        public SegmentCostAnalysis workerInstance(ClusterWorkerContext clusterContext) {
+            return new SegmentCostAnalysis(role(), clusterContext, new LocalWorkerContext());
+        }
+
+        @Override
+        public int queueSize() {
+            return WorkerConfig.Queue.Segment.SegmentCostAnalysis.SIZE;
+        }
+    }
+
+    public enum Role implements com.a.eye.skywalking.collector.actor.Role {
+        INSTANCE;
+
+        @Override
+        public String roleName() {
+            return SegmentCostAnalysis.class.getSimpleName();
+        }
+
+        @Override
+        public WorkerSelector workerSelector() {
+            return new RollingSelector();
+        }
+    }
+}
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/analysis/SegmentExceptionAnalysis.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/analysis/SegmentExceptionAnalysis.java
new file mode 100644
index 0000000..f7df85b
--- /dev/null
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/analysis/SegmentExceptionAnalysis.java
@@ -0,0 +1,111 @@
+package com.a.eye.skywalking.collector.worker.segment.analysis;
+
+import com.a.eye.skywalking.collector.actor.*;
+import com.a.eye.skywalking.collector.actor.selector.RollingSelector;
+import com.a.eye.skywalking.collector.actor.selector.WorkerSelector;
+import com.a.eye.skywalking.collector.worker.RecordAnalysisMember;
+import com.a.eye.skywalking.collector.worker.config.WorkerConfig;
+import com.a.eye.skywalking.collector.worker.segment.SegmentExceptionIndex;
+import com.a.eye.skywalking.collector.worker.segment.SegmentPost;
+import com.a.eye.skywalking.collector.worker.segment.entity.LogData;
+import com.a.eye.skywalking.collector.worker.segment.entity.Segment;
+import com.a.eye.skywalking.collector.worker.segment.entity.Span;
+import com.a.eye.skywalking.collector.worker.segment.entity.tag.Tags;
+import com.a.eye.skywalking.collector.worker.segment.persistence.SegmentExceptionSave;
+import com.a.eye.skywalking.collector.worker.tools.CollectionTools;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonObject;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
+import java.util.List;
+
+/**
+ * @author pengys5
+ */
+public class SegmentExceptionAnalysis extends RecordAnalysisMember {
+
+    private Logger logger = LogManager.getFormatterLogger(SegmentExceptionAnalysis.class);
+
+    SegmentExceptionAnalysis(Role role, ClusterWorkerContext clusterContext, LocalWorkerContext selfContext) {
+        super(role, clusterContext, selfContext);
+    }
+
+    @Override
+    public void preStart() throws ProviderNotFoundException {
+        getClusterContext().findProvider(SegmentExceptionSave.Role.INSTANCE).create(this);
+    }
+
+    @Override
+    public void analyse(Object message) throws Exception {
+        if (message instanceof SegmentPost.SegmentWithTimeSlice) {
+            SegmentPost.SegmentWithTimeSlice segmentWithTimeSlice = (SegmentPost.SegmentWithTimeSlice) message;
+            Segment segment = segmentWithTimeSlice.getSegment();
+
+            if (CollectionTools.isNotEmpty(segment.getSpans())) {
+                for (Span span : segment.getSpans()) {
+                    boolean isError = Tags.ERROR.get(span);
+
+                    JsonObject dataJsonObj = new JsonObject();
+                    dataJsonObj.addProperty(SegmentExceptionIndex.IS_ERROR, isError);
+                    dataJsonObj.addProperty(SegmentExceptionIndex.SEG_ID, segment.getTraceSegmentId());
+
+                    JsonArray errorKind = new JsonArray();
+                    if (isError) {
+                        List<LogData> logDataList = span.getLogs();
+                        for (LogData logData : logDataList) {
+                            if (logData.getFields().containsKey("error.kind")) {
+                                errorKind.add(String.valueOf(logData.getFields().get("error.kind")));
+                            }
+                        }
+                    }
+                    dataJsonObj.add(SegmentExceptionIndex.ERROR_KIND, errorKind);
+                    set(segment.getTraceSegmentId(), dataJsonObj);
+                }
+            }
+        } else {
+            logger.error("unhandled message, message instance must SegmentPost.SegmentWithTimeSlice, but is %s", message.getClass().toString());
+        }
+    }
+
+    @Override
+    protected WorkerRefs aggWorkRefs() {
+        try {
+            return getSelfContext().lookup(SegmentExceptionSave.Role.INSTANCE);
+        } catch (WorkerNotFoundException e) {
+            logger.error("The role of %s worker not found", SegmentExceptionSave.Role.INSTANCE.roleName());
+        }
+        return null;
+    }
+
+    public static class Factory extends AbstractLocalAsyncWorkerProvider<SegmentExceptionAnalysis> {
+        @Override
+        public Role role() {
+            return SegmentExceptionAnalysis.Role.INSTANCE;
+        }
+
+        @Override
+        public SegmentExceptionAnalysis workerInstance(ClusterWorkerContext clusterContext) {
+            return new SegmentExceptionAnalysis(role(), clusterContext, new LocalWorkerContext());
+        }
+
+        @Override
+        public int queueSize() {
+            return WorkerConfig.Queue.Segment.SegmentExceptionAnalysis.SIZE;
+        }
+    }
+
+    public enum Role implements com.a.eye.skywalking.collector.actor.Role {
+        INSTANCE;
+
+        @Override
+        public String roleName() {
+            return SegmentExceptionAnalysis.class.getSimpleName();
+        }
+
+        @Override
+        public WorkerSelector workerSelector() {
+            return new RollingSelector();
+        }
+    }
+}
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/entity/DeserializeObject.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/entity/DeserializeObject.java
new file mode 100644
index 0000000..0f2febe
--- /dev/null
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/entity/DeserializeObject.java
@@ -0,0 +1,16 @@
+package com.a.eye.skywalking.collector.worker.segment.entity;
+
+/**
+ * @author pengys5
+ */
+public abstract class DeserializeObject {
+    private String jsonStr;
+
+    public String getJsonStr() {
+        return jsonStr;
+    }
+
+    public void setJsonStr(String jsonStr) {
+        this.jsonStr = jsonStr;
+    }
+}
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/entity/GlobalTraceId.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/entity/GlobalTraceId.java
new file mode 100644
index 0000000..b6c53f6
--- /dev/null
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/entity/GlobalTraceId.java
@@ -0,0 +1,22 @@
+package com.a.eye.skywalking.collector.worker.segment.entity;
+
+import com.google.gson.stream.JsonReader;
+
+import java.io.IOException;
+
+/**
+ * @author pengys5
+ */
+public class GlobalTraceId extends DeserializeObject {
+    private String globalTraceId;
+
+    public String get() {
+        return globalTraceId;
+    }
+
+    public GlobalTraceId deserialize(JsonReader reader) throws IOException {
+        this.globalTraceId = reader.nextString();
+        this.setJsonStr("\"" + globalTraceId + "\"");
+        return this;
+    }
+}
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/entity/JsonBuilder.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/entity/JsonBuilder.java
new file mode 100644
index 0000000..7c72987
--- /dev/null
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/entity/JsonBuilder.java
@@ -0,0 +1,70 @@
+package com.a.eye.skywalking.collector.worker.segment.entity;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author pengys5
+ */
+public enum JsonBuilder {
+    INSTANCE;
+
+    public void append(StringBuilder builder, String name, String value, boolean first) {
+        if (!first) {
+            builder.append(",");
+        }
+        builder.append("\"").append(name).append("\":\"").append(value).append("\"");
+    }
+
+    public void append(StringBuilder builder, String name, Number value, boolean first) {
+        if (!first) {
+            builder.append(",");
+        }
+        builder.append("\"").append(name).append("\":").append(value);
+    }
+
+    public void append(StringBuilder builder, String name, List<?> value, boolean first) {
+        if (!first) {
+            builder.append(",");
+        }
+        builder.append("\"").append(name).append("\":");
+        builder.append("[");
+
+        boolean isFirst = true;
+        for (int i = 0; i < value.size(); i++) {
+            DeserializeObject deserializeObject = (DeserializeObject) value.get(i);
+            if (!isFirst) {
+                builder.append(",");
+            }
+            builder.append(deserializeObject.getJsonStr());
+            isFirst = false;
+        }
+
+        builder.append("]");
+    }
+
+    public void append(StringBuilder builder, String name, Map<String, ?> tagsWithStr, boolean first) {
+        if (!first) {
+            builder.append(",");
+        }
+        builder.append("\"").append(name).append("\":");
+        builder.append("{");
+
+        boolean isFirst = true;
+        for (Map.Entry<String, ?> entry : tagsWithStr.entrySet()) {
+            String key = entry.getKey();
+            Object value = entry.getValue();
+            if (!isFirst) {
+                builder.append(",");
+            }
+            if (value instanceof String) {
+                builder.append("\"").append(key).append("\":\"").append(value).append("\"");
+            } else {
+                builder.append("\"").append(key).append("\":").append(value);
+            }
+            isFirst = false;
+        }
+
+        builder.append("}");
+    }
+}
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/entity/LogData.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/entity/LogData.java
new file mode 100644
index 0000000..1d2216d
--- /dev/null
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/entity/LogData.java
@@ -0,0 +1,59 @@
+package com.a.eye.skywalking.collector.worker.segment.entity;
+
+import com.google.gson.stream.JsonReader;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author pengys5
+ */
+public class LogData extends DeserializeObject {
+    private long time;
+    private Map<String, String> fields;
+
+    public long getTime() {
+        return time;
+    }
+
+    public Map<String, String> getFields() {
+        return fields;
+    }
+
+    public LogData deserialize(JsonReader reader) throws IOException {
+        StringBuilder stringBuilder = new StringBuilder();
+        stringBuilder.append("{");
+
+        boolean first = true;
+        reader.beginObject();
+        while (reader.hasNext()) {
+            switch (reader.nextName()) {
+                case "tm":
+                    Long tm = reader.nextLong();
+                    this.time = tm;
+                    JsonBuilder.INSTANCE.append(stringBuilder, "tm", tm, first);
+                    break;
+                case "fi":
+                    fields = new HashMap<>();
+                    reader.beginObject();
+
+                    while (reader.hasNext()) {
+                        String key = reader.nextName();
+                        String value = reader.nextString();
+                        fields.put(key, value);
+                    }
+                    reader.endObject();
+                    JsonBuilder.INSTANCE.append(stringBuilder, "fi", fields, first);
+                    break;
+                default:
+                    reader.skipValue();
+            }
+            first = false;
+        }
+        reader.endObject();
+        stringBuilder.append("}");
+        this.setJsonStr(stringBuilder.toString());
+        return this;
+    }
+}
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/entity/Segment.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/entity/Segment.java
new file mode 100644
index 0000000..4a1493d
--- /dev/null
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/entity/Segment.java
@@ -0,0 +1,127 @@
+package com.a.eye.skywalking.collector.worker.segment.entity;
+
+import com.google.gson.stream.JsonReader;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author pengys5
+ */
+public class Segment extends DeserializeObject {
+    private String traceSegmentId;
+    private long startTime;
+    private long endTime;
+    private List<TraceSegmentRef> refs;
+    private List<Span> spans;
+    private String applicationCode;
+    private List<GlobalTraceId> relatedGlobalTraces;
+
+    public String getTraceSegmentId() {
+        return traceSegmentId;
+    }
+
+    public long getStartTime() {
+        return startTime;
+    }
+
+    public long getEndTime() {
+        return endTime;
+    }
+
+    public String getApplicationCode() {
+        return applicationCode;
+    }
+
+    public List<TraceSegmentRef> getRefs() {
+        return refs;
+    }
+
+    public List<Span> getSpans() {
+        return spans;
+    }
+
+    public List<GlobalTraceId> getRelatedGlobalTraces() {
+        return relatedGlobalTraces;
+    }
+
+    public Segment deserialize(JsonReader reader) throws IOException {
+        StringBuilder stringBuilder = new StringBuilder();
+        stringBuilder.append("{");
+
+        boolean first = true;
+        reader.beginObject();
+        while (reader.hasNext()) {
+            switch (reader.nextName()) {
+                case "ts":
+                    String ts = reader.nextString();
+                    this.traceSegmentId = ts;
+                    JsonBuilder.INSTANCE.append(stringBuilder, "ts", ts, first);
+                    break;
+                case "ac":
+                    String ac = reader.nextString();
+                    this.applicationCode = ac;
+                    JsonBuilder.INSTANCE.append(stringBuilder, "ac", ac, first);
+                    break;
+                case "st":
+                    long st = reader.nextLong();
+                    this.startTime = st;
+                    JsonBuilder.INSTANCE.append(stringBuilder, "st", st, first);
+                    break;
+                case "et":
+                    long et = reader.nextLong();
+                    this.endTime = et;
+                    JsonBuilder.INSTANCE.append(stringBuilder, "et", et, first);
+                    break;
+                case "rs":
+                    refs = new ArrayList<>();
+                    reader.beginArray();
+
+                    while (reader.hasNext()) {
+                        TraceSegmentRef ref = new TraceSegmentRef();
+                        ref.deserialize(reader);
+                        refs.add(ref);
+                    }
+
+                    reader.endArray();
+                    JsonBuilder.INSTANCE.append(stringBuilder, "rs", refs, first);
+                    break;
+                case "ss":
+                    spans = new ArrayList<>();
+                    reader.beginArray();
+
+                    while (reader.hasNext()) {
+                        Span span = new Span();
+                        span.deserialize(reader);
+                        spans.add(span);
+                    }
+
+                    reader.endArray();
+                    JsonBuilder.INSTANCE.append(stringBuilder, "ss", spans, first);
+                    break;
+                case "gt":
+                    relatedGlobalTraces = new ArrayList<>();
+                    reader.beginArray();
+
+                    while (reader.hasNext()) {
+                        GlobalTraceId globalTraceId = new GlobalTraceId();
+                        globalTraceId.deserialize(reader);
+                        relatedGlobalTraces.add(globalTraceId);
+                    }
+                    JsonBuilder.INSTANCE.append(stringBuilder, "gt", relatedGlobalTraces, first);
+
+                    reader.endArray();
+                    break;
+                default:
+                    reader.skipValue();
+            }
+            first = false;
+        }
+        reader.endObject();
+
+        stringBuilder.append("}");
+        this.setJsonStr(stringBuilder.toString());
+        return this;
+    }
+}
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/entity/SegmentDeserialize.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/entity/SegmentDeserialize.java
new file mode 100644
index 0000000..5399387
--- /dev/null
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/entity/SegmentDeserialize.java
@@ -0,0 +1,45 @@
+package com.a.eye.skywalking.collector.worker.segment.entity;
+
+import com.google.gson.stream.JsonReader;
+
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author pengys5
+ */
+public enum SegmentDeserialize {
+    INSTANCE;
+
+    public Segment deserializeSingle(String singleSegmentJsonStr) throws IOException {
+        JsonReader reader = new JsonReader(new StringReader(singleSegmentJsonStr));
+        Segment segment = new Segment();
+        segment.deserialize(reader);
+        return segment;
+    }
+
+    public List<Segment> deserializeMultiple(String segmentJsonFile) throws Exception {
+        List<Segment> segmentList = new ArrayList<>();
+        streamReader(segmentList, new FileReader(segmentJsonFile));
+        return segmentList;
+    }
+
+    private void streamReader(List<Segment> segmentList, FileReader fileReader) throws Exception {
+        try (JsonReader reader = new JsonReader(fileReader)) {
+            readSegmentArray(segmentList, reader);
+        }
+    }
+
+    private void readSegmentArray(List<Segment> segmentList, JsonReader reader) throws Exception {
+        reader.beginArray();
+        while (reader.hasNext()) {
+            Segment segment = new Segment();
+            segment.deserialize(reader);
+            segmentList.add(segment);
+        }
+        reader.endArray();
+    }
+}
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/entity/Span.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/entity/Span.java
new file mode 100644
index 0000000..d003d17
--- /dev/null
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/entity/Span.java
@@ -0,0 +1,153 @@
+package com.a.eye.skywalking.collector.worker.segment.entity;
+
+import com.google.gson.stream.JsonReader;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author pengys5
+ */
+public class Span extends DeserializeObject {
+    private int spanId;
+    private int parentSpanId;
+    private long startTime;
+    private long endTime;
+    private String operationName;
+    private Map<String, String> tagsWithStr;
+    private Map<String, Boolean> tagsWithBool;
+    private Map<String, Integer> tagsWithInt;
+    private List<LogData> logs;
+
+    public int getSpanId() {
+        return spanId;
+    }
+
+    public int getParentSpanId() {
+        return parentSpanId;
+    }
+
+    public long getStartTime() {
+        return startTime;
+    }
+
+    public long getEndTime() {
+        return endTime;
+    }
+
+    public String getOperationName() {
+        return operationName;
+    }
+
+    public String getStrTag(String key) {
+        return tagsWithStr.get(key);
+    }
+
+    public Boolean getBoolTag(String key) {
+        return tagsWithBool.get(key);
+    }
+
+    public Integer getIntTag(String key) {
+        return tagsWithInt.get(key);
+    }
+
+    public List<LogData> getLogs() {
+        return logs;
+    }
+
+    public Span deserialize(JsonReader reader) throws IOException {
+        StringBuilder stringBuilder = new StringBuilder();
+        stringBuilder.append("{");
+
+        boolean first = true;
+        reader.beginObject();
+        while (reader.hasNext()) {
+            switch (reader.nextName()) {
+                case "si":
+                    Integer si = reader.nextInt();
+                    this.spanId = si;
+                    JsonBuilder.INSTANCE.append(stringBuilder, "si", si, first);
+                    break;
+                case "ps":
+                    Integer ps = reader.nextInt();
+                    this.parentSpanId = ps;
+                    JsonBuilder.INSTANCE.append(stringBuilder, "ps", ps, first);
+                    break;
+                case "st":
+                    Long st = reader.nextLong();
+                    this.startTime = st;
+                    JsonBuilder.INSTANCE.append(stringBuilder, "st", st, first);
+                    break;
+                case "et":
+                    Long et = reader.nextLong();
+                    this.endTime = et;
+                    JsonBuilder.INSTANCE.append(stringBuilder, "et", et, first);
+                    break;
+                case "on":
+                    String on = reader.nextString();
+                    this.operationName = on;
+                    JsonBuilder.INSTANCE.append(stringBuilder, "on", on, first);
+                    break;
+                case "ts":
+                    tagsWithStr = new HashMap<>();
+                    reader.beginObject();
+
+                    while (reader.hasNext()) {
+                        String key = reader.nextName();
+                        String value = reader.nextString();
+                        tagsWithStr.put(key, value);
+                    }
+                    reader.endObject();
+                    JsonBuilder.INSTANCE.append(stringBuilder, "ts", tagsWithStr, first);
+                    break;
+                case "tb":
+                    tagsWithBool = new HashMap<>();
+                    reader.beginObject();
+
+                    while (reader.hasNext()) {
+                        String key = reader.nextName();
+                        boolean value = reader.nextBoolean();
+                        tagsWithBool.put(key, value);
+                    }
+                    reader.endObject();
+                    JsonBuilder.INSTANCE.append(stringBuilder, "tb", tagsWithBool, first);
+                    break;
+                case "ti":
+                    tagsWithInt = new HashMap<>();
+                    reader.beginObject();
+
+                    while (reader.hasNext()) {
+                        String key = reader.nextName();
+                        Integer value = reader.nextInt();
+                        tagsWithInt.put(key, value);
+                    }
+                    reader.endObject();
+                    JsonBuilder.INSTANCE.append(stringBuilder, "ti", tagsWithInt, first);
+                    break;
+                case "lo":
+                    logs = new ArrayList<>();
+                    reader.beginArray();
+
+                    while (reader.hasNext()) {
+                        LogData logData = new LogData();
+                        logData.deserialize(reader);
+                        logs.add(logData);
+                    }
+                    reader.endArray();
+                    JsonBuilder.INSTANCE.append(stringBuilder, "lo", logs, first);
+                    break;
+                default:
+                    reader.skipValue();
+            }
+            first = false;
+        }
+        reader.endObject();
+
+        stringBuilder.append("}");
+        this.setJsonStr(stringBuilder.toString());
+        return this;
+    }
+}
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/logic/SpanView.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/entity/SpanView.java
similarity index 96%
rename from skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/logic/SpanView.java
rename to skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/entity/SpanView.java
index f38bb35..372340f 100644
--- a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/logic/SpanView.java
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/entity/SpanView.java
@@ -1,4 +1,4 @@
-package com.a.eye.skywalking.collector.worker.segment.logic;
+package com.a.eye.skywalking.collector.worker.segment.entity;
 
 import java.util.HashSet;
 import java.util.Set;
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/entity/TraceSegmentRef.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/entity/TraceSegmentRef.java
new file mode 100644
index 0000000..3386ec4
--- /dev/null
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/entity/TraceSegmentRef.java
@@ -0,0 +1,74 @@
+package com.a.eye.skywalking.collector.worker.segment.entity;
+
+import com.google.gson.stream.JsonReader;
+import java.io.IOException;
+
+/**
+ * @author pengys5
+ */
+public class TraceSegmentRef extends DeserializeObject {
+
+    private String traceSegmentId;
+
+    private int spanId = -1;
+
+    private String applicationCode;
+
+    private String peerHost;
+
+    public String getTraceSegmentId() {
+        return traceSegmentId;
+    }
+
+    public int getSpanId() {
+        return spanId;
+    }
+
+    public String getApplicationCode() {
+        return applicationCode;
+    }
+
+    public String getPeerHost() {
+        return peerHost;
+    }
+
+    public TraceSegmentRef deserialize(JsonReader reader) throws IOException {
+        StringBuilder stringBuilder = new StringBuilder();
+        stringBuilder.append("{");
+
+        boolean first = true;
+        reader.beginObject();
+        while (reader.hasNext()) {
+            switch (reader.nextName()) {
+                case "ts":
+                    String ts = reader.nextString();
+                    this.traceSegmentId = ts;
+                    JsonBuilder.INSTANCE.append(stringBuilder, "ts", ts, first);
+                    break;
+                case "si":
+                    Integer si = reader.nextInt();
+                    this.spanId = si;
+                    JsonBuilder.INSTANCE.append(stringBuilder, "si", si, first);
+                    break;
+                case "ac":
+                    String ac = reader.nextString();
+                    this.applicationCode = ac;
+                    JsonBuilder.INSTANCE.append(stringBuilder, "ac", ac, first);
+                    break;
+                case "ph":
+                    String ph = reader.nextString();
+                    this.peerHost = ph;
+                    JsonBuilder.INSTANCE.append(stringBuilder, "ph", ph, first);
+                    break;
+                default:
+                    reader.skipValue();
+            }
+            first = false;
+        }
+        reader.endObject();
+
+        stringBuilder.append("}");
+        this.setJsonStr(stringBuilder.toString());
+        return this;
+    }
+}
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/entity/tag/AbstractTag.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/entity/tag/AbstractTag.java
new file mode 100644
index 0000000..c9659f9
--- /dev/null
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/entity/tag/AbstractTag.java
@@ -0,0 +1,16 @@
+package com.a.eye.skywalking.collector.worker.segment.entity.tag;
+
+import com.a.eye.skywalking.collector.worker.segment.entity.Span;
+
+public abstract class AbstractTag<T> {
+    /**
+     * The key of this Tag.
+     */
+    protected final String key;
+
+    public AbstractTag(String tagKey) {
+        this.key = tagKey;
+    }
+
+    public abstract T get(Span span);
+}
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/entity/tag/BooleanTag.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/entity/tag/BooleanTag.java
new file mode 100644
index 0000000..d7a48c1
--- /dev/null
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/entity/tag/BooleanTag.java
@@ -0,0 +1,35 @@
+package com.a.eye.skywalking.collector.worker.segment.entity.tag;
+
+import com.a.eye.skywalking.collector.worker.segment.entity.Span;
+
+/**
+ * Do the same thing as {@link StringTag}, just with a {@link Boolean} value.
+ * <p>
+ * Created by wusheng on 2017/2/17.
+ */
+public class BooleanTag extends AbstractTag<Boolean> {
+
+    private boolean defaultValue;
+
+    public BooleanTag(String key, boolean defaultValue) {
+        super(key);
+        this.defaultValue = defaultValue;
+    }
+
+    /**
+     * Get a tag value, type of {@link Boolean}. After akka-message/serialize, all tags values are type of {@link
+     * String}, convert to {@link Boolean}, if necessary.
+     *
+     * @param span
+     * @return tag value
+     */
+    @Override
+    public Boolean get(Span span) {
+        Boolean tagValue = span.getBoolTag(super.key);
+        if (tagValue == null) {
+            return defaultValue;
+        } else {
+            return tagValue;
+        }
+    }
+}
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/entity/tag/IntTag.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/entity/tag/IntTag.java
new file mode 100644
index 0000000..c4481dc
--- /dev/null
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/entity/tag/IntTag.java
@@ -0,0 +1,31 @@
+package com.a.eye.skywalking.collector.worker.segment.entity.tag;
+
+import com.a.eye.skywalking.collector.worker.segment.entity.Span;
+
+/**
+ * Do the same thing as {@link StringTag}, just with a {@link Integer} value.
+ *
+ * Created by wusheng on 2017/2/18.
+ */
+public class IntTag extends AbstractTag<Integer> {
+    public IntTag(String key) {
+        super(key);
+    }
+
+    /**
+     * Get a tag value, type of {@link Integer}.
+     * After akka-message/serialize, all tags values are type of {@link String}, convert to {@link Integer}, if necessary.
+     *
+     * @param span
+     * @return tag value
+     */
+    @Override
+    public Integer get(Span span) {
+        Integer tagValue = span.getIntTag(super.key);
+        if (tagValue == null) {
+            return null;
+        } else {
+            return tagValue;
+        }
+    }
+}
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/entity/tag/ShortTag.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/entity/tag/ShortTag.java
new file mode 100644
index 0000000..7c6dc94
--- /dev/null
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/entity/tag/ShortTag.java
@@ -0,0 +1,30 @@
+package com.a.eye.skywalking.collector.worker.segment.entity.tag;
+
+import com.a.eye.skywalking.collector.worker.segment.entity.Span;
+
+/**
+ * Do the same thing as {@link StringTag}, just with a {@link Short} value.
+ *
+ * Created by wusheng on 2017/2/17.
+ */
+public class ShortTag extends AbstractTag<Short> {
+    public ShortTag(String key) {
+        super(key);
+    }
+
+    /**
+     * Get a tag value, type of {@link Short}.
+     * After akka-message/serialize, all tags values are type of {@link String}, convert to {@link Short}, if necessary.
+     *
+     * @param span
+     * @return tag value
+     */
+    @Override public Short get(Span span) {
+        Integer tagValue = span.getIntTag(super.key);
+        if (tagValue == null) {
+            return null;
+        } else {
+            return Short.valueOf(tagValue.toString());
+        }
+    }
+}
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/entity/tag/StringTag.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/entity/tag/StringTag.java
new file mode 100644
index 0000000..275a2d4
--- /dev/null
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/entity/tag/StringTag.java
@@ -0,0 +1,20 @@
+package com.a.eye.skywalking.collector.worker.segment.entity.tag;
+
+
+import com.a.eye.skywalking.collector.worker.segment.entity.Span;
+
+/**
+ * A subclass of {@link AbstractTag},
+ * represent a tag with a {@link String} value.
+ *
+ * Created by wusheng on 2017/2/17.
+ */
+public class StringTag extends AbstractTag<String> {
+    public StringTag(String tagKey) {
+        super(tagKey);
+    }
+
+    @Override public String get(Span span) {
+        return span.getStrTag(super.key);
+    }
+}
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/entity/tag/Tags.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/entity/tag/Tags.java
new file mode 100644
index 0000000..ba24020
--- /dev/null
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/entity/tag/Tags.java
@@ -0,0 +1,97 @@
+package com.a.eye.skywalking.collector.worker.segment.entity.tag;
+
+
+import com.a.eye.skywalking.collector.worker.segment.entity.Span;
+
+/**
+ * The span tags are supported by sky-walking engine.
+ * As default, all tags will be stored, but these ones have particular meanings.
+ * <p>
+ * Created by wusheng on 2017/2/17.
+ */
+public final class Tags {
+    private Tags() {
+    }
+
+    /**
+     * URL records the url of the incoming request.
+     */
+    public static final StringTag URL = new StringTag("url");
+
+    /**
+     * STATUS_CODE records the http status code of the response.
+     */
+    public static final IntTag STATUS_CODE = new IntTag("status_code");
+
+    /**
+     * SPAN_KIND hints at the relationship between spans, e.g. client/server.
+     */
+    public static final StringTag SPAN_KIND = new StringTag("span.kind");
+
+    /**
+     * A constant for setting the span kind to indicate that it represents a server span.
+     */
+    public static final String SPAN_KIND_SERVER = "server";
+
+    /**
+     * A constant for setting the span kind to indicate that it represents a client span.
+     */
+    public static final String SPAN_KIND_CLIENT = "client";
+
+    /**
+     * SPAN_LAYER represents the kind of span.
+     * <p>
+     * e.g.
+     * db=database;
+     * rpc=Remote Procedure Call Framework, like motan, thift;
+     * nosql=something like redis/memcache
+     */
+    public static final class SPAN_LAYER {
+        private static StringTag SPAN_LAYER_TAG = new StringTag("span.layer");
+
+        public static String get(Span span) {
+            return SPAN_LAYER_TAG.get(span);
+        }
+    }
+
+    /**
+     * COMPONENT is a low-cardinality identifier of the module, library, or package that is instrumented.
+     * Like dubbo/dubbox/motan
+     */
+    public static final StringTag COMPONENT = new StringTag("component");
+
+    /**
+     * ERROR indicates whether a Span ended in an error state.
+     */
+    public static final BooleanTag ERROR = new BooleanTag("error", false);
+
+    /**
+     * PEER_HOST records host address (ip:port, or ip1:port1,ip2:port2) of the peer, maybe IPV4, IPV6 or hostname.
+     */
+    public static final StringTag PEER_HOST = new StringTag("peer.host");
+
+    /**
+     * PEER_PORT records remote port of the peer
+     */
+    public static final IntTag PEER_PORT = new IntTag("peer.port");
+
+    /**
+     * PEERS records multiple host address and port of remote
+     */
+    public static final StringTag PEERS = new StringTag("peers");
+
+    /**
+     * DB_TYPE records database type, such as sql, redis, cassandra and so on.
+     */
+    public static final StringTag DB_TYPE = new StringTag("db.type");
+
+    /**
+     * DB_INSTANCE records database instance name.
+     */
+    public static final StringTag DB_INSTANCE = new StringTag("db.instance");
+
+    /**
+     * DB_STATEMENT records the sql statement of the database access.
+     */
+    public static final StringTag DB_STATEMENT = new StringTag("db.statement");
+}
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/logic/Segment.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/logic/Segment.java
deleted file mode 100644
index a001f3e..0000000
--- a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/logic/Segment.java
+++ /dev/null
@@ -1,141 +0,0 @@
-package com.a.eye.skywalking.collector.worker.segment.logic;
-
-import com.a.eye.skywalking.trace.Span;
-import com.a.eye.skywalking.trace.TraceId.DistributedTraceId;
-import com.a.eye.skywalking.trace.TraceId.DistributedTraceIds;
-import com.a.eye.skywalking.trace.TraceSegment;
-import com.a.eye.skywalking.trace.TraceSegmentRef;
-import com.google.gson.annotations.Expose;
-import com.google.gson.annotations.SerializedName;
-
-import java.util.Collections;
-import java.util.LinkedList;
-import java.util.List;
-
-/**
- * @author pengys5
- */
-public class Segment {
-
-    /**
-     * The id of this trace segment.
-     * Every segment has its unique-global-id.
-     */
-    @Expose
-    @SerializedName(value = "ts")
-    private String traceSegmentId;
-
-    /**
-     * The start time of this trace segment.
-     */
-    @Expose
-    @SerializedName(value = "st")
-    private long startTime;
-
-    /**
-     * The end time of this trace segment.
-     */
-    @Expose
-    @SerializedName(value = "et")
-    private long endTime;
-
-    /**
-     * The refs of parent trace segments, except the primary one.
-     * For most RPC call, {@link #refs} contains only one element,
-     * but if this segment is a start span of batch process, the segment faces multi parents,
-     * at this moment, we use this {@link #refs} to link them.
-     */
-    @Expose
-    @SerializedName(value = "rs")
-    private List<TraceSegmentRef> refs;
-
-    /**
-     * The spans belong to this trace segment.
-     * They all have finished.
-     * All active spans are hold and controlled by "skywalking-api" module.
-     */
-    @Expose
-    @SerializedName(value = "ss")
-    private List<Span> spans;
-
-    /**
-     * The <code>applicationCode</code> represents a NAME of current application/JVM and indicates which is business
-     * role in the cluster.
-     * <p>
-     * e.g. account_app, billing_app
-     */
-    @Expose
-    @SerializedName(value = "ac")
-    private String applicationCode;
-
-    /**
-     * The <code>relatedGlobalTraces</code> represent a set of all related trace. Most time it contains only one
-     * element, because only one parent {@link TraceSegment} exists, but, in batch scenario, the num becomes greater
-     * than 1, also meaning multi-parents {@link TraceSegment}.
-     * <p>
-     * The difference between <code>relatedGlobalTraces</code> and {@link #refs} is:
-     * {@link #refs} targets this {@link TraceSegment}'s direct parent,
-     * <p>
-     * and
-     * <p>
-     * <code>relatedGlobalTraces</code> targets this {@link TraceSegment}'s related call chain, a call chain contains
-     * multi {@link TraceSegment}s, only using {@link #refs} is not enough for analysis and ui.
-     */
-    @Expose
-    @SerializedName(value = "gt")
-    private DistributedTraceIds relatedGlobalTraces;
-
-    /**
-     * Establish the link between this segment and its parents.
-     *
-     * @param refSegment {@link TraceSegmentRef}
-     */
-    public void ref(TraceSegmentRef refSegment) {
-        if (refs == null) {
-            refs = new LinkedList<TraceSegmentRef>();
-        }
-        if (!refs.contains(refSegment)) {
-            refs.add(refSegment);
-        }
-    }
-
-    public void relatedGlobalTraces(List<DistributedTraceId> distributedTraceIds) {
-        if (distributedTraceIds == null || distributedTraceIds.size() == 0) {
-            return;
-        }
-        for (DistributedTraceId distributedTraceId : distributedTraceIds) {
-            relatedGlobalTraces.append(distributedTraceId);
-        }
-    }
-
-    public String getTraceSegmentId() {
-        return traceSegmentId;
-    }
-
-    public long getStartTime() {
-        return startTime;
-    }
-
-    public long getEndTime() {
-        return endTime;
-    }
-
-    public List<TraceSegmentRef> getRefs() {
-        if (refs == null) {
-            return null;
-        }
-        return Collections.unmodifiableList(refs);
-    }
-
-    public List<DistributedTraceId> getRelatedGlobalTraces() {
-        return relatedGlobalTraces.getRelatedGlobalTraces();
-    }
-
-    public List<Span> getSpans() {
-        return Collections.unmodifiableList(spans);
-    }
-
-    public String getApplicationCode() {
-        return applicationCode;
-    }
-}
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/logic/SegmentDeserialize.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/logic/SegmentDeserialize.java
deleted file mode 100644
index 3dedc35..0000000
--- a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/logic/SegmentDeserialize.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package com.a.eye.skywalking.collector.worker.segment.logic;
-
-import com.google.gson.Gson;
-
-/**
- * @author pengys5
- */
-public enum SegmentDeserialize {
-    INSTANCE;
-
-    private Gson gson = new Gson();
-
-    public Segment deserializeFromES(String segmentSource) {
-        Segment segment = gson.fromJson(segmentSource, Segment.class);
-        return segment;
-    }
-}
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/persistence/SegmentCostSave.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/persistence/SegmentCostSave.java
index 928c991..e1f8238 100644
--- a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/persistence/SegmentCostSave.java
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/persistence/SegmentCostSave.java
@@ -1,29 +1,18 @@
 package com.a.eye.skywalking.collector.worker.segment.persistence;
 
-import com.a.eye.skywalking.collector.actor.AbstractLocalAsyncWorkerProvider;
+import com.a.eye.skywalking.collector.actor.AbstractLocalSyncWorkerProvider;
 import com.a.eye.skywalking.collector.actor.ClusterWorkerContext;
 import com.a.eye.skywalking.collector.actor.LocalWorkerContext;
 import com.a.eye.skywalking.collector.actor.selector.RollingSelector;
 import com.a.eye.skywalking.collector.actor.selector.WorkerSelector;
 import com.a.eye.skywalking.collector.worker.RecordPersistenceMember;
-import com.a.eye.skywalking.collector.worker.config.WorkerConfig;
 import com.a.eye.skywalking.collector.worker.segment.SegmentCostIndex;
-import com.a.eye.skywalking.collector.worker.segment.SegmentPost;
-import com.a.eye.skywalking.collector.worker.storage.RecordData;
-import com.a.eye.skywalking.collector.worker.tools.CollectionTools;
-import com.a.eye.skywalking.trace.Span;
-import com.a.eye.skywalking.trace.TraceSegment;
-import com.google.gson.JsonObject;
-import org.apache.logging.log4j.LogManager;
-import org.apache.logging.log4j.Logger;
+import com.a.eye.skywalking.collector.worker.storage.PersistenceWorkerListener;
 
 /**
  * @author pengys5
  */
 public class SegmentCostSave extends RecordPersistenceMember {
-
-    private Logger logger = LogManager.getFormatterLogger(SegmentCostSave.class);
-
     @Override
     public String esIndex() {
         return SegmentCostIndex.INDEX;
@@ -35,61 +24,21 @@
     }
 
     protected SegmentCostSave(com.a.eye.skywalking.collector.actor.Role role, ClusterWorkerContext clusterContext,
-        LocalWorkerContext selfContext) {
+                              LocalWorkerContext selfContext) {
         super(role, clusterContext, selfContext);
     }
 
-    @Override
-    public void analyse(Object message) throws Exception {
-        if (message instanceof SegmentPost.SegmentWithTimeSlice) {
-            SegmentPost.SegmentWithTimeSlice segmentWithTimeSlice = (SegmentPost.SegmentWithTimeSlice)message;
-            TraceSegment segment = segmentWithTimeSlice.getTraceSegment();
-
-            if (CollectionTools.isNotEmpty(segment.getSpans())) {
-                for (Span span : segment.getSpans()) {
-                    if (span.getParentSpanId() == -1) {
-                        JsonObject dataJsonObj = new JsonObject();
-                        dataJsonObj.addProperty(SegmentCostIndex.SEG_ID, segment.getTraceSegmentId());
-                        dataJsonObj.addProperty(SegmentCostIndex.START_TIME, span.getStartTime());
-                        dataJsonObj.addProperty(SegmentCostIndex.END_TIME, span.getEndTime());
-                        dataJsonObj.addProperty(SegmentCostIndex.OPERATION_NAME, span.getOperationName());
-                        dataJsonObj.addProperty(SegmentCostIndex.TIME_SLICE, segmentWithTimeSlice.getMinute());
-
-                        long startTime = span.getStartTime();
-                        long endTime = span.getEndTime();
-                        long cost = endTime - startTime;
-                        if (cost == 0) {
-                            cost = 1;
-                        }
-                        dataJsonObj.addProperty(SegmentCostIndex.COST, cost);
-
-                        RecordData recordData = new RecordData(segment.getTraceSegmentId());
-                        recordData.setRecord(dataJsonObj);
-                        super.analyse(recordData);
-                    }
-                }
-            }
-        } else {
-            logger.error("unhandled message, message instance must JsonObject, but is %s", message.getClass().toString());
-        }
-    }
-
-    public static class Factory extends AbstractLocalAsyncWorkerProvider<SegmentCostSave> {
-        public static Factory INSTANCE = new Factory();
-
+    public static class Factory extends AbstractLocalSyncWorkerProvider<SegmentCostSave> {
         @Override
         public Role role() {
             return Role.INSTANCE;
         }
 
         @Override
-        public int queueSize() {
-            return WorkerConfig.Queue.Segment.SegmentCostSave.SIZE;
-        }
-
-        @Override
         public SegmentCostSave workerInstance(ClusterWorkerContext clusterContext) {
-            return new SegmentCostSave(role(), clusterContext, new LocalWorkerContext());
+            SegmentCostSave worker = new SegmentCostSave(role(), clusterContext, new LocalWorkerContext());
+            PersistenceWorkerListener.INSTANCE.register(worker);
+            return worker;
         }
     }
 
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/persistence/SegmentExceptionSave.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/persistence/SegmentExceptionSave.java
index d014be1..ca8d887 100644
--- a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/persistence/SegmentExceptionSave.java
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/persistence/SegmentExceptionSave.java
@@ -1,35 +1,19 @@
 package com.a.eye.skywalking.collector.worker.segment.persistence;
 
-import com.a.eye.skywalking.collector.actor.AbstractLocalAsyncWorkerProvider;
+import com.a.eye.skywalking.collector.actor.AbstractLocalSyncWorkerProvider;
 import com.a.eye.skywalking.collector.actor.ClusterWorkerContext;
 import com.a.eye.skywalking.collector.actor.LocalWorkerContext;
 import com.a.eye.skywalking.collector.actor.selector.RollingSelector;
 import com.a.eye.skywalking.collector.actor.selector.WorkerSelector;
 import com.a.eye.skywalking.collector.worker.RecordPersistenceMember;
-import com.a.eye.skywalking.collector.worker.config.WorkerConfig;
 import com.a.eye.skywalking.collector.worker.segment.SegmentExceptionIndex;
-import com.a.eye.skywalking.collector.worker.segment.SegmentPost;
 import com.a.eye.skywalking.collector.worker.storage.AbstractIndex;
-import com.a.eye.skywalking.collector.worker.storage.RecordData;
-import com.a.eye.skywalking.collector.worker.tools.CollectionTools;
-import com.a.eye.skywalking.trace.LogData;
-import com.a.eye.skywalking.trace.Span;
-import com.a.eye.skywalking.trace.TraceSegment;
-import com.a.eye.skywalking.trace.tag.Tags;
-import com.google.gson.JsonArray;
-import com.google.gson.JsonObject;
-import org.apache.logging.log4j.LogManager;
-import org.apache.logging.log4j.Logger;
-
-import java.util.List;
+import com.a.eye.skywalking.collector.worker.storage.PersistenceWorkerListener;
 
 /**
  * @author pengys5
  */
 public class SegmentExceptionSave extends RecordPersistenceMember {
-
-    private Logger logger = LogManager.getFormatterLogger(SegmentExceptionSave.class);
-
     @Override
     public String esIndex() {
         return SegmentExceptionIndex.INDEX;
@@ -41,61 +25,21 @@
     }
 
     protected SegmentExceptionSave(com.a.eye.skywalking.collector.actor.Role role, ClusterWorkerContext clusterContext,
-        LocalWorkerContext selfContext) {
+                                   LocalWorkerContext selfContext) {
         super(role, clusterContext, selfContext);
     }
 
-    @Override
-    public void analyse(Object message) throws Exception {
-        if (message instanceof SegmentPost.SegmentWithTimeSlice) {
-            SegmentPost.SegmentWithTimeSlice segmentWithTimeSlice = (SegmentPost.SegmentWithTimeSlice)message;
-            TraceSegment segment = segmentWithTimeSlice.getTraceSegment();
-
-            if (CollectionTools.isNotEmpty(segment.getSpans())) {
-                for (Span span : segment.getSpans()) {
-                    boolean isError = Tags.ERROR.get(span);
-
-                    JsonObject dataJsonObj = new JsonObject();
-                    dataJsonObj.addProperty(SegmentExceptionIndex.IS_ERROR, isError);
-                    dataJsonObj.addProperty(SegmentExceptionIndex.SEG_ID, segment.getTraceSegmentId());
-
-                    JsonArray errorKind = new JsonArray();
-                    if (isError) {
-                        List<LogData> logDataList = span.getLogs();
-                        for (LogData logData : logDataList) {
-                            if (logData.getFields().containsKey("error.kind")) {
-                                errorKind.add(String.valueOf(logData.getFields().get("error.kind")));
-                            }
-                        }
-                    }
-                    dataJsonObj.add(SegmentExceptionIndex.ERROR_KIND, errorKind);
-
-                    RecordData recordData = new RecordData(segment.getTraceSegmentId());
-                    recordData.setRecord(dataJsonObj);
-                    super.analyse(recordData);
-                }
-            }
-        } else {
-            logger.error("unhandled message, message instance must JsonObject, but is %s", message.getClass().toString());
-        }
-    }
-
-    public static class Factory extends AbstractLocalAsyncWorkerProvider<SegmentExceptionSave> {
-        public static Factory INSTANCE = new Factory();
-
+    public static class Factory extends AbstractLocalSyncWorkerProvider<SegmentExceptionSave> {
         @Override
         public Role role() {
             return Role.INSTANCE;
         }
 
         @Override
-        public int queueSize() {
-            return WorkerConfig.Queue.Segment.SegmentExceptionSave.SIZE;
-        }
-
-        @Override
         public SegmentExceptionSave workerInstance(ClusterWorkerContext clusterContext) {
-            return new SegmentExceptionSave(role(), clusterContext, new LocalWorkerContext());
+            SegmentExceptionSave worker = new SegmentExceptionSave(role(), clusterContext, new LocalWorkerContext());
+            PersistenceWorkerListener.INSTANCE.register(worker);
+            return worker;
         }
     }
 
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/persistence/SegmentExceptionWithSegId.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/persistence/SegmentExceptionWithSegId.java
index f492f8e..6201006 100644
--- a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/persistence/SegmentExceptionWithSegId.java
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/persistence/SegmentExceptionWithSegId.java
@@ -42,8 +42,6 @@
     }
 
     public static class Factory extends AbstractLocalSyncWorkerProvider<SegmentExceptionWithSegId> {
-        public static Factory INSTANCE = new Factory();
-
         @Override
         public Role role() {
             return WorkerRole.INSTANCE;
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/persistence/SegmentSave.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/persistence/SegmentSave.java
index 5870ee1..203e479 100644
--- a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/persistence/SegmentSave.java
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/persistence/SegmentSave.java
@@ -1,25 +1,29 @@
 package com.a.eye.skywalking.collector.worker.segment.persistence;
 
-import com.a.eye.skywalking.collector.actor.AbstractLocalAsyncWorkerProvider;
+import com.a.eye.skywalking.collector.actor.AbstractLocalSyncWorkerProvider;
 import com.a.eye.skywalking.collector.actor.ClusterWorkerContext;
 import com.a.eye.skywalking.collector.actor.LocalWorkerContext;
 import com.a.eye.skywalking.collector.actor.selector.RollingSelector;
 import com.a.eye.skywalking.collector.actor.selector.WorkerSelector;
-import com.a.eye.skywalking.collector.worker.RecordPersistenceMember;
-import com.a.eye.skywalking.collector.worker.config.WorkerConfig;
+import com.a.eye.skywalking.collector.worker.PersistenceMember;
+import com.a.eye.skywalking.collector.worker.config.CacheSizeConfig;
 import com.a.eye.skywalking.collector.worker.segment.SegmentIndex;
+import com.a.eye.skywalking.collector.worker.segment.entity.Segment;
 import com.a.eye.skywalking.collector.worker.storage.AbstractIndex;
-import com.a.eye.skywalking.collector.worker.storage.RecordData;
-import com.google.gson.JsonObject;
-import org.apache.logging.log4j.LogManager;
-import org.apache.logging.log4j.Logger;
+import com.a.eye.skywalking.collector.worker.storage.EsClient;
+import com.a.eye.skywalking.collector.worker.storage.PersistenceWorkerListener;
+import com.a.eye.skywalking.collector.worker.storage.SegmentData;
+import com.a.eye.skywalking.collector.worker.storage.SegmentPersistenceData;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import org.elasticsearch.action.index.IndexRequestBuilder;
+import org.elasticsearch.client.Client;
 
 /**
  * @author pengys5
  */
-public class SegmentSave extends RecordPersistenceMember {
-
-    private Logger logger = LogManager.getFormatterLogger(SegmentSave.class);
+public class SegmentSave extends PersistenceMember<SegmentPersistenceData, SegmentData> {
 
     @Override
     public String esIndex() {
@@ -32,38 +36,65 @@
     }
 
     public SegmentSave(com.a.eye.skywalking.collector.actor.Role role, ClusterWorkerContext clusterContext,
-        LocalWorkerContext selfContext) {
+                       LocalWorkerContext selfContext) {
         super(role, clusterContext, selfContext);
     }
 
     @Override
-    public void analyse(Object message) throws Exception {
-        if (message instanceof JsonObject) {
-            JsonObject segmentJson = (JsonObject)message;
-            RecordData recordData = new RecordData(segmentJson.get("ts").getAsString());
-            recordData.setRecord(segmentJson);
-            super.analyse(recordData);
+    public SegmentPersistenceData initializeData() {
+        return new SegmentPersistenceData();
+    }
+
+    @Override
+    final public void analyse(Object message) throws Exception {
+        if (message instanceof Segment) {
+            Segment segment = (Segment) message;
+            SegmentPersistenceData data = getPersistenceData();
+            data.hold();
+            data.getOrCreate(segment.getTraceSegmentId()).setSegmentStr(segment.getJsonStr());
+            if (data.size() >= CacheSizeConfig.Cache.Persistence.SIZE) {
+                persistence(data.asMap());
+            }
+            data.release();
         } else {
-            logger.error("unhandled message, message instance must JsonObject, but is %s", message.getClass().toString());
+            logger().error("unhandled message, message instance must Segment, but is %s", message.getClass().toString());
         }
     }
 
-    public static class Factory extends AbstractLocalAsyncWorkerProvider<SegmentSave> {
-        public static Factory INSTANCE = new Factory();
+    private void persistence(Map<String, SegmentData> dataMap) {
+        List<IndexRequestBuilder> builderList = new LinkedList<>();
+        Client client = EsClient.INSTANCE.getClient();
+        dataMap.forEach((key, value) -> {
+            IndexRequestBuilder builder = client.prepareIndex(esIndex(), esType(), key).setSource(value.getSegmentStr());
+            builderList.add(builder);
+        });
+        EsClient.INSTANCE.bulk(builderList);
+        dataMap.clear();
+    }
 
+    @Override
+    final protected void prepareIndex(List<IndexRequestBuilder> builderList) {
+        Map<String, SegmentData> lastData = getPersistenceData().getLast().asMap();
+
+        Client client = EsClient.INSTANCE.getClient();
+        lastData.forEach((key, value) -> {
+            IndexRequestBuilder builder = client.prepareIndex(esIndex(), esType(), key).setSource(value.getSegmentStr());
+            builderList.add(builder);
+        });
+        lastData.clear();
+    }
+
+    public static class Factory extends AbstractLocalSyncWorkerProvider<SegmentSave> {
         @Override
         public Role role() {
             return Role.INSTANCE;
         }
 
         @Override
-        public int queueSize() {
-            return WorkerConfig.Queue.Segment.SegmentSave.SIZE;
-        }
-
-        @Override
         public SegmentSave workerInstance(ClusterWorkerContext clusterContext) {
-            return new SegmentSave(role(), clusterContext, new LocalWorkerContext());
+            SegmentSave worker = new SegmentSave(role(), clusterContext, new LocalWorkerContext());
+            PersistenceWorkerListener.INSTANCE.register(worker);
+            return worker;
         }
     }
 
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/persistence/SegmentTopSearchWithGlobalTraceId.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/persistence/SegmentTopSearchWithGlobalTraceId.java
index 7c5ad4e..3dc324d 100644
--- a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/persistence/SegmentTopSearchWithGlobalTraceId.java
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/persistence/SegmentTopSearchWithGlobalTraceId.java
@@ -7,12 +7,12 @@
 import com.a.eye.skywalking.collector.worker.segment.SegmentCostIndex;
 import com.a.eye.skywalking.collector.worker.segment.SegmentExceptionIndex;
 import com.a.eye.skywalking.collector.worker.segment.SegmentIndex;
-import com.a.eye.skywalking.collector.worker.segment.logic.Segment;
-import com.a.eye.skywalking.collector.worker.segment.logic.SegmentDeserialize;
+import com.a.eye.skywalking.collector.worker.segment.entity.GlobalTraceId;
+import com.a.eye.skywalking.collector.worker.segment.entity.Segment;
+import com.a.eye.skywalking.collector.worker.segment.entity.SegmentDeserialize;
 import com.a.eye.skywalking.collector.worker.storage.EsClient;
-import com.a.eye.skywalking.collector.worker.storage.MergeData;
+import com.a.eye.skywalking.collector.worker.storage.JoinAndSplitData;
 import com.a.eye.skywalking.collector.worker.tools.CollectionTools;
-import com.a.eye.skywalking.trace.TraceId.DistributedTraceId;
 import com.google.gson.Gson;
 import com.google.gson.JsonArray;
 import com.google.gson.JsonObject;
@@ -55,7 +55,7 @@
 
             if (globalTraceObj != null && globalTraceObj.has(GlobalTraceIndex.SUB_SEG_IDS)) {
                 String subSegIdsStr = globalTraceObj.get(GlobalTraceIndex.SUB_SEG_IDS).getAsString();
-                String[] subSegIds = subSegIdsStr.split(MergeData.SPLIT);
+                String[] subSegIds = subSegIdsStr.split(JoinAndSplitData.SPLIT);
 
                 topSegPaging.addProperty("recordsTotal", subSegIds.length);
 
@@ -81,12 +81,12 @@
                     topSegmentJson.addProperty(SegmentCostIndex.COST, (Number)getResponse.getSource().get(SegmentCostIndex.COST));
 
                     String segmentSource = client.prepareGet(SegmentIndex.INDEX, SegmentIndex.TYPE_RECORD, segId).get().getSourceAsString();
-                    Segment segment = SegmentDeserialize.INSTANCE.deserializeFromES(segmentSource);
-                    List<DistributedTraceId> distributedTraceIdList = segment.getRelatedGlobalTraces();
+                    Segment segment = SegmentDeserialize.INSTANCE.deserializeSingle(segmentSource);
+                    List<GlobalTraceId> distributedTraceIdList = segment.getRelatedGlobalTraces();
 
                     JsonArray distributedTraceIdArray = new JsonArray();
                     if (CollectionTools.isNotEmpty(distributedTraceIdList)) {
-                        for (DistributedTraceId distributedTraceId : distributedTraceIdList) {
+                        for (GlobalTraceId distributedTraceId : distributedTraceIdList) {
                             distributedTraceIdArray.add(distributedTraceId.get());
                         }
                     }
@@ -138,8 +138,6 @@
     }
 
     public static class Factory extends AbstractLocalSyncWorkerProvider<SegmentTopSearchWithGlobalTraceId> {
-        public static Factory INSTANCE = new Factory();
-
         @Override
         public Role role() {
             return WorkerRole.INSTANCE;
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/persistence/SegmentTopSearchWithTimeSlice.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/persistence/SegmentTopSearchWithTimeSlice.java
index 42f7c52..0dbdde6 100644
--- a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/persistence/SegmentTopSearchWithTimeSlice.java
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/segment/persistence/SegmentTopSearchWithTimeSlice.java
@@ -1,18 +1,24 @@
 package com.a.eye.skywalking.collector.worker.segment.persistence;
 
-import com.a.eye.skywalking.collector.actor.*;
+import com.a.eye.skywalking.collector.actor.AbstractLocalSyncWorker;
+import com.a.eye.skywalking.collector.actor.AbstractLocalSyncWorkerProvider;
+import com.a.eye.skywalking.collector.actor.ClusterWorkerContext;
+import com.a.eye.skywalking.collector.actor.LocalWorkerContext;
+import com.a.eye.skywalking.collector.actor.ProviderNotFoundException;
+import com.a.eye.skywalking.collector.actor.Role;
 import com.a.eye.skywalking.collector.actor.selector.RollingSelector;
 import com.a.eye.skywalking.collector.actor.selector.WorkerSelector;
 import com.a.eye.skywalking.collector.worker.segment.SegmentCostIndex;
 import com.a.eye.skywalking.collector.worker.segment.SegmentExceptionIndex;
 import com.a.eye.skywalking.collector.worker.segment.SegmentIndex;
-import com.a.eye.skywalking.collector.worker.segment.logic.Segment;
-import com.a.eye.skywalking.collector.worker.segment.logic.SegmentDeserialize;
+import com.a.eye.skywalking.collector.worker.segment.entity.GlobalTraceId;
+import com.a.eye.skywalking.collector.worker.segment.entity.Segment;
+import com.a.eye.skywalking.collector.worker.segment.entity.SegmentDeserialize;
 import com.a.eye.skywalking.collector.worker.storage.EsClient;
 import com.a.eye.skywalking.collector.worker.tools.CollectionTools;
-import com.a.eye.skywalking.trace.TraceId.DistributedTraceId;
 import com.google.gson.JsonArray;
 import com.google.gson.JsonObject;
+import java.util.List;
 import org.elasticsearch.action.search.SearchRequestBuilder;
 import org.elasticsearch.action.search.SearchResponse;
 import org.elasticsearch.action.search.SearchType;
@@ -22,8 +28,6 @@
 import org.elasticsearch.search.SearchHit;
 import org.elasticsearch.search.sort.SortOrder;
 
-import java.util.List;
-
 /**
  * @author pengys5
  */
@@ -88,12 +92,13 @@
                 topSegmentJson.addProperty(SegmentCostIndex.COST, (Number)searchHit.getSource().get(SegmentCostIndex.COST));
 
                 String segmentSource = EsClient.INSTANCE.getClient().prepareGet(SegmentIndex.INDEX, SegmentIndex.TYPE_RECORD, segId).get().getSourceAsString();
-                Segment segment = SegmentDeserialize.INSTANCE.deserializeFromES(segmentSource);
-                List<DistributedTraceId> distributedTraceIdList = segment.getRelatedGlobalTraces();
+                logger().debug("segmentSource:" + segmentSource);
+                Segment segment = SegmentDeserialize.INSTANCE.deserializeSingle(segmentSource);
+                List<GlobalTraceId> distributedTraceIdList = segment.getRelatedGlobalTraces();
 
                 JsonArray distributedTraceIdArray = new JsonArray();
                 if (CollectionTools.isNotEmpty(distributedTraceIdList)) {
-                    for (DistributedTraceId distributedTraceId : distributedTraceIdList) {
+                    for (GlobalTraceId distributedTraceId : distributedTraceIdList) {
                         distributedTraceIdArray.add(distributedTraceId.get());
                     }
                 }
@@ -168,8 +173,6 @@
     }
 
     public static class Factory extends AbstractLocalSyncWorkerProvider<SegmentTopSearchWithTimeSlice> {
-        public static Factory INSTANCE = new Factory();
-
         @Override
         public Role role() {
             return WorkerRole.INSTANCE;
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/span/SpanGetWithId.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/span/SpanGetWithId.java
index e7e174d..04001c4 100644
--- a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/span/SpanGetWithId.java
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/span/SpanGetWithId.java
@@ -48,8 +48,6 @@
     }
 
     public static class Factory extends AbstractGetProvider<SpanGetWithId> {
-        public static Factory INSTANCE = new Factory();
-
         @Override
         public Role role() {
             return WorkerRole.INSTANCE;
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/span/persistence/SpanSearchWithId.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/span/persistence/SpanSearchWithId.java
index 8bf3c7a..6e981c6 100644
--- a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/span/persistence/SpanSearchWithId.java
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/span/persistence/SpanSearchWithId.java
@@ -5,10 +5,10 @@
 import com.a.eye.skywalking.collector.actor.selector.WorkerSelector;
 import com.a.eye.skywalking.collector.worker.Const;
 import com.a.eye.skywalking.collector.worker.segment.SegmentIndex;
-import com.a.eye.skywalking.collector.worker.segment.logic.Segment;
-import com.a.eye.skywalking.collector.worker.segment.logic.SegmentDeserialize;
+import com.a.eye.skywalking.collector.worker.segment.entity.Segment;
+import com.a.eye.skywalking.collector.worker.segment.entity.SegmentDeserialize;
+import com.a.eye.skywalking.collector.worker.segment.entity.Span;
 import com.a.eye.skywalking.collector.worker.storage.GetResponseFromEs;
-import com.a.eye.skywalking.trace.Span;
 import com.google.gson.Gson;
 import com.google.gson.JsonObject;
 import org.elasticsearch.action.get.GetResponse;
@@ -31,7 +31,7 @@
         if (request instanceof RequestEntity) {
             RequestEntity search = (RequestEntity)request;
             GetResponse getResponse = GetResponseFromEs.INSTANCE.get(SegmentIndex.INDEX, SegmentIndex.TYPE_RECORD, search.segId);
-            Segment segment = SegmentDeserialize.INSTANCE.deserializeFromES(getResponse.getSourceAsString());
+            Segment segment = SegmentDeserialize.INSTANCE.deserializeSingle(getResponse.getSourceAsString());
             List<Span> spanList = segment.getSpans();
 
             getResponse.getSource();
@@ -39,6 +39,7 @@
 
             for (Span span : spanList) {
                 if (String.valueOf(span.getSpanId()).equals(search.spanId)) {
+                    span.setJsonStr("");
                     String spanJsonStr = gson.toJson(span);
                     dataJson = gson.fromJson(spanJsonStr, JsonObject.class);
                 }
@@ -68,8 +69,6 @@
     }
 
     public static class Factory extends AbstractLocalSyncWorkerProvider<SpanSearchWithId> {
-        public static Factory INSTANCE = new Factory();
-
         @Override
         public Role role() {
             return WorkerRole.INSTANCE;
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/storage/AbstractIndex.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/storage/AbstractIndex.java
index b949e18..130e178 100644
--- a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/storage/AbstractIndex.java
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/storage/AbstractIndex.java
@@ -30,12 +30,15 @@
 
     final XContentBuilder createSettingBuilder() throws IOException {
         return XContentFactory.jsonBuilder()
-            .startObject()
-            .field("index.number_of_shards", EsConfig.Es.Index.Shards.NUMBER)
-            .field("index.number_of_replicas", EsConfig.Es.Index.Replicas.NUMBER)
-            .endObject();
+                .startObject()
+                .field("index.number_of_shards", EsConfig.Es.Index.Shards.NUMBER)
+                .field("index.number_of_replicas", EsConfig.Es.Index.Replicas.NUMBER)
+                .field("index.refresh_interval", String.valueOf(refreshInterval()) + "s")
+                .endObject();
     }
 
+    public abstract int refreshInterval();
+
     public abstract boolean isRecord();
 
     public abstract XContentBuilder createMappingBuilder() throws IOException;
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/storage/Data.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/storage/Data.java
new file mode 100644
index 0000000..199221d
--- /dev/null
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/storage/Data.java
@@ -0,0 +1,12 @@
+package com.a.eye.skywalking.collector.worker.storage;
+
+import java.util.Map;
+
+/**
+ * @author pengys5
+ */
+public interface Data {
+    String getId();
+
+    void merge(Map<String, ?> dbData);
+}
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/storage/EsClient.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/storage/EsClient.java
index a50ed93..784ddd0 100644
--- a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/storage/EsClient.java
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/storage/EsClient.java
@@ -5,6 +5,9 @@
 import org.apache.logging.log4j.Logger;
 import org.elasticsearch.action.admin.indices.refresh.RefreshRequest;
 import org.elasticsearch.action.admin.indices.refresh.RefreshResponse;
+import org.elasticsearch.action.bulk.BulkRequestBuilder;
+import org.elasticsearch.action.bulk.BulkResponse;
+import org.elasticsearch.action.index.IndexRequestBuilder;
 import org.elasticsearch.client.Client;
 import org.elasticsearch.common.settings.Settings;
 import org.elasticsearch.common.transport.InetSocketTransportAddress;
@@ -77,4 +80,21 @@
             this.port = port;
         }
     }
+
+    public void bulk(List<IndexRequestBuilder> dataList) {
+        Client client = EsClient.INSTANCE.getClient();
+        BulkRequestBuilder bulkRequest = client.prepareBulk();
+
+        logger.info("bulk data size: %s", dataList.size());
+        if (dataList.size() > 0) {
+            for (IndexRequestBuilder builder : dataList) {
+                bulkRequest.add(builder);
+            }
+
+            BulkResponse bulkResponse = bulkRequest.execute().actionGet();
+            if (bulkResponse.hasFailures()) {
+                logger.error(bulkResponse.buildFailureMessage());
+            }
+        }
+    }
 }
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/storage/FlushAndSwitch.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/storage/FlushAndSwitch.java
new file mode 100644
index 0000000..7b24bb6
--- /dev/null
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/storage/FlushAndSwitch.java
@@ -0,0 +1,7 @@
+package com.a.eye.skywalking.collector.worker.storage;
+
+/**
+ * @author pengys5
+ */
+public class FlushAndSwitch {
+}
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/storage/JoinAndSplitAnalysisData.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/storage/JoinAndSplitAnalysisData.java
new file mode 100644
index 0000000..9c4a966
--- /dev/null
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/storage/JoinAndSplitAnalysisData.java
@@ -0,0 +1,23 @@
+package com.a.eye.skywalking.collector.worker.storage;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+/**
+ * @author pengys5
+ */
+public class JoinAndSplitAnalysisData {
+
+    private WindowData<JoinAndSplitData> windowData = new WindowData(new LinkedHashMap<String, JoinAndSplitData>());
+
+    public JoinAndSplitData getOrCreate(String id) {
+        if (!windowData.containsKey(id)) {
+            windowData.put(id, new JoinAndSplitData(id));
+        }
+        return windowData.get(id);
+    }
+
+    public Map<String, JoinAndSplitData> asMap() {
+        return windowData.asMap();
+    }
+}
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/storage/JoinAndSplitData.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/storage/JoinAndSplitData.java
new file mode 100644
index 0000000..c78db64
--- /dev/null
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/storage/JoinAndSplitData.java
@@ -0,0 +1,70 @@
+package com.a.eye.skywalking.collector.worker.storage;
+
+import com.a.eye.skywalking.collector.actor.selector.AbstractHashMessage;
+
+import java.util.*;
+
+/**
+ * @author pengys5
+ */
+public class JoinAndSplitData extends AbstractHashMessage implements Data {
+
+    public static final String SPLIT = ",";
+
+    private String id;
+
+    private Map<String, Set<String>> data = new HashMap<>();
+
+    public JoinAndSplitData(String key) {
+        super(key);
+        this.id = key;
+    }
+
+    public String getId() {
+        return id;
+    }
+
+    public void set(String attributeName, String value) {
+        if (!data.containsKey(attributeName)) {
+            data.put(attributeName, new HashSet<>());
+        }
+        data.get(attributeName).add(value);
+    }
+
+    public void merge(JoinAndSplitData source) {
+        source.data.forEach((attributeName, valueSet) -> valueSet.forEach(value -> set(attributeName, value)));
+    }
+
+    public void merge(Map<String, ?> source) {
+        source.forEach((column, dbValue) -> {
+            if (!AbstractIndex.TIME_SLICE.equals(column) && !AbstractIndex.AGG_COLUMN.equals(column)) {
+                String[] dbValues = String.valueOf(dbValue).split(SPLIT);
+                for (String value : dbValues) {
+                    set(column, value);
+                }
+            }
+        });
+    }
+
+    public Map<String, String> asMap() {
+        Map<String, String> source = new HashMap<>();
+        data.forEach((attributeName, valueSet) -> {
+            Iterator<String> iterator = valueSet.iterator();
+            StringBuilder builder = new StringBuilder();
+
+            int i = 0;
+
+            while (iterator.hasNext()) {
+                if (i == 0) {
+                    builder.append(iterator.next());
+                } else {
+                    builder.append(SPLIT).append(iterator.next());
+                }
+                i++;
+            }
+            source.put(attributeName, builder.toString());
+        });
+
+        return source;
+    }
+}
\ No newline at end of file
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/storage/JoinAndSplitPersistenceData.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/storage/JoinAndSplitPersistenceData.java
new file mode 100644
index 0000000..00f8082
--- /dev/null
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/storage/JoinAndSplitPersistenceData.java
@@ -0,0 +1,25 @@
+package com.a.eye.skywalking.collector.worker.storage;
+
+/**
+ * @author pengys5
+ */
+public class JoinAndSplitPersistenceData extends Window<JoinAndSplitData> implements PersistenceData<JoinAndSplitData> {
+
+    private WindowData<JoinAndSplitData> lockedWindowData;
+
+    public JoinAndSplitData getOrCreate(String id) {
+        if (!lockedWindowData.containsKey(id)) {
+            lockedWindowData.put(id, new JoinAndSplitData(id));
+        }
+        return lockedWindowData.get(id);
+    }
+
+    public void hold() {
+        lockedWindowData = getCurrentAndHold();
+    }
+
+    public void release() {
+        lockedWindowData.release();
+        lockedWindowData = null;
+    }
+}
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/storage/MergeData.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/storage/MergeData.java
deleted file mode 100644
index 3752616..0000000
--- a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/storage/MergeData.java
+++ /dev/null
@@ -1,81 +0,0 @@
-package com.a.eye.skywalking.collector.worker.storage;
-
-import com.a.eye.skywalking.collector.actor.selector.AbstractHashMessage;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * @author pengys5
- */
-public class MergeData extends AbstractHashMessage {
-    public static final String SPLIT = ",";
-
-    private String id;
-
-    private Map<String, Set<String>> mergeData = new HashMap<>();
-
-    public MergeData(String key) {
-        super(key);
-        this.id = key;
-    }
-
-    public String getId() {
-        return id;
-    }
-
-    public void setMergeData(String column, String value) {
-        if (!mergeData.containsKey(column)) {
-            mergeData.put(column, new HashSet<>());
-        }
-        mergeData.get(column).add(value);
-    }
-
-    public void merge(MergeData data) {
-        for (Map.Entry<String, Set<String>> entry : data.mergeData.entrySet()) {
-            String column = entry.getKey();
-            Set<String> value = entry.getValue();
-            Iterator<String> iterator = value.iterator();
-            while (iterator.hasNext()) {
-                setMergeData(column, iterator.next());
-            }
-        }
-    }
-
-    public void merge(Map<String, Object> dbData) {
-        for (Map.Entry<String, Object> entry : dbData.entrySet()) {
-            if (!AbstractIndex.TIME_SLICE.equals(entry.getKey())
-                && !AbstractIndex.AGG_COLUMN.equals(entry.getKey())) {
-                String dbValue = String.valueOf(entry.getValue());
-                String[] dbValues = dbValue.split(SPLIT);
-                for (String value : dbValues) {
-                    setMergeData(entry.getKey(), value);
-                }
-            }
-        }
-    }
-
-    public Map<String, String> toMap() {
-        Map<String, String> source = new HashMap<>();
-        for (Map.Entry<String, Set<String>> entry : mergeData.entrySet()) {
-            String column = entry.getKey();
-            Iterator<String> iterator = entry.getValue().iterator();
-            StringBuffer value = new StringBuffer();
-
-            int i = 0;
-            while (iterator.hasNext()) {
-                if (i == 0) {
-                    value.append(iterator.next());
-                } else {
-                    value.append(SPLIT).append(iterator.next());
-                }
-                i++;
-            }
-            source.put(column, value.toString());
-        }
-
-        return source;
-    }
-}
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/storage/MergePersistenceData.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/storage/MergePersistenceData.java
deleted file mode 100644
index 4a5ccec..0000000
--- a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/storage/MergePersistenceData.java
+++ /dev/null
@@ -1,51 +0,0 @@
-package com.a.eye.skywalking.collector.worker.storage;
-
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Spliterator;
-import java.util.function.Consumer;
-
-/**
- * @author pengys5
- */
-public class MergePersistenceData implements Iterable {
-
-    private Map<String, MergeData> persistenceData = new HashMap<>();
-
-    public MergeData getElseCreate(String id) {
-        if (!persistenceData.containsKey(id)) {
-            persistenceData.put(id, new MergeData(id));
-        }
-        return persistenceData.get(id);
-    }
-
-    public int size() {
-        return persistenceData.size();
-    }
-
-    public void clear() {
-        persistenceData.clear();
-    }
-
-    public MergeData pushOne() {
-        MergeData one = persistenceData.entrySet().iterator().next().getValue();
-        persistenceData.remove(one.getId());
-        return one;
-    }
-
-    @Override
-    public void forEach(Consumer action) {
-        throw new UnsupportedOperationException("forEach");
-    }
-
-    @Override
-    public Spliterator spliterator() {
-        throw new UnsupportedOperationException("spliterator");
-    }
-
-    @Override
-    public Iterator<Map.Entry<String, MergeData>> iterator() {
-        return persistenceData.entrySet().iterator();
-    }
-}
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/storage/MetricAnalysisData.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/storage/MetricAnalysisData.java
new file mode 100644
index 0000000..394302f
--- /dev/null
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/storage/MetricAnalysisData.java
@@ -0,0 +1,23 @@
+package com.a.eye.skywalking.collector.worker.storage;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+/**
+ * @author pengys5
+ */
+public class MetricAnalysisData {
+
+    private WindowData<MetricData> windowData = new WindowData(new LinkedHashMap<String, MetricData>());
+
+    public MetricData getOrCreate(String id) {
+        if (!windowData.containsKey(id)) {
+            windowData.put(id, new MetricData(id));
+        }
+        return windowData.get(id);
+    }
+
+    public Map<String, MetricData> asMap() {
+        return windowData.asMap();
+    }
+}
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/storage/MetricData.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/storage/MetricData.java
index d10cc51..ea9a291 100644
--- a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/storage/MetricData.java
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/storage/MetricData.java
@@ -3,70 +3,69 @@
 import com.a.eye.skywalking.collector.actor.selector.AbstractHashMessage;
 import com.a.eye.skywalking.collector.worker.Const;
 
-import java.util.HashMap;
+import java.util.LinkedHashMap;
 import java.util.Map;
 
 /**
  * @author pengys5
  */
-public class MetricData extends AbstractHashMessage {
+public class MetricData extends AbstractHashMessage implements Data {
 
     private String id;
-    private Map<String, Object> value;
+    private Map<String, Object> data;
 
     public MetricData(String id) {
         super(id);
         this.id = id;
-        value = new HashMap<>();
+        data = new LinkedHashMap<>();
 
         String[] ids = id.split(Const.IDS_SPLIT);
         String slice = ids[0];
-        String aggId = "";
+        StringBuilder aggId = new StringBuilder();
         for (int i = 1; i < ids.length; i++) {
-            if (i == 1) {
-                aggId = ids[i];
-            } else {
-                aggId = aggId + Const.ID_SPLIT + ids[i];
-            }
+            if (i == 1) aggId = new StringBuilder(ids[i]);
+            else aggId.append(Const.ID_SPLIT).append(ids[i]);
         }
 
-        value.put(AbstractIndex.TIME_SLICE, Long.valueOf(slice));
-        value.put(AbstractIndex.AGG_COLUMN, aggId);
+        data.put(AbstractIndex.TIME_SLICE, Long.valueOf(slice));
+        data.put(AbstractIndex.AGG_COLUMN, aggId.toString());
     }
 
-    public void setMetric(String column, Long value) {
+    public void set(String metricName, Long value) {
         long valueAdd = value;
-        if (this.value.containsKey(column) && !AbstractIndex.TIME_SLICE.equals(column)
-            && !AbstractIndex.AGG_COLUMN.equals(column)) {
-            valueAdd += (Long)this.value.get(column);
+        if (this.data.containsKey(metricName) && !AbstractIndex.TIME_SLICE.equals(metricName)
+                && !AbstractIndex.AGG_COLUMN.equals(metricName)) {
+            valueAdd += (Long) this.data.get(metricName);
         }
-        this.value.put(column, valueAdd);
+        this.data.put(metricName, valueAdd);
     }
 
-    public void merge(MetricData metricData) {
-        for (Map.Entry<String, Object> entry : metricData.value.entrySet()) {
+    public void merge(MetricData source) {
+        for (Map.Entry<String, Object> entry : source.data.entrySet()) {
             if (!AbstractIndex.TIME_SLICE.equals(entry.getKey())
-                && !AbstractIndex.AGG_COLUMN.equals(entry.getKey())) {
-                setMetric(entry.getKey(), (Long)entry.getValue());
+                    && !AbstractIndex.AGG_COLUMN.equals(entry.getKey())) {
+                set(entry.getKey(), (Long) entry.getValue());
             }
         }
     }
 
-    public void merge(Map<String, Object> dbData) {
-        for (Map.Entry<String, Object> entry : dbData.entrySet()) {
+    @Override
+    public void merge(Map<String, ?> source) {
+        for (Map.Entry<String, ?> entry : source.entrySet()) {
             if (!AbstractIndex.TIME_SLICE.equals(entry.getKey())
-                && !AbstractIndex.AGG_COLUMN.equals(entry.getKey())) {
-                long dbValue = ((Number)entry.getValue()).longValue();
-                setMetric(entry.getKey(), dbValue);
+                    && !AbstractIndex.AGG_COLUMN.equals(entry.getKey())) {
+                long dbValue = ((Number) entry.getValue()).longValue();
+                set(entry.getKey(), dbValue);
             }
         }
     }
 
-    public Map<String, Object> toMap() {
-        return value;
-    }
-
+    @Override
     public String getId() {
         return id;
     }
+
+    public Map<String, Object> asMap() {
+        return data;
+    }
 }
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/storage/MetricPersistenceData.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/storage/MetricPersistenceData.java
index 23aa830..e8ed10b 100644
--- a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/storage/MetricPersistenceData.java
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/storage/MetricPersistenceData.java
@@ -1,45 +1,25 @@
 package com.a.eye.skywalking.collector.worker.storage;
 
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Spliterator;
-
 /**
  * @author pengys5
  */
-public class MetricPersistenceData implements Iterable {
+public class MetricPersistenceData extends Window<MetricData> implements PersistenceData<MetricData> {
 
-    private Map<String, MetricData> persistenceData = new HashMap<>();
+    private WindowData<MetricData> lockedWindowData;
 
-    public MetricData getElseCreate(String id) {
-        if (!persistenceData.containsKey(id)) {
-            persistenceData.put(id, new MetricData(id));
+    public MetricData getOrCreate(String id) {
+        if (!lockedWindowData.containsKey(id)) {
+            lockedWindowData.put(id, new MetricData(id));
         }
-        return persistenceData.get(id);
+        return lockedWindowData.get(id);
     }
 
-    public int size() {
-        return persistenceData.size();
+    public void hold() {
+        lockedWindowData = getCurrentAndHold();
     }
 
-    public void clear() {
-        persistenceData.clear();
-    }
-
-    public MetricData pushOne() {
-        MetricData one = persistenceData.entrySet().iterator().next().getValue();
-        persistenceData.remove(one.getId());
-        return one;
-    }
-
-    @Override
-    public Spliterator spliterator() {
-        throw new UnsupportedOperationException("spliterator");
-    }
-
-    @Override
-    public Iterator<Map.Entry<String, MetricData>> iterator() {
-        return persistenceData.entrySet().iterator();
+    public void release() {
+        lockedWindowData.release();
+        lockedWindowData = null;
     }
 }
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/storage/PersistenceData.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/storage/PersistenceData.java
new file mode 100644
index 0000000..f73f836
--- /dev/null
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/storage/PersistenceData.java
@@ -0,0 +1,13 @@
+package com.a.eye.skywalking.collector.worker.storage;
+
+/**
+ * @author pengys5
+ */
+public interface PersistenceData<T extends Data> {
+
+    T getOrCreate(String id);
+
+    void release();
+
+    void hold();
+}
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/storage/PersistenceTimer.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/storage/PersistenceTimer.java
new file mode 100644
index 0000000..a3c0072
--- /dev/null
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/storage/PersistenceTimer.java
@@ -0,0 +1,54 @@
+package com.a.eye.skywalking.collector.worker.storage;
+
+import com.a.eye.skywalking.collector.actor.AbstractLocalSyncWorker;
+import com.a.eye.skywalking.collector.worker.config.EsConfig;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.message.StringFormattedMessage;
+import org.elasticsearch.action.index.IndexRequestBuilder;
+
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * @author pengys5
+ */
+public enum PersistenceTimer {
+    INSTANCE;
+
+    private Logger logger = LogManager.getFormatterLogger(PersistenceTimer.class);
+
+    public void boot() {
+        logger.info("persistence timer start");
+        final long timeInterval = EsConfig.Es.Persistence.Timer.VALUE * 1000;
+
+        Runnable runnable = () -> {
+            while (true) {
+                try {
+                    extractDataAndSave();
+                    Thread.sleep(timeInterval);
+                } catch (Throwable e) {
+                    logger.error(e);
+                }
+            }
+        };
+        Thread persistenceThread = new Thread(runnable);
+        persistenceThread.setName("timerPersistence");
+        persistenceThread.start();
+    }
+
+    private void extractDataAndSave() {
+        List<IndexRequestBuilder> dataList = new LinkedList<>();
+
+        List<AbstractLocalSyncWorker> workers = PersistenceWorkerListener.INSTANCE.getWorkers();
+        for (AbstractLocalSyncWorker worker : workers) {
+            logger.info("worker role name: %s", worker.getRole().roleName());
+            try {
+                worker.allocateJob(new FlushAndSwitch(), dataList);
+            } catch (Exception e) {
+                logger.error(new StringFormattedMessage("flush persistence worker data error, worker role name: %s", worker.getRole().roleName()), e);
+            }
+        }
+        EsClient.INSTANCE.bulk(dataList);
+    }
+}
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/storage/PersistenceWorkerListener.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/storage/PersistenceWorkerListener.java
new file mode 100644
index 0000000..e686428
--- /dev/null
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/storage/PersistenceWorkerListener.java
@@ -0,0 +1,26 @@
+package com.a.eye.skywalking.collector.worker.storage;
+
+import com.a.eye.skywalking.collector.actor.AbstractLocalSyncWorker;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * @author pengys5
+ */
+public enum PersistenceWorkerListener {
+    INSTANCE;
+
+    private List<AbstractLocalSyncWorker> workers = new LinkedList<>();
+
+    public void register(AbstractLocalSyncWorker worker) {
+        workers.add(worker);
+    }
+
+    public List<AbstractLocalSyncWorker> getWorkers() {
+        return workers;
+    }
+
+    public void reset() {
+        workers.clear();
+    }
+}
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/storage/RecordAnalysisData.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/storage/RecordAnalysisData.java
new file mode 100644
index 0000000..aa96482
--- /dev/null
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/storage/RecordAnalysisData.java
@@ -0,0 +1,23 @@
+package com.a.eye.skywalking.collector.worker.storage;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+/**
+ * @author pengys5
+ */
+public class RecordAnalysisData {
+
+    private WindowData<RecordData> windowData = new WindowData(new LinkedHashMap<String, RecordData>());
+
+    public RecordData getOrCreate(String id) {
+        if (!windowData.containsKey(id)) {
+            windowData.put(id, new RecordData(id));
+        }
+        return windowData.get(id);
+    }
+
+    public Map<String, RecordData> asMap() {
+        return windowData.asMap();
+    }
+}
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/storage/RecordData.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/storage/RecordData.java
index f4b8f22..f326358 100644
--- a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/storage/RecordData.java
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/storage/RecordData.java
@@ -4,39 +4,45 @@
 import com.a.eye.skywalking.collector.worker.Const;
 import com.google.gson.JsonObject;
 
+import java.util.Map;
+
 /**
  * @author pengys5
  */
-public class RecordData extends AbstractHashMessage {
+public class RecordData extends AbstractHashMessage implements Data {
 
     private String id;
     private String aggId;
-    private JsonObject record;
+    private JsonObject data;
 
-    public RecordData(String key) {
-        super(key);
-        this.id = key;
-        String[] ids = id.split(Const.IDS_SPLIT);
+    public RecordData(String id) {
+        super(id);
+        this.id = id;
+        String[] ids = this.id.split(Const.IDS_SPLIT);
         for (int i = 1; i < ids.length; i++) {
             if (i == 1) {
                 this.aggId = ids[i];
             } else {
-                this.aggId = this.aggId + Const.ID_SPLIT + ids[i];
+                this.aggId += Const.ID_SPLIT + ids[i];
             }
         }
-        record = new JsonObject();
+        data = new JsonObject();
     }
 
     public String getId() {
         return id;
     }
 
-    public JsonObject getRecord() {
-        record.addProperty(AbstractIndex.AGG_COLUMN, this.aggId);
-        return record;
+    public JsonObject get() {
+        data.addProperty(AbstractIndex.AGG_COLUMN, this.aggId);
+        return data;
     }
 
-    public void setRecord(JsonObject record) {
-        this.record = record;
+    public void set(JsonObject record) {
+        this.data = record;
+    }
+
+    @Override
+    public void merge(Map<String, ?> source) {
     }
 }
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/storage/RecordPersistenceData.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/storage/RecordPersistenceData.java
index cfcf545..9d48908 100644
--- a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/storage/RecordPersistenceData.java
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/storage/RecordPersistenceData.java
@@ -1,55 +1,25 @@
 package com.a.eye.skywalking.collector.worker.storage;
 
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Spliterator;
-import java.util.function.Consumer;
-
 /**
  * @author pengys5
  */
-public class RecordPersistenceData implements Iterable {
+public class RecordPersistenceData extends Window<RecordData> implements PersistenceData<RecordData> {
 
-    private Map<String, RecordData> persistenceData = new HashMap();
+    private WindowData<RecordData> lockedWindowData;
 
-    public RecordData getElseCreate(String id) {
-        if (!persistenceData.containsKey(id)) {
-            persistenceData.put(id, new RecordData(id));
+    public RecordData getOrCreate(String id) {
+        if (!lockedWindowData.containsKey(id)) {
+            lockedWindowData.put(id, new RecordData(id));
         }
-        return persistenceData.get(id);
+        return lockedWindowData.get(id);
     }
 
-    public int size() {
-        return persistenceData.size();
+    public void hold() {
+        lockedWindowData = getCurrentAndHold();
     }
 
-    public void clear() {
-        persistenceData.clear();
-    }
-
-    public boolean hasNext() {
-        return persistenceData.entrySet().iterator().hasNext();
-    }
-
-    public RecordData pushOne() {
-        RecordData one = persistenceData.entrySet().iterator().next().getValue();
-        persistenceData.remove(one.getId());
-        return one;
-    }
-
-    @Override
-    public void forEach(Consumer action) {
-        throw new UnsupportedOperationException("forEach");
-    }
-
-    @Override
-    public Spliterator spliterator() {
-        throw new UnsupportedOperationException("spliterator");
-    }
-
-    @Override
-    public Iterator<Map.Entry<String, RecordData>> iterator() {
-        return persistenceData.entrySet().iterator();
+    public void release() {
+        lockedWindowData.release();
+        lockedWindowData = null;
     }
 }
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/storage/SegmentData.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/storage/SegmentData.java
new file mode 100644
index 0000000..79dfb61
--- /dev/null
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/storage/SegmentData.java
@@ -0,0 +1,32 @@
+package com.a.eye.skywalking.collector.worker.storage;
+
+import java.util.Map;
+
+/**
+ * @author pengys5
+ */
+public class SegmentData implements Data {
+
+    private String id;
+    private String segmentStr;
+
+    public SegmentData(String id) {
+        this.id = id;
+    }
+
+    public String getId() {
+        return id;
+    }
+
+    @Override
+    public void merge(Map<String, ?> source) {
+    }
+
+    public String getSegmentStr() {
+        return segmentStr;
+    }
+
+    public void setSegmentStr(String segmentStr) {
+        this.segmentStr = segmentStr;
+    }
+}
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/storage/SegmentPersistenceData.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/storage/SegmentPersistenceData.java
new file mode 100644
index 0000000..2934a48
--- /dev/null
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/storage/SegmentPersistenceData.java
@@ -0,0 +1,35 @@
+package com.a.eye.skywalking.collector.worker.storage;
+
+import java.util.Map;
+
+/**
+ * @author pengys5
+ */
+public class SegmentPersistenceData extends Window<SegmentData> implements PersistenceData<SegmentData> {
+
+    private WindowData<SegmentData> lockedWindowData;
+
+    public SegmentData getOrCreate(String id) {
+        if (!lockedWindowData.containsKey(id)) {
+            lockedWindowData.put(id, new SegmentData(id));
+        }
+        return lockedWindowData.get(id);
+    }
+
+    public void hold() {
+        lockedWindowData = getCurrentAndHold();
+    }
+
+    public void release() {
+        lockedWindowData.release();
+        lockedWindowData = null;
+    }
+
+    public int size() {
+        return lockedWindowData.size();
+    }
+
+    public Map<String, SegmentData> asMap() {
+        return lockedWindowData.asMap();
+    }
+}
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/storage/Window.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/storage/Window.java
new file mode 100644
index 0000000..615dbc1
--- /dev/null
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/storage/Window.java
@@ -0,0 +1,46 @@
+package com.a.eye.skywalking.collector.worker.storage;
+
+import java.util.HashMap;
+
+/**
+ * @author pengys5
+ */
+public abstract class Window<T extends Data> {
+
+    private WindowData<T> pointer;
+
+    private WindowData<T> windowDataA;
+    private WindowData<T> windowDataB;
+
+    public Window() {
+        windowDataA = new WindowData(new HashMap<>());
+        windowDataB = new WindowData(new HashMap<>());
+        pointer = windowDataA;
+    }
+
+    public void switchPointer() {
+        if (pointer == windowDataA) {
+            pointer = windowDataB;
+        } else {
+            pointer = windowDataA;
+        }
+    }
+
+    protected WindowData<T> getCurrentAndHold() {
+        if (pointer == windowDataA) {
+            windowDataA.hold();
+            return windowDataA;
+        } else {
+            windowDataB.hold();
+            return windowDataB;
+        }
+    }
+
+    public WindowData<T> getLast() {
+        if (pointer == windowDataA) {
+            return windowDataB;
+        } else {
+            return windowDataA;
+        }
+    }
+}
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/storage/WindowData.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/storage/WindowData.java
new file mode 100644
index 0000000..f630654
--- /dev/null
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/storage/WindowData.java
@@ -0,0 +1,52 @@
+package com.a.eye.skywalking.collector.worker.storage;
+
+import java.util.Map;
+
+/**
+ * @author pengys5
+ */
+public class WindowData<T extends Data> {
+    private Map<String, T> data;
+    private volatile boolean isHold;
+
+    WindowData(Map<String, T> data) {
+        this.data = data;
+        this.isHold = false;
+    }
+
+    public void release() {
+        isHold = false;
+    }
+
+    public void hold() {
+        isHold = true;
+    }
+
+    public boolean isHolding() {
+        return isHold;
+    }
+
+    public boolean containsKey(String key) {
+        return data.containsKey(key);
+    }
+
+    public void put(String key, T value) {
+        data.put(key, value);
+    }
+
+    public T get(String key) {
+        return data.get(key);
+    }
+
+    public int size() {
+        return data.size();
+    }
+
+    public void clear() {
+        data.clear();
+    }
+
+    public Map<String, T> asMap() {
+        return data;
+    }
+}
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/tools/ClientSpanIsLeafTools.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/tools/ClientSpanIsLeafTools.java
index 0727ffc..c071ac8 100644
--- a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/tools/ClientSpanIsLeafTools.java
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/tools/ClientSpanIsLeafTools.java
@@ -1,7 +1,7 @@
 package com.a.eye.skywalking.collector.worker.tools;
 
-import com.a.eye.skywalking.trace.Span;
-import com.a.eye.skywalking.trace.tag.Tags;
+import com.a.eye.skywalking.collector.worker.segment.entity.Span;
+import com.a.eye.skywalking.collector.worker.segment.entity.tag.Tags;
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
 
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/tools/SpanPeersTools.java b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/tools/SpanPeersTools.java
index 439684a..5e3cb3a 100644
--- a/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/tools/SpanPeersTools.java
+++ b/skywalking-collector/skywalking-collector-worker/src/main/java/com/a/eye/skywalking/collector/worker/tools/SpanPeersTools.java
@@ -2,8 +2,8 @@
 
 import com.a.eye.skywalking.api.util.StringUtil;
 import com.a.eye.skywalking.collector.worker.Const;
-import com.a.eye.skywalking.trace.Span;
-import com.a.eye.skywalking.trace.tag.Tags;
+import com.a.eye.skywalking.collector.worker.segment.entity.Span;
+import com.a.eye.skywalking.collector.worker.segment.entity.tag.Tags;
 
 /**
  * @author pengys5
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/resources/META-INF/services/com.a.eye.skywalking.collector.actor.AbstractLocalWorkerProvider b/skywalking-collector/skywalking-collector-worker/src/main/resources/META-INF/services/com.a.eye.skywalking.collector.actor.AbstractLocalWorkerProvider
index 30b0397..b6e1772 100644
--- a/skywalking-collector/skywalking-collector-worker/src/main/resources/META-INF/services/com.a.eye.skywalking.collector.actor.AbstractLocalWorkerProvider
+++ b/skywalking-collector/skywalking-collector-worker/src/main/resources/META-INF/services/com.a.eye.skywalking.collector.actor.AbstractLocalWorkerProvider
@@ -1,3 +1,7 @@
+com.a.eye.skywalking.collector.worker.segment.analysis.SegmentAnalysis$Factory
+com.a.eye.skywalking.collector.worker.segment.analysis.SegmentCostAnalysis$Factory
+com.a.eye.skywalking.collector.worker.segment.analysis.SegmentExceptionAnalysis$Factory
+
 com.a.eye.skywalking.collector.worker.segment.persistence.SegmentSave$Factory
 com.a.eye.skywalking.collector.worker.segment.persistence.SegmentCostSave$Factory
 com.a.eye.skywalking.collector.worker.segment.persistence.SegmentExceptionSave$Factory
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/resources/collector.config b/skywalking-collector/skywalking-collector-worker/src/main/resources/collector.config
index dfe77c6..51586ef 100644
--- a/skywalking-collector/skywalking-collector-worker/src/main/resources/collector.config
+++ b/skywalking-collector/skywalking-collector-worker/src/main/resources/collector.config
@@ -1,15 +1,11 @@
-# The remote server should connect to, hostname can be either hostname or IP address.
-# Suggestion: set the real ip address.
+# "hostname" and "port" are used to receive internal messages from other nodes of cluster。
+# Hostname can be either hostname or IP address.
 cluster.current.hostname=127.0.0.1
+# Listening port.
 cluster.current.port=11800
 
-# The roles of this member. List of strings, e.g. roles = A, B
-# In the future, the roles are part of the membership information and can be used by
-# routers or other services to distribute work to certain member types,
-# e.g. front-end and back-end nodes.
-# In this version, all members has same roles, each of them will listen others status,
-# because of network trouble or member jvm crash or every reason led to not reachable,
-# the routers will stop to sending the message to the untouchable member.
+# In this version, all members have same roles, and everyone of them is listening the status of others.
+# The routers do not send message to nodes, which is unreachable, caused by network trouble, jvm crash or any other reasons.
 cluster.current.roles=WorkersListener
 
 # Initial contact points of the cluster, e.g. seed_nodes = 127.0.0.1:11800, 127.0.0.1:11801.
@@ -19,77 +15,32 @@
 # This is akka configuration, see: http://doc.akka.io/docs/akka/2.4/general/configuration.html
 cluster.seed_nodes=127.0.0.1:11800
 
-# elasticsearch configuration, config/elasticsearch.yml, see cluster.name
+# elasticsearch configuration, see cluster.name in "config/elasticsearch.yml"
 es.cluster.name=CollectorDBCluster
 es.cluster.transport.sniffer=true
 
-# The elasticsearch nodes of cluster, comma separated, e.g. nodes=ip:port, ip:port
+# The elasticsearch nodes of cluster, separated by comma, e.g. nodes=ip:port, ip:port
 es.cluster.nodes=127.0.0.1:9300
 
-# Automatic create elasticsearch index
+# Initialized mode of elasticsearch index, default is auto.
 # Options: auto, forced, manual
-# auto: just create new index when index not created.
-# forced: delete the index then create
-es.index.initialize.mode=auto
+# auto: create index when it doesn't exist.
+# forced: delete and create.
+# manual: do nothing.
+es.index.initialize.mode=forced
+# Config of shards or replicas in Elasticsearch.
 es.index.shards.number=2
 es.index.replicas.number=0
 
-# You can configure a host either as a host name or IP address to identify a specific network
-# interface on which to listen.
-# Be used for web ui get the view data or agent post the trace segment.
+# "hostname", "port" and "contextPath" are used to provide HTTP RESTful services.
+# RESTful services include "receive segment" and "webui query services".
 http.hostname=127.0.0.1
-# The TCP/IP port on which the connector listens for connections.
 http.port=12800
-# The contextPath is a URL prefix that identifies which context a HTTP request is destined for.
+# Web context path
 http.contextPath=/
 
-# The analysis worker max cache size, when worker data size reach the size,
-# then worker will send all cached data to the next worker and clear the cache.
+# Cache size of analysis worker. The value determines whether sending to next worker and clear, or not.
 cache.analysis.size=1024
-# The persistence worker max cache size, same of "cache.analysis.size" ability.
-cache.persistence.size=1024
-
-WorkerNum.Node.NodeCompAgg.Value=10
-WorkerNum.Node.NodeMappingDayAgg.Value=10
-WorkerNum.Node.NodeMappingHourAgg.Value=10
-WorkerNum.Node.NodeMappingMinuteAgg.Value=10
-
-WorkerNum.NodeRef.NodeRefDayAgg.Value=10
-WorkerNum.NodeRef.NodeRefHourAgg.Value=10
-WorkerNum.NodeRef.NodeRefMinuteAgg.Value=10
-WorkerNum.NodeRef.NodeRefResSumDayAgg.Value=10
-WorkerNum.NodeRef.NodeRefResSumHourAgg.Value=10
-WorkerNum.NodeRef.NodeRefResSumMinuteAgg.Value=10
-
-WorkerNum.GlobalTrace.GlobalTraceAgg.Value=10
-
-Queue.GlobalTrace.GlobalTraceSave.Size=1024
-Queue.GlobalTrace.GlobalTraceAnalysis.Size=1024
-
-Queue.Segment.SegmentPost.Size=1024
-Queue.Segment.SegmentCostSave.Size=1024
-Queue.Segment.SegmentSave.Size=1024
-Queue.Segment.SegmentExceptionSave.Size=1024
-
-Queue.Node.NodeCompAnalysis.Size=1024
-Queue.Node.NodeMappingDayAnalysis.Size=1024
-Queue.Node.NodeMappingHourAnalysis.Size=1024
-Queue.Node.NodeMappingMinuteAnalysis.Size=1024
-Queue.Node.NodeCompSave.Size=1024
-Queue.Node.NodeMappingDaySave.Size=1024
-Queue.Node.NodeMappingHourSave.Size=1024
-Queue.Node.NodeMappingMinuteSave.Size=1024
-
-Queue.NodeRef.NodeRefDayAnalysis.Size=1024
-Queue.NodeRef.NodeRefHourAnalysis.Size=1024
-Queue.NodeRef.NodeRefMinuteAnalysis.Size=1024
-Queue.NodeRef.NodeRefDaySave.Size=1024
-Queue.NodeRef.NodeRefHourSave.Size=1024
-Queue.NodeRef.NodeRefMinuteSave.Size=1024
-Queue.NodeRef.NodeRefResSumDaySave.Size=1024
-Queue.NodeRef.NodeRefResSumHourSave.Size=1024
-Queue.NodeRef.NodeRefResSumMinuteSave.Size=1024
-Queue.NodeRef.NodeRefResSumDayAnalysis.Size=1024
-Queue.NodeRef.NodeRefResSumHourAnalysis.Size=1024
-Queue.NodeRef.NodeRefResSumMinuteAnalysis.Size=1024
+# Cache size of persistence worker. The value determines whether save data and clear, or not.
+cache.persistence.size=4096
 
diff --git a/skywalking-collector/skywalking-collector-worker/src/main/resources/log4j2.xml b/skywalking-collector/skywalking-collector-worker/src/main/resources/log4j2.xml
index fe1aada..0e2c12e 100644
--- a/skywalking-collector/skywalking-collector-worker/src/main/resources/log4j2.xml
+++ b/skywalking-collector/skywalking-collector-worker/src/main/resources/log4j2.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<Configuration status="DEBUG">
+<Configuration status="error">
     <Properties>
         <Property name="log-path">../logs</Property>
     </Properties>
@@ -16,10 +16,10 @@
         </RollingFile>
     </Appenders>
     <Loggers>
-        <Logger name="root" level="INFO" additivity="false">
-            <appender-ref ref="RollingFile" level="INFO"/>
-        </Logger>
-        <Root level="INFO" additivity="false">
+        <logger name="com.a.eye.skywalking.collector" level="debug">
+            <AppenderRef ref="RollingFile"/>
+        </logger>
+        <Root level="INFO">
             <AppenderRef ref="RollingFile"/>
         </Root>
     </Loggers>
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/JoinAndSplitPersistenceMemberTestCase.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/JoinAndSplitPersistenceMemberTestCase.java
new file mode 100644
index 0000000..5b44776
--- /dev/null
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/JoinAndSplitPersistenceMemberTestCase.java
@@ -0,0 +1,57 @@
+package com.a.eye.skywalking.collector.worker;
+
+import com.a.eye.skywalking.collector.actor.ClusterWorkerContext;
+import com.a.eye.skywalking.collector.actor.LocalWorkerContext;
+import com.a.eye.skywalking.collector.worker.mock.MockEsBulkClient;
+import com.a.eye.skywalking.collector.worker.storage.EsClient;
+import com.a.eye.skywalking.collector.worker.storage.JoinAndSplitData;
+import com.a.eye.skywalking.collector.worker.storage.JoinAndSplitPersistenceData;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mockito;
+import org.powermock.api.mockito.PowerMockito;
+import org.powermock.core.classloader.annotations.PowerMockIgnore;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import static org.powermock.api.mockito.PowerMockito.*;
+
+/**
+ * @author pengys5
+ */
+@RunWith(PowerMockRunner.class)
+@PrepareForTest({TestJoinAndSplitPersistenceMember.class, EsClient.class})
+@PowerMockIgnore({"javax.management.*"})
+public class JoinAndSplitPersistenceMemberTestCase {
+
+    private TestJoinAndSplitPersistenceMember mergePersistenceMember;
+    private JoinAndSplitPersistenceData persistenceData;
+
+    @Before
+    public void init() throws Exception {
+        MockEsBulkClient mockEsBulkClient = new MockEsBulkClient();
+        mockEsBulkClient.createMock();
+
+        ClusterWorkerContext clusterWorkerContext = new ClusterWorkerContext(null);
+        LocalWorkerContext localWorkerContext = new LocalWorkerContext();
+        mergePersistenceMember = PowerMockito.spy(new TestJoinAndSplitPersistenceMember(TestJoinAndSplitPersistenceMember.Role.INSTANCE, clusterWorkerContext, localWorkerContext));
+
+        persistenceData = mock(JoinAndSplitPersistenceData.class);
+        JoinAndSplitData joinAndSplitData = mock(JoinAndSplitData.class);
+
+        when(mergePersistenceMember, "getPersistenceData").thenReturn(persistenceData);
+        when(persistenceData.getOrCreate(Mockito.anyString())).thenReturn(joinAndSplitData);
+
+        doCallRealMethod().when(mergePersistenceMember).analyse(Mockito.any(JoinAndSplitData.class));
+    }
+
+    @Test
+    public void testAnalyse() throws Exception {
+        String id = "2016" + Const.ID_SPLIT + "A" + Const.ID_SPLIT + "B";
+        JoinAndSplitData joinAndSplitData = new JoinAndSplitData(id);
+        joinAndSplitData.set("Column", "VALUE");
+
+        mergePersistenceMember.analyse(joinAndSplitData);
+    }
+}
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/MergeAnalysisMemberTestCase.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/MergeAnalysisMemberTestCase.java
deleted file mode 100644
index 18b4e92..0000000
--- a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/MergeAnalysisMemberTestCase.java
+++ /dev/null
@@ -1,73 +0,0 @@
-package com.a.eye.skywalking.collector.worker;
-
-import com.a.eye.skywalking.collector.actor.ClusterWorkerContext;
-import com.a.eye.skywalking.collector.actor.LocalWorkerContext;
-import com.a.eye.skywalking.collector.worker.config.CacheSizeConfig;
-import com.a.eye.skywalking.collector.worker.storage.MergeData;
-import com.a.eye.skywalking.collector.worker.storage.MergePersistenceData;
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mockito;
-import org.powermock.api.mockito.PowerMockito;
-import org.powermock.core.classloader.annotations.PowerMockIgnore;
-import org.powermock.core.classloader.annotations.PrepareForTest;
-import org.powermock.modules.junit4.PowerMockRunner;
-
-import static org.powermock.api.mockito.PowerMockito.*;
-
-/**
- * @author pengys5
- */
-@RunWith(PowerMockRunner.class)
-@PrepareForTest(TestMergeAnalysisMember.class)
-@PowerMockIgnore({"javax.management.*"})
-public class MergeAnalysisMemberTestCase {
-
-    private TestMergeAnalysisMember mergeAnalysisMember;
-    private MergePersistenceData persistenceData;
-
-    @Before
-    public void init() throws Exception {
-        ClusterWorkerContext clusterWorkerContext = new ClusterWorkerContext(null);
-        LocalWorkerContext localWorkerContext = new LocalWorkerContext();
-        mergeAnalysisMember = PowerMockito.spy(new TestMergeAnalysisMember(TestMergeAnalysisMember.Role.INSTANCE, clusterWorkerContext, localWorkerContext));
-
-        persistenceData = mock(MergePersistenceData.class);
-        MergeData mergeData = mock(MergeData.class);
-
-        when(mergeAnalysisMember, "getPersistenceData").thenReturn(persistenceData);
-        when(persistenceData.getElseCreate(Mockito.anyString())).thenReturn(mergeData);
-
-        doCallRealMethod().when(mergeAnalysisMember).setMergeData(Mockito.anyString(), Mockito.anyString(), Mockito.anyString());
-    }
-
-    @Test
-    public void testSetMergeDataNotFull() throws Exception {
-        when(persistenceData.size()).thenReturn(CacheSizeConfig.Cache.Analysis.SIZE - 1);
-
-        mergeAnalysisMember.setMergeData("segment_1", "column", "value");
-        Mockito.verify(mergeAnalysisMember, Mockito.never()).aggregation();
-    }
-
-    @Test
-    public void testSetMergeDataFull() throws Exception {
-        when(persistenceData.size()).thenReturn(CacheSizeConfig.Cache.Analysis.SIZE);
-
-        mergeAnalysisMember.setMergeData("segment_1", "column", "value");
-        Mockito.verify(mergeAnalysisMember, Mockito.times(1)).aggregation();
-    }
-
-    @Test
-    public void testPushOne() throws Exception {
-        MergePersistenceData persistenceData = new MergePersistenceData();
-        persistenceData.getElseCreate("segment_1").setMergeData("column", "value");
-
-        when(mergeAnalysisMember, "getPersistenceData").thenReturn(persistenceData);
-        doCallRealMethod().when(mergeAnalysisMember).pushOne();
-
-        Assert.assertEquals("segment_1", mergeAnalysisMember.pushOne().getId());
-        Assert.assertEquals(null, mergeAnalysisMember.pushOne());
-    }
-}
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/MergePersistenceMemberTestCase.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/MergePersistenceMemberTestCase.java
deleted file mode 100644
index 263e0d6..0000000
--- a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/MergePersistenceMemberTestCase.java
+++ /dev/null
@@ -1,59 +0,0 @@
-package com.a.eye.skywalking.collector.worker;
-
-import com.a.eye.skywalking.collector.actor.ClusterWorkerContext;
-import com.a.eye.skywalking.collector.actor.LocalWorkerContext;
-import com.a.eye.skywalking.collector.queue.EndOfBatchCommand;
-import com.a.eye.skywalking.collector.worker.mock.MockEsBulkClient;
-import com.a.eye.skywalking.collector.worker.storage.EsClient;
-import com.a.eye.skywalking.collector.worker.storage.MergeData;
-import com.a.eye.skywalking.collector.worker.storage.MergePersistenceData;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mockito;
-import org.powermock.api.mockito.PowerMockito;
-import org.powermock.core.classloader.annotations.PowerMockIgnore;
-import org.powermock.core.classloader.annotations.PrepareForTest;
-import org.powermock.modules.junit4.PowerMockRunner;
-
-import static org.powermock.api.mockito.PowerMockito.*;
-
-/**
- * @author pengys5
- */
-@RunWith(PowerMockRunner.class)
-@PrepareForTest({TestMergePersistenceMember.class, EsClient.class})
-@PowerMockIgnore({"javax.management.*"})
-public class MergePersistenceMemberTestCase {
-
-    private TestMergePersistenceMember mergePersistenceMember;
-    private MergePersistenceData persistenceData;
-
-    @Before
-    public void init() throws Exception {
-        MockEsBulkClient mockEsBulkClient = new MockEsBulkClient();
-        mockEsBulkClient.createMock();
-
-        ClusterWorkerContext clusterWorkerContext = new ClusterWorkerContext(null);
-        LocalWorkerContext localWorkerContext = new LocalWorkerContext();
-        mergePersistenceMember = PowerMockito.spy(new TestMergePersistenceMember(TestMergePersistenceMember.Role.INSTANCE, clusterWorkerContext, localWorkerContext));
-
-        persistenceData = mock(MergePersistenceData.class);
-        MergeData mergeData = mock(MergeData.class);
-
-        when(mergePersistenceMember, "getPersistenceData").thenReturn(persistenceData);
-        when(persistenceData.getElseCreate(Mockito.anyString())).thenReturn(mergeData);
-
-        doCallRealMethod().when(mergePersistenceMember).analyse(Mockito.any(MergeData.class));
-    }
-
-    @Test
-    public void testAnalyse() throws Exception {
-        String id = "2016" + Const.ID_SPLIT + "A" + Const.ID_SPLIT + "B";
-        MergeData mergeData = new MergeData(id);
-        mergeData.setMergeData("Column", "VALUE");
-
-//        mergePersistenceMember.analyse(mergeData);
-//        mergePersistenceMember.onWork(new EndOfBatchCommand());
-    }
-}
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/RecordPersistenceMemberTestCase.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/RecordPersistenceMemberTestCase.java
new file mode 100644
index 0000000..c1d27e9
--- /dev/null
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/RecordPersistenceMemberTestCase.java
@@ -0,0 +1,41 @@
+package com.a.eye.skywalking.collector.worker;
+
+import com.a.eye.skywalking.collector.worker.storage.RecordData;
+import com.a.eye.skywalking.collector.worker.storage.RecordPersistenceData;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.api.mockito.PowerMockito;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import org.apache.logging.log4j.Logger;
+
+import static org.mockito.Mockito.*;
+
+/**
+ * @author pengys5
+ */
+@RunWith(PowerMockRunner.class)
+@PrepareForTest(RecordPersistenceMember.class)
+public class RecordPersistenceMemberTestCase {
+
+    @Test
+    public void analyse() throws Exception {
+        RecordPersistenceMember member = PowerMockito.mock(RecordPersistenceMember.class, CALLS_REAL_METHODS);
+        Logger logger = mock(Logger.class);
+        when(member.logger()).thenReturn(logger);
+
+        RecordPersistenceData data = mock(RecordPersistenceData.class);
+        RecordData recordData = new RecordData("test1");
+        when(data.getOrCreate(anyString())).thenReturn(recordData);
+
+        when(member.getPersistenceData()).thenReturn(data);
+
+        RecordData recordData_1 = new RecordData("test2");
+        member.analyse(recordData_1);
+
+        verify(data).hold();
+        verify(data).release();
+
+        member.analyse(new Object());
+    }
+}
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/TestMergeAnalysisMember.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/TestJoinAndSplitAnalysisMember.java
similarity index 74%
rename from skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/TestMergeAnalysisMember.java
rename to skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/TestJoinAndSplitAnalysisMember.java
index 9f9bdf9..8b9fdce 100644
--- a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/TestMergeAnalysisMember.java
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/TestJoinAndSplitAnalysisMember.java
@@ -3,14 +3,15 @@
 import com.a.eye.skywalking.collector.actor.ClusterWorkerContext;
 import com.a.eye.skywalking.collector.actor.LocalWorkerContext;
 import com.a.eye.skywalking.collector.actor.ProviderNotFoundException;
+import com.a.eye.skywalking.collector.actor.WorkerRefs;
 import com.a.eye.skywalking.collector.actor.selector.WorkerSelector;
 
 /**
  * @author pengys5
  */
-public class TestMergeAnalysisMember extends MergeAnalysisMember {
+public class TestJoinAndSplitAnalysisMember extends JoinAndSplitAnalysisMember {
 
-    TestMergeAnalysisMember(Role role, ClusterWorkerContext clusterContext, LocalWorkerContext selfContext) {
+    TestJoinAndSplitAnalysisMember(Role role, ClusterWorkerContext clusterContext, LocalWorkerContext selfContext) {
         super(role, clusterContext, selfContext);
     }
 
@@ -25,8 +26,8 @@
     }
 
     @Override
-    protected void aggregation() throws Exception {
-
+    protected WorkerRefs aggWorkRefs() {
+        return null;
     }
 
     public enum Role implements com.a.eye.skywalking.collector.actor.Role {
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/TestMergePersistenceMember.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/TestJoinAndSplitPersistenceMember.java
similarity index 78%
rename from skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/TestMergePersistenceMember.java
rename to skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/TestJoinAndSplitPersistenceMember.java
index 0f81a90..e69f182 100644
--- a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/TestMergePersistenceMember.java
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/TestJoinAndSplitPersistenceMember.java
@@ -7,8 +7,8 @@
 /**
  * @author pengys5
  */
-public class TestMergePersistenceMember extends MergePersistenceMember {
-    TestMergePersistenceMember(Role role, ClusterWorkerContext clusterContext, LocalWorkerContext selfContext) {
+public class TestJoinAndSplitPersistenceMember extends JoinAndSplitPersistenceMember {
+    TestJoinAndSplitPersistenceMember(Role role, ClusterWorkerContext clusterContext, LocalWorkerContext selfContext) {
         super(role, clusterContext, selfContext);
     }
 
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/config/CacheSizeConfigProviderTestCase.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/config/CacheSizeConfigProviderTestCase.java
new file mode 100644
index 0000000..05cd29b
--- /dev/null
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/config/CacheSizeConfigProviderTestCase.java
@@ -0,0 +1,18 @@
+package com.a.eye.skywalking.collector.worker.config;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * @author pengys5
+ */
+public class CacheSizeConfigProviderTestCase {
+
+    @Test
+    public void test() {
+        CacheSizeConfigProvider provider = new CacheSizeConfigProvider();
+        provider.cliArgs();
+
+        Assert.assertEquals(CacheSizeConfig.class, provider.configClass());
+    }
+}
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/config/CacheSizeConfigTestCase.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/config/CacheSizeConfigTestCase.java
new file mode 100644
index 0000000..fba27a2
--- /dev/null
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/config/CacheSizeConfigTestCase.java
@@ -0,0 +1,16 @@
+package com.a.eye.skywalking.collector.worker.config;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * @author pengys5
+ */
+public class CacheSizeConfigTestCase {
+
+    @Test
+    public void test() {
+        Assert.assertEquals(1024, CacheSizeConfig.Cache.Analysis.SIZE);
+        Assert.assertEquals(5000, CacheSizeConfig.Cache.Persistence.SIZE);
+    }
+}
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/config/EsConfigProviderTestCase.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/config/EsConfigProviderTestCase.java
new file mode 100644
index 0000000..05298f3
--- /dev/null
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/config/EsConfigProviderTestCase.java
@@ -0,0 +1,30 @@
+package com.a.eye.skywalking.collector.worker.config;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * @author pengys5
+ */
+public class EsConfigProviderTestCase {
+
+    @Test
+    public void test() {
+        EsConfigProvider provider = new EsConfigProvider();
+
+        Assert.assertEquals(EsConfig.class, provider.configClass());
+
+        System.setProperty("es.cluster.NAME", "A");
+        System.setProperty("es.cluster.NODES", "B");
+        System.setProperty("es.cluster.transport.SNIFFER", "C");
+        System.setProperty("es.index.shards.NUMBER", "10");
+        System.setProperty("es.index.replicas.NUMBER", "20");
+        provider.cliArgs();
+
+        Assert.assertEquals("A", EsConfig.Es.Cluster.NAME);
+        Assert.assertEquals("B", EsConfig.Es.Cluster.NODES);
+        Assert.assertEquals("C", EsConfig.Es.Cluster.Transport.SNIFFER);
+        Assert.assertEquals("10", EsConfig.Es.Index.Shards.NUMBER);
+        Assert.assertEquals("20", EsConfig.Es.Index.Replicas.NUMBER);
+    }
+}
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/config/HttpConfigProviderTestCase.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/config/HttpConfigProviderTestCase.java
new file mode 100644
index 0000000..b0677d7
--- /dev/null
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/config/HttpConfigProviderTestCase.java
@@ -0,0 +1,26 @@
+package com.a.eye.skywalking.collector.worker.config;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * @author pengys5
+ */
+public class HttpConfigProviderTestCase {
+
+    @Test
+    public void test() {
+        HttpConfigProvider provider = new HttpConfigProvider();
+
+        Assert.assertEquals(HttpConfig.class, provider.configClass());
+
+        System.setProperty("http.HOSTNAME", "A");
+        System.setProperty("http.PORT", "B");
+        System.setProperty("http.CONTEXTPATH", "C");
+        provider.cliArgs();
+
+        Assert.assertEquals("A", HttpConfig.Http.HOSTNAME);
+        Assert.assertEquals("B", HttpConfig.Http.PORT);
+        Assert.assertEquals("C", HttpConfig.Http.CONTEXTPATH);
+    }
+}
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/config/WorkerConfigProviderTestCase.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/config/WorkerConfigProviderTestCase.java
new file mode 100644
index 0000000..cb6a47b
--- /dev/null
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/config/WorkerConfigProviderTestCase.java
@@ -0,0 +1,18 @@
+package com.a.eye.skywalking.collector.worker.config;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * @author pengys5
+ */
+public class WorkerConfigProviderTestCase {
+
+    @Test
+    public void test() {
+        WorkerConfigProvider provider = new WorkerConfigProvider();
+        provider.cliArgs();
+
+        Assert.assertEquals(WorkerConfig.class, provider.configClass());
+    }
+}
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/datamerge/JsonDataMerge.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/datamerge/JsonDataMerge.java
index 803fb69..b14d036 100644
--- a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/datamerge/JsonDataMerge.java
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/datamerge/JsonDataMerge.java
@@ -40,7 +40,6 @@
             if (!entry.getValue().isJsonNull()) {
                 value = entry.getValue().getAsString();
             }
-            System.out.printf("key: %s, value: %s \n", key, value);
 
             if (entry.getValue().isJsonNull()) {
                 Assert.assertEquals(true, actualData.get(key).isJsonNull());
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/datamerge/MetricDataMergeJson.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/datamerge/MetricDataMergeJson.java
index 73d1427..30d487b 100644
--- a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/datamerge/MetricDataMergeJson.java
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/datamerge/MetricDataMergeJson.java
@@ -2,7 +2,6 @@
 
 import com.a.eye.skywalking.collector.worker.Const;
 import com.a.eye.skywalking.collector.worker.storage.MetricData;
-import com.a.eye.skywalking.collector.worker.storage.RecordData;
 import com.a.eye.skywalking.collector.worker.tools.DateTools;
 import com.a.eye.skywalking.collector.worker.tools.JsonFileReader;
 import com.google.gson.Gson;
@@ -56,7 +55,6 @@
             if (!entry.getValue().isJsonNull()) {
                 value = entry.getValue().getAsString();
             }
-            System.out.printf("key: %s, value: %s \n", key, value);
 
             if (entry.getValue().isJsonNull()) {
                 Assert.assertEquals(true, actualData.get(key).isJsonNull());
@@ -75,7 +73,7 @@
         Map<String, JsonObject> recordDataMap = new HashMap<>();
         Gson gson = new Gson();
         for (MetricData metricData : recordDataList) {
-            JsonObject jsonObject = gson.fromJson(gson.toJson(metricData.toMap()), JsonObject.class);
+            JsonObject jsonObject = gson.fromJson(gson.toJson(metricData.asMap()), JsonObject.class);
             recordDataMap.put(id2UTCSlice(metricData.getId()), jsonObject);
         }
         return recordDataMap;
@@ -91,7 +89,6 @@
             changedId = changedId + Const.ID_SPLIT + ids[i];
         }
         changedId = String.valueOf(changedSlice) + changedId;
-        System.out.printf("changedId: %s", changedId);
         return changedId;
     }
 }
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/datamerge/RecordDataMergeJson.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/datamerge/RecordDataMergeJson.java
index 6c9a96d..92f0da2 100644
--- a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/datamerge/RecordDataMergeJson.java
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/datamerge/RecordDataMergeJson.java
@@ -55,7 +55,6 @@
             if (!entry.getValue().isJsonNull()) {
                 value = entry.getValue().getAsString();
             }
-            System.out.printf("key: %s, value: %s \n", key, value);
 
             if (entry.getValue().isJsonNull()) {
                 Assert.assertEquals(true, actualData.get(key).isJsonNull());
@@ -71,7 +70,7 @@
     private Map<String, JsonObject> recordData2Map(List<RecordData> recordDataList) {
         Map<String, JsonObject> recordDataMap = new HashMap<>();
         for (RecordData recordData : recordDataList) {
-            recordDataMap.put(recordData.getId(), recordData.getRecord());
+            recordDataMap.put(recordData.getId(), recordData.get());
         }
         return recordDataMap;
     }
@@ -86,7 +85,6 @@
                 changedId = changedId + Const.ID_SPLIT + ids[i];
             }
             changedId = String.valueOf(changedSlice) + changedId;
-            System.out.printf("changedId: %s", changedId);
             return changedId;
         } else {
             return id;
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/globaltrace/GlobalTraceGetWithGlobalIdTestCase.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/globaltrace/GlobalTraceGetWithGlobalIdTestCase.java
index 573edc7..b6830d6 100644
--- a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/globaltrace/GlobalTraceGetWithGlobalIdTestCase.java
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/globaltrace/GlobalTraceGetWithGlobalIdTestCase.java
@@ -59,14 +59,15 @@
 
     @Test
     public void testFactory() {
-        Assert.assertEquals(GlobalTraceGetWithGlobalId.class.getSimpleName(), GlobalTraceGetWithGlobalId.Factory.INSTANCE.role().roleName());
-        Assert.assertEquals(GlobalTraceGetWithGlobalId.class.getSimpleName(), GlobalTraceGetWithGlobalId.Factory.INSTANCE.workerInstance(null).getClass().getSimpleName());
-        Assert.assertEquals("/globalTrace/globalId", GlobalTraceGetWithGlobalId.Factory.INSTANCE.servletPath());
+        GlobalTraceGetWithGlobalId.Factory factory = new GlobalTraceGetWithGlobalId.Factory();
+        Assert.assertEquals(GlobalTraceGetWithGlobalId.class.getSimpleName(), factory.role().roleName());
+        Assert.assertEquals(GlobalTraceGetWithGlobalId.class.getSimpleName(), factory.workerInstance(null).getClass().getSimpleName());
+        Assert.assertEquals("/globalTrace/globalId", factory.servletPath());
     }
 
     @Test
     public void testPreStart() throws ProviderNotFoundException {
-        when(clusterWorkerContext.findProvider(GlobalTraceSearchWithGlobalId.WorkerRole.INSTANCE)).thenReturn(GlobalTraceSearchWithGlobalId.Factory.INSTANCE);
+        when(clusterWorkerContext.findProvider(GlobalTraceSearchWithGlobalId.WorkerRole.INSTANCE)).thenReturn(new GlobalTraceSearchWithGlobalId.Factory());
 
         ArgumentCaptor<GlobalTraceSearchWithGlobalId.WorkerRole> argumentCaptor = ArgumentCaptor.forClass(GlobalTraceSearchWithGlobalId.WorkerRole.class);
         getObj.preStart();
@@ -94,8 +95,7 @@
 
         @Override
         public Object answer(InvocationOnMock invocation) throws Throwable {
-            String globalId = (String)invocation.getArguments()[0];
-            System.out.println(globalId);
+            String globalId = (String) invocation.getArguments()[0];
             Assert.assertEquals("Test", globalId);
             return null;
         }
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/globaltrace/GlobalTraceIndexTestCase.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/globaltrace/GlobalTraceIndexTestCase.java
index ebd9602..871495e 100644
--- a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/globaltrace/GlobalTraceIndexTestCase.java
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/globaltrace/GlobalTraceIndexTestCase.java
@@ -1,5 +1,6 @@
 package com.a.eye.skywalking.collector.worker.globaltrace;
 
+import com.a.eye.skywalking.collector.worker.config.EsConfig;
 import org.junit.Assert;
 import org.junit.Test;
 
@@ -20,6 +21,12 @@
     @Test
     public void testBuilder() throws IOException {
         GlobalTraceIndex index = new GlobalTraceIndex();
-        Assert.assertEquals("{\"properties\":{\"subSegIds\":{\"type\":\"text\",\"index\":\"not_analyzed\"}}}", index.createMappingBuilder().string());
+        Assert.assertEquals("{\"properties\":{\"subSegIds\":{\"type\":\"keyword\"}}}", index.createMappingBuilder().string());
+    }
+
+    @Test
+    public void refreshInterval() {
+        GlobalTraceIndex index = new GlobalTraceIndex();
+        Assert.assertEquals(EsConfig.Es.Index.RefreshInterval.GlobalTraceIndex.VALUE.intValue(), index.refreshInterval());
     }
 }
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/globaltrace/GlobalTraceSearchTestCase.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/globaltrace/GlobalTraceSearchTestCase.java
index 5d480a9..e8c2432 100644
--- a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/globaltrace/GlobalTraceSearchTestCase.java
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/globaltrace/GlobalTraceSearchTestCase.java
@@ -3,58 +3,53 @@
 import com.a.eye.skywalking.collector.worker.globaltrace.persistence.GlobalTraceSearchWithGlobalId;
 import com.a.eye.skywalking.collector.worker.segment.SegmentIndex;
 import com.a.eye.skywalking.collector.worker.storage.EsClient;
+import com.a.eye.skywalking.collector.worker.storage.GetResponseFromEs;
 import com.a.eye.skywalking.collector.worker.tools.JsonFileReader;
 import com.google.gson.JsonObject;
-import org.elasticsearch.action.get.GetRequestBuilder;
 import org.elasticsearch.action.get.GetResponse;
-import org.elasticsearch.client.Client;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.powermock.api.mockito.PowerMockito;
 import org.powermock.core.classloader.annotations.PowerMockIgnore;
 import org.powermock.core.classloader.annotations.PrepareForTest;
 import org.powermock.modules.junit4.PowerMockRunner;
+import org.powermock.reflect.Whitebox;
 
-import static org.powermock.api.mockito.PowerMockito.*;
+import static org.powermock.api.mockito.PowerMockito.mock;
+import static org.powermock.api.mockito.PowerMockito.when;
 
 /**
  * @author pengys5
  */
 @RunWith(PowerMockRunner.class)
-@PrepareForTest({EsClient.class})
+@PrepareForTest({EsClient.class, GetResponseFromEs.class})
 @PowerMockIgnore("javax.management.*")
 public class GlobalTraceSearchTestCase {
 
     @Test
     public void testSearchWithGlobalId() throws Exception {
-        Client client = mock(Client.class);
-        mockStatic(EsClient.class);
-//        when(EsClient.INSTANCE.getClient()).thenReturn(client);
-
         String globalTraceId = "Global.1";
-        String segment_1 = "SEGMENT.1";
-        String segment_2 = "SEGMENT.2";
+        String segment_1 = "Segment.1490922929258.927784221.5991.27.1";
 
-//        String globalData = JsonFileReader.INSTANCE.read(this.getClass().getResource("/").getPath() + "/json/globaltrace/global.json");
-//        mockSegment(client, GlobalTraceIndex.INDEX, GlobalTraceIndex.Type_Record, globalTraceId, globalData);
-//
-//        String segment_1_Data = JsonFileReader.INSTANCE.read(this.getClass().getResource("/").getPath() + "/json/globaltrace/segment_1.json");
-//        mockSegment(client, SegmentIndex.INDEX, SegmentIndex.Type_Record, segment_1, segment_1_Data);
-//
-//        String segment_2_Data = JsonFileReader.INSTANCE.read(this.getClass().getResource("/").getPath() + "/json/globaltrace/segment_2.json");
-//        mockSegment(client, SegmentIndex.INDEX, SegmentIndex.Type_Record, segment_2, segment_2_Data);
-//
-//        GlobalTraceSearchWithGlobalId search = new GlobalTraceSearchWithGlobalId(null, null, null);
-//
-//        JsonObject responseObj = new JsonObject();
+        GetResponseFromEs getResponseFromEs = PowerMockito.mock(GetResponseFromEs.class);
+        Whitebox.setInternalState(GetResponseFromEs.class, "INSTANCE", getResponseFromEs);
+
+        String globalData = JsonFileReader.INSTANCE.read(this.getClass().getResource("/").getPath() + "/json/globaltrace/persistence/globaltrace_search.json");
+        mockSegment(getResponseFromEs, GlobalTraceIndex.INDEX, GlobalTraceIndex.TYPE_RECORD, globalTraceId, globalData);
+
+        String segment_Data = JsonFileReader.INSTANCE.read(this.getClass().getResource("/").getPath() + "/json/globaltrace/persistence/globaltrace_segment.json");
+        mockSegment(getResponseFromEs, SegmentIndex.INDEX, SegmentIndex.TYPE_RECORD, segment_1, segment_Data);
+
+        GlobalTraceSearchWithGlobalId search = new GlobalTraceSearchWithGlobalId(GlobalTraceSearchWithGlobalId.WorkerRole.INSTANCE, null, null);
+
+        JsonObject responseObj = new JsonObject();
 //        search.allocateJob(globalTraceId, responseObj);
 //        System.out.println(responseObj);
     }
 
-    private void mockSegment(Client client, String index, String type, String segmentId, String source) {
-        GetRequestBuilder builder = mock(GetRequestBuilder.class);
-        when(client.prepareGet(index, type, segmentId)).thenReturn(builder);
-        GetResponse response = mock(GetResponse.class);
-        when(builder.get()).thenReturn(response);
-        when(response.getSourceAsString()).thenReturn(source);
+    private void mockSegment(GetResponseFromEs getResponseFromEs, String index, String type, String id, String source) {
+        GetResponse getResponse = mock(GetResponse.class);
+        when(getResponseFromEs.get(index, type, id)).thenReturn(getResponse);
+        when(getResponse.getSourceAsString()).thenReturn(source);
     }
 }
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/globaltrace/analysis/GlobalTraceAnalysisTestCase.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/globaltrace/analysis/GlobalTraceAnalysisTestCase.java
index 1c95619..b97502f 100644
--- a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/globaltrace/analysis/GlobalTraceAnalysisTestCase.java
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/globaltrace/analysis/GlobalTraceAnalysisTestCase.java
@@ -8,7 +8,7 @@
 import com.a.eye.skywalking.collector.worker.globaltrace.persistence.GlobalTraceAgg;
 import com.a.eye.skywalking.collector.worker.mock.MergeDataAnswer;
 import com.a.eye.skywalking.collector.worker.segment.mock.SegmentMock;
-import com.a.eye.skywalking.collector.worker.storage.MergeData;
+import com.a.eye.skywalking.collector.worker.storage.JoinAndSplitData;
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
@@ -46,7 +46,7 @@
         clusterWorkerContext = PowerMockito.mock(ClusterWorkerContext.class);
         WorkerRefs workerRefs = mock(WorkerRefs.class);
         answer = new MergeDataAnswer();
-        doAnswer(answer).when(workerRefs).tell(Mockito.any(MergeData.class));
+        doAnswer(answer).when(workerRefs).tell(Mockito.any(JoinAndSplitData.class));
 
         when(clusterWorkerContext.lookup(GlobalTraceAgg.Role.INSTANCE)).thenReturn(workerRefs);
 
@@ -62,22 +62,23 @@
 
     @Test
     public void testFactory() {
-        Assert.assertEquals(GlobalTraceAnalysis.class.getSimpleName(), GlobalTraceAnalysis.Factory.INSTANCE.role().roleName());
-        Assert.assertEquals(GlobalTraceAnalysis.class.getSimpleName(), GlobalTraceAnalysis.Factory.INSTANCE.workerInstance(null).getClass().getSimpleName());
+        GlobalTraceAnalysis.Factory factory = new GlobalTraceAnalysis.Factory();
+        Assert.assertEquals(GlobalTraceAnalysis.class.getSimpleName(), factory.role().roleName());
+        Assert.assertEquals(GlobalTraceAnalysis.class.getSimpleName(), factory.workerInstance(null).getClass().getSimpleName());
 
         int testSize = 10;
         WorkerConfig.Queue.GlobalTrace.GlobalTraceAnalysis.SIZE = testSize;
-        Assert.assertEquals(testSize, GlobalTraceAnalysis.Factory.INSTANCE.queueSize());
+        Assert.assertEquals(testSize, factory.queueSize());
     }
 
     @Test
     public void testAnalyse() throws Exception {
         segmentMock.executeAnalysis(analysis);
 
-        Assert.assertEquals(1, answer.getMergeDataList().size());
-        MergeData mergeData = answer.getMergeDataList().get(0);
-        Assert.assertEquals(id, mergeData.getId());
-        String subSegIds = mergeData.toMap().get("subSegIds");
+        Assert.assertEquals(1, answer.getJoinAndSplitDataList().size());
+        JoinAndSplitData joinAndSplitData = answer.getJoinAndSplitDataList().get(0);
+        Assert.assertEquals(id, joinAndSplitData.getId());
+        String subSegIds = joinAndSplitData.asMap().get("subSegIds").toString();
         Assert.assertEquals(cacheServiceSubSegIds, subSegIds);
     }
 
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/globaltrace/persistence/GlobalTraceAggTestCase.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/globaltrace/persistence/GlobalTraceAggTestCase.java
index cc70505..48dcce9 100644
--- a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/globaltrace/persistence/GlobalTraceAggTestCase.java
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/globaltrace/persistence/GlobalTraceAggTestCase.java
@@ -61,17 +61,18 @@
 
     @Test
     public void testFactory() {
-        Assert.assertEquals(GlobalTraceAgg.class.getSimpleName(), GlobalTraceAgg.Factory.INSTANCE.role().roleName());
-        Assert.assertEquals(GlobalTraceAgg.class.getSimpleName(), GlobalTraceAgg.Factory.INSTANCE.workerInstance(null).getClass().getSimpleName());
+        GlobalTraceAgg.Factory factory = new GlobalTraceAgg.Factory();
+        Assert.assertEquals(GlobalTraceAgg.class.getSimpleName(), factory.role().roleName());
+        Assert.assertEquals(GlobalTraceAgg.class.getSimpleName(), factory.workerInstance(null).getClass().getSimpleName());
 
         int testSize = 10;
         WorkerConfig.WorkerNum.GlobalTrace.GlobalTraceAgg.VALUE = testSize;
-        Assert.assertEquals(testSize, GlobalTraceAgg.Factory.INSTANCE.workerNum());
+        Assert.assertEquals(testSize, factory.workerNum());
     }
 
     @Test
     public void testPreStart() throws ProviderNotFoundException {
-        when(clusterWorkerContext.findProvider(GlobalTraceSave.Role.INSTANCE)).thenReturn(GlobalTraceSave.Factory.INSTANCE);
+        when(clusterWorkerContext.findProvider(GlobalTraceSave.Role.INSTANCE)).thenReturn(new GlobalTraceSave.Factory());
 
         ArgumentCaptor<GlobalTraceSave.Role> argumentCaptor = ArgumentCaptor.forClass(GlobalTraceSave.Role.class);
         agg.preStart();
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/globaltrace/persistence/GlobalTraceSaveTestCase.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/globaltrace/persistence/GlobalTraceSaveTestCase.java
index 9843bcf..2302901 100644
--- a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/globaltrace/persistence/GlobalTraceSaveTestCase.java
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/globaltrace/persistence/GlobalTraceSaveTestCase.java
@@ -3,7 +3,6 @@
 import com.a.eye.skywalking.collector.actor.ClusterWorkerContext;
 import com.a.eye.skywalking.collector.actor.LocalWorkerContext;
 import com.a.eye.skywalking.collector.actor.selector.HashCodeSelector;
-import com.a.eye.skywalking.collector.worker.config.WorkerConfig;
 import com.a.eye.skywalking.collector.worker.globaltrace.GlobalTraceIndex;
 import org.junit.Assert;
 import org.junit.Before;
@@ -46,11 +45,8 @@
 
     @Test
     public void testFactory() {
-        Assert.assertEquals(GlobalTraceSave.class.getSimpleName(), GlobalTraceSave.Factory.INSTANCE.role().roleName());
-        Assert.assertEquals(GlobalTraceSave.class.getSimpleName(), GlobalTraceSave.Factory.INSTANCE.workerInstance(null).getClass().getSimpleName());
-
-        int testSize = 10;
-        WorkerConfig.Queue.GlobalTrace.GlobalTraceSave.SIZE = testSize;
-        Assert.assertEquals(testSize, GlobalTraceSave.Factory.INSTANCE.queueSize());
+        GlobalTraceSave.Factory factory = new GlobalTraceSave.Factory();
+        Assert.assertEquals(GlobalTraceSave.class.getSimpleName(), factory.role().roleName());
+        Assert.assertEquals(GlobalTraceSave.class.getSimpleName(), factory.workerInstance(null).getClass().getSimpleName());
     }
 }
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/globaltrace/persistence/GlobalTraceSearchWithGlobalIdTestCase.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/globaltrace/persistence/GlobalTraceSearchWithGlobalIdTestCase.java
index f887aa6..dc1f7a4 100644
--- a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/globaltrace/persistence/GlobalTraceSearchWithGlobalIdTestCase.java
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/globaltrace/persistence/GlobalTraceSearchWithGlobalIdTestCase.java
@@ -53,8 +53,9 @@
 
     @Test
     public void testFactory() {
-        Assert.assertEquals(GlobalTraceSearchWithGlobalId.class.getSimpleName(), GlobalTraceSearchWithGlobalId.Factory.INSTANCE.role().roleName());
-        Assert.assertEquals(GlobalTraceSearchWithGlobalId.class.getSimpleName(), GlobalTraceSearchWithGlobalId.Factory.INSTANCE.workerInstance(null).getClass().getSimpleName());
+        GlobalTraceSearchWithGlobalId.Factory factory = new GlobalTraceSearchWithGlobalId.Factory();
+        Assert.assertEquals(GlobalTraceSearchWithGlobalId.class.getSimpleName(), factory.role().roleName());
+        Assert.assertEquals(GlobalTraceSearchWithGlobalId.class.getSimpleName(), factory.workerInstance(null).getClass().getSimpleName());
     }
 
     @Test
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/globaltrace/persistence/GlobalTraceSearchWithGlobalIdUseDB.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/globaltrace/persistence/GlobalTraceSearchWithGlobalIdUseDB.java
index b23cc9f..b916df5 100644
--- a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/globaltrace/persistence/GlobalTraceSearchWithGlobalIdUseDB.java
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/globaltrace/persistence/GlobalTraceSearchWithGlobalIdUseDB.java
@@ -2,8 +2,6 @@
 
 import com.a.eye.skywalking.collector.actor.ClusterWorkerContext;
 import com.a.eye.skywalking.collector.actor.LocalWorkerContext;
-import com.a.eye.skywalking.collector.worker.node.NodeMappingIndex;
-import com.a.eye.skywalking.collector.worker.node.persistence.NodeMappingSearchWithTimeSlice;
 import com.a.eye.skywalking.collector.worker.storage.EsClient;
 import com.google.gson.JsonArray;
 import com.google.gson.JsonObject;
@@ -25,11 +23,8 @@
         globalTraceSearchWithGlobalId.onWork("Trace.1491277147443.-1562443425.70539.65.2", response);
 
         JsonArray nodeArray = response.get("result").getAsJsonArray();
-        System.out.println(nodeArray.size());
-        System.out.println(nodeArray.toString());
         for (int i = 0; i < nodeArray.size(); i++) {
             JsonObject nodeJsonObj = nodeArray.get(i).getAsJsonObject();
-            System.out.println(nodeJsonObj);
         }
     }
 }
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/httpserver/AbstractPostTestCase.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/httpserver/AbstractPostTestCase.java
index d54e85d..3c0bf7a 100644
--- a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/httpserver/AbstractPostTestCase.java
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/httpserver/AbstractPostTestCase.java
@@ -41,6 +41,6 @@
     @Test
     public void testOnWorkError() throws Exception {
         post.onWork(new JsonObject());
-//        PowerMockito.verifyPrivate(post).invoke("saveException", any(IllegalArgumentException.class));
+        PowerMockito.verifyPrivate(post).invoke("saveException", any(IllegalArgumentException.class));
     }
 }
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/httpserver/GetWithHttpServletTestCase.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/httpserver/GetWithHttpServletTestCase.java
index 820f6a2..2f69a4b 100644
--- a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/httpserver/GetWithHttpServletTestCase.java
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/httpserver/GetWithHttpServletTestCase.java
@@ -30,7 +30,6 @@
             @Override
             public Object answer(InvocationOnMock invocation) throws Throwable {
                 Integer status = (Integer)invocation.getArguments()[0];
-                System.out.println(status);
                 Assert.assertEquals(new Integer(200), status);
                 return null;
             }
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/httpserver/PostWithHttpServletTestCase.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/httpserver/PostWithHttpServletTestCase.java
index 2ba296f..94a30ed 100644
--- a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/httpserver/PostWithHttpServletTestCase.java
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/httpserver/PostWithHttpServletTestCase.java
@@ -1,6 +1,7 @@
 package com.a.eye.skywalking.collector.worker.httpserver;
 
 import com.a.eye.skywalking.collector.actor.LocalAsyncWorkerRef;
+import com.a.eye.skywalking.collector.worker.segment.entity.Segment;
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
@@ -11,6 +12,7 @@
 import javax.servlet.http.HttpServletResponse;
 import java.io.BufferedReader;
 import java.io.PrintWriter;
+import java.io.StringReader;
 
 import static org.mockito.Matchers.anyInt;
 import static org.mockito.Mockito.*;
@@ -45,7 +47,6 @@
             @Override
             public Object answer(InvocationOnMock invocation) throws Throwable {
                 Integer status = (Integer)invocation.getArguments()[0];
-                System.out.println(status);
                 Assert.assertEquals(new Integer(200), status);
                 return null;
             }
@@ -54,15 +55,13 @@
         doAnswer(new Answer() {
             @Override
             public Object answer(InvocationOnMock invocation) throws Throwable {
-                String reqStr = (String)invocation.getArguments()[0];
-                System.out.println(reqStr);
-                Assert.assertEquals("TestTest2", reqStr);
+                Segment segment = (Segment)invocation.getArguments()[0];
+                Assert.assertEquals("TestTest2", segment.getTraceSegmentId());
                 return null;
             }
-        }).when(workerRef).tell(anyString());
+        }).when(workerRef).tell(any(Segment.class));
 
-        BufferedReader bufferedReader = mock(BufferedReader.class);
-        when(bufferedReader.readLine()).thenReturn("Test").thenReturn("Test2").thenReturn(null);
+        BufferedReader bufferedReader = new BufferedReader(new StringReader("[{\"ts\":\"TestTest2\"}]"));
 
         when(request.getReader()).thenReturn(bufferedReader);
 
@@ -75,7 +74,6 @@
             @Override
             public Object answer(InvocationOnMock invocation) throws Throwable {
                 Integer status = (Integer)invocation.getArguments()[0];
-                System.out.println(status);
                 Assert.assertEquals(new Integer(500), status);
                 return null;
             }
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/httpserver/TestAbstractGet.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/httpserver/TestAbstractGet.java
index d1a1df0..f00c45d 100644
--- a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/httpserver/TestAbstractGet.java
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/httpserver/TestAbstractGet.java
@@ -29,8 +29,6 @@
     }
 
     public static class Factory extends AbstractGetProvider<TestAbstractGet> {
-        public static Factory INSTANCE = new Factory();
-
         @Override
         public Role role() {
             return TestAbstractGet.WorkerRole.INSTANCE;
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/httpserver/TestAbstractGetProvider.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/httpserver/TestAbstractGetProvider.java
index 82ddc91..16e49e0 100644
--- a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/httpserver/TestAbstractGetProvider.java
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/httpserver/TestAbstractGetProvider.java
@@ -15,11 +15,11 @@
 
     @Override
     public Role role() {
-        return null;
+        return TestAbstractGet.WorkerRole.INSTANCE;
     }
 
     @Override
     public AbstractWorker workerInstance(ClusterWorkerContext clusterContext) {
-        return new TestAbstractGet(null, null, null);
+        return new TestAbstractGet(role(), null, null);
     }
 }
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/httpserver/TestAbstractPost.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/httpserver/TestAbstractPost.java
index 8c89580..0539137 100644
--- a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/httpserver/TestAbstractPost.java
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/httpserver/TestAbstractPost.java
@@ -21,8 +21,7 @@
     }
 
     @Override
-    protected void onReceive(String reqJsonStr) throws Exception {
-
+    protected void onReceive(Object message) throws Exception {
     }
 
     public enum WorkerRole implements Role {
@@ -40,8 +39,6 @@
     }
 
     public static class Factory extends AbstractPostProvider<TestAbstractPost> {
-        public static Factory INSTANCE = new Factory();
-
         @Override
         public String servletPath() {
             return "/TestAbstractPost";
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/httpserver/TestAbstractPostProvider.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/httpserver/TestAbstractPostProvider.java
index 086f651..e8c0191 100644
--- a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/httpserver/TestAbstractPostProvider.java
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/httpserver/TestAbstractPostProvider.java
@@ -25,6 +25,6 @@
 
     @Override
     public AbstractWorker workerInstance(ClusterWorkerContext clusterContext) {
-        return new TestAbstractPost(null, null, null);
+        return new TestAbstractPost(TestAbstractPost.WorkerRole.INSTANCE, null, null);
     }
 }
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/mock/MergeDataAnswer.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/mock/MergeDataAnswer.java
index cad7c47..46a13ff 100644
--- a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/mock/MergeDataAnswer.java
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/mock/MergeDataAnswer.java
@@ -1,33 +1,27 @@
 package com.a.eye.skywalking.collector.worker.mock;
 
-import com.a.eye.skywalking.collector.worker.storage.MergeData;
+import com.a.eye.skywalking.collector.worker.storage.JoinAndSplitData;
 import org.mockito.invocation.InvocationOnMock;
 import org.mockito.stubbing.Answer;
 
 import java.util.ArrayList;
 import java.util.List;
-import java.util.Map;
 
 /**
  * @author pengys5
  */
 public class MergeDataAnswer implements Answer<Object> {
 
-    private List<MergeData> mergeDataList = new ArrayList<>();
+    private List<JoinAndSplitData> joinAndSplitDataList = new ArrayList<>();
 
     @Override
     public Object answer(InvocationOnMock invocation) throws Throwable {
-        MergeData mergeData = (MergeData)invocation.getArguments()[0];
-        System.out.printf("id: %s \n", mergeData.getId());
-
-        for (Map.Entry<String, String> entry : mergeData.toMap().entrySet()) {
-            System.out.printf("key: %s, value: %s \n", entry.getKey(), entry.getValue());
-        }
-        mergeDataList.add(mergeData);
+        JoinAndSplitData joinAndSplitData = (JoinAndSplitData)invocation.getArguments()[0];
+        joinAndSplitDataList.add(joinAndSplitData);
         return null;
     }
 
-    public List<MergeData> getMergeDataList() {
-        return mergeDataList;
+    public List<JoinAndSplitData> getJoinAndSplitDataList() {
+        return joinAndSplitDataList;
     }
 }
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/mock/MetricDataAnswer.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/mock/MetricDataAnswer.java
index 9682611..e327dc9 100644
--- a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/mock/MetricDataAnswer.java
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/mock/MetricDataAnswer.java
@@ -20,12 +20,7 @@
     @Override
     public Object answer(InvocationOnMock invocation) throws Throwable {
         MetricData metricData = (MetricData)invocation.getArguments()[0];
-
-        System.out.printf("id: %s \n", metricData.getId());
         metricDataList.add(metricData);
-        Gson gson = new Gson();
-        String jsonStr = gson.toJson(metricData.toMap());
-        System.out.printf("data: %s \n", jsonStr);
         return null;
     }
 
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/mock/MockGetResponse.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/mock/MockGetResponse.java
index fbfd1f0..a4ce72f 100644
--- a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/mock/MockGetResponse.java
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/mock/MockGetResponse.java
@@ -23,4 +23,17 @@
 
         return getResponse;
     }
+
+    public GetResponse mockito(String index, String type, String id) {
+        MockEsClient mockEsClient = new MockEsClient();
+        Client client = mockEsClient.mock();
+
+        GetRequestBuilder builder = mock(GetRequestBuilder.class);
+        GetResponse getResponse = mock(GetResponse.class);
+        when(builder.get()).thenReturn(getResponse);
+
+        when(client.prepareGet(index, type, id)).thenReturn(builder);
+
+        return getResponse;
+    }
 }
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/mock/RecordDataAnswer.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/mock/RecordDataAnswer.java
index b7f4c30..f350eb2 100644
--- a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/mock/RecordDataAnswer.java
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/mock/RecordDataAnswer.java
@@ -1,14 +1,10 @@
 package com.a.eye.skywalking.collector.worker.mock;
 
 import com.a.eye.skywalking.collector.worker.storage.RecordData;
-import com.google.gson.JsonElement;
-import org.mockito.invocation.InvocationOnMock;
-import org.mockito.stubbing.Answer;
-
 import java.util.ArrayList;
 import java.util.List;
-import java.util.Map;
-import java.util.Set;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
 
 /**
  * @author pengys5
@@ -20,9 +16,6 @@
     @Override
     public Object answer(InvocationOnMock invocation) throws Throwable {
         RecordData recordData = (RecordData)invocation.getArguments()[0];
-        System.out.printf("id: %s \n", recordData.getId());
-        System.out.println(recordData.getRecord().toString());
-
         recordDataList.add(recordData);
         return null;
     }
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/mock/SaveToEsSourceAnswer.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/mock/SaveToEsSourceAnswer.java
index c57f297..c8abfd4 100644
--- a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/mock/SaveToEsSourceAnswer.java
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/mock/SaveToEsSourceAnswer.java
@@ -3,8 +3,6 @@
 import com.google.gson.Gson;
 import com.google.gson.JsonArray;
 import com.google.gson.JsonObject;
-import org.apache.logging.log4j.LogManager;
-import org.apache.logging.log4j.Logger;
 import org.mockito.invocation.InvocationOnMock;
 import org.mockito.stubbing.Answer;
 
@@ -13,8 +11,6 @@
  */
 public class SaveToEsSourceAnswer implements Answer<Object> {
 
-    private Logger logger = LogManager.getFormatterLogger(SaveToEsSourceAnswer.class);
-
     public SourceObj sourceObj = new SourceObj();
 
     @Override
@@ -22,8 +18,6 @@
         Gson gson = new Gson();
         String source = (String)invocation.getArguments()[0];
         JsonObject sourceJsonObj = gson.fromJson(source, JsonObject.class);
-        logger.debug("sourceJsonObj: %s", sourceJsonObj.toString());
-
         sourceObj.setSource(sourceJsonObj);
         return null;
     }
@@ -35,10 +29,6 @@
             source = new JsonArray();
         }
 
-        public JsonArray getSource() {
-            return source;
-        }
-
         public void setSource(JsonObject source) {
             this.source.add(source);
         }
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/node/NodeCompIndexTestCase.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/node/NodeCompIndexTestCase.java
index edab251..4c4628b 100644
--- a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/node/NodeCompIndexTestCase.java
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/node/NodeCompIndexTestCase.java
@@ -1,5 +1,6 @@
 package com.a.eye.skywalking.collector.worker.node;
 
+import com.a.eye.skywalking.collector.worker.config.EsConfig;
 import java.io.IOException;
 import org.junit.Assert;
 import org.junit.Test;
@@ -19,6 +20,12 @@
     @Test
     public void testBuilder() throws IOException {
         NodeCompIndex index = new NodeCompIndex();
-        Assert.assertEquals("{\"properties\":{\"name\":{\"type\":\"string\",\"index\":\"not_analyzed\"},\"peers\":{\"type\":\"string\",\"index\":\"not_analyzed\"},\"aggId\":{\"type\":\"string\",\"index\":\"not_analyzed\"}}}", index.createMappingBuilder().string());
+        Assert.assertEquals("{\"properties\":{\"name\":{\"type\":\"keyword\"},\"peers\":{\"type\":\"keyword\"},\"aggId\":{\"type\":\"keyword\"}}}", index.createMappingBuilder().string());
+    }
+
+    @Test
+    public void refreshInterval() {
+        NodeCompIndex index = new NodeCompIndex();
+        Assert.assertEquals(EsConfig.Es.Index.RefreshInterval.NodeCompIndex.VALUE.intValue(), index.refreshInterval());
     }
 }
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/node/NodeMappingIndexTestCase.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/node/NodeMappingIndexTestCase.java
index b69d379..e7e015c 100644
--- a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/node/NodeMappingIndexTestCase.java
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/node/NodeMappingIndexTestCase.java
@@ -1,5 +1,6 @@
 package com.a.eye.skywalking.collector.worker.node;
 
+import com.a.eye.skywalking.collector.worker.config.EsConfig;
 import org.junit.Assert;
 import org.junit.Test;
 
@@ -22,4 +23,10 @@
         NodeMappingIndex index = new NodeMappingIndex();
         Assert.assertEquals("{\"properties\":{\"code\":{\"type\":\"string\",\"index\":\"not_analyzed\"},\"peers\":{\"type\":\"string\",\"index\":\"not_analyzed\"},\"aggId\":{\"type\":\"string\",\"index\":\"not_analyzed\"},\"timeSlice\":{\"type\":\"long\",\"index\":\"not_analyzed\"}}}", index.createMappingBuilder().string());
     }
+
+    @Test
+    public void refreshInterval() {
+        NodeMappingIndex index = new NodeMappingIndex();
+        Assert.assertEquals(EsConfig.Es.Index.RefreshInterval.NodeMappingIndex.VALUE.intValue(), index.refreshInterval());
+    }
 }
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/node/analysis/NodeAnalysisVerify.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/node/analysis/NodeAnalysisVerify.java
index 6ea40d7..b2929c1 100644
--- a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/node/analysis/NodeAnalysisVerify.java
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/node/analysis/NodeAnalysisVerify.java
@@ -16,57 +16,57 @@
         Assert.assertEquals(9, recordDataList.size());
 
         RecordData data_1 = RecordDataTool.INSTANCE.getRecord(recordDataList, timeSlice + "..-..[localhost:-1]");
-        Assert.assertEquals("H2", data_1.getRecord().get("component").getAsString());
-        Assert.assertEquals("[localhost:-1]", data_1.getRecord().get("peers").getAsString());
-        Assert.assertEquals("[localhost:-1]", data_1.getRecord().get("aggId").getAsString());
-        Assert.assertEquals(timeSlice, data_1.getRecord().get("timeSlice").getAsLong());
+        Assert.assertEquals("H2", data_1.get().get("component").getAsString());
+        Assert.assertEquals("[localhost:-1]", data_1.get().get("peers").getAsString());
+        Assert.assertEquals("[localhost:-1]", data_1.get().get("aggId").getAsString());
+        Assert.assertEquals(timeSlice, data_1.get().get("timeSlice").getAsLong());
 
         RecordData data_2 = RecordDataTool.INSTANCE.getRecord(recordDataList, timeSlice + "..-..portal-service");
-        Assert.assertEquals("Tomcat", data_2.getRecord().get("component").getAsString());
-        Assert.assertEquals("portal-service", data_2.getRecord().get("peers").getAsString());
-        Assert.assertEquals("portal-service", data_2.getRecord().get("aggId").getAsString());
-        Assert.assertEquals(timeSlice, data_2.getRecord().get("timeSlice").getAsLong());
+        Assert.assertEquals("Tomcat", data_2.get().get("component").getAsString());
+        Assert.assertEquals("portal-service", data_2.get().get("peers").getAsString());
+        Assert.assertEquals("portal-service", data_2.get().get("aggId").getAsString());
+        Assert.assertEquals(timeSlice, data_2.get().get("timeSlice").getAsLong());
 
         RecordData data_3 = RecordDataTool.INSTANCE.getRecord(recordDataList, timeSlice + "..-..persistence-service");
-        Assert.assertEquals(false, data_3.getRecord().has("component"));
-        Assert.assertEquals("persistence-service", data_3.getRecord().get("peers").getAsString());
-        Assert.assertEquals("persistence-service", data_3.getRecord().get("aggId").getAsString());
-        Assert.assertEquals(timeSlice, data_3.getRecord().get("timeSlice").getAsLong());
+        Assert.assertEquals(false, data_3.get().has("component"));
+        Assert.assertEquals("persistence-service", data_3.get().get("peers").getAsString());
+        Assert.assertEquals("persistence-service", data_3.get().get("aggId").getAsString());
+        Assert.assertEquals(timeSlice, data_3.get().get("timeSlice").getAsLong());
 
         RecordData data_4 = RecordDataTool.INSTANCE.getRecord(recordDataList, timeSlice + "..-..[10.128.35.80:20880]");
-        Assert.assertEquals("HttpClient", data_4.getRecord().get("component").getAsString());
-        Assert.assertEquals("[10.128.35.80:20880]", data_4.getRecord().get("peers").getAsString());
-        Assert.assertEquals("[10.128.35.80:20880]", data_4.getRecord().get("aggId").getAsString());
-        Assert.assertEquals(timeSlice, data_4.getRecord().get("timeSlice").getAsLong());
+        Assert.assertEquals("HttpClient", data_4.get().get("component").getAsString());
+        Assert.assertEquals("[10.128.35.80:20880]", data_4.get().get("peers").getAsString());
+        Assert.assertEquals("[10.128.35.80:20880]", data_4.get().get("aggId").getAsString());
+        Assert.assertEquals(timeSlice, data_4.get().get("timeSlice").getAsLong());
 
         RecordData data_5 = RecordDataTool.INSTANCE.getRecord(recordDataList, timeSlice + "..-..[127.0.0.1:6379]");
-        Assert.assertEquals("Redis", data_5.getRecord().get("component").getAsString());
-        Assert.assertEquals("[127.0.0.1:6379]", data_5.getRecord().get("peers").getAsString());
-        Assert.assertEquals("[127.0.0.1:6379]", data_5.getRecord().get("aggId").getAsString());
-        Assert.assertEquals(timeSlice, data_5.getRecord().get("timeSlice").getAsLong());
+        Assert.assertEquals("Redis", data_5.get().get("component").getAsString());
+        Assert.assertEquals("[127.0.0.1:6379]", data_5.get().get("peers").getAsString());
+        Assert.assertEquals("[127.0.0.1:6379]", data_5.get().get("aggId").getAsString());
+        Assert.assertEquals(timeSlice, data_5.get().get("timeSlice").getAsLong());
 
         RecordData data_6 = RecordDataTool.INSTANCE.getRecord(recordDataList, timeSlice + "..-..[127.0.0.1:8002]");
-        Assert.assertEquals("Motan", data_6.getRecord().get("component").getAsString());
-        Assert.assertEquals("[127.0.0.1:8002]", data_6.getRecord().get("peers").getAsString());
-        Assert.assertEquals("[127.0.0.1:8002]", data_6.getRecord().get("aggId").getAsString());
-        Assert.assertEquals(timeSlice, data_6.getRecord().get("timeSlice").getAsLong());
+        Assert.assertEquals("Motan", data_6.get().get("component").getAsString());
+        Assert.assertEquals("[127.0.0.1:8002]", data_6.get().get("peers").getAsString());
+        Assert.assertEquals("[127.0.0.1:8002]", data_6.get().get("aggId").getAsString());
+        Assert.assertEquals(timeSlice, data_6.get().get("timeSlice").getAsLong());
 
         RecordData data_7 = RecordDataTool.INSTANCE.getRecord(recordDataList, timeSlice + "..-..User");
-        Assert.assertEquals(false, data_7.getRecord().has("component"));
-        Assert.assertEquals("User", data_7.getRecord().get("peers").getAsString());
-        Assert.assertEquals("User", data_7.getRecord().get("aggId").getAsString());
-        Assert.assertEquals(timeSlice, data_7.getRecord().get("timeSlice").getAsLong());
+        Assert.assertEquals(false, data_7.get().has("component"));
+        Assert.assertEquals("User", data_7.get().get("peers").getAsString());
+        Assert.assertEquals("User", data_7.get().get("aggId").getAsString());
+        Assert.assertEquals(timeSlice, data_7.get().get("timeSlice").getAsLong());
 
         RecordData data_8 = RecordDataTool.INSTANCE.getRecord(recordDataList, timeSlice + "..-..[127.0.0.1:3307]");
-        Assert.assertEquals("Mysql", data_8.getRecord().get("component").getAsString());
-        Assert.assertEquals("[127.0.0.1:3307]", data_8.getRecord().get("peers").getAsString());
-        Assert.assertEquals("[127.0.0.1:3307]", data_8.getRecord().get("aggId").getAsString());
-        Assert.assertEquals(timeSlice, data_8.getRecord().get("timeSlice").getAsLong());
+        Assert.assertEquals("Mysql", data_8.get().get("component").getAsString());
+        Assert.assertEquals("[127.0.0.1:3307]", data_8.get().get("peers").getAsString());
+        Assert.assertEquals("[127.0.0.1:3307]", data_8.get().get("aggId").getAsString());
+        Assert.assertEquals(timeSlice, data_8.get().get("timeSlice").getAsLong());
 
         RecordData data_9 = RecordDataTool.INSTANCE.getRecord(recordDataList, timeSlice + "..-..cache-service");
-        Assert.assertEquals(false, data_9.getRecord().has("component"));
-        Assert.assertEquals("cache-service", data_9.getRecord().get("peers").getAsString());
-        Assert.assertEquals("cache-service", data_9.getRecord().get("aggId").getAsString());
-        Assert.assertEquals(timeSlice, data_9.getRecord().get("timeSlice").getAsLong());
+        Assert.assertEquals(false, data_9.get().has("component"));
+        Assert.assertEquals("cache-service", data_9.get().get("peers").getAsString());
+        Assert.assertEquals("cache-service", data_9.get().get("aggId").getAsString());
+        Assert.assertEquals(timeSlice, data_9.get().get("timeSlice").getAsLong());
     }
 }
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/node/analysis/NodeCompAnalysisTestCase.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/node/analysis/NodeCompAnalysisTestCase.java
index e0baa04..af2fde4 100644
--- a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/node/analysis/NodeCompAnalysisTestCase.java
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/node/analysis/NodeCompAnalysisTestCase.java
@@ -64,12 +64,13 @@
 
     @Test
     public void testFactory() {
-        Assert.assertEquals(NodeCompAnalysis.class.getSimpleName(), NodeCompAnalysis.Factory.INSTANCE.role().roleName());
-        Assert.assertEquals(NodeCompAnalysis.class.getSimpleName(), NodeCompAnalysis.Factory.INSTANCE.workerInstance(null).getClass().getSimpleName());
+        NodeCompAnalysis.Factory factory = new NodeCompAnalysis.Factory();
+        Assert.assertEquals(NodeCompAnalysis.class.getSimpleName(), factory.role().roleName());
+        Assert.assertEquals(NodeCompAnalysis.class.getSimpleName(), factory.workerInstance(null).getClass().getSimpleName());
 
         int testSize = 10;
         WorkerConfig.Queue.Node.NodeCompAnalysis.SIZE = testSize;
-        Assert.assertEquals(testSize, NodeCompAnalysis.Factory.INSTANCE.queueSize());
+        Assert.assertEquals(testSize, factory.queueSize());
     }
 
     String jsonFile = "/json/node/analysis/node_comp_analysis.json";
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/node/analysis/NodeMappingDayAnalysisTestCase.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/node/analysis/NodeMappingDayAnalysisTestCase.java
index 76395b3..47e4dab 100644
--- a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/node/analysis/NodeMappingDayAnalysisTestCase.java
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/node/analysis/NodeMappingDayAnalysisTestCase.java
@@ -66,12 +66,13 @@
 
     @Test
     public void testFactory() {
-        Assert.assertEquals(NodeMappingDayAnalysis.class.getSimpleName(), NodeMappingDayAnalysis.Factory.INSTANCE.role().roleName());
-        Assert.assertEquals(NodeMappingDayAnalysis.class.getSimpleName(), NodeMappingDayAnalysis.Factory.INSTANCE.workerInstance(null).getClass().getSimpleName());
+        NodeMappingDayAnalysis.Factory factory = new NodeMappingDayAnalysis.Factory();
+        Assert.assertEquals(NodeMappingDayAnalysis.class.getSimpleName(), factory.role().roleName());
+        Assert.assertEquals(NodeMappingDayAnalysis.class.getSimpleName(), factory.workerInstance(null).getClass().getSimpleName());
 
         int testSize = 10;
         WorkerConfig.Queue.Node.NodeMappingDayAnalysis.SIZE = testSize;
-        Assert.assertEquals(testSize, NodeMappingDayAnalysis.Factory.INSTANCE.queueSize());
+        Assert.assertEquals(testSize, factory.queueSize());
     }
 
     @Test(expected = Exception.class)
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/node/analysis/NodeMappingHourAnalysisTestCase.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/node/analysis/NodeMappingHourAnalysisTestCase.java
index 5dd0f7c..8b2e550 100644
--- a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/node/analysis/NodeMappingHourAnalysisTestCase.java
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/node/analysis/NodeMappingHourAnalysisTestCase.java
@@ -63,12 +63,13 @@
 
     @Test
     public void testFactory() {
-        Assert.assertEquals(NodeMappingHourAnalysis.class.getSimpleName(), NodeMappingHourAnalysis.Factory.INSTANCE.role().roleName());
-        Assert.assertEquals(NodeMappingHourAnalysis.class.getSimpleName(), NodeMappingHourAnalysis.Factory.INSTANCE.workerInstance(null).getClass().getSimpleName());
+        NodeMappingHourAnalysis.Factory factory = new NodeMappingHourAnalysis.Factory();
+        Assert.assertEquals(NodeMappingHourAnalysis.class.getSimpleName(), factory.role().roleName());
+        Assert.assertEquals(NodeMappingHourAnalysis.class.getSimpleName(), factory.workerInstance(null).getClass().getSimpleName());
 
         int testSize = 10;
         WorkerConfig.Queue.Node.NodeMappingHourAnalysis.SIZE = testSize;
-        Assert.assertEquals(testSize, NodeMappingHourAnalysis.Factory.INSTANCE.queueSize());
+        Assert.assertEquals(testSize, factory.queueSize());
     }
 
     String jsonFile = "/json/node/analysis/node_mapping_hour_analysis.json";
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/node/analysis/NodeMappingMinuteAnalysisTestCase.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/node/analysis/NodeMappingMinuteAnalysisTestCase.java
index 6ab41c6..d6ecfdb 100644
--- a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/node/analysis/NodeMappingMinuteAnalysisTestCase.java
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/node/analysis/NodeMappingMinuteAnalysisTestCase.java
@@ -63,12 +63,13 @@
 
     @Test
     public void testFactory() {
-        Assert.assertEquals(NodeMappingMinuteAnalysis.class.getSimpleName(), NodeMappingMinuteAnalysis.Factory.INSTANCE.role().roleName());
-        Assert.assertEquals(NodeMappingMinuteAnalysis.class.getSimpleName(), NodeMappingMinuteAnalysis.Factory.INSTANCE.workerInstance(null).getClass().getSimpleName());
+        NodeMappingMinuteAnalysis.Factory factory = new NodeMappingMinuteAnalysis.Factory();
+        Assert.assertEquals(NodeMappingMinuteAnalysis.class.getSimpleName(), factory.role().roleName());
+        Assert.assertEquals(NodeMappingMinuteAnalysis.class.getSimpleName(), factory.workerInstance(null).getClass().getSimpleName());
 
         int testSize = 10;
         WorkerConfig.Queue.Node.NodeMappingMinuteAnalysis.SIZE = testSize;
-        Assert.assertEquals(testSize, NodeMappingMinuteAnalysis.Factory.INSTANCE.queueSize());
+        Assert.assertEquals(testSize, factory.queueSize());
     }
 
     String jsonFile = "/json/node/analysis/node_mapping_minute_analysis.json";
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/node/persistence/NodeCompAggTestCase.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/node/persistence/NodeCompAggTestCase.java
index 6e0fd4f..1c6a63e 100644
--- a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/node/persistence/NodeCompAggTestCase.java
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/node/persistence/NodeCompAggTestCase.java
@@ -62,28 +62,24 @@
 
     @Test
     public void testFactory() {
-        Assert.assertEquals(NodeCompAgg.class.getSimpleName(), NodeCompAgg.Factory.INSTANCE.role().roleName());
-        Assert.assertEquals(NodeCompAgg.class.getSimpleName(), NodeCompAgg.Factory.INSTANCE.workerInstance(null).getClass().getSimpleName());
+        NodeCompAgg.Factory factory = new NodeCompAgg.Factory();
+        Assert.assertEquals(NodeCompAgg.class.getSimpleName(), factory.role().roleName());
+        Assert.assertEquals(NodeCompAgg.class.getSimpleName(), factory.workerInstance(null).getClass().getSimpleName());
 
         int testSize = 10;
         WorkerConfig.WorkerNum.Node.NodeCompAgg.VALUE = testSize;
-        Assert.assertEquals(testSize, NodeCompAgg.Factory.INSTANCE.workerNum());
+        Assert.assertEquals(testSize, factory.workerNum());
     }
 
     @Test
     public void testPreStart() throws ProviderNotFoundException {
-        when(clusterWorkerContext.findProvider(NodeCompSave.Role.INSTANCE)).thenReturn(NodeCompSave.Factory.INSTANCE);
+        when(clusterWorkerContext.findProvider(NodeCompSave.Role.INSTANCE)).thenReturn(new NodeCompSave.Factory());
 
         ArgumentCaptor<NodeCompSave.Role> argumentCaptor = ArgumentCaptor.forClass(NodeCompSave.Role.class);
         agg.preStart();
         verify(clusterWorkerContext).findProvider(argumentCaptor.capture());
     }
 
-    @Test(expected = IllegalArgumentException.class)
-    public void testOnWorkError() throws Exception {
-        agg.onWork(new Object());
-    }
-
     @Test
     public void testOnWork() throws Exception {
         RecordDataAggTools.INSTANCE.testOnWork(agg, recordDataAnswer);
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/node/persistence/NodeCompSaveTestCase.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/node/persistence/NodeCompSaveTestCase.java
index e1ba4f8..f3bcea3 100644
--- a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/node/persistence/NodeCompSaveTestCase.java
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/node/persistence/NodeCompSaveTestCase.java
@@ -3,7 +3,6 @@
 import com.a.eye.skywalking.collector.actor.ClusterWorkerContext;
 import com.a.eye.skywalking.collector.actor.LocalWorkerContext;
 import com.a.eye.skywalking.collector.actor.selector.HashCodeSelector;
-import com.a.eye.skywalking.collector.worker.config.WorkerConfig;
 import com.a.eye.skywalking.collector.worker.node.NodeCompIndex;
 import org.junit.Assert;
 import org.junit.Before;
@@ -46,11 +45,8 @@
 
     @Test
     public void testFactory() {
-        Assert.assertEquals(NodeCompSave.class.getSimpleName(), NodeCompSave.Factory.INSTANCE.role().roleName());
-        Assert.assertEquals(NodeCompSave.class.getSimpleName(), NodeCompSave.Factory.INSTANCE.workerInstance(null).getClass().getSimpleName());
-
-        int testSize = 10;
-        WorkerConfig.Queue.Node.NodeCompSave.SIZE = testSize;
-        Assert.assertEquals(testSize, NodeCompSave.Factory.INSTANCE.queueSize());
+        NodeCompSave.Factory factory = new NodeCompSave.Factory();
+        Assert.assertEquals(NodeCompSave.class.getSimpleName(), factory.role().roleName());
+        Assert.assertEquals(NodeCompSave.class.getSimpleName(), factory.workerInstance(null).getClass().getSimpleName());
     }
 }
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/node/persistence/NodeCompWithTimeSliceUseDB.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/node/persistence/NodeCompWithTimeSliceUseDB.java
index 6de68b3..14940cb 100644
--- a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/node/persistence/NodeCompWithTimeSliceUseDB.java
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/node/persistence/NodeCompWithTimeSliceUseDB.java
@@ -23,11 +23,8 @@
         nodeCompLoad.onWork(null, response);
 
         JsonArray nodeArray = response.get("result").getAsJsonArray();
-        System.out.println(nodeArray.size());
-        System.out.println(nodeArray.toString());
         for (int i = 0; i < nodeArray.size(); i++) {
             JsonObject nodeJsonObj = nodeArray.get(i).getAsJsonObject();
-            System.out.println(nodeJsonObj);
         }
     }
 }
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/node/persistence/NodeMappingDayAggTestCase.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/node/persistence/NodeMappingDayAggTestCase.java
index b810950..894a62b 100644
--- a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/node/persistence/NodeMappingDayAggTestCase.java
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/node/persistence/NodeMappingDayAggTestCase.java
@@ -61,17 +61,18 @@
 
     @Test
     public void testFactory() {
-        Assert.assertEquals(NodeMappingDayAgg.class.getSimpleName(), NodeMappingDayAgg.Factory.INSTANCE.role().roleName());
-        Assert.assertEquals(NodeMappingDayAgg.class.getSimpleName(), NodeMappingDayAgg.Factory.INSTANCE.workerInstance(null).getClass().getSimpleName());
+        NodeMappingDayAgg.Factory factory = new NodeMappingDayAgg.Factory();
+        Assert.assertEquals(NodeMappingDayAgg.class.getSimpleName(), factory.role().roleName());
+        Assert.assertEquals(NodeMappingDayAgg.class.getSimpleName(), factory.workerInstance(null).getClass().getSimpleName());
 
         int testSize = 10;
         WorkerConfig.WorkerNum.Node.NodeMappingDayAgg.VALUE = testSize;
-        Assert.assertEquals(testSize, NodeMappingDayAgg.Factory.INSTANCE.workerNum());
+        Assert.assertEquals(testSize, factory.workerNum());
     }
 
     @Test
     public void testPreStart() throws ProviderNotFoundException {
-        when(clusterWorkerContext.findProvider(NodeMappingDaySave.Role.INSTANCE)).thenReturn(NodeMappingDaySave.Factory.INSTANCE);
+        when(clusterWorkerContext.findProvider(NodeMappingDaySave.Role.INSTANCE)).thenReturn(new NodeMappingDaySave.Factory());
 
         ArgumentCaptor<NodeMappingDaySave.Role> argumentCaptor = ArgumentCaptor.forClass(NodeMappingDaySave.Role.class);
         agg.preStart();
@@ -82,9 +83,4 @@
     public void testOnWork() throws Exception {
         RecordDataAggTools.INSTANCE.testOnWork(agg, recordDataAnswer);
     }
-
-    @Test(expected = IllegalArgumentException.class)
-    public void testOnWorkError() throws Exception {
-        agg.onWork(new Object());
-    }
 }
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/node/persistence/NodeMappingDaySaveTestCase.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/node/persistence/NodeMappingDaySaveTestCase.java
index 70c5246..84e554e 100644
--- a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/node/persistence/NodeMappingDaySaveTestCase.java
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/node/persistence/NodeMappingDaySaveTestCase.java
@@ -3,7 +3,6 @@
 import com.a.eye.skywalking.collector.actor.ClusterWorkerContext;
 import com.a.eye.skywalking.collector.actor.LocalWorkerContext;
 import com.a.eye.skywalking.collector.actor.selector.HashCodeSelector;
-import com.a.eye.skywalking.collector.worker.config.WorkerConfig;
 import com.a.eye.skywalking.collector.worker.node.NodeMappingIndex;
 import org.junit.Assert;
 import org.junit.Before;
@@ -46,11 +45,8 @@
 
     @Test
     public void testFactory() {
-        Assert.assertEquals(NodeMappingDaySave.class.getSimpleName(), NodeMappingDaySave.Factory.INSTANCE.role().roleName());
-        Assert.assertEquals(NodeMappingDaySave.class.getSimpleName(), NodeMappingDaySave.Factory.INSTANCE.workerInstance(null).getClass().getSimpleName());
-
-        int testSize = 10;
-        WorkerConfig.Queue.Node.NodeMappingDaySave.SIZE = testSize;
-        Assert.assertEquals(testSize, NodeMappingDaySave.Factory.INSTANCE.queueSize());
+        NodeMappingDaySave.Factory factory = new NodeMappingDaySave.Factory();
+        Assert.assertEquals(NodeMappingDaySave.class.getSimpleName(), factory.role().roleName());
+        Assert.assertEquals(NodeMappingDaySave.class.getSimpleName(), factory.workerInstance(null).getClass().getSimpleName());
     }
 }
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/node/persistence/NodeMappingHourAggTestCase.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/node/persistence/NodeMappingHourAggTestCase.java
index c1f781a..a05933d 100644
--- a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/node/persistence/NodeMappingHourAggTestCase.java
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/node/persistence/NodeMappingHourAggTestCase.java
@@ -61,17 +61,18 @@
 
     @Test
     public void testFactory() {
-        Assert.assertEquals(NodeMappingHourAgg.class.getSimpleName(), NodeMappingHourAgg.Factory.INSTANCE.role().roleName());
-        Assert.assertEquals(NodeMappingHourAgg.class.getSimpleName(), NodeMappingHourAgg.Factory.INSTANCE.workerInstance(null).getClass().getSimpleName());
+        NodeMappingHourAgg.Factory factory = new NodeMappingHourAgg.Factory();
+        Assert.assertEquals(NodeMappingHourAgg.class.getSimpleName(), factory.role().roleName());
+        Assert.assertEquals(NodeMappingHourAgg.class.getSimpleName(), factory.workerInstance(null).getClass().getSimpleName());
 
         int testSize = 10;
         WorkerConfig.WorkerNum.Node.NodeMappingHourAgg.VALUE = testSize;
-        Assert.assertEquals(testSize, NodeMappingHourAgg.Factory.INSTANCE.workerNum());
+        Assert.assertEquals(testSize, factory.workerNum());
     }
 
     @Test
     public void testPreStart() throws ProviderNotFoundException {
-        when(clusterWorkerContext.findProvider(NodeMappingHourSave.Role.INSTANCE)).thenReturn(NodeMappingHourSave.Factory.INSTANCE);
+        when(clusterWorkerContext.findProvider(NodeMappingHourSave.Role.INSTANCE)).thenReturn(new NodeMappingHourSave.Factory());
 
         ArgumentCaptor<NodeMappingHourSave.Role> argumentCaptor = ArgumentCaptor.forClass(NodeMappingHourSave.Role.class);
         agg.preStart();
@@ -82,9 +83,4 @@
     public void testOnWork() throws Exception {
         RecordDataAggTools.INSTANCE.testOnWork(agg, recordDataAnswer);
     }
-
-    @Test(expected = IllegalArgumentException.class)
-    public void testOnWorkError() throws Exception {
-        agg.onWork(new Object());
-    }
 }
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/node/persistence/NodeMappingHourSaveTestCase.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/node/persistence/NodeMappingHourSaveTestCase.java
index 9d3425d..879299f 100644
--- a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/node/persistence/NodeMappingHourSaveTestCase.java
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/node/persistence/NodeMappingHourSaveTestCase.java
@@ -3,7 +3,6 @@
 import com.a.eye.skywalking.collector.actor.ClusterWorkerContext;
 import com.a.eye.skywalking.collector.actor.LocalWorkerContext;
 import com.a.eye.skywalking.collector.actor.selector.HashCodeSelector;
-import com.a.eye.skywalking.collector.worker.config.WorkerConfig;
 import com.a.eye.skywalking.collector.worker.node.NodeMappingIndex;
 import org.junit.Assert;
 import org.junit.Before;
@@ -46,11 +45,8 @@
 
     @Test
     public void testFactory() {
-        Assert.assertEquals(NodeMappingHourSave.class.getSimpleName(), NodeMappingHourSave.Factory.INSTANCE.role().roleName());
-        Assert.assertEquals(NodeMappingHourSave.class.getSimpleName(), NodeMappingHourSave.Factory.INSTANCE.workerInstance(null).getClass().getSimpleName());
-
-        int testSize = 10;
-        WorkerConfig.Queue.Node.NodeMappingHourSave.SIZE = testSize;
-        Assert.assertEquals(testSize, NodeMappingHourSave.Factory.INSTANCE.queueSize());
+        NodeMappingHourSave.Factory factory = new NodeMappingHourSave.Factory();
+        Assert.assertEquals(NodeMappingHourSave.class.getSimpleName(), factory.role().roleName());
+        Assert.assertEquals(NodeMappingHourSave.class.getSimpleName(), factory.workerInstance(null).getClass().getSimpleName());
     }
 }
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/node/persistence/NodeMappingMinuteAggTestCase.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/node/persistence/NodeMappingMinuteAggTestCase.java
index 26311b8..afd7b6e 100644
--- a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/node/persistence/NodeMappingMinuteAggTestCase.java
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/node/persistence/NodeMappingMinuteAggTestCase.java
@@ -61,17 +61,18 @@
 
     @Test
     public void testFactory() {
-        Assert.assertEquals(NodeMappingMinuteAgg.class.getSimpleName(), NodeMappingMinuteAgg.Factory.INSTANCE.role().roleName());
-        Assert.assertEquals(NodeMappingMinuteAgg.class.getSimpleName(), NodeMappingMinuteAgg.Factory.INSTANCE.workerInstance(null).getClass().getSimpleName());
+        NodeMappingMinuteAgg.Factory factory = new NodeMappingMinuteAgg.Factory();
+        Assert.assertEquals(NodeMappingMinuteAgg.class.getSimpleName(), factory.role().roleName());
+        Assert.assertEquals(NodeMappingMinuteAgg.class.getSimpleName(), factory.workerInstance(null).getClass().getSimpleName());
 
         int testSize = 10;
         WorkerConfig.WorkerNum.Node.NodeMappingMinuteAgg.VALUE = testSize;
-        Assert.assertEquals(testSize, NodeMappingMinuteAgg.Factory.INSTANCE.workerNum());
+        Assert.assertEquals(testSize, factory.workerNum());
     }
 
     @Test
     public void testPreStart() throws ProviderNotFoundException {
-        when(clusterWorkerContext.findProvider(NodeMappingMinuteSave.Role.INSTANCE)).thenReturn(NodeMappingMinuteSave.Factory.INSTANCE);
+        when(clusterWorkerContext.findProvider(NodeMappingMinuteSave.Role.INSTANCE)).thenReturn(new NodeMappingMinuteSave.Factory());
 
         ArgumentCaptor<NodeMappingMinuteSave.Role> argumentCaptor = ArgumentCaptor.forClass(NodeMappingMinuteSave.Role.class);
         agg.preStart();
@@ -82,9 +83,4 @@
     public void testOnWork() throws Exception {
         RecordDataAggTools.INSTANCE.testOnWork(agg, recordDataAnswer);
     }
-
-    @Test(expected = IllegalArgumentException.class)
-    public void testOnWorkError() throws Exception {
-        agg.onWork(new Object());
-    }
 }
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/node/persistence/NodeMappingMinuteSaveTestCase.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/node/persistence/NodeMappingMinuteSaveTestCase.java
index 08970d8..644df54 100644
--- a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/node/persistence/NodeMappingMinuteSaveTestCase.java
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/node/persistence/NodeMappingMinuteSaveTestCase.java
@@ -3,7 +3,6 @@
 import com.a.eye.skywalking.collector.actor.ClusterWorkerContext;
 import com.a.eye.skywalking.collector.actor.LocalWorkerContext;
 import com.a.eye.skywalking.collector.actor.selector.HashCodeSelector;
-import com.a.eye.skywalking.collector.worker.config.WorkerConfig;
 import com.a.eye.skywalking.collector.worker.node.NodeMappingIndex;
 import org.junit.Assert;
 import org.junit.Before;
@@ -46,11 +45,8 @@
 
     @Test
     public void testFactory() {
-        Assert.assertEquals(NodeMappingMinuteSave.class.getSimpleName(), NodeMappingMinuteSave.Factory.INSTANCE.role().roleName());
-        Assert.assertEquals(NodeMappingMinuteSave.class.getSimpleName(), NodeMappingMinuteSave.Factory.INSTANCE.workerInstance(null).getClass().getSimpleName());
-
-        int testSize = 10;
-        WorkerConfig.Queue.Node.NodeMappingMinuteSave.SIZE = testSize;
-        Assert.assertEquals(testSize, NodeMappingMinuteSave.Factory.INSTANCE.queueSize());
+        NodeMappingMinuteSave.Factory factory = new NodeMappingMinuteSave.Factory();
+        Assert.assertEquals(NodeMappingMinuteSave.class.getSimpleName(), factory.role().roleName());
+        Assert.assertEquals(NodeMappingMinuteSave.class.getSimpleName(), factory.workerInstance(null).getClass().getSimpleName());
     }
 }
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/node/persistence/NodeMappingSearchWithTimeSliceUseDB.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/node/persistence/NodeMappingSearchWithTimeSliceUseDB.java
index d45b14e..3bddfbe 100644
--- a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/node/persistence/NodeMappingSearchWithTimeSliceUseDB.java
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/node/persistence/NodeMappingSearchWithTimeSliceUseDB.java
@@ -28,11 +28,8 @@
         nodeMappingSearch.onWork(requestEntity, response);
 
         JsonArray nodeArray = response.get("result").getAsJsonArray();
-        System.out.println(nodeArray.size());
-        System.out.println(nodeArray.toString());
         for (int i = 0; i < nodeArray.size(); i++) {
             JsonObject nodeJsonObj = nodeArray.get(i).getAsJsonObject();
-            System.out.println(nodeJsonObj);
         }
     }
 }
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/NodeRefIndexTestCase.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/NodeRefIndexTestCase.java
index 3e7c2f7..edc3080 100644
--- a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/NodeRefIndexTestCase.java
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/NodeRefIndexTestCase.java
@@ -1,11 +1,10 @@
 package com.a.eye.skywalking.collector.worker.noderef;
 
-import com.a.eye.skywalking.collector.worker.globaltrace.GlobalTraceIndex;
+import com.a.eye.skywalking.collector.worker.config.EsConfig;
+import java.io.IOException;
 import org.junit.Assert;
 import org.junit.Test;
 
-import java.io.IOException;
-
 /**
  * @author pengys5
  */
@@ -21,6 +20,12 @@
     @Test
     public void testBuilder() throws IOException {
         NodeRefIndex index = new NodeRefIndex();
-        Assert.assertEquals("{\"properties\":{\"front\":{\"type\":\"string\",\"index\":\"not_analyzed\"},\"frontIsRealCode\":{\"type\":\"boolean\",\"index\":\"not_analyzed\"},\"behind\":{\"type\":\"string\",\"index\":\"not_analyzed\"},\"behindIsRealCode\":{\"type\":\"boolean\",\"index\":\"not_analyzed\"},\"aggId\":{\"type\":\"string\",\"index\":\"not_analyzed\"},\"timeSlice\":{\"type\":\"long\",\"index\":\"not_analyzed\"}}}", index.createMappingBuilder().string());
+        Assert.assertEquals("{\"properties\":{\"front\":{\"type\":\"keyword\"},\"frontIsRealCode\":{\"type\":\"boolean\",\"index\":\"not_analyzed\"},\"behind\":{\"type\":\"keyword\"},\"behindIsRealCode\":{\"type\":\"boolean\",\"index\":\"not_analyzed\"},\"aggId\":{\"type\":\"keyword\"},\"timeSlice\":{\"type\":\"long\",\"index\":\"not_analyzed\"}}}", index.createMappingBuilder().string());
+    }
+
+    @Test
+    public void refreshInterval() {
+        NodeRefIndex index = new NodeRefIndex();
+        Assert.assertEquals(EsConfig.Es.Index.RefreshInterval.NodeRefIndex.VALUE.intValue(), index.refreshInterval());
     }
 }
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/NodeRefResSumGetGroupWithTimeSliceTestCase.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/NodeRefResSumGetGroupWithTimeSliceTestCase.java
index be821c2..a9e3599 100644
--- a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/NodeRefResSumGetGroupWithTimeSliceTestCase.java
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/NodeRefResSumGetGroupWithTimeSliceTestCase.java
@@ -63,14 +63,15 @@
 
     @Test
     public void testFactory() {
-        Assert.assertEquals(NodeRefResSumGetGroupWithTimeSlice.class.getSimpleName(), NodeRefResSumGetGroupWithTimeSlice.Factory.INSTANCE.role().roleName());
-        Assert.assertEquals(NodeRefResSumGetGroupWithTimeSlice.class.getSimpleName(), NodeRefResSumGetGroupWithTimeSlice.Factory.INSTANCE.workerInstance(null).getClass().getSimpleName());
-        Assert.assertEquals("/nodeRef/resSum/groupTimeSlice", NodeRefResSumGetGroupWithTimeSlice.Factory.INSTANCE.servletPath());
+        NodeRefResSumGetGroupWithTimeSlice.Factory factory = new NodeRefResSumGetGroupWithTimeSlice.Factory();
+        Assert.assertEquals(NodeRefResSumGetGroupWithTimeSlice.class.getSimpleName(), factory.role().roleName());
+        Assert.assertEquals(NodeRefResSumGetGroupWithTimeSlice.class.getSimpleName(), factory.workerInstance(null).getClass().getSimpleName());
+        Assert.assertEquals("/nodeRef/resSum/groupTimeSlice", factory.servletPath());
     }
 
     @Test
     public void testPreStart() throws ProviderNotFoundException {
-        when(clusterWorkerContext.findProvider(NodeRefResSumGroupWithTimeSlice.WorkerRole.INSTANCE)).thenReturn(NodeRefResSumGroupWithTimeSlice.Factory.INSTANCE);
+        when(clusterWorkerContext.findProvider(NodeRefResSumGroupWithTimeSlice.WorkerRole.INSTANCE)).thenReturn(new NodeRefResSumGroupWithTimeSlice.Factory());
 
         ArgumentCaptor<NodeRefResSumGroupWithTimeSlice.WorkerRole> argumentCaptor = ArgumentCaptor.forClass(NodeRefResSumGroupWithTimeSlice.WorkerRole.class);
         getObj.preStart();
@@ -128,7 +129,7 @@
 
         @Override
         public Object answer(InvocationOnMock invocation) throws Throwable {
-            NodeRefResSumGroupWithTimeSlice.RequestEntity requestEntity = (NodeRefResSumGroupWithTimeSlice.RequestEntity)invocation.getArguments()[0];
+            NodeRefResSumGroupWithTimeSlice.RequestEntity requestEntity = (NodeRefResSumGroupWithTimeSlice.RequestEntity) invocation.getArguments()[0];
             Assert.assertEquals(100L, requestEntity.getStartTime());
             Assert.assertEquals(200L, requestEntity.getEndTime());
             Assert.assertEquals("minute", requestEntity.getSliceType());
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/NodeRefResSumIndexTestCase.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/NodeRefResSumIndexTestCase.java
index 5042572..d32c665 100644
--- a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/NodeRefResSumIndexTestCase.java
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/NodeRefResSumIndexTestCase.java
@@ -1,5 +1,6 @@
 package com.a.eye.skywalking.collector.worker.noderef;
 
+import com.a.eye.skywalking.collector.worker.config.EsConfig;
 import org.junit.Assert;
 import org.junit.Test;
 
@@ -20,6 +21,12 @@
     @Test
     public void testBuilder() throws IOException {
         NodeRefResSumIndex index = new NodeRefResSumIndex();
-        Assert.assertEquals("{\"properties\":{\"oneSecondLess\":{\"type\":\"long\",\"index\":\"not_analyzed\"},\"threeSecondLess\":{\"type\":\"long\",\"index\":\"not_analyzed\"},\"fiveSecondLess\":{\"type\":\"long\",\"index\":\"not_analyzed\"},\"fiveSecondGreater\":{\"type\":\"long\",\"index\":\"not_analyzed\"},\"error\":{\"type\":\"long\",\"index\":\"not_analyzed\"},\"summary\":{\"type\":\"long\",\"index\":\"not_analyzed\"},\"aggId\":{\"type\":\"string\",\"index\":\"not_analyzed\"},\"timeSlice\":{\"type\":\"long\",\"index\":\"not_analyzed\"}}}", index.createMappingBuilder().string());
+        Assert.assertEquals("{\"properties\":{\"oneSecondLess\":{\"type\":\"long\",\"index\":\"not_analyzed\"},\"threeSecondLess\":{\"type\":\"long\",\"index\":\"not_analyzed\"},\"fiveSecondLess\":{\"type\":\"long\",\"index\":\"not_analyzed\"},\"fiveSecondGreater\":{\"type\":\"long\",\"index\":\"not_analyzed\"},\"error\":{\"type\":\"long\",\"index\":\"not_analyzed\"},\"summary\":{\"type\":\"long\",\"index\":\"not_analyzed\"},\"aggId\":{\"type\":\"keyword\"},\"timeSlice\":{\"type\":\"long\",\"index\":\"not_analyzed\"}}}", index.createMappingBuilder().string());
+    }
+
+    @Test
+    public void refreshInterval() {
+        NodeRefResSumIndex index = new NodeRefResSumIndex();
+        Assert.assertEquals(EsConfig.Es.Index.RefreshInterval.NodeRefResSumIndex.VALUE.intValue(), index.refreshInterval());
     }
 }
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/analysis/AbstractNodeRefResSumAnalysisTestCase.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/analysis/AbstractNodeRefResSumAnalysisTestCase.java
new file mode 100644
index 0000000..9c61e0e
--- /dev/null
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/analysis/AbstractNodeRefResSumAnalysisTestCase.java
@@ -0,0 +1,95 @@
+package com.a.eye.skywalking.collector.worker.noderef.analysis;
+
+import com.a.eye.skywalking.collector.actor.ClusterWorkerContext;
+import com.a.eye.skywalking.collector.actor.LocalWorkerContext;
+import com.a.eye.skywalking.collector.actor.WorkerRefs;
+import com.a.eye.skywalking.collector.actor.selector.RollingSelector;
+import com.a.eye.skywalking.collector.actor.selector.WorkerSelector;
+import com.a.eye.skywalking.collector.worker.Const;
+import com.a.eye.skywalking.collector.worker.storage.MetricAnalysisData;
+import java.lang.reflect.Field;
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * @author pengys5
+ */
+public class AbstractNodeRefResSumAnalysisTestCase {
+
+    @Test
+    public void analyseResSum() throws Exception {
+        Impl impl = new Impl(Role.INSTANCE, null, null);
+
+        AbstractNodeRefResSumAnalysis.NodeRefResRecord record =
+            new AbstractNodeRefResSumAnalysis.NodeRefResRecord(1, 2, 3, 4);
+        record.setStartTime(10);
+        record.setEndTime(20);
+        record.setError(false);
+
+        String id = 2017 + Const.ID_SPLIT + "A" + Const.ID_SPLIT + "B";
+        record.setNodeRefId(id);
+        Assert.assertEquals(id, record.getNodeRefId());
+
+        impl.analyseResSum(record);
+
+        record.setStartTime(0);
+        record.setEndTime(2000);
+        record.setError(false);
+        impl.analyseResSum(record);
+
+        record.setStartTime(0);
+        record.setEndTime(4000);
+        record.setError(false);
+        impl.analyseResSum(record);
+
+        record.setStartTime(0);
+        record.setEndTime(6000);
+        record.setError(false);
+        impl.analyseResSum(record);
+
+        record.setStartTime(0);
+        record.setEndTime(6000);
+        record.setError(true);
+        impl.analyseResSum(record);
+
+        Field testAField = impl.getClass().getSuperclass().getSuperclass().getDeclaredField("metricAnalysisData");
+        testAField.setAccessible(true);
+
+        MetricAnalysisData metricAnalysisData = (MetricAnalysisData)testAField.get(impl);
+
+        Assert.assertEquals(1L, metricAnalysisData.asMap().get("2017..-..A..-..B").asMap().get("oneSecondLess"));
+        Assert.assertEquals(1L, metricAnalysisData.asMap().get("2017..-..A..-..B").asMap().get("threeSecondLess"));
+        Assert.assertEquals(1L, metricAnalysisData.asMap().get("2017..-..A..-..B").asMap().get("fiveSecondLess"));
+        Assert.assertEquals(1L, metricAnalysisData.asMap().get("2017..-..A..-..B").asMap().get("fiveSecondGreater"));
+        Assert.assertEquals(1L, metricAnalysisData.asMap().get("2017..-..A..-..B").asMap().get("error"));
+        Assert.assertEquals(5L, metricAnalysisData.asMap().get("2017..-..A..-..B").asMap().get("summary"));
+    }
+
+    class Impl extends AbstractNodeRefResSumAnalysis {
+        Impl(Role role, ClusterWorkerContext clusterContext, LocalWorkerContext selfContext) {
+            super(role, clusterContext, selfContext);
+        }
+
+        @Override public void analyse(Object message) throws Exception {
+
+        }
+
+        @Override protected WorkerRefs aggWorkRefs() {
+            return null;
+        }
+    }
+
+    enum Role implements com.a.eye.skywalking.collector.actor.Role {
+        INSTANCE;
+
+        @Override
+        public String roleName() {
+            return Impl.class.getSimpleName();
+        }
+
+        @Override
+        public WorkerSelector workerSelector() {
+            return new RollingSelector();
+        }
+    }
+}
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/analysis/NodeRefAnalyse.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/analysis/NodeRefAnalyse.java
index 829af52..8a176d5 100644
--- a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/analysis/NodeRefAnalyse.java
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/analysis/NodeRefAnalyse.java
@@ -26,9 +26,6 @@
 
         Gson gson = new Gson();
         String recordJsonStr = gson.toJson(recordAnswer.getNodeRefResRecordList());
-        System.out.println(recordJsonStr);
-
-        System.out.println("--------------------------------");
         JsonArray recordJsonArray = gson.fromJson(recordJsonStr, JsonArray.class);
         JsonDataMerge.INSTANCE.merge(resSumJsonFile, recordJsonArray);
     }
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/analysis/NodeRefDayAnalysisTestCase.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/analysis/NodeRefDayAnalysisTestCase.java
index e01e49c..ecacd94 100644
--- a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/analysis/NodeRefDayAnalysisTestCase.java
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/analysis/NodeRefDayAnalysisTestCase.java
@@ -68,12 +68,13 @@
 
     @Test
     public void testFactory() {
-        Assert.assertEquals(NodeRefDayAnalysis.class.getSimpleName(), NodeRefDayAnalysis.Factory.INSTANCE.role().roleName());
-        Assert.assertEquals(NodeRefDayAnalysis.class.getSimpleName(), NodeRefDayAnalysis.Factory.INSTANCE.workerInstance(null).getClass().getSimpleName());
+        NodeRefDayAnalysis.Factory factory = new NodeRefDayAnalysis.Factory();
+        Assert.assertEquals(NodeRefDayAnalysis.class.getSimpleName(), factory.role().roleName());
+        Assert.assertEquals(NodeRefDayAnalysis.class.getSimpleName(), factory.workerInstance(null).getClass().getSimpleName());
 
         int testSize = 10;
         WorkerConfig.Queue.NodeRef.NodeRefDayAnalysis.SIZE = testSize;
-        Assert.assertEquals(testSize, NodeRefDayAnalysis.Factory.INSTANCE.queueSize());
+        Assert.assertEquals(testSize, factory.queueSize());
     }
 
     String jsonFile = "/json/noderef/analysis/noderef_day_analysis.json";
@@ -86,7 +87,7 @@
 
     @Test
     public void testPreStart() throws ProviderNotFoundException {
-        Mockito.when(clusterWorkerContext.findProvider(NodeRefResSumDayAnalysis.Role.INSTANCE)).thenReturn(NodeRefResSumDayAnalysis.Factory.INSTANCE);
+        Mockito.when(clusterWorkerContext.findProvider(NodeRefResSumDayAnalysis.Role.INSTANCE)).thenReturn(new NodeRefResSumDayAnalysis.Factory());
 
         ArgumentCaptor<NodeRefResSumDayAnalysis.Role> argumentCaptor = ArgumentCaptor.forClass(NodeRefResSumDayAnalysis.Role.class);
         analysis.preStart();
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/analysis/NodeRefHourAnalysisTestCase.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/analysis/NodeRefHourAnalysisTestCase.java
index 798b394..c46c743 100644
--- a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/analysis/NodeRefHourAnalysisTestCase.java
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/analysis/NodeRefHourAnalysisTestCase.java
@@ -67,12 +67,13 @@
 
     @Test
     public void testFactory() {
-        Assert.assertEquals(NodeRefHourAnalysis.class.getSimpleName(), NodeRefHourAnalysis.Factory.INSTANCE.role().roleName());
-        Assert.assertEquals(NodeRefHourAnalysis.class.getSimpleName(), NodeRefHourAnalysis.Factory.INSTANCE.workerInstance(null).getClass().getSimpleName());
+        NodeRefHourAnalysis.Factory factory = new NodeRefHourAnalysis.Factory();
+        Assert.assertEquals(NodeRefHourAnalysis.class.getSimpleName(), factory.role().roleName());
+        Assert.assertEquals(NodeRefHourAnalysis.class.getSimpleName(), factory.workerInstance(null).getClass().getSimpleName());
 
         int testSize = 10;
         WorkerConfig.Queue.NodeRef.NodeRefHourAnalysis.SIZE = testSize;
-        Assert.assertEquals(testSize, NodeRefHourAnalysis.Factory.INSTANCE.queueSize());
+        Assert.assertEquals(testSize, factory.queueSize());
     }
 
     String jsonFile = "/json/noderef/analysis/noderef_hour_analysis.json";
@@ -85,7 +86,7 @@
 
     @Test
     public void testPreStart() throws ProviderNotFoundException {
-        Mockito.when(clusterWorkerContext.findProvider(NodeRefResSumHourAnalysis.Role.INSTANCE)).thenReturn(NodeRefResSumHourAnalysis.Factory.INSTANCE);
+        Mockito.when(clusterWorkerContext.findProvider(NodeRefResSumHourAnalysis.Role.INSTANCE)).thenReturn(new NodeRefResSumHourAnalysis.Factory());
 
         ArgumentCaptor<NodeRefResSumHourAnalysis.Role> argumentCaptor = ArgumentCaptor.forClass(NodeRefResSumHourAnalysis.Role.class);
         analysis.preStart();
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/analysis/NodeRefMinuteAnalysisTestCase.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/analysis/NodeRefMinuteAnalysisTestCase.java
index 39f5be5..39eba7e 100644
--- a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/analysis/NodeRefMinuteAnalysisTestCase.java
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/analysis/NodeRefMinuteAnalysisTestCase.java
@@ -68,12 +68,13 @@
 
     @Test
     public void testFactory() {
-        Assert.assertEquals(NodeRefMinuteAnalysis.class.getSimpleName(), NodeRefMinuteAnalysis.Factory.INSTANCE.role().roleName());
-        Assert.assertEquals(NodeRefMinuteAnalysis.class.getSimpleName(), NodeRefMinuteAnalysis.Factory.INSTANCE.workerInstance(null).getClass().getSimpleName());
+        NodeRefMinuteAnalysis.Factory factory = new NodeRefMinuteAnalysis.Factory();
+        Assert.assertEquals(NodeRefMinuteAnalysis.class.getSimpleName(), factory.role().roleName());
+        Assert.assertEquals(NodeRefMinuteAnalysis.class.getSimpleName(), factory.workerInstance(null).getClass().getSimpleName());
 
         int testSize = 10;
         WorkerConfig.Queue.NodeRef.NodeRefMinuteAnalysis.SIZE = testSize;
-        Assert.assertEquals(testSize, NodeRefMinuteAnalysis.Factory.INSTANCE.queueSize());
+        Assert.assertEquals(testSize, factory.queueSize());
     }
 
     String jsonFile = "/json/noderef/analysis/noderef_minute_analysis.json";
@@ -86,7 +87,7 @@
 
     @Test
     public void testPreStart() throws ProviderNotFoundException {
-        Mockito.when(clusterWorkerContext.findProvider(NodeRefResSumMinuteAnalysis.Role.INSTANCE)).thenReturn(NodeRefResSumMinuteAnalysis.Factory.INSTANCE);
+        Mockito.when(clusterWorkerContext.findProvider(NodeRefResSumMinuteAnalysis.Role.INSTANCE)).thenReturn(new NodeRefResSumMinuteAnalysis.Factory());
 
         ArgumentCaptor<NodeRefResSumMinuteAnalysis.Role> argumentCaptor = ArgumentCaptor.forClass(NodeRefResSumMinuteAnalysis.Role.class);
         analysis.preStart();
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/analysis/NodeRefResRecordAnswer.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/analysis/NodeRefResRecordAnswer.java
index 5694594..36b9593 100644
--- a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/analysis/NodeRefResRecordAnswer.java
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/analysis/NodeRefResRecordAnswer.java
@@ -21,9 +21,6 @@
         AbstractNodeRefResSumAnalysis.NodeRefResRecord nodeRefResRecord = (AbstractNodeRefResSumAnalysis.NodeRefResRecord)invocation.getArguments()[0];
         String recordJsonStr = gson.toJson(nodeRefResRecord);
         JsonObject recordJsonObj = gson.fromJson(recordJsonStr, JsonObject.class);
-
-        System.out.printf("NodeRefId: %s \n", nodeRefResRecord.getNodeRefId());
-        System.out.printf("NodeRefResRecord data: %s \n", recordJsonStr);
         nodeRefResRecordList.add(recordJsonObj);
         return null;
     }
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/analysis/NodeRefResSumDayAnalysisTestCase.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/analysis/NodeRefResSumDayAnalysisTestCase.java
index a46fbf8..d7dfdef 100644
--- a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/analysis/NodeRefResSumDayAnalysisTestCase.java
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/analysis/NodeRefResSumDayAnalysisTestCase.java
@@ -59,12 +59,13 @@
 
     @Test
     public void testFactory() {
-        Assert.assertEquals(NodeRefResSumDayAnalysis.class.getSimpleName(), NodeRefResSumDayAnalysis.Factory.INSTANCE.role().roleName());
-        Assert.assertEquals(NodeRefResSumDayAnalysis.class.getSimpleName(), NodeRefResSumDayAnalysis.Factory.INSTANCE.workerInstance(null).getClass().getSimpleName());
+        NodeRefResSumDayAnalysis.Factory factory = new NodeRefResSumDayAnalysis.Factory();
+        Assert.assertEquals(NodeRefResSumDayAnalysis.class.getSimpleName(), factory.role().roleName());
+        Assert.assertEquals(NodeRefResSumDayAnalysis.class.getSimpleName(), factory.workerInstance(null).getClass().getSimpleName());
 
         int testSize = 10;
         WorkerConfig.Queue.NodeRef.NodeRefResSumDayAnalysis.SIZE = testSize;
-        Assert.assertEquals(testSize, NodeRefResSumDayAnalysis.Factory.INSTANCE.queueSize());
+        Assert.assertEquals(testSize, factory.queueSize());
     }
 
     String jsonFile = "/json/noderef/analysis/noderef_ressum_day_analysis.json";
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/analysis/NodeRefResSumHourAnalysisTestCase.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/analysis/NodeRefResSumHourAnalysisTestCase.java
index 335f5d2..703454b 100644
--- a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/analysis/NodeRefResSumHourAnalysisTestCase.java
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/analysis/NodeRefResSumHourAnalysisTestCase.java
@@ -59,12 +59,13 @@
 
     @Test
     public void testFactory() {
-        Assert.assertEquals(NodeRefResSumHourAnalysis.class.getSimpleName(), NodeRefResSumHourAnalysis.Factory.INSTANCE.role().roleName());
-        Assert.assertEquals(NodeRefResSumHourAnalysis.class.getSimpleName(), NodeRefResSumHourAnalysis.Factory.INSTANCE.workerInstance(null).getClass().getSimpleName());
+        NodeRefResSumHourAnalysis.Factory factory = new NodeRefResSumHourAnalysis.Factory();
+        Assert.assertEquals(NodeRefResSumHourAnalysis.class.getSimpleName(), factory.role().roleName());
+        Assert.assertEquals(NodeRefResSumHourAnalysis.class.getSimpleName(), factory.workerInstance(null).getClass().getSimpleName());
 
         int testSize = 10;
         WorkerConfig.Queue.NodeRef.NodeRefResSumHourAnalysis.SIZE = testSize;
-        Assert.assertEquals(testSize, NodeRefResSumHourAnalysis.Factory.INSTANCE.queueSize());
+        Assert.assertEquals(testSize, factory.queueSize());
     }
 
     String jsonFile = "/json/noderef/analysis/noderef_ressum_hour_analysis.json";
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/analysis/NodeRefResSumMinuteAnalysisTestCase.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/analysis/NodeRefResSumMinuteAnalysisTestCase.java
index e8921a4..dfd079a 100644
--- a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/analysis/NodeRefResSumMinuteAnalysisTestCase.java
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/analysis/NodeRefResSumMinuteAnalysisTestCase.java
@@ -59,12 +59,13 @@
 
     @Test
     public void testFactory() {
-        Assert.assertEquals(NodeRefResSumMinuteAnalysis.class.getSimpleName(), NodeRefResSumMinuteAnalysis.Factory.INSTANCE.role().roleName());
-        Assert.assertEquals(NodeRefResSumMinuteAnalysis.class.getSimpleName(), NodeRefResSumMinuteAnalysis.Factory.INSTANCE.workerInstance(null).getClass().getSimpleName());
+        NodeRefResSumMinuteAnalysis.Factory factory = new NodeRefResSumMinuteAnalysis.Factory();
+        Assert.assertEquals(NodeRefResSumMinuteAnalysis.class.getSimpleName(), factory.role().roleName());
+        Assert.assertEquals(NodeRefResSumMinuteAnalysis.class.getSimpleName(), factory.workerInstance(null).getClass().getSimpleName());
 
         int testSize = 10;
         WorkerConfig.Queue.NodeRef.NodeRefResSumMinuteAnalysis.SIZE = testSize;
-        Assert.assertEquals(testSize, NodeRefResSumMinuteAnalysis.Factory.INSTANCE.queueSize());
+        Assert.assertEquals(testSize, factory.queueSize());
     }
 
     String jsonFile = "/json/noderef/analysis/noderef_ressum_minute_analysis.json";
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefDayAggTestCase.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefDayAggTestCase.java
index d6abdeb..bfccd74 100644
--- a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefDayAggTestCase.java
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefDayAggTestCase.java
@@ -62,17 +62,18 @@
 
     @Test
     public void testFactory() {
-        Assert.assertEquals(NodeRefDayAgg.class.getSimpleName(), NodeRefDayAgg.Factory.INSTANCE.role().roleName());
-        Assert.assertEquals(NodeRefDayAgg.class.getSimpleName(), NodeRefDayAgg.Factory.INSTANCE.workerInstance(null).getClass().getSimpleName());
+        NodeRefDayAgg.Factory factory = new NodeRefDayAgg.Factory();
+        Assert.assertEquals(NodeRefDayAgg.class.getSimpleName(), factory.role().roleName());
+        Assert.assertEquals(NodeRefDayAgg.class.getSimpleName(), factory.workerInstance(null).getClass().getSimpleName());
 
         int testSize = 10;
         WorkerConfig.WorkerNum.NodeRef.NodeRefDayAgg.VALUE = testSize;
-        Assert.assertEquals(testSize, NodeRefDayAgg.Factory.INSTANCE.workerNum());
+        Assert.assertEquals(testSize, factory.workerNum());
     }
 
     @Test
     public void testPreStart() throws ProviderNotFoundException {
-        when(clusterWorkerContext.findProvider(NodeRefDaySave.Role.INSTANCE)).thenReturn(NodeRefDaySave.Factory.INSTANCE);
+        when(clusterWorkerContext.findProvider(NodeRefDaySave.Role.INSTANCE)).thenReturn(new NodeRefDaySave.Factory());
 
         ArgumentCaptor<NodeRefDaySave.Role> argumentCaptor = ArgumentCaptor.forClass(NodeRefDaySave.Role.class);
         agg.preStart();
@@ -80,11 +81,6 @@
     }
 
     @Test
-    public void testOnWorkError() throws Exception {
-        agg.onWork(new Object());
-    }
-
-    @Test
     public void testOnWork() throws Exception {
         RecordDataAggTools.INSTANCE.testOnWork(agg, recordDataAnswer);
     }
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefDaySaveTestCase.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefDaySaveTestCase.java
index 33eb20a..82f0cc0 100644
--- a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefDaySaveTestCase.java
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefDaySaveTestCase.java
@@ -3,7 +3,6 @@
 import com.a.eye.skywalking.collector.actor.ClusterWorkerContext;
 import com.a.eye.skywalking.collector.actor.LocalWorkerContext;
 import com.a.eye.skywalking.collector.actor.selector.HashCodeSelector;
-import com.a.eye.skywalking.collector.worker.config.WorkerConfig;
 import com.a.eye.skywalking.collector.worker.noderef.NodeRefIndex;
 import org.junit.Assert;
 import org.junit.Before;
@@ -46,11 +45,8 @@
 
     @Test
     public void testFactory() {
-        Assert.assertEquals(NodeRefDaySave.class.getSimpleName(), NodeRefDaySave.Factory.INSTANCE.role().roleName());
-        Assert.assertEquals(NodeRefDaySave.class.getSimpleName(), NodeRefDaySave.Factory.INSTANCE.workerInstance(null).getClass().getSimpleName());
-
-        int testSize = 10;
-        WorkerConfig.Queue.NodeRef.NodeRefDaySave.SIZE = testSize;
-        Assert.assertEquals(testSize, NodeRefDaySave.Factory.INSTANCE.queueSize());
+        NodeRefDaySave.Factory factory = new NodeRefDaySave.Factory();
+        Assert.assertEquals(NodeRefDaySave.class.getSimpleName(), factory.role().roleName());
+        Assert.assertEquals(NodeRefDaySave.class.getSimpleName(), factory.workerInstance(null).getClass().getSimpleName());
     }
 }
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefHourAggTestCase.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefHourAggTestCase.java
index fa16921..ebb9dc6 100644
--- a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefHourAggTestCase.java
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefHourAggTestCase.java
@@ -62,17 +62,18 @@
 
     @Test
     public void testFactory() {
-        Assert.assertEquals(NodeRefHourAgg.class.getSimpleName(), NodeRefHourAgg.Factory.INSTANCE.role().roleName());
-        Assert.assertEquals(NodeRefHourAgg.class.getSimpleName(), NodeRefHourAgg.Factory.INSTANCE.workerInstance(null).getClass().getSimpleName());
+        NodeRefHourAgg.Factory factory = new NodeRefHourAgg.Factory();
+        Assert.assertEquals(NodeRefHourAgg.class.getSimpleName(), factory.role().roleName());
+        Assert.assertEquals(NodeRefHourAgg.class.getSimpleName(), factory.workerInstance(null).getClass().getSimpleName());
 
         int testSize = 10;
         WorkerConfig.WorkerNum.NodeRef.NodeRefHourAgg.VALUE = testSize;
-        Assert.assertEquals(testSize, NodeRefHourAgg.Factory.INSTANCE.workerNum());
+        Assert.assertEquals(testSize, factory.workerNum());
     }
 
     @Test
     public void testPreStart() throws ProviderNotFoundException {
-        when(clusterWorkerContext.findProvider(NodeRefHourSave.Role.INSTANCE)).thenReturn(NodeRefHourSave.Factory.INSTANCE);
+        when(clusterWorkerContext.findProvider(NodeRefHourSave.Role.INSTANCE)).thenReturn(new NodeRefHourSave.Factory());
 
         ArgumentCaptor<NodeRefHourSave.Role> argumentCaptor = ArgumentCaptor.forClass(NodeRefHourSave.Role.class);
         agg.preStart();
@@ -80,11 +81,6 @@
     }
 
     @Test
-    public void testOnWorkError() throws Exception {
-        agg.onWork(new Object());
-    }
-
-    @Test
     public void testOnWork() throws Exception {
         RecordDataAggTools.INSTANCE.testOnWork(agg, recordDataAnswer);
     }
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefHourSaveTestCase.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefHourSaveTestCase.java
index 423a1cb..a000f1d 100644
--- a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefHourSaveTestCase.java
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefHourSaveTestCase.java
@@ -46,11 +46,8 @@
 
     @Test
     public void testFactory() {
-        Assert.assertEquals(NodeRefHourSave.class.getSimpleName(), NodeRefHourSave.Factory.INSTANCE.role().roleName());
-        Assert.assertEquals(NodeRefHourSave.class.getSimpleName(), NodeRefHourSave.Factory.INSTANCE.workerInstance(null).getClass().getSimpleName());
-
-        int testSize = 10;
-        WorkerConfig.Queue.NodeRef.NodeRefHourSave.SIZE = testSize;
-        Assert.assertEquals(testSize, NodeRefHourSave.Factory.INSTANCE.queueSize());
+        NodeRefHourSave.Factory factory = new NodeRefHourSave.Factory();
+        Assert.assertEquals(NodeRefHourSave.class.getSimpleName(), factory.role().roleName());
+        Assert.assertEquals(NodeRefHourSave.class.getSimpleName(), factory.workerInstance(null).getClass().getSimpleName());
     }
 }
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefMinuteAggTestCase.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefMinuteAggTestCase.java
index c38e2c9..1b38eb2 100644
--- a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefMinuteAggTestCase.java
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefMinuteAggTestCase.java
@@ -62,17 +62,18 @@
 
     @Test
     public void testFactory() {
-        Assert.assertEquals(NodeRefMinuteAgg.class.getSimpleName(), NodeRefMinuteAgg.Factory.INSTANCE.role().roleName());
-        Assert.assertEquals(NodeRefMinuteAgg.class.getSimpleName(), NodeRefMinuteAgg.Factory.INSTANCE.workerInstance(null).getClass().getSimpleName());
+        NodeRefMinuteAgg.Factory factory = new NodeRefMinuteAgg.Factory();
+        Assert.assertEquals(NodeRefMinuteAgg.class.getSimpleName(), factory.role().roleName());
+        Assert.assertEquals(NodeRefMinuteAgg.class.getSimpleName(), factory.workerInstance(null).getClass().getSimpleName());
 
         int testSize = 10;
         WorkerConfig.WorkerNum.NodeRef.NodeRefMinuteAgg.VALUE = testSize;
-        Assert.assertEquals(testSize, NodeRefMinuteAgg.Factory.INSTANCE.workerNum());
+        Assert.assertEquals(testSize, factory.workerNum());
     }
 
     @Test
     public void testPreStart() throws ProviderNotFoundException {
-        when(clusterWorkerContext.findProvider(NodeRefMinuteSave.Role.INSTANCE)).thenReturn(NodeRefMinuteSave.Factory.INSTANCE);
+        when(clusterWorkerContext.findProvider(NodeRefMinuteSave.Role.INSTANCE)).thenReturn(new NodeRefMinuteSave.Factory());
 
         ArgumentCaptor<NodeRefMinuteSave.Role> argumentCaptor = ArgumentCaptor.forClass(NodeRefMinuteSave.Role.class);
         agg.preStart();
@@ -80,11 +81,6 @@
     }
 
     @Test
-    public void testOnWorkError() throws Exception {
-        agg.onWork(new Object());
-    }
-
-    @Test
     public void testOnWork() throws Exception {
         RecordDataAggTools.INSTANCE.testOnWork(agg, recordDataAnswer);
     }
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefMinuteSaveTestCase.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefMinuteSaveTestCase.java
index 8f9acb6..c93e9d8 100644
--- a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefMinuteSaveTestCase.java
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefMinuteSaveTestCase.java
@@ -3,7 +3,6 @@
 import com.a.eye.skywalking.collector.actor.ClusterWorkerContext;
 import com.a.eye.skywalking.collector.actor.LocalWorkerContext;
 import com.a.eye.skywalking.collector.actor.selector.HashCodeSelector;
-import com.a.eye.skywalking.collector.worker.config.WorkerConfig;
 import com.a.eye.skywalking.collector.worker.noderef.NodeRefIndex;
 import org.junit.Assert;
 import org.junit.Before;
@@ -46,11 +45,8 @@
 
     @Test
     public void testFactory() {
-        Assert.assertEquals(NodeRefMinuteSave.class.getSimpleName(), NodeRefMinuteSave.Factory.INSTANCE.role().roleName());
-        Assert.assertEquals(NodeRefMinuteSave.class.getSimpleName(), NodeRefMinuteSave.Factory.INSTANCE.workerInstance(null).getClass().getSimpleName());
-
-        int testSize = 10;
-        WorkerConfig.Queue.NodeRef.NodeRefMinuteSave.SIZE = testSize;
-        Assert.assertEquals(testSize, NodeRefMinuteSave.Factory.INSTANCE.queueSize());
+        NodeRefMinuteSave.Factory factory = new NodeRefMinuteSave.Factory();
+        Assert.assertEquals(NodeRefMinuteSave.class.getSimpleName(), factory.role().roleName());
+        Assert.assertEquals(NodeRefMinuteSave.class.getSimpleName(), factory.workerInstance(null).getClass().getSimpleName());
     }
 }
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefResSumDayAggTestCase.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefResSumDayAggTestCase.java
index 0836ad8..dd63c71 100644
--- a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefResSumDayAggTestCase.java
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefResSumDayAggTestCase.java
@@ -62,17 +62,18 @@
 
     @Test
     public void testFactory() {
-        Assert.assertEquals(NodeRefResSumDayAgg.class.getSimpleName(), NodeRefResSumDayAgg.Factory.INSTANCE.role().roleName());
-        Assert.assertEquals(NodeRefResSumDayAgg.class.getSimpleName(), NodeRefResSumDayAgg.Factory.INSTANCE.workerInstance(null).getClass().getSimpleName());
+        NodeRefResSumDayAgg.Factory factory = new NodeRefResSumDayAgg.Factory();
+        Assert.assertEquals(NodeRefResSumDayAgg.class.getSimpleName(), factory.role().roleName());
+        Assert.assertEquals(NodeRefResSumDayAgg.class.getSimpleName(), factory.workerInstance(null).getClass().getSimpleName());
 
         int testSize = 10;
         WorkerConfig.WorkerNum.NodeRef.NodeRefResSumDayAgg.VALUE = testSize;
-        Assert.assertEquals(testSize, NodeRefResSumDayAgg.Factory.INSTANCE.workerNum());
+        Assert.assertEquals(testSize, factory.workerNum());
     }
 
     @Test
     public void testPreStart() throws ProviderNotFoundException {
-        when(clusterWorkerContext.findProvider(NodeRefResSumDaySave.Role.INSTANCE)).thenReturn(NodeRefResSumDaySave.Factory.INSTANCE);
+        when(clusterWorkerContext.findProvider(NodeRefResSumDaySave.Role.INSTANCE)).thenReturn(new NodeRefResSumDaySave.Factory());
 
         ArgumentCaptor<NodeRefResSumDaySave.Role> argumentCaptor = ArgumentCaptor.forClass(NodeRefResSumDaySave.Role.class);
         agg.preStart();
@@ -80,11 +81,6 @@
     }
 
     @Test
-    public void testOnWorkError() throws Exception {
-        agg.onWork(new Object());
-    }
-
-    @Test
     public void testOnWork() throws Exception {
         MetricDataAggTools.INSTANCE.testOnWork(agg, metricDataAnswer);
     }
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefResSumDaySaveTestCase.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefResSumDaySaveTestCase.java
index 7cb1de9..0e75fcd 100644
--- a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefResSumDaySaveTestCase.java
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefResSumDaySaveTestCase.java
@@ -3,7 +3,6 @@
 import com.a.eye.skywalking.collector.actor.ClusterWorkerContext;
 import com.a.eye.skywalking.collector.actor.LocalWorkerContext;
 import com.a.eye.skywalking.collector.actor.selector.HashCodeSelector;
-import com.a.eye.skywalking.collector.worker.config.WorkerConfig;
 import com.a.eye.skywalking.collector.worker.noderef.NodeRefResSumIndex;
 import org.junit.Assert;
 import org.junit.Before;
@@ -45,11 +44,8 @@
 
     @Test
     public void testFactory() {
-        Assert.assertEquals(NodeRefResSumDaySave.class.getSimpleName(), NodeRefResSumDaySave.Factory.INSTANCE.role().roleName());
-        Assert.assertEquals(NodeRefResSumDaySave.class.getSimpleName(), NodeRefResSumDaySave.Factory.INSTANCE.workerInstance(null).getClass().getSimpleName());
-
-        int testSize = 10;
-        WorkerConfig.Queue.NodeRef.NodeRefResSumDaySave.SIZE = testSize;
-        Assert.assertEquals(testSize, NodeRefResSumDaySave.Factory.INSTANCE.queueSize());
+        NodeRefResSumDaySave.Factory factory = new NodeRefResSumDaySave.Factory();
+        Assert.assertEquals(NodeRefResSumDaySave.class.getSimpleName(), factory.role().roleName());
+        Assert.assertEquals(NodeRefResSumDaySave.class.getSimpleName(), factory.workerInstance(null).getClass().getSimpleName());
     }
 }
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefResSumGroupWithTimeSliceUseDB.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefResSumGroupWithTimeSliceUseDB.java
index 9814447..a09d75a 100644
--- a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefResSumGroupWithTimeSliceUseDB.java
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefResSumGroupWithTimeSliceUseDB.java
@@ -28,10 +28,8 @@
         nodeRefSearch.onWork(requestEntity, response);
 
         JsonArray nodeRefArray = response.get("result").getAsJsonArray();
-        System.out.println(nodeRefArray.toString());
         for (int i = 0; i < nodeRefArray.size(); i++) {
             JsonObject nodeRefJsonObj = nodeRefArray.get(i).getAsJsonObject();
-            System.out.println(nodeRefJsonObj);
         }
     }
 }
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefResSumHourAggTestCase.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefResSumHourAggTestCase.java
index c441940..7ddf064 100644
--- a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefResSumHourAggTestCase.java
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefResSumHourAggTestCase.java
@@ -62,17 +62,18 @@
 
     @Test
     public void testFactory() {
-        Assert.assertEquals(NodeRefResSumHourAgg.class.getSimpleName(), NodeRefResSumHourAgg.Factory.INSTANCE.role().roleName());
-        Assert.assertEquals(NodeRefResSumHourAgg.class.getSimpleName(), NodeRefResSumHourAgg.Factory.INSTANCE.workerInstance(null).getClass().getSimpleName());
+        NodeRefResSumHourAgg.Factory factory = new NodeRefResSumHourAgg.Factory();
+        Assert.assertEquals(NodeRefResSumHourAgg.class.getSimpleName(), factory.role().roleName());
+        Assert.assertEquals(NodeRefResSumHourAgg.class.getSimpleName(), factory.workerInstance(null).getClass().getSimpleName());
 
         int testSize = 10;
         WorkerConfig.WorkerNum.NodeRef.NodeRefResSumHourAgg.VALUE = testSize;
-        Assert.assertEquals(testSize, NodeRefResSumHourAgg.Factory.INSTANCE.workerNum());
+        Assert.assertEquals(testSize, factory.workerNum());
     }
 
     @Test
     public void testPreStart() throws ProviderNotFoundException {
-        when(clusterWorkerContext.findProvider(NodeRefResSumHourSave.Role.INSTANCE)).thenReturn(NodeRefResSumHourSave.Factory.INSTANCE);
+        when(clusterWorkerContext.findProvider(NodeRefResSumHourSave.Role.INSTANCE)).thenReturn(new NodeRefResSumHourSave.Factory());
 
         ArgumentCaptor<NodeRefResSumHourSave.Role> argumentCaptor = ArgumentCaptor.forClass(NodeRefResSumHourSave.Role.class);
         agg.preStart();
@@ -80,11 +81,6 @@
     }
 
     @Test
-    public void testOnWorkError() throws Exception {
-        agg.onWork(new Object());
-    }
-
-    @Test
     public void testOnWork() throws Exception {
         MetricDataAggTools.INSTANCE.testOnWork(agg, metricDataAnswer);
     }
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefResSumHourSaveTestCase.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefResSumHourSaveTestCase.java
index e519688..e9e20e4 100644
--- a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefResSumHourSaveTestCase.java
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefResSumHourSaveTestCase.java
@@ -3,7 +3,6 @@
 import com.a.eye.skywalking.collector.actor.ClusterWorkerContext;
 import com.a.eye.skywalking.collector.actor.LocalWorkerContext;
 import com.a.eye.skywalking.collector.actor.selector.HashCodeSelector;
-import com.a.eye.skywalking.collector.worker.config.WorkerConfig;
 import com.a.eye.skywalking.collector.worker.noderef.NodeRefResSumIndex;
 import org.junit.Assert;
 import org.junit.Before;
@@ -46,11 +45,8 @@
 
     @Test
     public void testFactory() {
-        Assert.assertEquals(NodeRefResSumHourSave.class.getSimpleName(), NodeRefResSumHourSave.Factory.INSTANCE.role().roleName());
-        Assert.assertEquals(NodeRefResSumHourSave.class.getSimpleName(), NodeRefResSumHourSave.Factory.INSTANCE.workerInstance(null).getClass().getSimpleName());
-
-        int testSize = 10;
-        WorkerConfig.Queue.NodeRef.NodeRefResSumHourSave.SIZE = testSize;
-        Assert.assertEquals(testSize, NodeRefResSumHourSave.Factory.INSTANCE.queueSize());
+        NodeRefResSumHourSave.Factory factory = new NodeRefResSumHourSave.Factory();
+        Assert.assertEquals(NodeRefResSumHourSave.class.getSimpleName(), factory.role().roleName());
+        Assert.assertEquals(NodeRefResSumHourSave.class.getSimpleName(), factory.workerInstance(null).getClass().getSimpleName());
     }
 }
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefResSumMinuteAggTestCase.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefResSumMinuteAggTestCase.java
index 2f3f24f..fb5fb70 100644
--- a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefResSumMinuteAggTestCase.java
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefResSumMinuteAggTestCase.java
@@ -62,17 +62,18 @@
 
     @Test
     public void testFactory() {
-        Assert.assertEquals(NodeRefResSumMinuteAgg.class.getSimpleName(), NodeRefResSumMinuteAgg.Factory.INSTANCE.role().roleName());
-        Assert.assertEquals(NodeRefResSumMinuteAgg.class.getSimpleName(), NodeRefResSumMinuteAgg.Factory.INSTANCE.workerInstance(null).getClass().getSimpleName());
+        NodeRefResSumMinuteAgg.Factory factory = new NodeRefResSumMinuteAgg.Factory();
+        Assert.assertEquals(NodeRefResSumMinuteAgg.class.getSimpleName(), factory.role().roleName());
+        Assert.assertEquals(NodeRefResSumMinuteAgg.class.getSimpleName(), factory.workerInstance(null).getClass().getSimpleName());
 
         int testSize = 10;
         WorkerConfig.WorkerNum.NodeRef.NodeRefResSumMinuteAgg.VALUE = testSize;
-        Assert.assertEquals(testSize, NodeRefResSumMinuteAgg.Factory.INSTANCE.workerNum());
+        Assert.assertEquals(testSize, factory.workerNum());
     }
 
     @Test
     public void testPreStart() throws ProviderNotFoundException {
-        when(clusterWorkerContext.findProvider(NodeRefResSumMinuteSave.Role.INSTANCE)).thenReturn(NodeRefResSumMinuteSave.Factory.INSTANCE);
+        when(clusterWorkerContext.findProvider(NodeRefResSumMinuteSave.Role.INSTANCE)).thenReturn(new NodeRefResSumMinuteSave.Factory());
 
         ArgumentCaptor<NodeRefResSumMinuteSave.Role> argumentCaptor = ArgumentCaptor.forClass(NodeRefResSumMinuteSave.Role.class);
         agg.preStart();
@@ -80,11 +81,6 @@
     }
 
     @Test
-    public void testOnWorkError() throws Exception {
-        agg.onWork(new Object());
-    }
-
-    @Test
     public void testOnWork() throws Exception {
         MetricDataAggTools.INSTANCE.testOnWork(agg, metricDataAnswer);
     }
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefResSumMinuteSaveTestCase.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefResSumMinuteSaveTestCase.java
index c941a08..754c327 100644
--- a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefResSumMinuteSaveTestCase.java
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefResSumMinuteSaveTestCase.java
@@ -3,7 +3,6 @@
 import com.a.eye.skywalking.collector.actor.ClusterWorkerContext;
 import com.a.eye.skywalking.collector.actor.LocalWorkerContext;
 import com.a.eye.skywalking.collector.actor.selector.HashCodeSelector;
-import com.a.eye.skywalking.collector.worker.config.WorkerConfig;
 import com.a.eye.skywalking.collector.worker.noderef.NodeRefResSumIndex;
 import org.junit.Assert;
 import org.junit.Before;
@@ -46,11 +45,8 @@
 
     @Test
     public void testFactory() {
-        Assert.assertEquals(NodeRefResSumMinuteSave.class.getSimpleName(), NodeRefResSumMinuteSave.Factory.INSTANCE.role().roleName());
-        Assert.assertEquals(NodeRefResSumMinuteSave.class.getSimpleName(), NodeRefResSumMinuteSave.Factory.INSTANCE.workerInstance(null).getClass().getSimpleName());
-
-        int testSize = 10;
-        WorkerConfig.Queue.NodeRef.NodeRefResSumMinuteSave.SIZE = testSize;
-        Assert.assertEquals(testSize, NodeRefResSumMinuteSave.Factory.INSTANCE.queueSize());
+        NodeRefResSumMinuteSave.Factory factory = new NodeRefResSumMinuteSave.Factory();
+        Assert.assertEquals(NodeRefResSumMinuteSave.class.getSimpleName(), factory.role().roleName());
+        Assert.assertEquals(NodeRefResSumMinuteSave.class.getSimpleName(), factory.workerInstance(null).getClass().getSimpleName());
     }
 }
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefResSumSearchWithTimeSliceUseDB.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefResSumSearchWithTimeSliceUseDB.java
index 4986dfe..6a26334 100644
--- a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefResSumSearchWithTimeSliceUseDB.java
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefResSumSearchWithTimeSliceUseDB.java
@@ -28,10 +28,8 @@
         nodeRefSearch.onWork(requestEntity, response);
 
         JsonArray nodeRefArray = response.get("result").getAsJsonArray();
-        System.out.println(nodeRefArray.toString());
         for (int i = 0; i < nodeRefArray.size(); i++) {
             JsonObject nodeRefJsonObj = nodeRefArray.get(i).getAsJsonObject();
-            System.out.println(nodeRefJsonObj);
         }
     }
 }
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefSearchWithTimeSliceUseDB.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefSearchWithTimeSliceUseDB.java
index b17fd55..175c28f 100644
--- a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefSearchWithTimeSliceUseDB.java
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/noderef/persistence/NodeRefSearchWithTimeSliceUseDB.java
@@ -28,10 +28,8 @@
         nodeRefSearch.onWork(requestEntity, response);
 
         JsonArray nodeRefArray = response.get("result").getAsJsonArray();
-        System.out.println(nodeRefArray.toString());
         for (int i = 0; i < nodeRefArray.size(); i++) {
             JsonObject nodeRefJsonObj = nodeRefArray.get(i).getAsJsonObject();
-            System.out.println(nodeRefJsonObj);
         }
     }
 }
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/segment/HttpClientTools.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/segment/HttpClientTools.java
index ce28e67..2934e86 100644
--- a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/segment/HttpClientTools.java
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/segment/HttpClientTools.java
@@ -36,18 +36,17 @@
 
             try (CloseableHttpResponse response = httpClient.execute(httpget)) {
                 HttpEntity entity = response.getEntity();
-                System.out.println(response.getStatusLine());
                 if (entity != null) {
                     return EntityUtils.toString(entity);
                 }
             }
         } catch (Exception e) {
-            e.printStackTrace();
+            logger.error(e);
         } finally {
             try {
                 httpClient.close();
             } catch (IOException e) {
-                e.printStackTrace();
+                logger.error(e);
             }
         }
         return null;
@@ -66,12 +65,12 @@
                 }
             }
         } catch (Exception e) {
-            e.printStackTrace();
+            logger.error(e);
         } finally {
             try {
                 httpClient.close();
             } catch (Exception e) {
-                e.printStackTrace();
+                logger.error(e);
             }
         }
         return null;
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/segment/SegmentCostIndexTestCase.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/segment/SegmentCostIndexTestCase.java
index 3f789db..50f02f0 100644
--- a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/segment/SegmentCostIndexTestCase.java
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/segment/SegmentCostIndexTestCase.java
@@ -1,11 +1,10 @@
 package com.a.eye.skywalking.collector.worker.segment;
 
-import com.a.eye.skywalking.collector.worker.globaltrace.GlobalTraceIndex;
+import com.a.eye.skywalking.collector.worker.config.EsConfig;
+import java.io.IOException;
 import org.junit.Assert;
 import org.junit.Test;
 
-import java.io.IOException;
-
 /**
  * @author pengys5
  */
@@ -21,6 +20,12 @@
     @Test
     public void testBuilder() throws IOException {
         SegmentCostIndex index = new SegmentCostIndex();
-        Assert.assertEquals("{\"properties\":{\"segId\":{\"type\":\"string\",\"index\":\"not_analyzed\"},\"startTime\":{\"type\":\"long\",\"index\":\"not_analyzed\"},\"END_TIME\":{\"type\":\"long\",\"index\":\"not_analyzed\"},\"operationName\":{\"type\":\"string\",\"index\":\"not_analyzed\"},\"cost\":{\"type\":\"long\",\"index\":\"not_analyzed\"}}}", index.createMappingBuilder().string());
+        Assert.assertEquals("{\"properties\":{\"segId\":{\"type\":\"keyword\"},\"startTime\":{\"type\":\"long\",\"index\":\"not_analyzed\"},\"END_TIME\":{\"type\":\"long\",\"index\":\"not_analyzed\"},\"operationName\":{\"type\":\"keyword\"},\"cost\":{\"type\":\"long\",\"index\":\"not_analyzed\"}}}", index.createMappingBuilder().string());
+    }
+
+    @Test
+    public void refreshInterval() {
+        SegmentCostIndex index = new SegmentCostIndex();
+        Assert.assertEquals(EsConfig.Es.Index.RefreshInterval.SegmentCostIndex.VALUE.intValue(), index.refreshInterval());
     }
 }
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/segment/SegmentExceptionIndexTestCase.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/segment/SegmentExceptionIndexTestCase.java
index 0f818ca..bec3361 100644
--- a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/segment/SegmentExceptionIndexTestCase.java
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/segment/SegmentExceptionIndexTestCase.java
@@ -1,11 +1,10 @@
 package com.a.eye.skywalking.collector.worker.segment;
 
-import com.a.eye.skywalking.collector.worker.globaltrace.GlobalTraceIndex;
+import com.a.eye.skywalking.collector.worker.config.EsConfig;
+import java.io.IOException;
 import org.junit.Assert;
 import org.junit.Test;
 
-import java.io.IOException;
-
 /**
  * @author pengys5
  */
@@ -21,6 +20,12 @@
     @Test
     public void testBuilder() throws IOException {
         SegmentExceptionIndex index = new SegmentExceptionIndex();
-        Assert.assertEquals("{\"properties\":{\"segId\":{\"type\":\"string\",\"index\":\"not_analyzed\"},\"isError\":{\"type\":\"boolean\",\"index\":\"not_analyzed\"},\"errorKind\":{\"type\":\"string\",\"index\":\"not_analyzed\"}}}", index.createMappingBuilder().string());
+        Assert.assertEquals("{\"properties\":{\"segId\":{\"type\":\"keyword\"},\"isError\":{\"type\":\"boolean\",\"index\":\"not_analyzed\"},\"errorKind\":{\"type\":\"keyword\"}}}", index.createMappingBuilder().string());
+    }
+
+    @Test
+    public void refreshInterval() {
+        SegmentExceptionIndex index = new SegmentExceptionIndex();
+        Assert.assertEquals(EsConfig.Es.Index.RefreshInterval.SegmentExceptionIndex.VALUE.intValue(), index.refreshInterval());
     }
 }
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/segment/SegmentIndexTestCase.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/segment/SegmentIndexTestCase.java
index 930351b..d16667c 100644
--- a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/segment/SegmentIndexTestCase.java
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/segment/SegmentIndexTestCase.java
@@ -1,5 +1,6 @@
 package com.a.eye.skywalking.collector.worker.segment;
 
+import com.a.eye.skywalking.collector.worker.config.EsConfig;
 import org.junit.Assert;
 import org.junit.Test;
 
@@ -20,6 +21,12 @@
     @Test
     public void testBuilder() throws IOException {
         SegmentIndex index = new SegmentIndex();
-        Assert.assertEquals("{\"properties\":{\"traceSegmentId\":{\"type\":\"string\",\"index\":\"not_analyzed\"},\"startTime\":{\"type\":\"date\",\"index\":\"not_analyzed\"},\"endTime\":{\"type\":\"date\",\"index\":\"not_analyzed\"},\"applicationCode\":{\"type\":\"string\",\"index\":\"not_analyzed\"},\"minute\":{\"type\":\"long\",\"index\":\"not_analyzed\"},\"hour\":{\"type\":\"long\",\"index\":\"not_analyzed\"},\"day\":{\"type\":\"long\",\"index\":\"not_analyzed\"}}}", index.createMappingBuilder().string());
+        Assert.assertEquals("{\"properties\":{\"traceSegmentId\":{\"type\":\"keyword\"},\"startTime\":{\"type\":\"date\",\"index\":\"not_analyzed\"},\"endTime\":{\"type\":\"date\",\"index\":\"not_analyzed\"},\"applicationCode\":{\"type\":\"keyword\"},\"minute\":{\"type\":\"long\",\"index\":\"not_analyzed\"},\"hour\":{\"type\":\"long\",\"index\":\"not_analyzed\"},\"day\":{\"type\":\"long\",\"index\":\"not_analyzed\"}}}", index.createMappingBuilder().string());
+    }
+
+    @Test
+    public void refreshInterval() {
+        SegmentIndex index = new SegmentIndex();
+        Assert.assertEquals(EsConfig.Es.Index.RefreshInterval.SegmentIndex.VALUE.intValue(), index.refreshInterval());
     }
 }
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/segment/SegmentPostTestCase.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/segment/SegmentPostTestCase.java
index af22a34..0155968 100644
--- a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/segment/SegmentPostTestCase.java
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/segment/SegmentPostTestCase.java
@@ -9,6 +9,9 @@
 import com.a.eye.skywalking.collector.worker.node.analysis.NodeMappingHourAnalysis;
 import com.a.eye.skywalking.collector.worker.node.analysis.NodeMappingMinuteAnalysis;
 import com.a.eye.skywalking.collector.worker.noderef.analysis.*;
+import com.a.eye.skywalking.collector.worker.segment.analysis.SegmentAnalysis;
+import com.a.eye.skywalking.collector.worker.segment.analysis.SegmentCostAnalysis;
+import com.a.eye.skywalking.collector.worker.segment.analysis.SegmentExceptionAnalysis;
 import com.a.eye.skywalking.collector.worker.segment.mock.SegmentMock;
 import com.a.eye.skywalking.collector.worker.segment.persistence.SegmentCostSave;
 import com.a.eye.skywalking.collector.worker.segment.persistence.SegmentExceptionSave;
@@ -69,9 +72,9 @@
         initNodeNodeMappingAnalysis();
         initNodeCompAnalysis();
         initNodeRefAnalysis();
-        initSegmentExceptionSave();
-        initSegmentSave();
-        initSegmentCostSave();
+        initSegmentExceptionAnalysis();
+        initSegmentAnalysis();
+        initSegmentCostAnalysis();
         initGlobalTraceAnalysis();
     }
 
@@ -83,58 +86,82 @@
 
     @Test
     public void testFactory() {
-        Assert.assertEquals(SegmentPost.class.getSimpleName(), SegmentPost.Factory.INSTANCE.role().roleName());
-        Assert.assertEquals(SegmentPost.class.getSimpleName(), SegmentPost.Factory.INSTANCE.workerInstance(null).getClass().getSimpleName());
-        Assert.assertEquals("/segments", SegmentPost.Factory.INSTANCE.servletPath());
+        SegmentPost.Factory factory = new SegmentPost.Factory();
+        Assert.assertEquals(SegmentPost.class.getSimpleName(), factory.role().roleName());
+        Assert.assertEquals(SegmentPost.class.getSimpleName(), factory.workerInstance(null).getClass().getSimpleName());
+        Assert.assertEquals("/segments", factory.servletPath());
 
         int testSize = 10;
         WorkerConfig.Queue.Segment.SegmentPost.SIZE = testSize;
-        Assert.assertEquals(testSize, SegmentPost.Factory.INSTANCE.queueSize());
+        Assert.assertEquals(testSize, factory.queueSize());
     }
 
     @Test
     public void testPreStart() throws ProviderNotFoundException {
-        when(clusterWorkerContext.findProvider(GlobalTraceAnalysis.Role.INSTANCE)).thenReturn(GlobalTraceAnalysis.Factory.INSTANCE);
-        when(clusterWorkerContext.findProvider(NodeCompAnalysis.Role.INSTANCE)).thenReturn(NodeCompAnalysis.Factory.INSTANCE);
-        when(clusterWorkerContext.findProvider(SegmentSave.Role.INSTANCE)).thenReturn(SegmentSave.Factory.INSTANCE);
-        when(clusterWorkerContext.findProvider(SegmentCostSave.Role.INSTANCE)).thenReturn(SegmentCostSave.Factory.INSTANCE);
-        when(clusterWorkerContext.findProvider(SegmentExceptionSave.Role.INSTANCE)).thenReturn(SegmentExceptionSave.Factory.INSTANCE);
+        when(clusterWorkerContext.findProvider(GlobalTraceAnalysis.Role.INSTANCE)).thenReturn(new GlobalTraceAnalysis.Factory());
+        when(clusterWorkerContext.findProvider(NodeCompAnalysis.Role.INSTANCE)).thenReturn(new NodeCompAnalysis.Factory());
 
-        NodeRefMinuteAnalysis.Factory.INSTANCE.setClusterContext(clusterWorkerContext);
-        when(clusterWorkerContext.findProvider(NodeRefResSumMinuteAnalysis.Role.INSTANCE)).thenReturn(NodeRefResSumMinuteAnalysis.Factory.INSTANCE);
-        when(clusterWorkerContext.findProvider(NodeRefMinuteAnalysis.Role.INSTANCE)).thenReturn(NodeRefMinuteAnalysis.Factory.INSTANCE);
+        SegmentAnalysis.Factory segmentAnalysisFactory = new SegmentAnalysis.Factory();
+        segmentAnalysisFactory.setClusterContext(clusterWorkerContext);
 
-        NodeRefHourAnalysis.Factory.INSTANCE.setClusterContext(clusterWorkerContext);
-        when(clusterWorkerContext.findProvider(NodeRefResSumHourAnalysis.Role.INSTANCE)).thenReturn(NodeRefResSumHourAnalysis.Factory.INSTANCE);
-        when(clusterWorkerContext.findProvider(NodeRefHourAnalysis.Role.INSTANCE)).thenReturn(NodeRefHourAnalysis.Factory.INSTANCE);
+        when(clusterWorkerContext.findProvider(SegmentAnalysis.Role.INSTANCE)).thenReturn(segmentAnalysisFactory);
 
-        NodeRefDayAnalysis.Factory.INSTANCE.setClusterContext(clusterWorkerContext);
-        when(clusterWorkerContext.findProvider(NodeRefResSumDayAnalysis.Role.INSTANCE)).thenReturn(NodeRefResSumDayAnalysis.Factory.INSTANCE);
-        when(clusterWorkerContext.findProvider(NodeRefDayAnalysis.Role.INSTANCE)).thenReturn(NodeRefDayAnalysis.Factory.INSTANCE);
+        SegmentCostAnalysis.Factory segmentCostAnalysisFactory = new SegmentCostAnalysis.Factory();
+        segmentCostAnalysisFactory.setClusterContext(clusterWorkerContext);
 
-        when(clusterWorkerContext.findProvider(NodeMappingDayAnalysis.Role.INSTANCE)).thenReturn(NodeMappingDayAnalysis.Factory.INSTANCE);
-        when(clusterWorkerContext.findProvider(NodeMappingHourAnalysis.Role.INSTANCE)).thenReturn(NodeMappingHourAnalysis.Factory.INSTANCE);
-        when(clusterWorkerContext.findProvider(NodeMappingMinuteAnalysis.Role.INSTANCE)).thenReturn(NodeMappingMinuteAnalysis.Factory.INSTANCE);
+        when(clusterWorkerContext.findProvider(SegmentCostAnalysis.Role.INSTANCE)).thenReturn(segmentCostAnalysisFactory);
+
+        SegmentExceptionAnalysis.Factory segmentExceptionAnalysisFactory = new SegmentExceptionAnalysis.Factory();
+        segmentExceptionAnalysisFactory.setClusterContext(clusterWorkerContext);
+        when(clusterWorkerContext.findProvider(SegmentExceptionAnalysis.Role.INSTANCE)).thenReturn(segmentExceptionAnalysisFactory);
+
+        NodeRefMinuteAnalysis.Factory nodeRefMinuteAnalysisFactory = new NodeRefMinuteAnalysis.Factory();
+        nodeRefMinuteAnalysisFactory.setClusterContext(clusterWorkerContext);
+        when(clusterWorkerContext.findProvider(NodeRefResSumMinuteAnalysis.Role.INSTANCE)).thenReturn(new NodeRefResSumMinuteAnalysis.Factory());
+        when(clusterWorkerContext.findProvider(NodeRefMinuteAnalysis.Role.INSTANCE)).thenReturn(nodeRefMinuteAnalysisFactory);
+
+        NodeRefHourAnalysis.Factory nodeRefHourAnalysisFactory = new NodeRefHourAnalysis.Factory();
+        nodeRefHourAnalysisFactory.setClusterContext(clusterWorkerContext);
+        when(clusterWorkerContext.findProvider(NodeRefResSumHourAnalysis.Role.INSTANCE)).thenReturn(new NodeRefResSumHourAnalysis.Factory());
+        when(clusterWorkerContext.findProvider(NodeRefHourAnalysis.Role.INSTANCE)).thenReturn(nodeRefHourAnalysisFactory);
+
+        NodeRefDayAnalysis.Factory nodeRefDayAnalysisFactory = new NodeRefDayAnalysis.Factory();
+        nodeRefDayAnalysisFactory.setClusterContext(clusterWorkerContext);
+        when(clusterWorkerContext.findProvider(NodeRefResSumDayAnalysis.Role.INSTANCE)).thenReturn(new NodeRefResSumDayAnalysis.Factory());
+        when(clusterWorkerContext.findProvider(NodeRefDayAnalysis.Role.INSTANCE)).thenReturn(nodeRefDayAnalysisFactory);
+
+        when(clusterWorkerContext.findProvider(NodeMappingDayAnalysis.Role.INSTANCE)).thenReturn(new NodeMappingDayAnalysis.Factory());
+        when(clusterWorkerContext.findProvider(NodeMappingHourAnalysis.Role.INSTANCE)).thenReturn(new NodeMappingHourAnalysis.Factory());
+        when(clusterWorkerContext.findProvider(NodeMappingMinuteAnalysis.Role.INSTANCE)).thenReturn(new NodeMappingMinuteAnalysis.Factory());
 
         ArgumentCaptor<Role> argumentCaptor = ArgumentCaptor.forClass(Role.class);
 
         segmentPost.preStart();
 
-        verify(clusterWorkerContext, times(14)).findProvider(argumentCaptor.capture());
+        verify(clusterWorkerContext, times(17)).findProvider(argumentCaptor.capture());
         Assert.assertEquals(GlobalTraceAnalysis.Role.INSTANCE.roleName(), argumentCaptor.getAllValues().get(0).roleName());
-        Assert.assertEquals(NodeCompAnalysis.Role.INSTANCE.roleName(), argumentCaptor.getAllValues().get(1).roleName());
+
+        Assert.assertEquals(SegmentAnalysis.Role.INSTANCE.roleName(), argumentCaptor.getAllValues().get(1).roleName());
         Assert.assertEquals(SegmentSave.Role.INSTANCE.roleName(), argumentCaptor.getAllValues().get(2).roleName());
-        Assert.assertEquals(SegmentCostSave.Role.INSTANCE.roleName(), argumentCaptor.getAllValues().get(3).roleName());
-        Assert.assertEquals(SegmentExceptionSave.Role.INSTANCE.roleName(), argumentCaptor.getAllValues().get(4).roleName());
-        Assert.assertEquals(NodeRefMinuteAnalysis.Role.INSTANCE.roleName(), argumentCaptor.getAllValues().get(5).roleName());
-        Assert.assertEquals(NodeRefResSumMinuteAnalysis.Role.INSTANCE.roleName(), argumentCaptor.getAllValues().get(6).roleName());
-        Assert.assertEquals(NodeRefHourAnalysis.Role.INSTANCE.roleName(), argumentCaptor.getAllValues().get(7).roleName());
-        Assert.assertEquals(NodeRefResSumHourAnalysis.Role.INSTANCE.roleName(), argumentCaptor.getAllValues().get(8).roleName());
-        Assert.assertEquals(NodeRefDayAnalysis.Role.INSTANCE.roleName(), argumentCaptor.getAllValues().get(9).roleName());
-        Assert.assertEquals(NodeRefResSumDayAnalysis.Role.INSTANCE.roleName(), argumentCaptor.getAllValues().get(10).roleName());
-        Assert.assertEquals(NodeMappingDayAnalysis.Role.INSTANCE.roleName(), argumentCaptor.getAllValues().get(11).roleName());
-        Assert.assertEquals(NodeMappingHourAnalysis.Role.INSTANCE.roleName(), argumentCaptor.getAllValues().get(12).roleName());
-        Assert.assertEquals(NodeMappingMinuteAnalysis.Role.INSTANCE.roleName(), argumentCaptor.getAllValues().get(13).roleName());
+
+        Assert.assertEquals(SegmentCostAnalysis.Role.INSTANCE.roleName(), argumentCaptor.getAllValues().get(3).roleName());
+        Assert.assertEquals(SegmentCostSave.Role.INSTANCE.roleName(), argumentCaptor.getAllValues().get(4).roleName());
+
+        Assert.assertEquals(SegmentExceptionAnalysis.Role.INSTANCE.roleName(), argumentCaptor.getAllValues().get(5).roleName());
+        Assert.assertEquals(SegmentExceptionSave.Role.INSTANCE.roleName(), argumentCaptor.getAllValues().get(6).roleName());
+
+        Assert.assertEquals(NodeRefMinuteAnalysis.Role.INSTANCE.roleName(), argumentCaptor.getAllValues().get(7).roleName());
+        Assert.assertEquals(NodeRefResSumMinuteAnalysis.Role.INSTANCE.roleName(), argumentCaptor.getAllValues().get(8).roleName());
+        Assert.assertEquals(NodeRefHourAnalysis.Role.INSTANCE.roleName(), argumentCaptor.getAllValues().get(9).roleName());
+        Assert.assertEquals(NodeRefResSumHourAnalysis.Role.INSTANCE.roleName(), argumentCaptor.getAllValues().get(10).roleName());
+        Assert.assertEquals(NodeRefDayAnalysis.Role.INSTANCE.roleName(), argumentCaptor.getAllValues().get(11).roleName());
+        Assert.assertEquals(NodeRefResSumDayAnalysis.Role.INSTANCE.roleName(), argumentCaptor.getAllValues().get(12).roleName());
+
+        Assert.assertEquals(NodeCompAnalysis.Role.INSTANCE.roleName(), argumentCaptor.getAllValues().get(13).roleName());
+
+        Assert.assertEquals(NodeMappingDayAnalysis.Role.INSTANCE.roleName(), argumentCaptor.getAllValues().get(14).roleName());
+        Assert.assertEquals(NodeMappingHourAnalysis.Role.INSTANCE.roleName(), argumentCaptor.getAllValues().get(15).roleName());
+        Assert.assertEquals(NodeMappingMinuteAnalysis.Role.INSTANCE.roleName(), argumentCaptor.getAllValues().get(16).roleName());
     }
 
     @Test
@@ -150,23 +177,27 @@
     private SegmentSaveAnswer segmentSaveAnswer_1;
     private SegmentSaveAnswer segmentSaveAnswer_2;
 
-    public void initSegmentSave() throws Exception {
-        WorkerRef segmentSave = mock(WorkerRef.class);
-        doReturn(SegmentSave.Role.INSTANCE).when(segmentSave, "getRole");
-        localWorkerContext.put(segmentSave);
+    public void initSegmentAnalysis() throws Exception {
+        when(clusterWorkerContext.findProvider(SegmentSave.Role.INSTANCE)).thenReturn(new SegmentSave.Factory());
+
+        WorkerRef segmentAnalysis = mock(WorkerRef.class);
+        doReturn(SegmentAnalysis.Role.INSTANCE).when(segmentAnalysis, "getRole");
+        localWorkerContext.put(segmentAnalysis);
 
         segmentSaveAnswer_1 = new SegmentSaveAnswer();
-        doAnswer(segmentSaveAnswer_1).when(segmentSave).tell(Mockito.argThat(new IsCacheServiceSegment_1()));
+        doAnswer(segmentSaveAnswer_1).when(segmentAnalysis).tell(Mockito.argThat(new IsCacheServiceSegment_1()));
 
         segmentSaveAnswer_2 = new SegmentSaveAnswer();
-        doAnswer(segmentSaveAnswer_2).when(segmentSave).tell(Mockito.argThat(new IsCacheServiceSegment_2()));
+        doAnswer(segmentSaveAnswer_2).when(segmentAnalysis).tell(Mockito.argThat(new IsCacheServiceSegment_2()));
     }
 
     private SegmentOtherAnswer segmentCostSaveAnswer;
 
-    public void initSegmentCostSave() throws Exception {
+    public void initSegmentCostAnalysis() throws Exception {
+        when(clusterWorkerContext.findProvider(SegmentCostSave.Role.INSTANCE)).thenReturn(new SegmentCostSave.Factory());
+
         WorkerRef segmentCostSave = mock(WorkerRef.class);
-        doReturn(SegmentCostSave.Role.INSTANCE).when(segmentCostSave, "getRole");
+        doReturn(SegmentCostAnalysis.Role.INSTANCE).when(segmentCostSave, "getRole");
         localWorkerContext.put(segmentCostSave);
 
         segmentCostSaveAnswer = new SegmentOtherAnswer();
@@ -186,9 +217,11 @@
 
     private SegmentOtherAnswer segmentExceptionSaveAnswer;
 
-    public void initSegmentExceptionSave() throws Exception {
+    public void initSegmentExceptionAnalysis() throws Exception {
+        when(clusterWorkerContext.findProvider(SegmentExceptionSave.Role.INSTANCE)).thenReturn(new SegmentExceptionSave.Factory());
+
         WorkerRef segmentExceptionSave = mock(WorkerRef.class);
-        doReturn(SegmentExceptionSave.Role.INSTANCE).when(segmentExceptionSave, "getRole");
+        doReturn(SegmentExceptionAnalysis.Role.INSTANCE).when(segmentExceptionSave, "getRole");
         localWorkerContext.put(segmentExceptionSave);
 
         segmentExceptionSaveAnswer = new SegmentOtherAnswer();
@@ -260,7 +293,7 @@
         doAnswer(nodeMappingDayAnalysisAnswer).when(nodeMappingDayAnalysis).tell(Mockito.argThat(new IsSegmentWithTimeSlice()));
     }
 
-    @Test
+    //    @Test
     public void testOnReceive() throws Exception {
         String cacheServiceSegmentAsString = segmentMock.mockCacheServiceSegmentAsString();
 
@@ -305,7 +338,7 @@
 
         @Override
         public Object answer(InvocationOnMock invocation) throws Throwable {
-            segmentWithTimeSlice = (SegmentPost.SegmentWithTimeSlice)invocation.getArguments()[0];
+            segmentWithTimeSlice = (SegmentPost.SegmentWithTimeSlice) invocation.getArguments()[0];
             return null;
         }
     }
@@ -317,7 +350,7 @@
 
         @Override
         public Object answer(InvocationOnMock invocation) throws Throwable {
-            JsonObject jsonObject = (JsonObject)invocation.getArguments()[0];
+            JsonObject jsonObject = (JsonObject) invocation.getArguments()[0];
             logger.info("SegmentSave json: " + jsonObject.toString());
             minute = jsonObject.get("minute").getAsLong();
             hour = jsonObject.get("hour").getAsLong();
@@ -330,7 +363,7 @@
         private static final String SegId = "Segment.1490922929258.927784221.5991.27.1";
 
         public boolean matches(Object para) {
-            JsonObject paraJson = (JsonObject)para;
+            JsonObject paraJson = (JsonObject) para;
             return SegId.equals(paraJson.get("ts").getAsString());
         }
     }
@@ -339,7 +372,7 @@
         private static final String SegId = "Segment.1490922929298.927784221.5991.28.1";
 
         public boolean matches(Object para) {
-            JsonObject paraJson = (JsonObject)para;
+            JsonObject paraJson = (JsonObject) para;
             return SegId.equals(paraJson.get("ts").getAsString());
         }
     }
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/segment/SegmentRealPost.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/segment/SegmentRealPost.java
index 6595383..555e742 100644
--- a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/segment/SegmentRealPost.java
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/segment/SegmentRealPost.java
@@ -16,13 +16,13 @@
 //        HttpClientTools.INSTANCE.post("http://localhost:7001/segments", portalServiceExceptionSegmentAsString);
 
         String cacheServiceSegmentAsString = mock.mockCacheServiceSegmentAsString();
-        HttpClientTools.INSTANCE.post("http://localhost:7001/segments", cacheServiceSegmentAsString);
+        HttpClientTools.INSTANCE.post("http://localhost:12800/segments", cacheServiceSegmentAsString);
 
         String persistenceServiceSegmentAsString = mock.mockPersistenceServiceSegmentAsString();
-        HttpClientTools.INSTANCE.post("http://localhost:7001/segments", persistenceServiceSegmentAsString);
+        HttpClientTools.INSTANCE.post("http://localhost:12800/segments", persistenceServiceSegmentAsString);
 
         String portalServiceSegmentAsString = mock.mockPortalServiceSegmentAsString();
-        HttpClientTools.INSTANCE.post("http://localhost:7001/segments", portalServiceSegmentAsString);
+        HttpClientTools.INSTANCE.post("http://localhost:12800/segments", portalServiceSegmentAsString);
 
 //        String specialSegmentAsString = mock.mockSpecialSegmentAsString();
 //        HttpClientTools.INSTANCE.post("http://localhost:7001/segments", specialSegmentAsString);
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/segment/SegmentTopGetWithGlobalTraceIdTestCase.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/segment/SegmentTopGetWithGlobalTraceIdTestCase.java
index 1310663..7128690 100644
--- a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/segment/SegmentTopGetWithGlobalTraceIdTestCase.java
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/segment/SegmentTopGetWithGlobalTraceIdTestCase.java
@@ -64,18 +64,22 @@
 
     @Test
     public void testFactory() {
-        Assert.assertEquals(SegmentTopGetWithGlobalTraceId.class.getSimpleName(), SegmentTopGetWithGlobalTraceId.Factory.INSTANCE.role().roleName());
-        Assert.assertEquals(SegmentTopGetWithGlobalTraceId.class.getSimpleName(), SegmentTopGetWithGlobalTraceId.Factory.INSTANCE.workerInstance(null).getClass().getSimpleName());
-        Assert.assertEquals("/segments/top/globalTraceId", SegmentTopGetWithGlobalTraceId.Factory.INSTANCE.servletPath());
+        SegmentTopGetWithGlobalTraceId.Factory factory = new SegmentTopGetWithGlobalTraceId.Factory();
+        Assert.assertEquals(SegmentTopGetWithGlobalTraceId.class.getSimpleName(), factory.role().roleName());
+        Assert.assertEquals(SegmentTopGetWithGlobalTraceId.class.getSimpleName(), factory.workerInstance(null).getClass().getSimpleName());
+        Assert.assertEquals("/segments/top/globalTraceId", factory.servletPath());
     }
 
     @Test
     public void testPreStart() throws ProviderNotFoundException {
         ClusterWorkerContext exceptionContext = PowerMockito.mock(ClusterWorkerContext.class);
-        when(exceptionContext.findProvider(SegmentExceptionWithSegId.WorkerRole.INSTANCE)).thenReturn(SegmentExceptionWithSegId.Factory.INSTANCE);
-        SegmentTopSearchWithGlobalTraceId.Factory.INSTANCE.setClusterContext(exceptionContext);
+        SegmentExceptionWithSegId.Factory factory = new SegmentExceptionWithSegId.Factory();
+        when(exceptionContext.findProvider(SegmentExceptionWithSegId.WorkerRole.INSTANCE)).thenReturn(factory);
 
-        when(clusterWorkerContext.findProvider(SegmentTopSearchWithGlobalTraceId.WorkerRole.INSTANCE)).thenReturn(SegmentTopSearchWithGlobalTraceId.Factory.INSTANCE);
+        SegmentTopSearchWithGlobalTraceId.Factory factory1 = new SegmentTopSearchWithGlobalTraceId.Factory();
+        factory1.setClusterContext(exceptionContext);
+
+        when(clusterWorkerContext.findProvider(SegmentTopSearchWithGlobalTraceId.WorkerRole.INSTANCE)).thenReturn(factory1);
 
         ArgumentCaptor<SegmentTopSearchWithGlobalTraceId.WorkerRole> argumentCaptor = ArgumentCaptor.forClass(SegmentTopSearchWithGlobalTraceId.WorkerRole.class);
         getObj.preStart();
@@ -135,7 +139,7 @@
 
         @Override
         public Object answer(InvocationOnMock invocation) throws Throwable {
-            SegmentTopSearchWithGlobalTraceId.RequestEntity requestEntity = (SegmentTopSearchWithGlobalTraceId.RequestEntity)invocation.getArguments()[0];
+            SegmentTopSearchWithGlobalTraceId.RequestEntity requestEntity = (SegmentTopSearchWithGlobalTraceId.RequestEntity) invocation.getArguments()[0];
             Assert.assertEquals("TestId", requestEntity.getGlobalTraceId());
             Assert.assertEquals(20, requestEntity.getFrom());
             Assert.assertEquals(50, requestEntity.getLimit());
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/segment/SegmentTopGetWithTimeSliceTestCase.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/segment/SegmentTopGetWithTimeSliceTestCase.java
index a1fee3f..5fad718 100644
--- a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/segment/SegmentTopGetWithTimeSliceTestCase.java
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/segment/SegmentTopGetWithTimeSliceTestCase.java
@@ -64,18 +64,22 @@
 
     @Test
     public void testFactory() {
-        Assert.assertEquals(SegmentTopGetWithTimeSlice.class.getSimpleName(), SegmentTopGetWithTimeSlice.Factory.INSTANCE.role().roleName());
-        Assert.assertEquals(SegmentTopGetWithTimeSlice.class.getSimpleName(), SegmentTopGetWithTimeSlice.Factory.INSTANCE.workerInstance(null).getClass().getSimpleName());
-        Assert.assertEquals("/segments/top/timeSlice", SegmentTopGetWithTimeSlice.Factory.INSTANCE.servletPath());
+        SegmentTopGetWithTimeSlice.Factory factory = new SegmentTopGetWithTimeSlice.Factory();
+        Assert.assertEquals(SegmentTopGetWithTimeSlice.class.getSimpleName(), factory.role().roleName());
+        Assert.assertEquals(SegmentTopGetWithTimeSlice.class.getSimpleName(), factory.workerInstance(null).getClass().getSimpleName());
+        Assert.assertEquals("/segments/top/timeSlice", factory.servletPath());
     }
 
     @Test
     public void testPreStart() throws ProviderNotFoundException {
         ClusterWorkerContext exceptionContext = PowerMockito.mock(ClusterWorkerContext.class);
-        when(exceptionContext.findProvider(SegmentExceptionWithSegId.WorkerRole.INSTANCE)).thenReturn(SegmentExceptionWithSegId.Factory.INSTANCE);
-        SegmentTopSearchWithTimeSlice.Factory.INSTANCE.setClusterContext(exceptionContext);
+        SegmentExceptionWithSegId.Factory factory = new SegmentExceptionWithSegId.Factory();
+        when(exceptionContext.findProvider(SegmentExceptionWithSegId.WorkerRole.INSTANCE)).thenReturn(factory);
 
-        when(clusterWorkerContext.findProvider(SegmentTopSearchWithTimeSlice.WorkerRole.INSTANCE)).thenReturn(SegmentTopSearchWithTimeSlice.Factory.INSTANCE);
+        SegmentTopSearchWithTimeSlice.Factory factory1 = new SegmentTopSearchWithTimeSlice.Factory();
+        factory1.setClusterContext(exceptionContext);
+
+        when(clusterWorkerContext.findProvider(SegmentTopSearchWithTimeSlice.WorkerRole.INSTANCE)).thenReturn(factory1);
 
         ArgumentCaptor<SegmentTopSearchWithTimeSlice.WorkerRole> argumentCaptor = ArgumentCaptor.forClass(SegmentTopSearchWithTimeSlice.WorkerRole.class);
         getObj.preStart();
@@ -150,7 +154,7 @@
 
         @Override
         public Object answer(InvocationOnMock invocation) throws Throwable {
-            SegmentTopSearchWithTimeSlice.RequestEntity requestEntity = (SegmentTopSearchWithTimeSlice.RequestEntity)invocation.getArguments()[0];
+            SegmentTopSearchWithTimeSlice.RequestEntity requestEntity = (SegmentTopSearchWithTimeSlice.RequestEntity) invocation.getArguments()[0];
             Assert.assertEquals(10, requestEntity.getStartTime());
             Assert.assertEquals(20, requestEntity.getEndTime());
             Assert.assertEquals(30, requestEntity.getFrom());
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/segment/analysis/SegmentCostAnalysisTestCase.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/segment/analysis/SegmentCostAnalysisTestCase.java
new file mode 100644
index 0000000..3ad7b0a
--- /dev/null
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/segment/analysis/SegmentCostAnalysisTestCase.java
@@ -0,0 +1,35 @@
+package com.a.eye.skywalking.collector.worker.segment.analysis;
+
+import com.a.eye.skywalking.collector.actor.LocalSyncWorkerRef;
+import com.a.eye.skywalking.collector.actor.LocalWorkerContext;
+import com.a.eye.skywalking.collector.actor.WorkerNotFoundException;
+import com.a.eye.skywalking.collector.actor.WorkerRef;
+import com.a.eye.skywalking.collector.actor.WorkerRefs;
+import com.a.eye.skywalking.collector.worker.segment.persistence.SegmentCostSave;
+import java.lang.reflect.Field;
+import java.util.List;
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * @author pengys5
+ */
+public class SegmentCostAnalysisTestCase {
+
+    @Test
+    public void aggWorkRefs() throws WorkerNotFoundException, NoSuchFieldException, IllegalAccessException {
+        LocalWorkerContext localWorkerContext = new LocalWorkerContext();
+
+        WorkerRef workerRef = new LocalSyncWorkerRef(SegmentCostSave.Role.INSTANCE, null);
+        localWorkerContext.put(workerRef);
+
+        SegmentCostAnalysis analysis = new SegmentCostAnalysis(SegmentCostAnalysis.Role.INSTANCE, null, localWorkerContext);
+        WorkerRefs workerRefs = analysis.aggWorkRefs();
+
+        Field testAField = workerRefs.getClass().getDeclaredField("workerRefs");
+        testAField.setAccessible(true);
+        List<LocalSyncWorkerRef> list = (List<LocalSyncWorkerRef>)testAField.get(workerRefs);
+
+        Assert.assertEquals(workerRef, list.get(0));
+    }
+}
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/segment/entity/LogDataTestCase.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/segment/entity/LogDataTestCase.java
new file mode 100644
index 0000000..63bd6ee
--- /dev/null
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/segment/entity/LogDataTestCase.java
@@ -0,0 +1,29 @@
+package com.a.eye.skywalking.collector.worker.segment.entity;
+
+import com.google.gson.stream.JsonReader;
+import java.io.IOException;
+import java.io.StringReader;
+import java.util.Map;
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * @author pengys5
+ */
+public class LogDataTestCase {
+
+    @Test
+    public void deserialize() throws IOException {
+        LogData logData = new LogData();
+
+        JsonReader reader = new JsonReader(new StringReader("{\"tm\":1, \"fi\": {\"test1\":\"test1\",\"test2\":\"test2\"}, \"skip\":\"skip\"}"));
+        logData.deserialize(reader);
+
+        Assert.assertEquals(1L, logData.getTime());
+
+        Map<String, String> fields = logData.getFields();
+        Assert.assertEquals("test1", fields.get("test1"));
+        Assert.assertEquals("test2", fields.get("test2"));
+        Assert.assertEquals(false, fields.containsKey("skip"));
+    }
+}
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/segment/entity/SpanViewTestCase.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/segment/entity/SpanViewTestCase.java
new file mode 100644
index 0000000..b98186c
--- /dev/null
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/segment/entity/SpanViewTestCase.java
@@ -0,0 +1,37 @@
+package com.a.eye.skywalking.collector.worker.segment.entity;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * @author pengys5
+ */
+public class SpanViewTestCase {
+
+    @Test
+    public void test() {
+        SpanView spanView = new SpanView();
+        spanView.setSpanId(1);
+        Assert.assertEquals(1, spanView.getSpanId());
+
+        spanView.setSegId("1");
+        Assert.assertEquals("1", spanView.getSegId());
+
+        spanView.setAppCode("2");
+        Assert.assertEquals("2", spanView.getAppCode());
+
+        spanView.setRelativeStartTime(10L);
+        Assert.assertEquals(10L, spanView.getRelativeStartTime());
+
+        spanView.setCost(20L);
+        Assert.assertEquals(20L, spanView.getCost());
+
+        spanView.setOperationName("3");
+        Assert.assertEquals("3", spanView.getOperationName());
+
+        SpanView child = new SpanView();
+        spanView.addChild(child);
+
+        spanView.compareTo(child);
+    }
+}
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/segment/entity/TraceSegmentRefTestCase.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/segment/entity/TraceSegmentRefTestCase.java
new file mode 100644
index 0000000..6bb6a0e
--- /dev/null
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/segment/entity/TraceSegmentRefTestCase.java
@@ -0,0 +1,25 @@
+package com.a.eye.skywalking.collector.worker.segment.entity;
+
+import com.google.gson.stream.JsonReader;
+import java.io.IOException;
+import java.io.StringReader;
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * @author pengys5
+ */
+public class TraceSegmentRefTestCase {
+
+    @Test
+    public void deserialize() throws IOException {
+        TraceSegmentRef traceSegmentRef = new TraceSegmentRef();
+        JsonReader reader = new JsonReader(new StringReader("{\"ts\" :\"ts\",\"si\":0,\"ac\":\"ac\",\"ph\":\"ph\", \"skip\":\"skip\"}"));
+        traceSegmentRef.deserialize(reader);
+
+        Assert.assertEquals("ts", traceSegmentRef.getTraceSegmentId());
+        Assert.assertEquals("ac", traceSegmentRef.getApplicationCode());
+        Assert.assertEquals("ph", traceSegmentRef.getPeerHost());
+        Assert.assertEquals(0, traceSegmentRef.getSpanId());
+    }
+}
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/segment/entity/tag/BooleanTagTestCase.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/segment/entity/tag/BooleanTagTestCase.java
new file mode 100644
index 0000000..41ca798
--- /dev/null
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/segment/entity/tag/BooleanTagTestCase.java
@@ -0,0 +1,31 @@
+package com.a.eye.skywalking.collector.worker.segment.entity.tag;
+
+import com.a.eye.skywalking.collector.worker.segment.entity.Span;
+import java.lang.reflect.Field;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * @author pengys5
+ */
+public class BooleanTagTestCase {
+
+    @Test
+    public void test() throws NoSuchFieldException, IllegalAccessException {
+        BooleanTag booleanTag = new BooleanTag("test", false);
+
+        Map<String, Boolean> tagsWithInt = new LinkedHashMap<>();
+
+        Span span = new Span();
+        Field testAField = span.getClass().getDeclaredField("tagsWithBool");
+        testAField.setAccessible(true);
+        testAField.set(span, tagsWithInt);
+
+        Assert.assertEquals(false, booleanTag.get(span));
+
+        tagsWithInt.put("test", true);
+        Assert.assertEquals(true, booleanTag.get(span));
+    }
+}
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/segment/entity/tag/IntTagTestCase.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/segment/entity/tag/IntTagTestCase.java
new file mode 100644
index 0000000..8d739bf
--- /dev/null
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/segment/entity/tag/IntTagTestCase.java
@@ -0,0 +1,31 @@
+package com.a.eye.skywalking.collector.worker.segment.entity.tag;
+
+import com.a.eye.skywalking.collector.worker.segment.entity.Span;
+import java.lang.reflect.Field;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * @author pengys5
+ */
+public class IntTagTestCase {
+
+    @Test
+    public void test() throws NoSuchFieldException, IllegalAccessException {
+        IntTag intTag = new IntTag("test");
+
+        Map<String, Integer> tagsWithInt = new LinkedHashMap<>();
+
+        Span span = new Span();
+        Field testAField = span.getClass().getDeclaredField("tagsWithInt");
+        testAField.setAccessible(true);
+        testAField.set(span, tagsWithInt);
+
+        Assert.assertEquals(null, intTag.get(span));
+
+        tagsWithInt.put("test", 10);
+        Assert.assertEquals(10, intTag.get(span).intValue());
+    }
+}
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/segment/entity/tag/ShortTagTestCase.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/segment/entity/tag/ShortTagTestCase.java
new file mode 100644
index 0000000..61cedbc
--- /dev/null
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/segment/entity/tag/ShortTagTestCase.java
@@ -0,0 +1,35 @@
+package com.a.eye.skywalking.collector.worker.segment.entity.tag;
+
+import com.a.eye.skywalking.collector.worker.segment.entity.Span;
+import com.a.eye.skywalking.collector.worker.storage.SegmentData;
+import com.a.eye.skywalking.collector.worker.storage.WindowData;
+import java.lang.reflect.Field;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * @author pengys5
+ */
+public class ShortTagTestCase {
+
+    @Test
+    public void test() throws NoSuchFieldException, IllegalAccessException {
+        ShortTag shortTag = new ShortTag("short");
+
+        Map<String, Integer> tagsWithInt = new LinkedHashMap<>();
+
+        Span span = new Span();
+        Field testAField = span.getClass().getDeclaredField("tagsWithInt");
+        testAField.setAccessible(true);
+        testAField.set(span, tagsWithInt);
+
+        Short tag = shortTag.get(span);
+        Assert.assertEquals(null, tag);
+
+        tagsWithInt.put("short", 10);
+        tag = shortTag.get(span);
+        Assert.assertEquals(10, tag.intValue());
+    }
+}
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/segment/entity/tag/TagsTestCase.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/segment/entity/tag/TagsTestCase.java
new file mode 100644
index 0000000..5dafb8b
--- /dev/null
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/segment/entity/tag/TagsTestCase.java
@@ -0,0 +1,28 @@
+package com.a.eye.skywalking.collector.worker.segment.entity.tag;
+
+import com.a.eye.skywalking.collector.worker.segment.entity.Span;
+import java.lang.reflect.Field;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * @author pengys5
+ */
+public class TagsTestCase {
+
+    @Test
+    public void test() throws NoSuchFieldException, IllegalAccessException {
+        Span span = new Span();
+
+        Map<String, String> tagsWithStr = new LinkedHashMap<>();
+        tagsWithStr.put("span.layer", "db");
+
+        Field testAField = span.getClass().getDeclaredField("tagsWithStr");
+        testAField.setAccessible(true);
+        testAField.set(span, tagsWithStr);
+
+        Assert.assertEquals("db", Tags.SPAN_LAYER.get(span));
+    }
+}
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/segment/mock/SegmentMock.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/segment/mock/SegmentMock.java
index e221959..14b6cfd 100644
--- a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/segment/mock/SegmentMock.java
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/segment/mock/SegmentMock.java
@@ -3,13 +3,10 @@
 import com.a.eye.skywalking.collector.queue.EndOfBatchCommand;
 import com.a.eye.skywalking.collector.worker.AnalysisMember;
 import com.a.eye.skywalking.collector.worker.segment.SegmentPost;
+import com.a.eye.skywalking.collector.worker.segment.entity.Segment;
+import com.a.eye.skywalking.collector.worker.segment.entity.SegmentDeserialize;
 import com.a.eye.skywalking.collector.worker.tools.DateTools;
 import com.a.eye.skywalking.collector.worker.tools.JsonFileReader;
-import com.a.eye.skywalking.trace.SegmentsMessage;
-import com.a.eye.skywalking.trace.TraceSegment;
-import com.google.gson.Gson;
-import org.apache.logging.log4j.LogManager;
-import org.apache.logging.log4j.Logger;
 
 import java.io.FileNotFoundException;
 import java.util.ArrayList;
@@ -19,10 +16,6 @@
  * @author pengys5
  */
 public class SegmentMock {
-
-    private Logger logger = LogManager.getFormatterLogger(SegmentMock.class);
-
-    private Gson gson = new Gson();
     private String path = this.getClass().getResource("/").getPath();
 
     private final String CacheServiceJsonFile = path + "/json/segment/post/normal/cache-service.json";
@@ -38,10 +31,6 @@
         return JsonFileReader.INSTANCE.read(path + fileName);
     }
 
-    public String mockSpecialSegmentAsString() throws FileNotFoundException {
-        return JsonFileReader.INSTANCE.read(SpecialJsonFile);
-    }
-
     public String mockCacheServiceSegmentAsString() throws FileNotFoundException {
         return JsonFileReader.INSTANCE.read(CacheServiceJsonFile);
     }
@@ -54,69 +43,44 @@
         return JsonFileReader.INSTANCE.read(PortalServiceJsonFile);
     }
 
-    public String mockCacheServiceExceptionSegmentAsString() throws FileNotFoundException {
-        return JsonFileReader.INSTANCE.read(CacheServiceExceptionJsonFile);
+    public List<SegmentPost.SegmentWithTimeSlice> mockCacheServiceExceptionSegmentTimeSlice() throws Exception {
+        return createSegmentWithTimeSliceList(CacheServiceExceptionJsonFile);
     }
 
-    public String mockPortalServiceExceptionSegmentAsString() throws FileNotFoundException {
-        return JsonFileReader.INSTANCE.read(PortalServiceExceptionJsonFile);
+    public List<SegmentPost.SegmentWithTimeSlice> mockPortalServiceExceptionSegmentTimeSlice() throws Exception {
+        return createSegmentWithTimeSliceList(PortalServiceExceptionJsonFile);
     }
 
-    public List<SegmentPost.SegmentWithTimeSlice> mockSpecialSegmentTimeSlice() throws FileNotFoundException {
-        String specialSegmentAsString = mockSpecialSegmentAsString();
-        logger.debug(specialSegmentAsString);
-        return createSegmentWithTimeSliceList(specialSegmentAsString);
+    public List<SegmentPost.SegmentWithTimeSlice> mockCacheServiceSegmentSegmentTimeSlice() throws Exception {
+        return createSegmentWithTimeSliceList(CacheServiceJsonFile);
     }
 
-    public List<SegmentPost.SegmentWithTimeSlice> mockCacheServiceExceptionSegmentTimeSlice() throws FileNotFoundException {
-        String cacheServiceExceptionSegmentAsString = mockCacheServiceExceptionSegmentAsString();
-        logger.debug(cacheServiceExceptionSegmentAsString);
-        return createSegmentWithTimeSliceList(cacheServiceExceptionSegmentAsString);
+    public List<SegmentPost.SegmentWithTimeSlice> mockPersistenceServiceSegmentTimeSlice() throws Exception {
+        return createSegmentWithTimeSliceList(PersistenceServiceJsonFile);
     }
 
-    public List<SegmentPost.SegmentWithTimeSlice> mockPortalServiceExceptionSegmentTimeSlice() throws FileNotFoundException {
-        String portalServiceExceptionSegmentAsString = mockPortalServiceExceptionSegmentAsString();
-        logger.debug(portalServiceExceptionSegmentAsString);
-        return createSegmentWithTimeSliceList(portalServiceExceptionSegmentAsString);
+    public List<SegmentPost.SegmentWithTimeSlice> mockPortalServiceSegmentSegmentTimeSlice() throws Exception {
+        return createSegmentWithTimeSliceList(PortalServiceJsonFile);
     }
 
-    public List<SegmentPost.SegmentWithTimeSlice> mockCacheServiceSegmentSegmentTimeSlice() throws FileNotFoundException {
-        String cacheServiceSegmentAsString = mockCacheServiceSegmentAsString();
-        logger.debug(cacheServiceSegmentAsString);
-        return createSegmentWithTimeSliceList(cacheServiceSegmentAsString);
-    }
-
-    public List<SegmentPost.SegmentWithTimeSlice> mockPersistenceServiceSegmentTimeSlice() throws FileNotFoundException {
-        String persistenceServiceSegmentAsString = mockPersistenceServiceSegmentAsString();
-        logger.debug(persistenceServiceSegmentAsString);
-        return createSegmentWithTimeSliceList(persistenceServiceSegmentAsString);
-    }
-
-    public List<SegmentPost.SegmentWithTimeSlice> mockPortalServiceSegmentSegmentTimeSlice() throws FileNotFoundException {
-        String portalServiceSegmentAsString = mockPortalServiceSegmentAsString();
-        logger.debug(portalServiceSegmentAsString);
-        return createSegmentWithTimeSliceList(portalServiceSegmentAsString);
-    }
-
-    private List<SegmentPost.SegmentWithTimeSlice> createSegmentWithTimeSliceList(String segmentJsonStr) {
-        SegmentsMessage segmentsMessage = gson.fromJson(segmentJsonStr, SegmentsMessage.class);
-        List<TraceSegment> segmentList = segmentsMessage.getSegments();
+    private List<SegmentPost.SegmentWithTimeSlice> createSegmentWithTimeSliceList(String jsonFilePath) throws Exception {
+        List<Segment> segmentList = SegmentDeserialize.INSTANCE.deserializeMultiple(jsonFilePath);
 
         List<SegmentPost.SegmentWithTimeSlice> segmentWithTimeSliceList = new ArrayList<>();
-        for (TraceSegment newSegment : segmentList) {
-            SegmentPost.SegmentWithTimeSlice segmentWithTimeSlice = createSegmentWithTimeSlice(newSegment);
+        for (Segment segment : segmentList) {
+            SegmentPost.SegmentWithTimeSlice segmentWithTimeSlice = createSegmentWithTimeSlice(segment);
             segmentWithTimeSliceList.add(segmentWithTimeSlice);
         }
         return segmentWithTimeSliceList;
     }
 
-    private SegmentPost.SegmentWithTimeSlice createSegmentWithTimeSlice(TraceSegment newSegment) {
-        long minuteSlice = DateTools.getMinuteSlice(newSegment.getStartTime());
-        long hourSlice = DateTools.getHourSlice(newSegment.getStartTime());
-        long daySlice = DateTools.getDaySlice(newSegment.getStartTime());
-        int second = DateTools.getSecond(newSegment.getStartTime());
+    private SegmentPost.SegmentWithTimeSlice createSegmentWithTimeSlice(Segment segment) {
+        long minuteSlice = DateTools.getMinuteSlice(segment.getStartTime());
+        long hourSlice = DateTools.getHourSlice(segment.getStartTime());
+        long daySlice = DateTools.getDaySlice(segment.getStartTime());
+        int second = DateTools.getSecond(segment.getStartTime());
 
-        SegmentPost.SegmentWithTimeSlice segmentWithTimeSlice = new SegmentPost.SegmentWithTimeSlice(newSegment, minuteSlice, hourSlice, daySlice, second);
+        SegmentPost.SegmentWithTimeSlice segmentWithTimeSlice = new SegmentPost.SegmentWithTimeSlice(segment, minuteSlice, hourSlice, daySlice, second);
         return segmentWithTimeSlice;
     }
 
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/segment/persistence/SegmentCostSaveTestCase.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/segment/persistence/SegmentCostSaveTestCase.java
index d0ea11e..a29a164 100644
--- a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/segment/persistence/SegmentCostSaveTestCase.java
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/segment/persistence/SegmentCostSaveTestCase.java
@@ -3,17 +3,11 @@
 import com.a.eye.skywalking.collector.actor.ClusterWorkerContext;
 import com.a.eye.skywalking.collector.actor.LocalWorkerContext;
 import com.a.eye.skywalking.collector.actor.selector.RollingSelector;
-import com.a.eye.skywalking.collector.worker.config.CacheSizeConfig;
-import com.a.eye.skywalking.collector.worker.config.WorkerConfig;
 import com.a.eye.skywalking.collector.worker.mock.MockEsBulkClient;
 import com.a.eye.skywalking.collector.worker.mock.SaveToEsSourceAnswer;
 import com.a.eye.skywalking.collector.worker.segment.SegmentCostIndex;
-import com.a.eye.skywalking.collector.worker.segment.SegmentPost;
 import com.a.eye.skywalking.collector.worker.segment.mock.SegmentMock;
 import com.a.eye.skywalking.collector.worker.storage.EsClient;
-import com.a.eye.skywalking.collector.worker.tools.DateTools;
-import com.google.gson.JsonArray;
-import com.google.gson.JsonObject;
 import org.apache.logging.log4j.LogManager;
 import org.elasticsearch.client.Client;
 import org.junit.Assert;
@@ -25,7 +19,6 @@
 import org.powermock.core.classloader.annotations.PrepareForTest;
 import org.powermock.modules.junit4.PowerMockRunner;
 
-import java.util.List;
 import java.util.TimeZone;
 
 import static org.powermock.api.mockito.PowerMockito.when;
@@ -77,136 +70,8 @@
 
     @Test
     public void testFactory() {
-        Assert.assertEquals(SegmentCostSave.class.getSimpleName(), SegmentCostSave.Factory.INSTANCE.role().roleName());
-        Assert.assertEquals(SegmentCostSave.class.getSimpleName(), SegmentCostSave.Factory.INSTANCE.workerInstance(null).getClass().getSimpleName());
-
-        int testSize = 10;
-        WorkerConfig.Queue.Segment.SegmentCostSave.SIZE = testSize;
-        Assert.assertEquals(testSize, SegmentCostSave.Factory.INSTANCE.queueSize());
-    }
-
-    @Test
-    public void testPersistenceServiceAnalyse() throws Exception {
-        CacheSizeConfig.Cache.Persistence.SIZE = 1;
-
-        List<SegmentPost.SegmentWithTimeSlice> segmentWithTimeSliceList = segmentMock.mockPersistenceServiceSegmentTimeSlice();
-
-        for (SegmentPost.SegmentWithTimeSlice segmentWithTimeSlice : segmentWithTimeSliceList) {
-            segmentCostSave.analyse(segmentWithTimeSlice);
-        }
-
-        JsonArray sourceArray = saveToEsSourceAnswer.sourceObj.getSource();
-        Assert.assertEquals(1, sourceArray.size());
-
-        JsonObject costJsonObj = sourceArray.get(0).getAsJsonObject();
-        Assert.assertEquals("Segment.1490922929274.1382198130.5997.47.1", costJsonObj.get("segId").getAsString());
-        Assert.assertEquals(1490922929274L, costJsonObj.get("startTime").getAsLong());
-        Assert.assertEquals(1490922929288L, costJsonObj.get("END_TIME").getAsLong());
-        Assert.assertEquals("/persistence/query", costJsonObj.get("operationName").getAsString());
-        Assert.assertEquals(DateTools.changeToUTCSlice(201703310915L), costJsonObj.get("timeSlice").getAsLong());
-        Assert.assertEquals(14, costJsonObj.get("cost").getAsInt());
-    }
-
-    @Test
-    public void testCacheServiceAnalyse() throws Exception {
-        CacheSizeConfig.Cache.Persistence.SIZE = 2;
-
-        List<SegmentPost.SegmentWithTimeSlice> segmentWithTimeSliceList = segmentMock.mockCacheServiceSegmentSegmentTimeSlice();
-
-        for (SegmentPost.SegmentWithTimeSlice segmentWithTimeSlice : segmentWithTimeSliceList) {
-            segmentCostSave.analyse(segmentWithTimeSlice);
-        }
-
-        JsonArray sourceArray = saveToEsSourceAnswer.sourceObj.getSource();
-        Assert.assertEquals(2, sourceArray.size());
-
-        JsonObject costJsonObj_0 = null;
-        JsonObject costJsonObj_1 = null;
-        for (int i = 0; i < sourceArray.size(); i++) {
-            JsonObject costJsonObj = sourceArray.get(i).getAsJsonObject();
-            if (costJsonObj.get("segId").getAsString().equals("Segment.1490922929258.927784221.5991.27.1")) {
-                costJsonObj_0 = costJsonObj;
-            } else if (costJsonObj.get("segId").getAsString().equals("Segment.1490922929298.927784221.5991.28.1")) {
-                costJsonObj_1 = costJsonObj;
-            }
-        }
-
-        Assert.assertEquals(1490922929258L, costJsonObj_0.get("startTime").getAsLong());
-        Assert.assertEquals(1490922929261L, costJsonObj_0.get("END_TIME").getAsLong());
-        Assert.assertEquals("com.a.eye.skywalking.test.cache.CacheService.findCache(java.lang.String)", costJsonObj_0.get("operationName").getAsString());
-        Assert.assertEquals(DateTools.changeToUTCSlice(201703310915L), costJsonObj_0.get("timeSlice").getAsLong());
-        Assert.assertEquals(3, costJsonObj_0.get("cost").getAsInt());
-
-        Assert.assertEquals(1490922929298L, costJsonObj_1.get("startTime").getAsLong());
-        Assert.assertEquals(1490922929303L, costJsonObj_1.get("END_TIME").getAsLong());
-        Assert.assertEquals("com.a.eye.skywalking.test.cache.CacheService.updateCache(java.lang.String,java.lang.String)", costJsonObj_1.get("operationName").getAsString());
-        Assert.assertEquals(DateTools.changeToUTCSlice(201703310915L), costJsonObj_1.get("timeSlice").getAsLong());
-        Assert.assertEquals(5, costJsonObj_1.get("cost").getAsInt());
-    }
-
-    @Test
-    public void testPortalServiceAnalyse() throws Exception {
-        CacheSizeConfig.Cache.Persistence.SIZE = 1;
-
-        List<SegmentPost.SegmentWithTimeSlice> segmentWithTimeSliceList = segmentMock.mockPortalServiceSegmentSegmentTimeSlice();
-
-        for (SegmentPost.SegmentWithTimeSlice segmentWithTimeSlice : segmentWithTimeSliceList) {
-            segmentCostSave.analyse(segmentWithTimeSlice);
-        }
-
-        JsonArray sourceArray = saveToEsSourceAnswer.sourceObj.getSource();
-        Assert.assertEquals(1, sourceArray.size());
-
-        JsonObject costJsonObj = sourceArray.get(0).getAsJsonObject();
-        Assert.assertEquals("Segment.1490922929254.1797892356.6003.69.1", costJsonObj.get("segId").getAsString());
-        Assert.assertEquals(1490922929254L, costJsonObj.get("startTime").getAsLong());
-        Assert.assertEquals(1490922929306L, costJsonObj.get("END_TIME").getAsLong());
-        Assert.assertEquals("/portal/", costJsonObj.get("operationName").getAsString());
-        Assert.assertEquals(DateTools.changeToUTCSlice(201703310915L), costJsonObj.get("timeSlice").getAsLong());
-        Assert.assertEquals(52, costJsonObj.get("cost").getAsInt());
-    }
-
-    @Test
-    public void testCacheServiceExceptionAnalyse() throws Exception {
-        CacheSizeConfig.Cache.Persistence.SIZE = 1;
-
-        List<SegmentPost.SegmentWithTimeSlice> segmentWithTimeSliceList = segmentMock.mockCacheServiceExceptionSegmentTimeSlice();
-
-        for (SegmentPost.SegmentWithTimeSlice segmentWithTimeSlice : segmentWithTimeSliceList) {
-            segmentCostSave.analyse(segmentWithTimeSlice);
-        }
-
-        JsonArray sourceArray = saveToEsSourceAnswer.sourceObj.getSource();
-        Assert.assertEquals(1, sourceArray.size());
-
-        JsonObject costJsonObj = sourceArray.get(0).getAsJsonObject();
-        Assert.assertEquals("Segment.1490923010328.927784221.5991.32.1", costJsonObj.get("segId").getAsString());
-        Assert.assertEquals(1490923010328L, costJsonObj.get("startTime").getAsLong());
-        Assert.assertEquals(1490923010329L, costJsonObj.get("END_TIME").getAsLong());
-        Assert.assertEquals("com.a.eye.skywalking.test.cache.CacheService.findCacheWithException(java.lang.String)", costJsonObj.get("operationName").getAsString());
-        Assert.assertEquals(DateTools.changeToUTCSlice(201703310916L), costJsonObj.get("timeSlice").getAsLong());
-        Assert.assertEquals(1, costJsonObj.get("cost").getAsInt());
-    }
-
-    @Test
-    public void testPortalServiceExceptionAnalyse() throws Exception {
-        CacheSizeConfig.Cache.Persistence.SIZE = 1;
-
-        List<SegmentPost.SegmentWithTimeSlice> segmentWithTimeSliceList = segmentMock.mockPortalServiceExceptionSegmentTimeSlice();
-
-        for (SegmentPost.SegmentWithTimeSlice segmentWithTimeSlice : segmentWithTimeSliceList) {
-            segmentCostSave.analyse(segmentWithTimeSlice);
-        }
-
-        JsonArray sourceArray = saveToEsSourceAnswer.sourceObj.getSource();
-        Assert.assertEquals(1, sourceArray.size());
-
-        JsonObject costJsonObj = sourceArray.get(0).getAsJsonObject();
-        Assert.assertEquals("Segment.1490923010324.1797892356.6003.67.1", costJsonObj.get("segId").getAsString());
-        Assert.assertEquals(1490923010324L, costJsonObj.get("startTime").getAsLong());
-        Assert.assertEquals(1490923010336L, costJsonObj.get("END_TIME").getAsLong());
-        Assert.assertEquals("/portal/cache/exception/test", costJsonObj.get("operationName").getAsString());
-        Assert.assertEquals(DateTools.changeToUTCSlice(201703310916L), costJsonObj.get("timeSlice").getAsLong());
-        Assert.assertEquals(12, costJsonObj.get("cost").getAsInt());
+        SegmentCostSave.Factory factory = new SegmentCostSave.Factory();
+        Assert.assertEquals(SegmentCostSave.class.getSimpleName(), factory.role().roleName());
+        Assert.assertEquals(SegmentCostSave.class.getSimpleName(), factory.workerInstance(null).getClass().getSimpleName());
     }
 }
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/segment/persistence/SegmentExceptionSaveTestCase.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/segment/persistence/SegmentExceptionSaveTestCase.java
index 6426bf0..294deed 100644
--- a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/segment/persistence/SegmentExceptionSaveTestCase.java
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/segment/persistence/SegmentExceptionSaveTestCase.java
@@ -4,7 +4,6 @@
 import com.a.eye.skywalking.collector.actor.LocalWorkerContext;
 import com.a.eye.skywalking.collector.actor.selector.RollingSelector;
 import com.a.eye.skywalking.collector.worker.config.CacheSizeConfig;
-import com.a.eye.skywalking.collector.worker.config.WorkerConfig;
 import com.a.eye.skywalking.collector.worker.mock.MockEsBulkClient;
 import com.a.eye.skywalking.collector.worker.segment.SegmentExceptionIndex;
 import com.a.eye.skywalking.collector.worker.segment.SegmentPost;
@@ -81,44 +80,9 @@
 
     @Test
     public void testFactory() {
-        Assert.assertEquals(SegmentExceptionSave.class.getSimpleName(), SegmentExceptionSave.Factory.INSTANCE.role().roleName());
-        Assert.assertEquals(SegmentExceptionSave.class.getSimpleName(), SegmentExceptionSave.Factory.INSTANCE.workerInstance(null).getClass().getSimpleName());
-
-        int testSize = 10;
-        WorkerConfig.Queue.Segment.SegmentExceptionSave.SIZE = testSize;
-        Assert.assertEquals(testSize, SegmentExceptionSave.Factory.INSTANCE.queueSize());
-    }
-
-    @Test
-    public void testSuccessAnalyse() throws Exception {
-        CacheSizeConfig.Cache.Persistence.SIZE = 1;
-
-        List<SegmentPost.SegmentWithTimeSlice> cacheServiceList = segmentMock.mockCacheServiceSegmentSegmentTimeSlice();
-        for (SegmentPost.SegmentWithTimeSlice segmentWithTimeSlice : cacheServiceList) {
-            segmentExceptionSave.analyse(segmentWithTimeSlice);
-        }
-
-        JsonObject isError_1 = saveToEsSource.isErrorMap.get("Segment.1490922929258.927784221.5991.27.1");
-        Assert.assertEquals(false, isError_1.get("isError").getAsBoolean());
-        Assert.assertEquals(0, isError_1.get("errorKind").getAsJsonArray().size());
-
-        JsonObject isError_2 = saveToEsSource.isErrorMap.get("Segment.1490922929298.927784221.5991.28.1");
-        Assert.assertEquals(false, isError_2.get("isError").getAsBoolean());
-        Assert.assertEquals(0, isError_2.get("errorKind").getAsJsonArray().size());
-    }
-
-    @Test
-    public void testErrorAnalyse() throws Exception {
-        CacheSizeConfig.Cache.Persistence.SIZE = 1;
-
-        List<SegmentPost.SegmentWithTimeSlice> cacheServiceList = segmentMock.mockCacheServiceExceptionSegmentTimeSlice();
-        for (SegmentPost.SegmentWithTimeSlice segmentWithTimeSlice : cacheServiceList) {
-            segmentExceptionSave.analyse(segmentWithTimeSlice);
-        }
-
-        JsonObject isError_1 = saveToEsSource.isErrorMap.get("Segment.1490923010328.927784221.5991.32.1");
-        Assert.assertEquals(true, isError_1.get("isError").getAsBoolean());
-        Assert.assertEquals("com.weibo.api.motan.exception.MotanBizException", isError_1.get("errorKind").getAsJsonArray().get(0).getAsString());
+        SegmentExceptionSave.Factory factory = new SegmentExceptionSave.Factory();
+        Assert.assertEquals(SegmentExceptionSave.class.getSimpleName(), factory.role().roleName());
+        Assert.assertEquals(SegmentExceptionSave.class.getSimpleName(), factory.workerInstance(null).getClass().getSimpleName());
     }
 
     class SaveToEsSource implements Answer<Object> {
@@ -128,7 +92,7 @@
         @Override
         public Object answer(InvocationOnMock invocation) throws Throwable {
             Gson gson = new Gson();
-            String source = (String)invocation.getArguments()[0];
+            String source = (String) invocation.getArguments()[0];
             JsonObject sourceJsonObj = gson.fromJson(source, JsonObject.class);
             logger.info("es source: %s", sourceJsonObj.toString());
             isErrorMap.put(sourceJsonObj.get("segId").getAsString(), sourceJsonObj);
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/segment/persistence/SegmentSaveTestCase.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/segment/persistence/SegmentSaveTestCase.java
index a66b805..86a07e7 100644
--- a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/segment/persistence/SegmentSaveTestCase.java
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/segment/persistence/SegmentSaveTestCase.java
@@ -4,7 +4,6 @@
 import com.a.eye.skywalking.collector.actor.LocalWorkerContext;
 import com.a.eye.skywalking.collector.actor.selector.RollingSelector;
 import com.a.eye.skywalking.collector.worker.config.CacheSizeConfig;
-import com.a.eye.skywalking.collector.worker.config.WorkerConfig;
 import com.a.eye.skywalking.collector.worker.mock.MockEsBulkClient;
 import com.a.eye.skywalking.collector.worker.segment.SegmentIndex;
 import com.a.eye.skywalking.collector.worker.storage.EsClient;
@@ -71,23 +70,9 @@
 
     @Test
     public void testFactory() {
-        Assert.assertEquals(SegmentSave.class.getSimpleName(), SegmentSave.Factory.INSTANCE.role().roleName());
-        Assert.assertEquals(SegmentSave.class.getSimpleName(), SegmentSave.Factory.INSTANCE.workerInstance(null).getClass().getSimpleName());
-
-        int testSize = 10;
-        WorkerConfig.Queue.Segment.SegmentSave.SIZE = testSize;
-        Assert.assertEquals(testSize, SegmentSave.Factory.INSTANCE.queueSize());
-    }
-
-    @Test
-    public void testAnalyse() throws Exception {
-        CacheSizeConfig.Cache.Persistence.SIZE = 1;
-
-        JsonObject segment_1 = new JsonObject();
-        segment_1.addProperty("ts", "segment_1");
-        segmentSave.analyse(segment_1);
-
-        Assert.assertEquals("segment_1", saveToEsSource.ts);
+        SegmentSave.Factory factory = new SegmentSave.Factory();
+        Assert.assertEquals(SegmentSave.class.getSimpleName(), factory.role().roleName());
+        Assert.assertEquals(SegmentSave.class.getSimpleName(), factory.workerInstance(null).getClass().getSimpleName());
     }
 
     class SaveToEsSource implements Answer<Object> {
@@ -97,7 +82,7 @@
         @Override
         public Object answer(InvocationOnMock invocation) throws Throwable {
             Gson gson = new Gson();
-            String source = (String)invocation.getArguments()[0];
+            String source = (String) invocation.getArguments()[0];
             JsonObject sourceJsonObj = gson.fromJson(source, JsonObject.class);
             ts = sourceJsonObj.get("ts").getAsString();
             return null;
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/span/SpanGetWithIdTestCase.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/span/SpanGetWithIdTestCase.java
index de33510..5c1b5a8 100644
--- a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/span/SpanGetWithIdTestCase.java
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/span/SpanGetWithIdTestCase.java
@@ -63,14 +63,15 @@
 
     @Test
     public void testFactory() {
-        Assert.assertEquals(SpanGetWithId.class.getSimpleName(), SpanGetWithId.Factory.INSTANCE.role().roleName());
-        Assert.assertEquals(SpanGetWithId.class.getSimpleName(), SpanGetWithId.Factory.INSTANCE.workerInstance(null).getClass().getSimpleName());
-        Assert.assertEquals("/span/spanId", SpanGetWithId.Factory.INSTANCE.servletPath());
+        SpanGetWithId.Factory factory = new SpanGetWithId.Factory();
+        Assert.assertEquals(SpanGetWithId.class.getSimpleName(), factory.role().roleName());
+        Assert.assertEquals(SpanGetWithId.class.getSimpleName(), factory.workerInstance(null).getClass().getSimpleName());
+        Assert.assertEquals("/span/spanId", factory.servletPath());
     }
 
     @Test
     public void testPreStart() throws ProviderNotFoundException {
-        when(clusterWorkerContext.findProvider(SpanSearchWithId.WorkerRole.INSTANCE)).thenReturn(SpanSearchWithId.Factory.INSTANCE);
+        when(clusterWorkerContext.findProvider(SpanSearchWithId.WorkerRole.INSTANCE)).thenReturn(new SpanSearchWithId.Factory());
 
         ArgumentCaptor<SpanSearchWithId.WorkerRole> argumentCaptor = ArgumentCaptor.forClass(SpanSearchWithId.WorkerRole.class);
         getObj.preStart();
@@ -99,7 +100,7 @@
 
         @Override
         public Object answer(InvocationOnMock invocation) throws Throwable {
-            SpanSearchWithId.RequestEntity requestEntity = (SpanSearchWithId.RequestEntity)invocation.getArguments()[0];
+            SpanSearchWithId.RequestEntity requestEntity = (SpanSearchWithId.RequestEntity) invocation.getArguments()[0];
             Assert.assertEquals("10", requestEntity.getSegId());
             Assert.assertEquals("20", requestEntity.getSpanId());
             return null;
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/span/persistence/SpanSearchWithIdTestCase.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/span/persistence/SpanSearchWithIdTestCase.java
index 204f6e4..49c89c9 100644
--- a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/span/persistence/SpanSearchWithIdTestCase.java
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/span/persistence/SpanSearchWithIdTestCase.java
@@ -5,10 +5,10 @@
 import com.a.eye.skywalking.collector.actor.selector.RollingSelector;
 import com.a.eye.skywalking.collector.worker.Const;
 import com.a.eye.skywalking.collector.worker.segment.SegmentIndex;
+import com.a.eye.skywalking.collector.worker.segment.mock.SegmentMock;
 import com.a.eye.skywalking.collector.worker.storage.GetResponseFromEs;
 import com.a.eye.skywalking.trace.Span;
 import com.a.eye.skywalking.trace.TraceSegment;
-import com.google.gson.Gson;
 import com.google.gson.JsonObject;
 import org.elasticsearch.action.get.GetResponse;
 import org.junit.Assert;
@@ -53,8 +53,9 @@
 
     @Test
     public void testFactory() {
-        Assert.assertEquals(SpanSearchWithId.class.getSimpleName(), SpanSearchWithId.Factory.INSTANCE.role().roleName());
-        Assert.assertEquals(SpanSearchWithId.class.getSimpleName(), SpanSearchWithId.Factory.INSTANCE.workerInstance(null).getClass().getSimpleName());
+        SpanSearchWithId.Factory factory = new SpanSearchWithId.Factory();
+        Assert.assertEquals(SpanSearchWithId.class.getSimpleName(), factory.role().roleName());
+        Assert.assertEquals(SpanSearchWithId.class.getSimpleName(), factory.workerInstance(null).getClass().getSimpleName());
     }
 
     @Test
@@ -63,10 +64,8 @@
         LocalWorkerContext localWorkerContext = new LocalWorkerContext();
         SpanSearchWithId spanSearchWithId = new SpanSearchWithId(SpanSearchWithId.WorkerRole.INSTANCE, clusterWorkerContext, localWorkerContext);
 
-        TraceSegment segment = create();
-        Gson gson = new Gson();
-        String sourceString = gson.toJson(segment);
-
+        SegmentMock mock = new SegmentMock();
+        String sourceString = mock.loadJsonFile("/json/span/persistence/segment.json");
         GetResponse getResponse = mock(GetResponse.class);
         when(getResponseFromEs.get(SegmentIndex.INDEX, SegmentIndex.TYPE_RECORD, "1")).thenReturn(getResponse);
         when(getResponse.getSourceAsString()).thenReturn(sourceString);
@@ -75,9 +74,9 @@
         JsonObject response = new JsonObject();
         spanSearchWithId.onWork(request, response);
 
-        JsonObject segJsonObj = response.get(Const.RESULT).getAsJsonObject();
-        String value = segJsonObj.get("ts").getAsJsonObject().get("Tag").getAsString();
-        Assert.assertEquals("VALUE", value);
+        JsonObject spanJsonObj = response.get(Const.RESULT).getAsJsonObject();
+        String value = spanJsonObj.get("operationName").getAsString();
+        Assert.assertEquals("/portal/", value);
     }
 
     private TraceSegment create() {
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/storage/AbstractIndexTestCase.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/storage/AbstractIndexTestCase.java
index cfbbc8b..f4fe462 100644
--- a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/storage/AbstractIndexTestCase.java
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/storage/AbstractIndexTestCase.java
@@ -22,7 +22,7 @@
     @Test
     public void testCreateSettingBuilder() throws IOException {
         IndexTest indexTest = new IndexTest();
-        Assert.assertEquals("{\"index.number_of_shards\":\"\",\"index.number_of_replicas\":\"\"}", indexTest.createSettingBuilder().string());
+        Assert.assertEquals("{\"index.number_of_shards\":\"\",\"index.number_of_replicas\":\"\",\"index.refresh_interval\":\"0s\"}", indexTest.createSettingBuilder().string());
     }
 
     class IndexTest extends AbstractIndex {
@@ -49,5 +49,10 @@
         public String index() {
             return "Index_Test";
         }
+
+        @Override
+        public int refreshInterval() {
+            return 0;
+        }
     }
 }
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/storage/IndexCreatorTestCase.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/storage/IndexCreatorTestCase.java
index 416b2e2..2bb19fe 100644
--- a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/storage/IndexCreatorTestCase.java
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/storage/IndexCreatorTestCase.java
@@ -120,6 +120,11 @@
         }
 
         @Override
+        public int refreshInterval() {
+            return 0;
+        }
+
+        @Override
         public XContentBuilder createMappingBuilder() throws IOException {
             return XContentFactory.jsonBuilder();
         }
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/storage/JoinAndSplitAnalysisDataTestCase.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/storage/JoinAndSplitAnalysisDataTestCase.java
new file mode 100644
index 0000000..074c5d8
--- /dev/null
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/storage/JoinAndSplitAnalysisDataTestCase.java
@@ -0,0 +1,28 @@
+package com.a.eye.skywalking.collector.worker.storage;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * @author pengys5
+ */
+public class JoinAndSplitAnalysisDataTestCase {
+
+    @Test
+    public void getOrCreate() {
+        JoinAndSplitAnalysisData joinAndSplitAnalysisData = new JoinAndSplitAnalysisData();
+        JoinAndSplitData joinAndSplitData = joinAndSplitAnalysisData.getOrCreate("Test1");
+
+        JoinAndSplitData joinAndSplitData_1 = joinAndSplitAnalysisData.getOrCreate("Test1");
+        Assert.assertEquals(joinAndSplitData, joinAndSplitData_1);
+    }
+
+    @Test
+    public void asMap() {
+        JoinAndSplitAnalysisData joinAndSplitAnalysisData = new JoinAndSplitAnalysisData();
+        JoinAndSplitData joinAndSplitData = joinAndSplitAnalysisData.getOrCreate("Test1");
+
+        JoinAndSplitData joinAndSplitData_1 = joinAndSplitAnalysisData.asMap().get("Test1");
+        Assert.assertEquals(joinAndSplitData, joinAndSplitData_1);
+    }
+}
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/storage/JoinAndSplitPersistenceDataTestCase.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/storage/JoinAndSplitPersistenceDataTestCase.java
new file mode 100644
index 0000000..4d4565b
--- /dev/null
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/storage/JoinAndSplitPersistenceDataTestCase.java
@@ -0,0 +1,66 @@
+package com.a.eye.skywalking.collector.worker.storage;
+
+import java.lang.reflect.Field;
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * @author pengys5
+ */
+public class JoinAndSplitPersistenceDataTestCase {
+
+    @Test
+    public void testGetElseCreate() {
+        JoinAndSplitPersistenceData persistenceData = new JoinAndSplitPersistenceData();
+        persistenceData.hold();
+        JoinAndSplitData joinAndSplitData = persistenceData.getOrCreate("test");
+        Assert.assertEquals("test", joinAndSplitData.getId());
+    }
+
+    @Test
+    public void testSize() {
+        JoinAndSplitPersistenceData persistenceData = new JoinAndSplitPersistenceData();
+        persistenceData.hold();
+        persistenceData.getOrCreate("test_1");
+        Assert.assertEquals(1, persistenceData.getCurrentAndHold().size());
+        persistenceData.getOrCreate("test_1");
+        Assert.assertEquals(1, persistenceData.getCurrentAndHold().size());
+        persistenceData.getOrCreate("test_2");
+        Assert.assertEquals(2, persistenceData.getCurrentAndHold().size());
+    }
+
+    @Test
+    public void testClear() {
+        JoinAndSplitPersistenceData persistenceData = new JoinAndSplitPersistenceData();
+        persistenceData.hold();
+        persistenceData.getOrCreate("test_1");
+        Assert.assertEquals(1, persistenceData.getCurrentAndHold().size());
+        persistenceData.getCurrentAndHold().clear();
+        Assert.assertEquals(0, persistenceData.getCurrentAndHold().size());
+    }
+
+    @Test
+    public void hold() throws NoSuchFieldException, IllegalAccessException {
+        JoinAndSplitPersistenceData persistenceData = new JoinAndSplitPersistenceData();
+        persistenceData.hold();
+
+        Field testAField = persistenceData.getClass().getDeclaredField("lockedWindowData");
+        testAField.setAccessible(true);
+        WindowData<JoinAndSplitData> windowData = (WindowData<JoinAndSplitData>)testAField.get(persistenceData);
+        Assert.assertEquals(true, windowData.isHolding());
+    }
+
+    @Test
+    public void release() throws NoSuchFieldException, IllegalAccessException {
+        JoinAndSplitPersistenceData persistenceData = new JoinAndSplitPersistenceData();
+        persistenceData.hold();
+
+        Field testAField = persistenceData.getClass().getDeclaredField("lockedWindowData");
+        testAField.setAccessible(true);
+        WindowData<JoinAndSplitData> windowData = (WindowData<JoinAndSplitData>)testAField.get(persistenceData);
+        Assert.assertEquals(true, windowData.isHolding());
+
+        persistenceData.release();
+        Assert.assertEquals(false, windowData.isHolding());
+    }
+}
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/storage/MergeDataTestCase.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/storage/MergeDataTestCase.java
deleted file mode 100644
index eaedddf..0000000
--- a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/storage/MergeDataTestCase.java
+++ /dev/null
@@ -1,64 +0,0 @@
-package com.a.eye.skywalking.collector.worker.storage;
-
-import org.junit.Assert;
-import org.junit.Test;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * @author pengys5
- */
-public class MergeDataTestCase {
-
-    @Test
-    public void testConstruction() {
-        String id = "Test";
-        MergeData mergeData = new MergeData(id);
-
-        Assert.assertEquals(id, mergeData.getId());
-    }
-
-    @Test
-    public void testSetMergeData() {
-        String id = "Test";
-        MergeData mergeData = new MergeData(id);
-
-        mergeData.setMergeData("Column_1", "Value_1");
-        Assert.assertEquals("Value_1", mergeData.toMap().get("Column_1"));
-        mergeData.setMergeData("Column_1", "Value_1");
-        Assert.assertEquals("Value_1", mergeData.toMap().get("Column_1"));
-
-        mergeData.setMergeData("Column_1", "Value_2");
-        Assert.assertEquals("Value_2,Value_1", mergeData.toMap().get("Column_1"));
-
-        mergeData.setMergeData("Column_2", "Value_3");
-        Assert.assertEquals("Value_3", mergeData.toMap().get("Column_2"));
-    }
-
-    @Test
-    public void testMerge() {
-        String id = "Test";
-        MergeData mergeData_1 = new MergeData(id);
-        mergeData_1.setMergeData("Column_1", "Value_1");
-
-        MergeData mergeData_2 = new MergeData(id);
-        mergeData_2.setMergeData("Column_1", "Value_2");
-
-        mergeData_1.merge(mergeData_2);
-        Assert.assertEquals("Value_2,Value_1", mergeData_1.toMap().get("Column_1"));
-    }
-
-    @Test
-    public void testMergeMap() {
-        String id = "Test";
-        MergeData mergeData_1 = new MergeData(id);
-        mergeData_1.setMergeData("Column_1", "Value_1");
-
-        Map<String, Object> dbData = new HashMap<>();
-        dbData.put("Column_1", "Value_2");
-
-        mergeData_1.merge(dbData);
-        Assert.assertEquals("Value_2,Value_1", mergeData_1.toMap().get("Column_1"));
-    }
-}
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/storage/MergePersistenceDataTestCase.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/storage/MergePersistenceDataTestCase.java
deleted file mode 100644
index d8c0c48..0000000
--- a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/storage/MergePersistenceDataTestCase.java
+++ /dev/null
@@ -1,86 +0,0 @@
-package com.a.eye.skywalking.collector.worker.storage;
-
-import org.junit.Assert;
-import org.junit.Test;
-
-import java.util.Iterator;
-import java.util.Map;
-
-/**
- * @author pengys5
- */
-public class MergePersistenceDataTestCase {
-
-    @Test
-    public void testGetElseCreate() {
-        MergePersistenceData persistenceData = new MergePersistenceData();
-        MergeData mergeData = persistenceData.getElseCreate("test");
-        Assert.assertEquals("test", mergeData.getId());
-    }
-
-    @Test
-    public void testSize() {
-        MergePersistenceData persistenceData = new MergePersistenceData();
-        persistenceData.getElseCreate("test_1");
-        Assert.assertEquals(1, persistenceData.size());
-        persistenceData.getElseCreate("test_1");
-        Assert.assertEquals(1, persistenceData.size());
-        persistenceData.getElseCreate("test_2");
-        Assert.assertEquals(2, persistenceData.size());
-    }
-
-    @Test
-    public void testClear() {
-        MergePersistenceData persistenceData = new MergePersistenceData();
-        persistenceData.getElseCreate("test_1");
-        Assert.assertEquals(1, persistenceData.size());
-        persistenceData.clear();
-        Assert.assertEquals(0, persistenceData.size());
-    }
-
-    @Test
-    public void testPushOne() {
-        MergePersistenceData persistenceData = new MergePersistenceData();
-        persistenceData.getElseCreate("test_1");
-        persistenceData.getElseCreate("test_2");
-        persistenceData.getElseCreate("test_3");
-
-        Assert.assertEquals(3, persistenceData.size());
-        MergeData mergeData = persistenceData.pushOne();
-        Assert.assertEquals("test_3", mergeData.getId());
-        Assert.assertEquals(2, persistenceData.size());
-
-        mergeData = persistenceData.pushOne();
-        Assert.assertEquals("test_2", mergeData.getId());
-        Assert.assertEquals(1, persistenceData.size());
-
-        mergeData = persistenceData.pushOne();
-        Assert.assertEquals("test_1", mergeData.getId());
-        Assert.assertEquals(0, persistenceData.size());
-    }
-
-    @Test(expected = UnsupportedOperationException.class)
-    public void testForEach() {
-        MergePersistenceData persistenceData = new MergePersistenceData();
-        persistenceData.forEach(c -> System.out.println(c));
-    }
-
-    @Test(expected = UnsupportedOperationException.class)
-    public void testSpliterator() {
-        MergePersistenceData persistenceData = new MergePersistenceData();
-        persistenceData.spliterator();
-    }
-
-    @Test
-    public void testIterator() {
-        MergePersistenceData persistenceData = new MergePersistenceData();
-        persistenceData.getElseCreate("test_1");
-        persistenceData.getElseCreate("test_2");
-        persistenceData.getElseCreate("test_3");
-
-        Iterator<Map.Entry<String, MergeData>> iterator = persistenceData.iterator();
-        Assert.assertEquals("test_3", iterator.next().getKey());
-        Assert.assertEquals("test_2", iterator.next().getKey());
-        Assert.assertEquals("test_1", iterator.next().getKey());
-    }
-}
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/storage/MergeWindowDataTestCase.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/storage/MergeWindowDataTestCase.java
new file mode 100644
index 0000000..3667d8f
--- /dev/null
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/storage/MergeWindowDataTestCase.java
@@ -0,0 +1,64 @@
+package com.a.eye.skywalking.collector.worker.storage;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author pengys5
+ */
+public class MergeWindowDataTestCase {
+
+    @Test
+    public void testConstruction() {
+        String id = "Test";
+        JoinAndSplitData joinAndSplitData = new JoinAndSplitData(id);
+
+        Assert.assertEquals(id, joinAndSplitData.getId());
+    }
+
+    @Test
+    public void testSetMergeData() {
+        String id = "Test";
+        JoinAndSplitData joinAndSplitData = new JoinAndSplitData(id);
+
+        joinAndSplitData.set("Column_1", "Value_1");
+        Assert.assertEquals("Value_1", joinAndSplitData.asMap().get("Column_1"));
+        joinAndSplitData.set("Column_1", "Value_1");
+        Assert.assertEquals("Value_1", joinAndSplitData.asMap().get("Column_1"));
+
+        joinAndSplitData.set("Column_1", "Value_2");
+        Assert.assertEquals("Value_2,Value_1", joinAndSplitData.asMap().get("Column_1"));
+
+        joinAndSplitData.set("Column_2", "Value_3");
+        Assert.assertEquals("Value_3", joinAndSplitData.asMap().get("Column_2"));
+    }
+
+    @Test
+    public void testMerge() {
+        String id = "Test";
+        JoinAndSplitData joinAndSplitData_1 = new JoinAndSplitData(id);
+        joinAndSplitData_1.set("Column_1", "Value_1");
+
+        JoinAndSplitData joinAndSplitData_2 = new JoinAndSplitData(id);
+        joinAndSplitData_2.set("Column_1", "Value_2");
+
+        joinAndSplitData_1.merge(joinAndSplitData_2);
+        Assert.assertEquals("Value_2,Value_1", joinAndSplitData_1.asMap().get("Column_1"));
+    }
+
+    @Test
+    public void testMergeMap() {
+        String id = "Test";
+        JoinAndSplitData joinAndSplitData_1 = new JoinAndSplitData(id);
+        joinAndSplitData_1.set("Column_1", "Value_1");
+
+        Map<String, Object> dbData = new HashMap<>();
+        dbData.put("Column_1", "Value_2");
+
+        joinAndSplitData_1.merge(dbData);
+        Assert.assertEquals("Value_2,Value_1", joinAndSplitData_1.asMap().get("Column_1"));
+    }
+}
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/storage/MetricAnalysisDataTestCase.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/storage/MetricAnalysisDataTestCase.java
new file mode 100644
index 0000000..1714199
--- /dev/null
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/storage/MetricAnalysisDataTestCase.java
@@ -0,0 +1,31 @@
+package com.a.eye.skywalking.collector.worker.storage;
+
+import com.a.eye.skywalking.collector.worker.Const;
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * @author pengys5
+ */
+public class MetricAnalysisDataTestCase {
+
+    @Test
+    public void getOrCreate() {
+        String id = "2016" + Const.ID_SPLIT + "A" + Const.ID_SPLIT + "B";
+        MetricAnalysisData metricAnalysisData = new MetricAnalysisData();
+        MetricData metricData = metricAnalysisData.getOrCreate(id);
+
+        MetricData metricData_1 = metricAnalysisData.getOrCreate(id);
+        Assert.assertEquals(metricData, metricData_1);
+    }
+
+    @Test
+    public void asMap() {
+        String id = "2016" + Const.ID_SPLIT + "A" + Const.ID_SPLIT + "B";
+        MetricAnalysisData metricAnalysisData = new MetricAnalysisData();
+        MetricData metricData = metricAnalysisData.getOrCreate(id);
+
+        MetricData metricData_1 = metricAnalysisData.asMap().get(id);
+        Assert.assertEquals(metricData, metricData_1);
+    }
+}
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/storage/MetricPersistenceDataTestCase.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/storage/MetricPersistenceDataTestCase.java
deleted file mode 100644
index 717780f..0000000
--- a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/storage/MetricPersistenceDataTestCase.java
+++ /dev/null
@@ -1,79 +0,0 @@
-package com.a.eye.skywalking.collector.worker.storage;
-
-import com.a.eye.skywalking.collector.worker.Const;
-import org.junit.Assert;
-import org.junit.Test;
-
-import java.util.Iterator;
-import java.util.Map;
-
-/**
- * @author pengys5
- */
-public class MetricPersistenceDataTestCase {
-
-    @Test
-    public void testGetElseCreate() {
-        String id = "2016" + Const.ID_SPLIT + "A" + Const.ID_SPLIT + "B";
-
-        MetricPersistenceData metricPersistenceData = new MetricPersistenceData();
-        MetricData metricData = metricPersistenceData.getElseCreate(id);
-        metricData.setMetric("Column_1", 10L);
-        Assert.assertEquals(id, metricData.getId());
-
-        MetricData metricData1 = metricPersistenceData.getElseCreate(id);
-        Assert.assertEquals(10L, metricData1.toMap().get("Column_1"));
-    }
-
-    @Test
-    public void testSize() {
-        String id = "2016" + Const.ID_SPLIT + "A" + Const.ID_SPLIT + "B";
-
-        MetricPersistenceData metricPersistenceData = new MetricPersistenceData();
-        metricPersistenceData.getElseCreate(id);
-
-        Assert.assertEquals(1, metricPersistenceData.size());
-        String id_1 = "2016" + Const.ID_SPLIT + "B" + Const.ID_SPLIT + "C";
-        metricPersistenceData.getElseCreate(id_1);
-        Assert.assertEquals(2, metricPersistenceData.size());
-
-        metricPersistenceData.clear();
-        Assert.assertEquals(0, metricPersistenceData.size());
-    }
-
-    @Test
-    public void testPushOne() {
-        String id_1 = "2016" + Const.ID_SPLIT + "A" + Const.ID_SPLIT + "B";
-        String id_2 = "2016" + Const.ID_SPLIT + "B" + Const.ID_SPLIT + "C";
-
-        MetricPersistenceData metricPersistenceData = new MetricPersistenceData();
-        metricPersistenceData.getElseCreate(id_1);
-        metricPersistenceData.getElseCreate(id_2);
-
-        MetricData metricData_2 = metricPersistenceData.pushOne();
-        Assert.assertEquals(id_2, metricData_2.getId());
-
-        MetricData metricData_1 = metricPersistenceData.pushOne();
-        Assert.assertEquals(id_1, metricData_1.getId());
-    }
-
-    @Test(expected = UnsupportedOperationException.class)
-    public void testSpliterator() {
-        MetricPersistenceData metricPersistenceData = new MetricPersistenceData();
-        metricPersistenceData.spliterator();
-    }
-
-    @Test
-    public void testIterator() {
-        String id_1 = "2016" + Const.ID_SPLIT + "A" + Const.ID_SPLIT + "B";
-        String id_2 = "2016" + Const.ID_SPLIT + "B" + Const.ID_SPLIT + "C";
-
-        MetricPersistenceData metricPersistenceData = new MetricPersistenceData();
-        metricPersistenceData.getElseCreate(id_1);
-        metricPersistenceData.getElseCreate(id_2);
-
-        Iterator<Map.Entry<String, MetricData>> iterator = metricPersistenceData.iterator();
-        Assert.assertEquals(id_2, iterator.next().getKey());
-        Assert.assertEquals(id_1, iterator.next().getKey());
-    }
-}
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/storage/MetricPersistenceTestCase.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/storage/MetricPersistenceTestCase.java
new file mode 100644
index 0000000..0b907af
--- /dev/null
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/storage/MetricPersistenceTestCase.java
@@ -0,0 +1,68 @@
+package com.a.eye.skywalking.collector.worker.storage;
+
+import com.a.eye.skywalking.collector.worker.Const;
+import java.lang.reflect.Field;
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * @author pengys5
+ */
+public class MetricPersistenceTestCase {
+
+    @Test
+    public void testGetElseCreate() {
+        String id = "2016" + Const.ID_SPLIT + "A" + Const.ID_SPLIT + "B";
+
+        MetricPersistenceData metricPersistenceData = new MetricPersistenceData();
+        metricPersistenceData.hold();
+        MetricData metricData = metricPersistenceData.getOrCreate(id);
+        metricData.set("Column_1", 10L);
+        Assert.assertEquals(id, metricData.getId());
+
+        MetricData metricData1 = metricPersistenceData.getOrCreate(id);
+        Assert.assertEquals(10L, metricData1.asMap().get("Column_1"));
+    }
+
+    @Test
+    public void testSize() {
+        String id = "2016" + Const.ID_SPLIT + "A" + Const.ID_SPLIT + "B";
+
+        MetricPersistenceData metricPersistenceData = new MetricPersistenceData();
+        metricPersistenceData.hold();
+        metricPersistenceData.getOrCreate(id);
+
+        Assert.assertEquals(1, metricPersistenceData.getCurrentAndHold().size());
+        String id_1 = "2016" + Const.ID_SPLIT + "B" + Const.ID_SPLIT + "C";
+        metricPersistenceData.getOrCreate(id_1);
+        Assert.assertEquals(2, metricPersistenceData.getCurrentAndHold().size());
+
+        metricPersistenceData.getCurrentAndHold().clear();
+        Assert.assertEquals(0, metricPersistenceData.getCurrentAndHold().size());
+    }
+
+    @Test
+    public void hold() throws NoSuchFieldException, IllegalAccessException {
+        MetricPersistenceData persistenceData = new MetricPersistenceData();
+        persistenceData.hold();
+
+        Field testAField = persistenceData.getClass().getDeclaredField("lockedWindowData");
+        testAField.setAccessible(true);
+        WindowData<JoinAndSplitData> windowData = (WindowData<JoinAndSplitData>)testAField.get(persistenceData);
+        Assert.assertEquals(true, windowData.isHolding());
+    }
+
+    @Test
+    public void release() throws NoSuchFieldException, IllegalAccessException {
+        MetricPersistenceData persistenceData = new MetricPersistenceData();
+        persistenceData.hold();
+
+        Field testAField = persistenceData.getClass().getDeclaredField("lockedWindowData");
+        testAField.setAccessible(true);
+        WindowData<JoinAndSplitData> windowData = (WindowData<JoinAndSplitData>)testAField.get(persistenceData);
+        Assert.assertEquals(true, windowData.isHolding());
+
+        persistenceData.release();
+        Assert.assertEquals(false, windowData.isHolding());
+    }
+}
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/storage/MetricDataTestCase.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/storage/MetricWindowDataTestCase.java
similarity index 66%
rename from skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/storage/MetricDataTestCase.java
rename to skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/storage/MetricWindowDataTestCase.java
index 1e8b921..a01cad7 100644
--- a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/storage/MetricDataTestCase.java
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/storage/MetricWindowDataTestCase.java
@@ -10,7 +10,7 @@
 /**
  * @author pengys5
  */
-public class MetricDataTestCase {
+public class MetricWindowDataTestCase {
 
     @Test
     public void testConstruction() {
@@ -18,15 +18,15 @@
         MetricData metricData_1 = new MetricData(id_1);
 
         Assert.assertEquals(id_1, metricData_1.getId());
-        Assert.assertEquals(2016L, metricData_1.toMap().get(AbstractIndex.TIME_SLICE));
-        Assert.assertEquals("B", metricData_1.toMap().get(AbstractIndex.AGG_COLUMN));
+        Assert.assertEquals(2016L, metricData_1.asMap().get(AbstractIndex.TIME_SLICE));
+        Assert.assertEquals("B", metricData_1.asMap().get(AbstractIndex.AGG_COLUMN));
 
         String id_2 = "2017" + Const.ID_SPLIT + "B" + Const.ID_SPLIT + "C";
         MetricData metricData_2 = new MetricData(id_2);
 
         Assert.assertEquals(id_2, metricData_2.getId());
-        Assert.assertEquals(2017L, metricData_2.toMap().get(AbstractIndex.TIME_SLICE));
-        Assert.assertEquals("B" + Const.ID_SPLIT + "C", metricData_2.toMap().get(AbstractIndex.AGG_COLUMN));
+        Assert.assertEquals(2017L, metricData_2.asMap().get(AbstractIndex.TIME_SLICE));
+        Assert.assertEquals("B" + Const.ID_SPLIT + "C", metricData_2.asMap().get(AbstractIndex.AGG_COLUMN));
     }
 
     @Test
@@ -34,36 +34,36 @@
         String id_1 = "2016" + Const.ID_SPLIT + "B";
         MetricData metricData = new MetricData(id_1);
 
-        metricData.setMetric("Column", 10L);
-        Assert.assertEquals(10L, metricData.toMap().get("Column"));
+        metricData.set("Column", 10L);
+        Assert.assertEquals(10L, metricData.asMap().get("Column"));
 
-        metricData.setMetric("Column", 10L);
-        Assert.assertEquals(20L, metricData.toMap().get("Column"));
+        metricData.set("Column", 10L);
+        Assert.assertEquals(20L, metricData.asMap().get("Column"));
     }
 
     @Test
     public void testMerge() {
         String id_1 = "2016" + Const.ID_SPLIT + "B";
         MetricData metricData_1 = new MetricData(id_1);
-        metricData_1.setMetric("Column", 10L);
+        metricData_1.set("Column", 10L);
 
         MetricData metricData_2 = new MetricData(id_1);
-        metricData_2.setMetric("Column", 10L);
+        metricData_2.set("Column", 10L);
 
         metricData_1.merge(metricData_2);
-        Assert.assertEquals(20L, metricData_1.toMap().get("Column"));
+        Assert.assertEquals(20L, metricData_1.asMap().get("Column"));
     }
 
     @Test
     public void testMergeMapData() {
         String id_1 = "2016" + Const.ID_SPLIT + "B";
         MetricData metricData_1 = new MetricData(id_1);
-        metricData_1.setMetric("Column", 10L);
+        metricData_1.set("Column", 10L);
 
         Map<String, Object> dbData = new HashMap<>();
         dbData.put("Column", 10L);
 
         metricData_1.merge(dbData);
-        Assert.assertEquals(20L, metricData_1.toMap().get("Column"));
+        Assert.assertEquals(20L, metricData_1.asMap().get("Column"));
     }
 }
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/storage/PersistenceWorkerListenerTestCase.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/storage/PersistenceWorkerListenerTestCase.java
new file mode 100644
index 0000000..70917c3
--- /dev/null
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/storage/PersistenceWorkerListenerTestCase.java
@@ -0,0 +1,23 @@
+package com.a.eye.skywalking.collector.worker.storage;
+
+import com.a.eye.skywalking.collector.actor.AbstractLocalSyncWorker;
+import java.util.List;
+import org.junit.Assert;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+/**
+ * @author pengys5
+ */
+public class PersistenceWorkerListenerTestCase {
+
+    @Test
+    public void register() {
+        PersistenceWorkerListener.INSTANCE.reset();
+        AbstractLocalSyncWorker worker = Mockito.mock(AbstractLocalSyncWorker.class);
+        PersistenceWorkerListener.INSTANCE.register(worker);
+
+        List<AbstractLocalSyncWorker> workers = PersistenceWorkerListener.INSTANCE.getWorkers();
+        Assert.assertEquals(worker, workers.get(0));
+    }
+}
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/storage/RecordAnalysisDataTestCase.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/storage/RecordAnalysisDataTestCase.java
new file mode 100644
index 0000000..5438ea1
--- /dev/null
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/storage/RecordAnalysisDataTestCase.java
@@ -0,0 +1,29 @@
+package com.a.eye.skywalking.collector.worker.storage;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * @author pengys5
+ */
+public class RecordAnalysisDataTestCase {
+
+    @Test
+    public void getOrCreate() {
+        RecordAnalysisData recordAnalysisData = new RecordAnalysisData();
+        RecordData recordData = recordAnalysisData.getOrCreate("Test1");
+
+        RecordData recordData_1 = recordAnalysisData.getOrCreate("Test1");
+        Assert.assertEquals(recordData, recordData_1);
+    }
+
+    @Test
+    public void asMap() {
+        RecordAnalysisData recordAnalysisData = new RecordAnalysisData();
+        RecordData recordData = recordAnalysisData.getOrCreate("Test1");
+        recordData.merge(null);
+
+        RecordData recordData_1 = recordAnalysisData.asMap().get("Test1");
+        Assert.assertEquals(recordData, recordData_1);
+    }
+}
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/storage/RecordPersistenceDataTestCase.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/storage/RecordPersistenceDataTestCase.java
deleted file mode 100644
index beb32fa..0000000
--- a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/storage/RecordPersistenceDataTestCase.java
+++ /dev/null
@@ -1,99 +0,0 @@
-package com.a.eye.skywalking.collector.worker.storage;
-
-import com.a.eye.skywalking.collector.worker.Const;
-import com.google.gson.JsonObject;
-import org.junit.Assert;
-import org.junit.Test;
-
-import java.util.Iterator;
-import java.util.Map;
-
-/**
- * @author pengys5
- */
-public class RecordPersistenceDataTestCase {
-
-    @Test
-    public void testGetElseCreate() {
-        String id = "2016" + Const.ID_SPLIT + "A" + Const.ID_SPLIT + "B";
-
-        JsonObject record = new JsonObject();
-        record.addProperty("Column_1", "Value_1");
-        RecordPersistenceData recordPersistenceData = new RecordPersistenceData();
-        RecordData recordData = recordPersistenceData.getElseCreate(id);
-        recordData.setRecord(record);
-
-        Assert.assertEquals(id, recordData.getId());
-
-        RecordData recordData1 = recordPersistenceData.getElseCreate(id);
-        Assert.assertEquals("Value_1", recordData1.getRecord().get("Column_1").getAsString());
-    }
-
-    @Test
-    public void testClear() {
-        String id_1 = "2016" + Const.ID_SPLIT + "A" + Const.ID_SPLIT + "B";
-        String id_2 = "2016" + Const.ID_SPLIT + "B" + Const.ID_SPLIT + "C";
-        RecordPersistenceData recordPersistenceData = new RecordPersistenceData();
-        recordPersistenceData.getElseCreate(id_1);
-        Assert.assertEquals(1, recordPersistenceData.size());
-        recordPersistenceData.getElseCreate(id_2);
-        Assert.assertEquals(2, recordPersistenceData.size());
-
-        Assert.assertEquals(true, recordPersistenceData.hasNext());
-
-        recordPersistenceData.clear();
-        Assert.assertEquals(0, recordPersistenceData.size());
-
-        Assert.assertEquals(false, recordPersistenceData.hasNext());
-    }
-
-    @Test
-    public void testPushOne() {
-        String id_1 = "2016" + Const.ID_SPLIT + "A" + Const.ID_SPLIT + "B";
-        String id_2 = "2016" + Const.ID_SPLIT + "B" + Const.ID_SPLIT + "C";
-        RecordPersistenceData recordPersistenceData = new RecordPersistenceData();
-        JsonObject obj_1 = new JsonObject();
-        obj_1.addProperty("Column_1", "Value_1");
-        recordPersistenceData.getElseCreate(id_1).setRecord(obj_1);
-
-        JsonObject obj_2 = new JsonObject();
-        obj_2.addProperty("Column_2", "Value_2");
-        recordPersistenceData.getElseCreate(id_2).setRecord(obj_2);
-
-        RecordData recordData_2 = recordPersistenceData.pushOne();
-        Assert.assertEquals("Value_2", recordData_2.getRecord().get("Column_2").getAsString());
-
-        RecordData recordData_1 = recordPersistenceData.pushOne();
-        Assert.assertEquals("Value_1", recordData_1.getRecord().get("Column_1").getAsString());
-    }
-
-    @Test(expected = UnsupportedOperationException.class)
-    public void testForEach() {
-        RecordPersistenceData recordPersistenceData = new RecordPersistenceData();
-        recordPersistenceData.forEach(r -> System.out.println(r));
-    }
-
-    @Test(expected = UnsupportedOperationException.class)
-    public void testSpliterator() {
-        RecordPersistenceData recordPersistenceData = new RecordPersistenceData();
-        recordPersistenceData.spliterator();
-    }
-
-    @Test
-    public void testIterator() {
-        String id_1 = "2016" + Const.ID_SPLIT + "A" + Const.ID_SPLIT + "B";
-        String id_2 = "2016" + Const.ID_SPLIT + "B" + Const.ID_SPLIT + "C";
-        RecordPersistenceData recordPersistenceData = new RecordPersistenceData();
-        JsonObject obj_1 = new JsonObject();
-        obj_1.addProperty("Column_1", "Value_1");
-        recordPersistenceData.getElseCreate(id_1).setRecord(obj_1);
-
-        JsonObject obj_2 = new JsonObject();
-        obj_2.addProperty("Column_2", "Value_2");
-        recordPersistenceData.getElseCreate(id_2).setRecord(obj_2);
-
-        Iterator<Map.Entry<String, RecordData>> iterator = recordPersistenceData.iterator();
-        Assert.assertEquals("Value_2", iterator.next().getValue().getRecord().get("Column_2").getAsString());
-        Assert.assertEquals("Value_1", iterator.next().getValue().getRecord().get("Column_1").getAsString());
-    }
-}
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/storage/RecordPersistenceTestCase.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/storage/RecordPersistenceTestCase.java
new file mode 100644
index 0000000..799757c
--- /dev/null
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/storage/RecordPersistenceTestCase.java
@@ -0,0 +1,72 @@
+package com.a.eye.skywalking.collector.worker.storage;
+
+import com.a.eye.skywalking.collector.worker.Const;
+import com.google.gson.JsonObject;
+import java.lang.reflect.Field;
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * @author pengys5
+ */
+public class RecordPersistenceTestCase {
+
+    @Test
+    public void testGetElseCreate() {
+        String id = "2016" + Const.ID_SPLIT + "A" + Const.ID_SPLIT + "B";
+
+        JsonObject record = new JsonObject();
+        record.addProperty("Column_1", "Value_1");
+        RecordPersistenceData recordPersistenceData = new RecordPersistenceData();
+        recordPersistenceData.hold();
+
+        RecordData recordData = recordPersistenceData.getOrCreate(id);
+        recordData.set(record);
+
+        Assert.assertEquals(id, recordData.getId());
+
+        RecordData recordData1 = recordPersistenceData.getOrCreate(id);
+        Assert.assertEquals("Value_1", recordData1.get().get("Column_1").getAsString());
+    }
+
+    @Test
+    public void testClear() {
+        String id_1 = "2016" + Const.ID_SPLIT + "A" + Const.ID_SPLIT + "B";
+        String id_2 = "2016" + Const.ID_SPLIT + "B" + Const.ID_SPLIT + "C";
+        RecordPersistenceData recordPersistenceData = new RecordPersistenceData();
+        recordPersistenceData.hold();
+
+        recordPersistenceData.getOrCreate(id_1);
+        Assert.assertEquals(1, recordPersistenceData.getCurrentAndHold().size());
+        recordPersistenceData.getOrCreate(id_2);
+        Assert.assertEquals(2, recordPersistenceData.getCurrentAndHold().size());
+
+        recordPersistenceData.getCurrentAndHold().clear();
+        Assert.assertEquals(0, recordPersistenceData.getCurrentAndHold().size());
+    }
+
+    @Test
+    public void hold() throws NoSuchFieldException, IllegalAccessException {
+        RecordPersistenceData persistenceData = new RecordPersistenceData();
+        persistenceData.hold();
+
+        Field testAField = persistenceData.getClass().getDeclaredField("lockedWindowData");
+        testAField.setAccessible(true);
+        WindowData<JoinAndSplitData> windowData = (WindowData<JoinAndSplitData>)testAField.get(persistenceData);
+        Assert.assertEquals(true, windowData.isHolding());
+    }
+
+    @Test
+    public void release() throws NoSuchFieldException, IllegalAccessException {
+        RecordPersistenceData persistenceData = new RecordPersistenceData();
+        persistenceData.hold();
+
+        Field testAField = persistenceData.getClass().getDeclaredField("lockedWindowData");
+        testAField.setAccessible(true);
+        WindowData<JoinAndSplitData> windowData = (WindowData<JoinAndSplitData>)testAField.get(persistenceData);
+        Assert.assertEquals(true, windowData.isHolding());
+
+        persistenceData.release();
+        Assert.assertEquals(false, windowData.isHolding());
+    }
+}
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/storage/RecordDataTestCase.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/storage/RecordWindowDataTestCase.java
similarity index 78%
rename from skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/storage/RecordDataTestCase.java
rename to skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/storage/RecordWindowDataTestCase.java
index bf5e5c8..fd158cb 100644
--- a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/storage/RecordDataTestCase.java
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/storage/RecordWindowDataTestCase.java
@@ -8,7 +8,7 @@
 /**
  * @author pengys5
  */
-public class RecordDataTestCase {
+public class RecordWindowDataTestCase {
 
     @Test
     public void testConstruction() {
@@ -16,7 +16,7 @@
         RecordData recordData = new RecordData(id_1);
 
         Assert.assertEquals(id_1, recordData.getId());
-        Assert.assertEquals("B" + Const.ID_SPLIT + "C", recordData.getRecord().get("aggId").getAsString());
+        Assert.assertEquals("B" + Const.ID_SPLIT + "C", recordData.get().get("aggId").getAsString());
     }
 
     @Test
@@ -26,10 +26,10 @@
 
         JsonObject record = new JsonObject();
         record.addProperty("Column", "VALUE");
-        recordData.setRecord(record);
+        recordData.set(record);
 
         Assert.assertEquals(id_1, recordData.getId());
-        Assert.assertEquals("B" + Const.ID_SPLIT + "C", recordData.getRecord().get("aggId").getAsString());
-        Assert.assertEquals("VALUE", recordData.getRecord().get("Column").getAsString());
+        Assert.assertEquals("B" + Const.ID_SPLIT + "C", recordData.get().get("aggId").getAsString());
+        Assert.assertEquals("VALUE", recordData.get().get("Column").getAsString());
     }
 }
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/storage/SegmentDataTestCase.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/storage/SegmentDataTestCase.java
new file mode 100644
index 0000000..fb1e2b4
--- /dev/null
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/storage/SegmentDataTestCase.java
@@ -0,0 +1,21 @@
+package com.a.eye.skywalking.collector.worker.storage;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * @author pengys5
+ */
+public class SegmentDataTestCase {
+
+    @Test
+    public void test() {
+        SegmentData segmentData = new SegmentData("Test1");
+
+        segmentData.merge(null);
+        Assert.assertEquals("Test1", segmentData.getId());
+
+        segmentData.setSegmentStr("Test2");
+        Assert.assertEquals("Test2", segmentData.getSegmentStr());
+    }
+}
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/storage/SegmentPersistenceDataTestCase.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/storage/SegmentPersistenceDataTestCase.java
new file mode 100644
index 0000000..080d62d
--- /dev/null
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/storage/SegmentPersistenceDataTestCase.java
@@ -0,0 +1,36 @@
+package com.a.eye.skywalking.collector.worker.storage;
+
+import java.lang.reflect.Field;
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * @author pengys5
+ */
+public class SegmentPersistenceDataTestCase {
+
+    @Test
+    public void getOrCreate() throws NoSuchFieldException, IllegalAccessException {
+        SegmentPersistenceData segmentPersistenceData = new SegmentPersistenceData();
+        segmentPersistenceData.hold();
+        SegmentData segmentData = segmentPersistenceData.getOrCreate("Test1");
+
+        SegmentData segmentData_1 = segmentPersistenceData.getOrCreate("Test1");
+        Assert.assertEquals(segmentData, segmentData_1);
+
+        SegmentData segmentData_2 = segmentPersistenceData.getOrCreate("Test2");
+        Assert.assertEquals(2, segmentPersistenceData.size());
+
+        System.out.println(segmentPersistenceData.asMap().toString());
+        Assert.assertEquals(segmentData, segmentPersistenceData.asMap().get("Test1"));
+        Assert.assertEquals(segmentData_2, segmentPersistenceData.asMap().get("Test2"));
+
+        Field testAField = segmentPersistenceData.getClass().getDeclaredField("lockedWindowData");
+        testAField.setAccessible(true);
+        WindowData<SegmentData> windowData = (WindowData<SegmentData>)testAField.get(segmentPersistenceData);
+        Assert.assertEquals(true, windowData.isHolding());
+
+        segmentPersistenceData.release();
+        Assert.assertEquals(false, windowData.isHolding());
+    }
+}
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/storage/WindowTestCase.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/storage/WindowTestCase.java
new file mode 100644
index 0000000..c0f20d8
--- /dev/null
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/storage/WindowTestCase.java
@@ -0,0 +1,67 @@
+package com.a.eye.skywalking.collector.worker.storage;
+
+import java.lang.reflect.Field;
+import java.util.Map;
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * @author pengys5
+ */
+public class WindowTestCase {
+
+    @Test
+    public void switchPointer() throws NoSuchFieldException, IllegalAccessException {
+        Impl impl = new Impl();
+
+        Field pointerField = impl.getClass().getSuperclass().getDeclaredField("pointer");
+        pointerField.setAccessible(true);
+        WindowData<DataImpl> pointer = (WindowData<DataImpl>)pointerField.get(impl);
+
+        Field windowDataAField = impl.getClass().getSuperclass().getDeclaredField("windowDataA");
+        windowDataAField.setAccessible(true);
+        WindowData<DataImpl> windowDataA = (WindowData<DataImpl>)windowDataAField.get(impl);
+
+        Field windowDataBField = impl.getClass().getSuperclass().getDeclaredField("windowDataB");
+        windowDataBField.setAccessible(true);
+        WindowData<DataImpl> windowDataB = (WindowData<DataImpl>)windowDataBField.get(impl);
+
+        Assert.assertEquals(false, windowDataA.isHolding());
+        WindowData<DataImpl> current = impl.getCurrentAndHold();
+        Assert.assertEquals(current, windowDataA);
+        Assert.assertEquals(true, windowDataA.isHolding());
+
+        WindowData<DataImpl> last = impl.getLast();
+        Assert.assertEquals(last, windowDataB);
+
+        Assert.assertEquals(pointer, windowDataA);
+        impl.switchPointer();
+        pointer = (WindowData<DataImpl>)pointerField.get(impl);
+        Assert.assertEquals(pointer, windowDataB);
+
+        current = impl.getCurrentAndHold();
+        Assert.assertEquals(current, windowDataB);
+        Assert.assertEquals(true, windowDataB.isHolding());
+
+        last = impl.getLast();
+        Assert.assertEquals(last, windowDataA);
+
+        impl.switchPointer();
+        pointer = (WindowData<DataImpl>)pointerField.get(impl);
+        Assert.assertEquals(pointer, windowDataA);
+    }
+
+    class Impl extends Window<DataImpl> {
+
+    }
+
+    class DataImpl implements Data {
+        @Override public String getId() {
+            return null;
+        }
+
+        @Override public void merge(Map<String, ?> dbData) {
+
+        }
+    }
+}
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/tools/DateToolsTestCase.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/tools/DateToolsTestCase.java
index bba1a3f..e18905e 100644
--- a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/tools/DateToolsTestCase.java
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/tools/DateToolsTestCase.java
@@ -35,10 +35,10 @@
         Calendar calendar = Calendar.getInstance();
         calendar.setTimeInMillis(1490922929258L);
         calendar.set(Calendar.SECOND, calendar.get(Calendar.SECOND) - 3);
-        System.out.println(calendar.getTimeInMillis());
+//        System.out.println(calendar.getTimeInMillis());
         calendar.set(Calendar.SECOND, calendar.get(Calendar.SECOND) - 2);
-        System.out.println(calendar.getTimeInMillis());
+//        System.out.println(calendar.getTimeInMillis());
         calendar.set(Calendar.SECOND, calendar.get(Calendar.SECOND) - 2);
-        System.out.println(calendar.getTimeInMillis());
+//        System.out.println(calendar.getTimeInMillis());
     }
 }
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/tools/IdSplitTestCase.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/tools/IdSplitTestCase.java
index dadb89a..5ccde52 100644
--- a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/tools/IdSplitTestCase.java
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/tools/IdSplitTestCase.java
@@ -13,7 +13,7 @@
         String id = "201703221502..-..portal-service..-..[127.0.0.1:8002]";
         String[] ids = id.split(Const.IDS_SPLIT);
         for (String splitId : ids) {
-            System.out.println(splitId);
+//            System.out.println(splitId);
         }
     }
 }
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/tools/MergeDataAggTools.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/tools/MergeDataAggTools.java
index e242ff8..f800f24 100644
--- a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/tools/MergeDataAggTools.java
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/tools/MergeDataAggTools.java
@@ -3,7 +3,7 @@
 import com.a.eye.skywalking.collector.actor.AbstractClusterWorker;
 import com.a.eye.skywalking.collector.worker.Const;
 import com.a.eye.skywalking.collector.worker.mock.MergeDataAnswer;
-import com.a.eye.skywalking.collector.worker.storage.MergeData;
+import com.a.eye.skywalking.collector.worker.storage.JoinAndSplitData;
 import org.junit.Assert;
 
 /**
@@ -14,9 +14,9 @@
 
     public void testOnWork(AbstractClusterWorker agg, MergeDataAnswer mergeDataAnswer) throws Exception {
         String id = "2016" + Const.ID_SPLIT + "A" + Const.ID_SPLIT + "B";
-        MergeData mergeData = new MergeData(id);
-        mergeData.setMergeData("Column", "VALUE");
-        agg.allocateJob(mergeData);
-        Assert.assertEquals("VALUE", mergeDataAnswer.getMergeDataList().get(0).toMap().get("Column"));
+        JoinAndSplitData joinAndSplitData = new JoinAndSplitData(id);
+        joinAndSplitData.set("Column", "VALUE");
+        agg.allocateJob(joinAndSplitData);
+        Assert.assertEquals("VALUE", mergeDataAnswer.getJoinAndSplitDataList().get(0).asMap().get("Column"));
     }
 }
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/tools/MetricDataAggTools.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/tools/MetricDataAggTools.java
index 4119c32..c060529 100644
--- a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/tools/MetricDataAggTools.java
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/tools/MetricDataAggTools.java
@@ -16,6 +16,6 @@
         String id = "2016" + Const.ID_SPLIT + "A" + Const.ID_SPLIT + "B";
         MetricData metricData = new MetricData(id);
         agg.allocateJob(metricData);
-        Assert.assertEquals("A" + Const.ID_SPLIT + "B", metricDataAnswer.getMetricDataList().get(0).toMap().get("aggId"));
+        Assert.assertEquals("A" + Const.ID_SPLIT + "B", metricDataAnswer.getMetricDataList().get(0).asMap().get("aggId"));
     }
 }
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/tools/RecordDataAggTools.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/tools/RecordDataAggTools.java
index 41dd004..d38fa84 100644
--- a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/tools/RecordDataAggTools.java
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/tools/RecordDataAggTools.java
@@ -17,6 +17,6 @@
         RecordData recordData = new RecordData(id);
         agg.allocateJob(recordData);
         RecordData result = RecordDataTool.INSTANCE.getRecord(recordDataAnswer.getRecordDataList(), id);
-        Assert.assertEquals("A" + Const.ID_SPLIT + "B", result.getRecord().get("aggId").getAsString());
+        Assert.assertEquals("A" + Const.ID_SPLIT + "B", result.get().get("aggId").getAsString());
     }
 }
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/tools/SpanPeersToolsTestCase.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/tools/SpanPeersToolsTestCase.java
index 8abaa82..5e63b38 100644
--- a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/tools/SpanPeersToolsTestCase.java
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/tools/SpanPeersToolsTestCase.java
@@ -1,6 +1,6 @@
 package com.a.eye.skywalking.collector.worker.tools;
 
-import com.a.eye.skywalking.trace.Span;
+import com.a.eye.skywalking.collector.worker.segment.entity.Span;
 import org.junit.Assert;
 import org.junit.Test;
 
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/tracedag/TraceDagGetWithTimeSliceTestCase.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/tracedag/TraceDagGetWithTimeSliceTestCase.java
index 80eefd0..d8d650a 100644
--- a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/tracedag/TraceDagGetWithTimeSliceTestCase.java
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/tracedag/TraceDagGetWithTimeSliceTestCase.java
@@ -86,10 +86,10 @@
 
     @Test
     public void testPreStart() throws ProviderNotFoundException {
-        when(clusterWorkerContext.findProvider(NodeCompLoad.WorkerRole.INSTANCE)).thenReturn(NodeCompLoad.Factory.INSTANCE);
-        when(clusterWorkerContext.findProvider(NodeMappingSearchWithTimeSlice.WorkerRole.INSTANCE)).thenReturn(NodeMappingSearchWithTimeSlice.Factory.INSTANCE);
-        when(clusterWorkerContext.findProvider(NodeRefSearchWithTimeSlice.WorkerRole.INSTANCE)).thenReturn(NodeRefSearchWithTimeSlice.Factory.INSTANCE);
-        when(clusterWorkerContext.findProvider(NodeRefResSumSearchWithTimeSlice.WorkerRole.INSTANCE)).thenReturn(NodeRefResSumSearchWithTimeSlice.Factory.INSTANCE);
+        when(clusterWorkerContext.findProvider(NodeCompLoad.WorkerRole.INSTANCE)).thenReturn(new NodeCompLoad.Factory());
+        when(clusterWorkerContext.findProvider(NodeMappingSearchWithTimeSlice.WorkerRole.INSTANCE)).thenReturn(new NodeMappingSearchWithTimeSlice.Factory());
+        when(clusterWorkerContext.findProvider(NodeRefSearchWithTimeSlice.WorkerRole.INSTANCE)).thenReturn(new NodeRefSearchWithTimeSlice.Factory());
+        when(clusterWorkerContext.findProvider(NodeRefResSumSearchWithTimeSlice.WorkerRole.INSTANCE)).thenReturn(new NodeRefResSumSearchWithTimeSlice.Factory());
 
         ArgumentCaptor<Role> argumentCaptor = ArgumentCaptor.forClass(Role.class);
         getObj.preStart();
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/tracedag/TraceDagDataBuilderTestCase.java b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/tracedag/TraceDagWindowDataBuilderTestCase.java
similarity index 95%
rename from skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/tracedag/TraceDagDataBuilderTestCase.java
rename to skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/tracedag/TraceDagWindowDataBuilderTestCase.java
index 1bf956c..3c6a86d 100644
--- a/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/tracedag/TraceDagDataBuilderTestCase.java
+++ b/skywalking-collector/skywalking-collector-worker/src/test/java/com/a/eye/skywalking/collector/worker/tracedag/TraceDagWindowDataBuilderTestCase.java
@@ -8,7 +8,7 @@
 /**
  * @author pengys5
  */
-public class TraceDagDataBuilderTestCase {
+public class TraceDagWindowDataBuilderTestCase {
 
     private Gson gson = new Gson();
 
@@ -26,11 +26,11 @@
         JsonArray lineArray = dagJsonObj.getAsJsonArray("nodeRefs");
 
         for (int i = 0; i < pointArray.size(); i++) {
-            System.out.println(pointArray.get(i).getAsJsonObject());
+//            System.out.println(pointArray.get(i).getAsJsonObject());
         }
 
         for (int i = 0; i < lineArray.size(); i++) {
-            System.out.println(lineArray.get(i).getAsJsonObject());
+//            System.out.println(lineArray.get(i).getAsJsonObject());
         }
     }
 
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/resources/json/globaltrace/persistence/globaltrace_search.json b/skywalking-collector/skywalking-collector-worker/src/test/resources/json/globaltrace/persistence/globaltrace_search.json
new file mode 100644
index 0000000..0dec694
--- /dev/null
+++ b/skywalking-collector/skywalking-collector-worker/src/test/resources/json/globaltrace/persistence/globaltrace_search.json
@@ -0,0 +1,3 @@
+{
+  "subSegIds": "Segment.1490922929258.927784221.5991.27.1"
+}
\ No newline at end of file
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/resources/json/globaltrace/persistence/globaltrace_segment.json b/skywalking-collector/skywalking-collector-worker/src/test/resources/json/globaltrace/persistence/globaltrace_segment.json
new file mode 100644
index 0000000..3fed5b6
--- /dev/null
+++ b/skywalking-collector/skywalking-collector-worker/src/test/resources/json/globaltrace/persistence/globaltrace_segment.json
@@ -0,0 +1,185 @@
+{
+  "ts": "Segment.1490922929258.927784221.5991.27.1",
+  "st": 1490922929258,
+  "et": 1490922929261,
+  "rs": [
+    {
+      "ts": "Segment.1490922929254.1797892356.6003.69.1",
+      "si": 2,
+      "ac": "portal-service",
+      "ph": "127.0.0.1:8002"
+    }
+  ],
+  "ss": [
+    {
+      "si": 2,
+      "ps": 1,
+      "st": 1490922929258,
+      "et": 1490922929258,
+      "on": "Jedis/getClient",
+      "ts": {
+        "span.layer": "db",
+        "component": "Redis",
+        "db.type": "Redis",
+        "peer.host": "127.0.0.1",
+        "span.kind": "client"
+      },
+      "tb": {},
+      "ti": {
+        "peer.port": 6379
+      },
+      "lo": []
+    },
+    {
+      "si": 3,
+      "ps": 1,
+      "st": 1490922929258,
+      "et": 1490922929258,
+      "on": "Jedis/getClient",
+      "ts": {
+        "span.layer": "db",
+        "component": "Redis",
+        "db.type": "Redis",
+        "peer.host": "127.0.0.1",
+        "span.kind": "client"
+      },
+      "tb": {},
+      "ti": {
+        "peer.port": 6379
+      },
+      "lo": []
+    },
+    {
+      "si": 4,
+      "ps": 1,
+      "st": 1490922929258,
+      "et": 1490922929258,
+      "on": "Jedis/isConnected",
+      "ts": {
+        "span.layer": "db",
+        "component": "Redis",
+        "db.type": "Redis",
+        "peer.host": "127.0.0.1",
+        "span.kind": "client"
+      },
+      "tb": {},
+      "ti": {
+        "peer.port": 6379
+      },
+      "lo": []
+    },
+    {
+      "si": 5,
+      "ps": 1,
+      "st": 1490922929258,
+      "et": 1490922929259,
+      "on": "Jedis/ping",
+      "ts": {
+        "span.layer": "db",
+        "component": "Redis",
+        "db.type": "Redis",
+        "peer.host": "127.0.0.1",
+        "span.kind": "client"
+      },
+      "tb": {},
+      "ti": {
+        "peer.port": 6379
+      },
+      "lo": []
+    },
+    {
+      "si": 6,
+      "ps": 1,
+      "st": 1490922929259,
+      "et": 1490922929259,
+      "on": "Jedis/get",
+      "ts": {
+        "span.layer": "db",
+        "component": "Redis",
+        "db.type": "Redis",
+        "peer.host": "127.0.0.1",
+        "span.kind": "client",
+        "db.statement": "get test"
+      },
+      "tb": {},
+      "ti": {
+        "peer.port": 6379
+      },
+      "lo": []
+    },
+    {
+      "si": 7,
+      "ps": 1,
+      "st": 1490922929261,
+      "et": 1490922929261,
+      "on": "H2/JDBI/PreparedStatement/executeQuery",
+      "ts": {
+        "db.instance": "dataSource",
+        "span.layer": "db",
+        "db.type": "sql",
+        "component": "H2",
+        "span.kind": "client",
+        "db.statement": "SELECT id,CACHE_VALUE, CACHE_KEY FROM CACHE_TABLE WHERE CACHE_KEY \u003d ?",
+        "peer.host": "localhost"
+      },
+      "tb": {},
+      "ti": {
+        "peer.port": -1
+      },
+      "lo": []
+    },
+    {
+      "si": 8,
+      "ps": 1,
+      "st": 1490922929261,
+      "et": 1490922929261,
+      "on": "H2/JDBI/Connection/close",
+      "ts": {
+        "db.instance": "dataSource",
+        "span.layer": "db",
+        "db.type": "sql",
+        "component": "H2",
+        "span.kind": "client",
+        "db.statement": "",
+        "peer.host": "localhost"
+      },
+      "tb": {},
+      "ti": {
+        "peer.port": -1
+      },
+      "lo": []
+    },
+    {
+      "si": 1,
+      "ps": 0,
+      "st": 0,
+      "et": 1490922929261,
+      "on": "Motan_default_rpc_com.a.eye.skywalking.test.cache.CacheService.findCache(java.lang.String)",
+      "ts": {
+        "requestId": "1563346001467539461"
+      },
+      "tb": {},
+      "ti": {},
+      "lo": []
+    },
+    {
+      "si": 0,
+      "ps": -1,
+      "st": 1490922929258,
+      "et": 1490922929261,
+      "on": "com.a.eye.skywalking.test.cache.CacheService.findCache(java.lang.String)",
+      "ts": {
+        "span.layer": "rpc",
+        "component": "Motan",
+        "span.kind": "server"
+      },
+      "tb": {},
+      "ti": {},
+      "lo": []
+    }
+  ],
+  "ac": "cache-service",
+  "gt": [
+    "Trace.1490922929254.1797892356.6003.69.2"
+  ]
+}
\ No newline at end of file
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/resources/json/span/persistence/segment.json b/skywalking-collector/skywalking-collector-worker/src/test/resources/json/span/persistence/segment.json
new file mode 100644
index 0000000..89f2b31
--- /dev/null
+++ b/skywalking-collector/skywalking-collector-worker/src/test/resources/json/span/persistence/segment.json
@@ -0,0 +1,134 @@
+{
+  "ts": "Segment.1490922929254.1797892356.6003.69.1",
+  "st": 1490922929254,
+  "et": 1490922929306,
+  "ss": [
+    {
+      "si": 2,
+      "ps": 1,
+      "st": 1490922929257,
+      "et": 1490922929262,
+      "on": "com.a.eye.skywalking.test.cache.CacheService.findCache(java.lang.String)",
+      "ts": {
+        "span.layer": "rpc",
+        "peer.host": "127.0.0.1",
+        "component": "Motan",
+        "span.kind": "client",
+        "url": "motan://127.0.0.1:8002/default_rpc/com.a.eye.skywalking.test.cache.CacheService/1.0/referer"
+      },
+      "tb": {},
+      "ti": {
+        "peer.port": 8002
+      },
+      "lo": []
+    },
+    {
+      "si": 1,
+      "ps": 0,
+      "st": 0,
+      "et": 1490922929262,
+      "on": "Motan_default_rpc_com.a.eye.skywalking.test.cache.CacheService.findCache(java.lang.String)",
+      "ts": {
+        "requestId": "1563346001467539461"
+      },
+      "tb": {},
+      "ti": {},
+      "lo": []
+    },
+    {
+      "si": 4,
+      "ps": 3,
+      "st": 1490922929262,
+      "et": 1490922929293,
+      "on": "/persistence/query",
+      "ts": {
+        "span.layer": "http",
+        "peer.host": "10.128.35.80",
+        "component": "HttpClient",
+        "span.kind": "client",
+        "url": "http://10.128.35.80:20880/persistence/query"
+      },
+      "tb": {},
+      "ti": {
+        "peer.port": 20880,
+        "status_code": 200
+      },
+      "lo": []
+    },
+    {
+      "si": 3,
+      "ps": 0,
+      "st": 1490922929262,
+      "et": 1490922929297,
+      "on": "com.a.eye.skywalking.test.persistence.PersistenceService.query(String)",
+      "ts": {
+        "span.layer": "rpc",
+        "component": "Dubbo",
+        "peer.host": "10.128.35.80",
+        "span.kind": "client",
+        "url": "rest://10.128.35.80:20880/com.a.eye.skywalking.test.persistence.PersistenceService.query(String)"
+      },
+      "tb": {},
+      "ti": {
+        "peer.port": 20880
+      },
+      "lo": []
+    },
+    {
+      "si": 6,
+      "ps": 5,
+      "st": 1490922929297,
+      "et": 1490922929303,
+      "on": "com.a.eye.skywalking.test.cache.CacheService.updateCache(java.lang.String,java.lang.String)",
+      "ts": {
+        "span.layer": "rpc",
+        "peer.host": "127.0.0.1",
+        "component": "Motan",
+        "span.kind": "client",
+        "url": "motan://127.0.0.1:8002/default_rpc/com.a.eye.skywalking.test.cache.CacheService/1.0/referer"
+      },
+      "tb": {},
+      "ti": {
+        "peer.port": 8002
+      },
+      "lo": []
+    },
+    {
+      "si": 5,
+      "ps": 0,
+      "st": 0,
+      "et": 1490922929303,
+      "on": "Motan_default_rpc_com.a.eye.skywalking.test.cache.CacheService.updateCache(java.lang.String,java.lang.String)",
+      "ts": {
+        "requestId": "1563346001510531078"
+      },
+      "tb": {},
+      "ti": {},
+      "lo": []
+    },
+    {
+      "si": 0,
+      "ps": -1,
+      "st": 1490922929254,
+      "et": 1490922929306,
+      "on": "/portal/",
+      "ts": {
+        "span.layer": "http",
+        "component": "Tomcat",
+        "peer.host": "0:0:0:0:0:0:0:1",
+        "span.kind": "server",
+        "url": "http://localhost:38080/portal/"
+      },
+      "tb": {},
+      "ti": {
+        "peer.port": 57837,
+        "status_code": 200
+      },
+      "lo": []
+    }
+  ],
+  "ac": "portal-service",
+  "gt": [
+    "Trace.1490922929254.1797892356.6003.69.2"
+  ]
+}
\ No newline at end of file
diff --git a/skywalking-collector/skywalking-collector-worker/src/test/resources/log4j2.xml b/skywalking-collector/skywalking-collector-worker/src/test/resources/log4j2.xml
new file mode 100644
index 0000000..070276a
--- /dev/null
+++ b/skywalking-collector/skywalking-collector-worker/src/test/resources/log4j2.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Configuration status="error">
+    <Properties>
+        <Property name="log-path">../logs</Property>
+    </Properties>
+    <Appenders>
+        <RollingFile name="RollingFile" fileName="${log-path}/skywalking-server-log4j2.log"
+                     filePattern="${log-path}/skywalking-server-log4j2-%d{yyyy-MM-dd}-%i.log">
+            <PatternLayout>
+                <pattern>%d - %c -%-4r [%t] %-5p %x - %m%n</pattern>
+            </PatternLayout>
+            <Policies>
+                <SizeBasedTriggeringPolicy size="102400KB"/>
+            </Policies>
+            <DefaultRolloverStrategy max="30"/>
+        </RollingFile>
+    </Appenders>
+    <Loggers>
+        <logger name="com.a.eye.skywalking.collector" level="ERROR">
+            <AppenderRef ref="RollingFile"/>
+        </logger>
+        <Root level="ERROR">
+            <AppenderRef ref="RollingFile"/>
+        </Root>
+    </Loggers>
+</Configuration>
diff --git a/skywalking-commons/skywalking-trace/src/test/java/com/a/eye/skywalking/trace/TraceSegmentTestCase.java b/skywalking-commons/skywalking-trace/src/test/java/com/a/eye/skywalking/trace/TraceSegmentTestCase.java
index 2f64aee..b23909b 100644
--- a/skywalking-commons/skywalking-trace/src/test/java/com/a/eye/skywalking/trace/TraceSegmentTestCase.java
+++ b/skywalking-commons/skywalking-trace/src/test/java/com/a/eye/skywalking/trace/TraceSegmentTestCase.java
@@ -110,8 +110,6 @@
         message.append(segment);
         String json = gson.toJson(message);
 
-        System.out.println(json);
-
         message = gson.fromJson(json, SegmentsMessage.class);
 
         TraceSegment newSegment = message.getSegments().get(0);
diff --git a/skywalking-sniffer/skywalking-api/src/main/java/com/a/eye/skywalking/api/context/TracerContext.java b/skywalking-sniffer/skywalking-api/src/main/java/com/a/eye/skywalking/api/context/TracerContext.java
index bb94629..35fb6b3 100644
--- a/skywalking-sniffer/skywalking-api/src/main/java/com/a/eye/skywalking/api/context/TracerContext.java
+++ b/skywalking-sniffer/skywalking-api/src/main/java/com/a/eye/skywalking/api/context/TracerContext.java
@@ -7,7 +7,6 @@
 import com.a.eye.skywalking.trace.TraceSegment;
 import com.a.eye.skywalking.trace.TraceSegmentRef;
 import com.a.eye.skywalking.trace.tag.Tags;
-import java.util.ArrayList;
 import java.util.LinkedList;
 import java.util.List;
 
@@ -22,13 +21,12 @@
 
     /**
      * Active spans stored in a Stack, usually called 'ActiveSpanStack'.
-     * This {@link ArrayList} is the in-memory storage-structure.
+     * This {@link LinkedList} is the in-memory storage-structure.
      *
-     * I use {@link ArrayList#size()} as a pointer, to the top element of 'ActiveSpanStack'.
-     * And provide the top 3 important methods of stack:
+     * I use {@link LinkedList#removeLast()}, {@link LinkedList#addLast(Object)} and {@link LinkedList#last} instead of
      * {@link #pop()}, {@link #push(Span)}, {@link #peek()}
      */
-    private List<Span> activeSpanStack = new ArrayList<Span>(20);
+    private LinkedList<Span> activeSpanStack = new LinkedList<Span>();
 
     private int spanIdGenerator;
 
@@ -166,7 +164,7 @@
      * @return the top element of 'ActiveSpanStack', and remove it.
      */
     private Span pop() {
-        return activeSpanStack.remove(getTopElementIdx());
+        return activeSpanStack.removeLast();
     }
 
     /**
@@ -175,7 +173,7 @@
      * @param span
      */
     private void push(Span span) {
-        activeSpanStack.add(activeSpanStack.size(), span);
+        activeSpanStack.addLast(span);
     }
 
     /**
@@ -185,16 +183,7 @@
         if (activeSpanStack.isEmpty()) {
             return null;
         }
-        return activeSpanStack.get(getTopElementIdx());
-    }
-
-    /**
-     * Get the index of 'ActiveSpanStack'
-     *
-     * @return the index
-     */
-    private int getTopElementIdx() {
-        return activeSpanStack.size() - 1;
+        return activeSpanStack.getLast();
     }
 
     public static class ListenerManager {
diff --git a/skywalking-sniffer/skywalking-api/src/test/java/com/a/eye/skywalking/api/client/HTTPRestServiceTestApp.java b/skywalking-sniffer/skywalking-api/src/test/java/com/a/eye/skywalking/api/client/HTTPRestServiceTestApp.java
index 24f481f..361344f 100644
--- a/skywalking-sniffer/skywalking-api/src/test/java/com/a/eye/skywalking/api/client/HTTPRestServiceTestApp.java
+++ b/skywalking-sniffer/skywalking-api/src/test/java/com/a/eye/skywalking/api/client/HTTPRestServiceTestApp.java
@@ -50,7 +50,6 @@
         post.setEntity(entity);
         try {
             CloseableHttpResponse httpResponse = httpclient.execute(post);
-            System.out.println(httpResponse.getStatusLine().getStatusCode());
         } catch (IOException e) {
             e.printStackTrace();
         }
@@ -69,7 +68,6 @@
                 while ((str = br.readLine()) != null) {
                     wholeStr += str;
                 }
-                System.out.println(wholeStr);
                 response.setContentType("text/html; charset=utf-8");
                 response.setStatus(HttpServletResponse.SC_OK);
                 baseRequest.setHandled(true);
diff --git a/skywalking-sniffer/skywalking-toolkit-activation/skywalking-toolkit-opentracing-activation/src/main/java/com/a/eye/skywalking/toolkit/activation/opentracing/span/SkyWalkingSpanActivation.java b/skywalking-sniffer/skywalking-toolkit-activation/skywalking-toolkit-opentracing-activation/src/main/java/com/a/eye/skywalking/toolkit/activation/opentracing/span/SkyWalkingSpanActivation.java
index 737b920..100b57c 100644
--- a/skywalking-sniffer/skywalking-toolkit-activation/skywalking-toolkit-opentracing-activation/src/main/java/com/a/eye/skywalking/toolkit/activation/opentracing/span/SkyWalkingSpanActivation.java
+++ b/skywalking-sniffer/skywalking-toolkit-activation/skywalking-toolkit-opentracing-activation/src/main/java/com/a/eye/skywalking/toolkit/activation/opentracing/span/SkyWalkingSpanActivation.java
@@ -2,11 +2,10 @@
 
 import com.a.eye.skywalking.api.plugin.interceptor.ConstructorInterceptPoint;
 import com.a.eye.skywalking.api.plugin.interceptor.InstanceMethodsInterceptPoint;
-
 import com.a.eye.skywalking.api.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine;
+import java.util.Map;
 import net.bytebuddy.description.method.MethodDescription;
 import net.bytebuddy.matcher.ElementMatcher;
-import java.util.Map;
 
 import static net.bytebuddy.matcher.ElementMatchers.named;
 import static net.bytebuddy.matcher.ElementMatchers.takesArguments;
diff --git a/skywalking-sniffer/skywalking-toolkit-activation/skywalking-toolkit-opentracing-activation/src/main/java/com/a/eye/skywalking/toolkit/activation/opentracing/span/interceptor/SpanSetTagInterceptor.java b/skywalking-sniffer/skywalking-toolkit-activation/skywalking-toolkit-opentracing-activation/src/main/java/com/a/eye/skywalking/toolkit/activation/opentracing/span/interceptor/SpanSetTagInterceptor.java
index e3a6e7b..77560ff 100644
--- a/skywalking-sniffer/skywalking-toolkit-activation/skywalking-toolkit-opentracing-activation/src/main/java/com/a/eye/skywalking/toolkit/activation/opentracing/span/interceptor/SpanSetTagInterceptor.java
+++ b/skywalking-sniffer/skywalking-toolkit-activation/skywalking-toolkit-opentracing-activation/src/main/java/com/a/eye/skywalking/toolkit/activation/opentracing/span/interceptor/SpanSetTagInterceptor.java
@@ -6,6 +6,7 @@
 import com.a.eye.skywalking.api.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
 import com.a.eye.skywalking.api.plugin.interceptor.enhance.MethodInterceptResult;
 import com.a.eye.skywalking.toolkit.opentracing.SkyWalkingSpan;
+import io.opentracing.tag.Tags;
 
 /**
  * Intercept these following methods:
@@ -15,10 +16,15 @@
  */
 public class SpanSetTagInterceptor implements InstanceMethodsAroundInterceptor {
 
+    /**
+     * key of {@link com.a.eye.skywalking.trace.tag.Tags#PEER_HOST}
+     */
+    private static final String KEY_OF_PEER_HOST_TAG = "peer.host";
+
     @Override
     public void beforeMethod(EnhancedClassInstanceContext context, InstanceMethodInvokeContext interceptorContext,
         MethodInterceptResult result) {
-        String key = (String)interceptorContext.allArguments()[0];
+        String key = adaptTag((String)interceptorContext.allArguments()[0]);
         Object value = interceptorContext.allArguments()[1];
         if (value instanceof String)
             ContextManager.activeSpan().setTag(key, (String)value);
@@ -26,10 +32,39 @@
             ContextManager.activeSpan().setTag(key, (Boolean)value);
         else if (value instanceof Integer)
             ContextManager.activeSpan().setTag(key, (Integer)value);
+        else if (value instanceof Short)
+            ContextManager.activeSpan().setTag(key, ((Short)value).intValue());
         else
             ContextManager.activeSpan().setTag(key, value.toString());
     }
 
+    /**
+     * Adapt {@link Tags} of open tracing.
+     *
+     * @return tag key
+     */
+    private String adaptTag(String tagKey) {
+        String key = tagKey;
+
+        if (isPeerTag(key)) {
+            key = KEY_OF_PEER_HOST_TAG;
+        }
+
+        return key;
+    }
+
+    /**
+     * Check whether current tag is one of {@link Tags#PEER_HOSTNAME}, {@link Tags#PEER_HOST_IPV4} and {@link Tags#PEER_HOST_IPV6}.
+     * If yes, will use the {@link com.a.eye.skywalking.trace.tag.Tags#PEER_HOST} as the key, instead of original key,
+     * in {@link #adaptTag(String)}.
+     *
+     * @param key of current tag
+     * @return true if this tag is host related.
+     */
+    private boolean isPeerTag(String key) {
+        return Tags.PEER_HOST_IPV4.equals(key) || Tags.PEER_HOST_IPV6.equals(key) || Tags.PEER_HOSTNAME.equals(key);
+    }
+
     @Override
     public Object afterMethod(EnhancedClassInstanceContext context, InstanceMethodInvokeContext interceptorContext,
         Object ret) {
diff --git a/skywalking-sniffer/skywalking-toolkit-activation/skywalking-toolkit-opentracing-activation/src/main/java/com/a/eye/skywalking/toolkit/activation/opentracing/tracer/SkyWalkingTracerActivation.java b/skywalking-sniffer/skywalking-toolkit-activation/skywalking-toolkit-opentracing-activation/src/main/java/com/a/eye/skywalking/toolkit/activation/opentracing/tracer/SkyWalkingTracerActivation.java
index a1974a5..b91fc17 100644
--- a/skywalking-sniffer/skywalking-toolkit-activation/skywalking-toolkit-opentracing-activation/src/main/java/com/a/eye/skywalking/toolkit/activation/opentracing/tracer/SkyWalkingTracerActivation.java
+++ b/skywalking-sniffer/skywalking-toolkit-activation/skywalking-toolkit-opentracing-activation/src/main/java/com/a/eye/skywalking/toolkit/activation/opentracing/tracer/SkyWalkingTracerActivation.java
@@ -6,11 +6,7 @@
 import net.bytebuddy.description.method.MethodDescription;
 import net.bytebuddy.matcher.ElementMatcher;
 
-import java.nio.ByteBuffer;
-
-import static com.a.eye.skywalking.api.plugin.bytebuddy.ArgumentTypeNameMatch.takesArgumentWithType;
 import static net.bytebuddy.matcher.ElementMatchers.named;
-import static net.bytebuddy.matcher.ElementMatchers.takesArgument;
 
 /**
  * @author wusheng
@@ -32,34 +28,23 @@
             new InstanceMethodsInterceptPoint() {
                 @Override
                 public ElementMatcher<MethodDescription> getMethodsMatcher() {
-                    return named("formatCrossProcessPropagationContextData");
+                    return named("formatInjectCrossProcessPropagationContextData");
                 }
 
                 @Override
                 public String getMethodsInterceptor() {
-                    return "com.a.eye.skywalking.toolkit.activation.opentracing.tracer.interceptor.TracerFormatCrossProcessContextInterceptor";
+                    return "com.a.eye.skywalking.toolkit.activation.opentracing.tracer.interceptor.TracerInjectFormatCrossProcessContextInterceptor";
                 }
             },
             new InstanceMethodsInterceptPoint() {
                 @Override
                 public ElementMatcher<MethodDescription> getMethodsMatcher() {
-                    return named("extractCrossProcessPropagationContextData").and(takesArgumentWithType(0, "io.opentracing.propagation.TextMap"));
+                    return named("formatExtractCrossProcessPropagationContextData");
                 }
 
                 @Override
                 public String getMethodsInterceptor() {
-                    return "com.a.eye.skywalking.toolkit.activation.opentracing.tracer.interceptor.TracerExtractCrossProcessTextMapContextInterceptor";
-                }
-            },
-            new InstanceMethodsInterceptPoint() {
-                @Override
-                public ElementMatcher<MethodDescription> getMethodsMatcher() {
-                    return named("extractCrossProcessPropagationContextData").and(takesArgument(0, ByteBuffer.class));
-                }
-
-                @Override
-                public String getMethodsInterceptor() {
-                    return "com.a.eye.skywalking.toolkit.activation.opentracing.tracer.interceptor.TracerExtractCrossProcessByteBufferContextInterceptor";
+                    return "com.a.eye.skywalking.toolkit.activation.opentracing.tracer.interceptor.TracerExtractCrossProcessContextInterceptor";
                 }
             }
         };
diff --git a/skywalking-sniffer/skywalking-toolkit-activation/skywalking-toolkit-opentracing-activation/src/main/java/com/a/eye/skywalking/toolkit/activation/opentracing/tracer/interceptor/TracerExtractCrossProcessByteBufferContextInterceptor.java b/skywalking-sniffer/skywalking-toolkit-activation/skywalking-toolkit-opentracing-activation/src/main/java/com/a/eye/skywalking/toolkit/activation/opentracing/tracer/interceptor/TracerExtractCrossProcessByteBufferContextInterceptor.java
deleted file mode 100644
index 034c8de..0000000
--- a/skywalking-sniffer/skywalking-toolkit-activation/skywalking-toolkit-opentracing-activation/src/main/java/com/a/eye/skywalking/toolkit/activation/opentracing/tracer/interceptor/TracerExtractCrossProcessByteBufferContextInterceptor.java
+++ /dev/null
@@ -1,43 +0,0 @@
-package com.a.eye.skywalking.toolkit.activation.opentracing.tracer.interceptor;
-
-import com.a.eye.skywalking.api.context.ContextCarrier;
-import com.a.eye.skywalking.api.context.ContextManager;
-import com.a.eye.skywalking.api.plugin.interceptor.EnhancedClassInstanceContext;
-import com.a.eye.skywalking.api.plugin.interceptor.enhance.InstanceMethodInvokeContext;
-import com.a.eye.skywalking.api.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
-import com.a.eye.skywalking.api.plugin.interceptor.enhance.MethodInterceptResult;
-
-import com.a.eye.skywalking.toolkit.opentracing.SkyWalkingTracer;
-import io.opentracing.propagation.TextMap;
-import java.nio.ByteBuffer;
-import java.nio.charset.Charset;
-
-/**
- * Intercept {@link SkyWalkingTracer#extractCrossProcessPropagationContextData(TextMap)}
- */
-public class TracerExtractCrossProcessByteBufferContextInterceptor implements InstanceMethodsAroundInterceptor {
-    @Override
-    public void beforeMethod(EnhancedClassInstanceContext context, InstanceMethodInvokeContext interceptorContext,
-        MethodInterceptResult result) {
-
-    }
-
-    @Override
-    public Object afterMethod(EnhancedClassInstanceContext context, InstanceMethodInvokeContext interceptorContext,
-        Object ret) {
-        ByteBuffer byteBuffer = (ByteBuffer)interceptorContext.allArguments()[0];
-        String contextDataStr = new String(byteBuffer.array(), Charset.forName("UTF-8"));
-
-        ContextCarrier carrier = new ContextCarrier();
-        carrier.deserialize(contextDataStr);
-
-        ContextManager.extract(carrier);
-        return ret;
-    }
-
-    @Override
-    public void handleMethodException(Throwable t, EnhancedClassInstanceContext context,
-        InstanceMethodInvokeContext interceptorContext) {
-
-    }
-}
diff --git a/skywalking-sniffer/skywalking-toolkit-activation/skywalking-toolkit-opentracing-activation/src/main/java/com/a/eye/skywalking/toolkit/activation/opentracing/tracer/interceptor/TracerFormatCrossProcessContextInterceptor.java b/skywalking-sniffer/skywalking-toolkit-activation/skywalking-toolkit-opentracing-activation/src/main/java/com/a/eye/skywalking/toolkit/activation/opentracing/tracer/interceptor/TracerExtractCrossProcessContextInterceptor.java
similarity index 75%
copy from skywalking-sniffer/skywalking-toolkit-activation/skywalking-toolkit-opentracing-activation/src/main/java/com/a/eye/skywalking/toolkit/activation/opentracing/tracer/interceptor/TracerFormatCrossProcessContextInterceptor.java
copy to skywalking-sniffer/skywalking-toolkit-activation/skywalking-toolkit-opentracing-activation/src/main/java/com/a/eye/skywalking/toolkit/activation/opentracing/tracer/interceptor/TracerExtractCrossProcessContextInterceptor.java
index d9de6c2..3c62264 100644
--- a/skywalking-sniffer/skywalking-toolkit-activation/skywalking-toolkit-opentracing-activation/src/main/java/com/a/eye/skywalking/toolkit/activation/opentracing/tracer/interceptor/TracerFormatCrossProcessContextInterceptor.java
+++ b/skywalking-sniffer/skywalking-toolkit-activation/skywalking-toolkit-opentracing-activation/src/main/java/com/a/eye/skywalking/toolkit/activation/opentracing/tracer/interceptor/TracerExtractCrossProcessContextInterceptor.java
@@ -9,9 +9,9 @@
 import com.a.eye.skywalking.toolkit.opentracing.SkyWalkingTracer;
 
 /**
- * Intercept {@link SkyWalkingTracer#formatCrossProcessPropagationContextData()}
+ * Intercept {@link SkyWalkingTracer#formatExtractCrossProcessPropagationContextData(String)}
  */
-public class TracerFormatCrossProcessContextInterceptor implements InstanceMethodsAroundInterceptor {
+public class TracerExtractCrossProcessContextInterceptor implements InstanceMethodsAroundInterceptor {
     @Override
     public void beforeMethod(EnhancedClassInstanceContext context, InstanceMethodInvokeContext interceptorContext,
         MethodInterceptResult result) {
@@ -21,9 +21,13 @@
     @Override
     public Object afterMethod(EnhancedClassInstanceContext context, InstanceMethodInvokeContext interceptorContext,
         Object ret) {
+        String contextDataStr = (String)interceptorContext.allArguments()[0];
+
         ContextCarrier carrier = new ContextCarrier();
-        ContextManager.inject(carrier);
-        return carrier.serialize();
+        carrier.deserialize(contextDataStr);
+
+        ContextManager.extract(carrier);
+        return ret;
     }
 
     @Override
diff --git a/skywalking-sniffer/skywalking-toolkit-activation/skywalking-toolkit-opentracing-activation/src/main/java/com/a/eye/skywalking/toolkit/activation/opentracing/tracer/interceptor/TracerExtractCrossProcessTextMapContextInterceptor.java b/skywalking-sniffer/skywalking-toolkit-activation/skywalking-toolkit-opentracing-activation/src/main/java/com/a/eye/skywalking/toolkit/activation/opentracing/tracer/interceptor/TracerExtractCrossProcessTextMapContextInterceptor.java
deleted file mode 100644
index 9e42239..0000000
--- a/skywalking-sniffer/skywalking-toolkit-activation/skywalking-toolkit-opentracing-activation/src/main/java/com/a/eye/skywalking/toolkit/activation/opentracing/tracer/interceptor/TracerExtractCrossProcessTextMapContextInterceptor.java
+++ /dev/null
@@ -1,49 +0,0 @@
-package com.a.eye.skywalking.toolkit.activation.opentracing.tracer.interceptor;
-
-import com.a.eye.skywalking.api.context.ContextCarrier;
-import com.a.eye.skywalking.api.context.ContextManager;
-import com.a.eye.skywalking.api.plugin.interceptor.EnhancedClassInstanceContext;
-import com.a.eye.skywalking.api.plugin.interceptor.enhance.InstanceMethodInvokeContext;
-import com.a.eye.skywalking.api.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
-import com.a.eye.skywalking.api.plugin.interceptor.enhance.MethodInterceptResult;
-import com.a.eye.skywalking.toolkit.opentracing.SkyWalkingTracer;
-import io.opentracing.propagation.TextMap;
-import java.util.Iterator;
-import java.util.Map;
-
-/**
- * Intercept {@link SkyWalkingTracer#extractCrossProcessPropagationContextData(TextMap)}
- */
-public class TracerExtractCrossProcessTextMapContextInterceptor implements InstanceMethodsAroundInterceptor {
-
-    public static final String SKY_WALKING_TRACING_NAME = "SW-TRACING-NAME";
-
-    @Override
-    public void beforeMethod(EnhancedClassInstanceContext context, InstanceMethodInvokeContext interceptorContext,
-        MethodInterceptResult result) {
-        // Do nothing
-    }
-
-    @Override
-    public Object afterMethod(EnhancedClassInstanceContext context, InstanceMethodInvokeContext interceptorContext,
-        Object ret) {
-        TextMap textMap = (TextMap)interceptorContext.allArguments()[0];
-        Iterator<Map.Entry<String, String>> iterator = textMap.iterator();
-        while (iterator.hasNext()) {
-            Map.Entry<String, String> entry = iterator.next();
-            if (SKY_WALKING_TRACING_NAME.equals(entry.getKey())) {
-                ContextCarrier carrier = new ContextCarrier();
-                carrier.deserialize(entry.getValue());
-
-                ContextManager.extract(carrier);
-            }
-        }
-        return ret;
-    }
-
-    @Override
-    public void handleMethodException(Throwable t, EnhancedClassInstanceContext context,
-        InstanceMethodInvokeContext interceptorContext) {
-
-    }
-}
diff --git a/skywalking-sniffer/skywalking-toolkit-activation/skywalking-toolkit-opentracing-activation/src/main/java/com/a/eye/skywalking/toolkit/activation/opentracing/tracer/interceptor/TracerFormatCrossProcessContextInterceptor.java b/skywalking-sniffer/skywalking-toolkit-activation/skywalking-toolkit-opentracing-activation/src/main/java/com/a/eye/skywalking/toolkit/activation/opentracing/tracer/interceptor/TracerInjectFormatCrossProcessContextInterceptor.java
similarity index 86%
rename from skywalking-sniffer/skywalking-toolkit-activation/skywalking-toolkit-opentracing-activation/src/main/java/com/a/eye/skywalking/toolkit/activation/opentracing/tracer/interceptor/TracerFormatCrossProcessContextInterceptor.java
rename to skywalking-sniffer/skywalking-toolkit-activation/skywalking-toolkit-opentracing-activation/src/main/java/com/a/eye/skywalking/toolkit/activation/opentracing/tracer/interceptor/TracerInjectFormatCrossProcessContextInterceptor.java
index d9de6c2..6afe02e 100644
--- a/skywalking-sniffer/skywalking-toolkit-activation/skywalking-toolkit-opentracing-activation/src/main/java/com/a/eye/skywalking/toolkit/activation/opentracing/tracer/interceptor/TracerFormatCrossProcessContextInterceptor.java
+++ b/skywalking-sniffer/skywalking-toolkit-activation/skywalking-toolkit-opentracing-activation/src/main/java/com/a/eye/skywalking/toolkit/activation/opentracing/tracer/interceptor/TracerInjectFormatCrossProcessContextInterceptor.java
@@ -9,9 +9,9 @@
 import com.a.eye.skywalking.toolkit.opentracing.SkyWalkingTracer;
 
 /**
- * Intercept {@link SkyWalkingTracer#formatCrossProcessPropagationContextData()}
+ * Intercept {@link SkyWalkingTracer#formatInjectCrossProcessPropagationContextData()}
  */
-public class TracerFormatCrossProcessContextInterceptor implements InstanceMethodsAroundInterceptor {
+public class TracerInjectFormatCrossProcessContextInterceptor implements InstanceMethodsAroundInterceptor {
     @Override
     public void beforeMethod(EnhancedClassInstanceContext context, InstanceMethodInvokeContext interceptorContext,
         MethodInterceptResult result) {