You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@servicecomb.apache.org by GitBox <gi...@apache.org> on 2018/11/24 02:15:10 UTC

[GitHub] wujimin closed pull request #1002: [SCB-1034] Metrics performance optimize

wujimin closed pull request #1002: [SCB-1034] Metrics performance optimize
URL: https://github.com/apache/servicecomb-java-chassis/pull/1002
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/SpringmvcClient.java b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/SpringmvcClient.java
index e38080460..411aa11b8 100644
--- a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/SpringmvcClient.java
+++ b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/SpringmvcClient.java
@@ -125,10 +125,6 @@ public static void run() {
 
     //    TestMgr.check(true, metrics.get("jvm(name=heapUsed,statistic=gauge)") != 0);
     TestMgr.check(true, metrics.size() > 0);
-    TestMgr.check(true,
-        metrics.get(
-            "servicecomb.invocation(operation=springmvc.codeFirst.saySomething,role=PRODUCER,stage=total,statistic=count,status=200,transport=highway)")
-            >= 0);
 
     //prometheus integration test
     try {
diff --git a/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/CodeFirstSpringmvc.java b/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/CodeFirstSpringmvc.java
index 0ab7487d3..36adfcbe1 100644
--- a/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/CodeFirstSpringmvc.java
+++ b/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/CodeFirstSpringmvc.java
@@ -24,6 +24,7 @@
 import java.util.Map;
 import java.util.concurrent.atomic.AtomicInteger;
 
+import javax.inject.Inject;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.Part;
 import javax.ws.rs.QueryParam;
@@ -44,6 +45,7 @@
 import org.apache.servicecomb.demo.jaxbbean.JAXBPerson;
 import org.apache.servicecomb.demo.server.User;
 import org.apache.servicecomb.demo.springmvc.decoderesponse.DecodeTestResponse;
+import org.apache.servicecomb.metrics.core.MetricsBootListener;
 import org.apache.servicecomb.provider.rest.common.RestSchema;
 import org.apache.servicecomb.swagger.extend.annotations.RawJsonRequestBody;
 import org.apache.servicecomb.swagger.extend.annotations.ResponseHeaders;
@@ -361,9 +363,15 @@ public String testform(HttpServletRequest request) {
     return form1 + form2;
   }
 
+  @Inject
+  MetricsBootListener metricsBootListener;
+
   //Only for Prometheus integration test
   @RequestMapping(path = "/prometheusForTest", method = RequestMethod.GET)
   public String prometheusForTest() {
+    // just for test, this makes client always can got latest metrics
+    metricsBootListener.getMetricsBootstrap().pollMeters();
+
     RestTemplate defaultRestTemplate = new RestTemplate();
     return defaultRestTemplate.getForObject("http://localhost:9696/metrics", String.class);
   }
diff --git a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/event/EventBus.java b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/event/EventBus.java
deleted file mode 100644
index 849089a89..000000000
--- a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/event/EventBus.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.foundation.common.event;
-
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.CopyOnWriteArrayList;
-
-import org.apache.servicecomb.foundation.common.concurrent.ConcurrentHashMapEx;
-import org.apache.servicecomb.foundation.common.utils.SPIServiceUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class EventBus {
-  private static final Logger LOGGER = LoggerFactory.getLogger(EventBus.class);
-
-  //key is event object type,fast locate listener and fire
-  @SuppressWarnings("rawtypes")
-  private final Map<Class, List<EventListener>> allEventListeners = new ConcurrentHashMapEx<>();
-
-  private static final EventBus INSTANCE = new EventBus();
-
-  public static EventBus getInstance() {
-    return INSTANCE;
-  }
-
-  //event class will get from getEventClass method
-  @SuppressWarnings({"rawtypes"})
-  private EventBus() {
-    List<EventListener> listeners = SPIServiceUtils.getAllService(EventListener.class);
-    for (EventListener listener : listeners) {
-      this.registerEventListener(listener);
-      LOGGER.info("EventBus register " + listener.getClass().getName()
-          + " for process " + listener.getEventClass().getName());
-    }
-  }
-
-  //event class will get from getEventClass method
-  @SuppressWarnings("rawtypes")
-  public void registerEventListener(EventListener eventListener) {
-    List<EventListener> eventListeners = allEventListeners
-        .computeIfAbsent(eventListener.getEventClass(), f -> new CopyOnWriteArrayList<>());
-    eventListeners.add(eventListener);
-  }
-
-  //event class will get from getEventClass method
-  @SuppressWarnings("rawtypes")
-  public void unregisterEventListener(EventListener eventListener) {
-    List<EventListener> eventListeners = allEventListeners
-        .computeIfAbsent(eventListener.getEventClass(), f -> new CopyOnWriteArrayList<>());
-    if (eventListeners.contains(eventListener)) {
-      eventListeners.remove(eventListener);
-    }
-  }
-
-  @SuppressWarnings({"rawtypes", "unchecked"})
-  public void triggerEvent(Object event) {
-    List<EventListener> eventListeners = allEventListeners.getOrDefault(event.getClass(), Collections.emptyList());
-    for (EventListener eventListener : eventListeners) {
-      eventListener.process(event);
-    }
-  }
-}
diff --git a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/event/EventManager.java b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/event/EventManager.java
index cb72a21a4..6e59293f4 100644
--- a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/event/EventManager.java
+++ b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/event/EventManager.java
@@ -24,7 +24,7 @@
  *
  */
 public class EventManager {
-  public static EventBus eventBus = new EventBus();
+  public static EventBus eventBus = new SimpleEventBus();
 
   public static EventBus getEventBus() {
     return eventBus;
diff --git a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/event/SimpleEventBus.java b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/event/SimpleEventBus.java
new file mode 100644
index 000000000..1dfbd97ef
--- /dev/null
+++ b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/event/SimpleEventBus.java
@@ -0,0 +1,92 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.servicecomb.foundation.common.event;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.lang3.reflect.MethodUtils;
+import org.apache.servicecomb.foundation.common.concurrent.ConcurrentHashMapEx;
+
+import com.google.common.eventbus.EventBus;
+import com.google.common.eventbus.Subscribe;
+
+/**
+ * for register/unregister rarely
+ */
+public class SimpleEventBus extends EventBus {
+  private final Map<Object, List<SimpleSubscriber>> subscribersMap = new ConcurrentHashMapEx<>();
+
+  // key is event class
+  private Map<Class<?>, List<SimpleSubscriber>> subscribersCache = new ConcurrentHashMapEx<>();
+
+  private List<SimpleSubscriber> collectSubscribers(Object instance) {
+    List<SimpleSubscriber> subscribers = new ArrayList<>();
+    Method[] methods = MethodUtils.getMethodsWithAnnotation(instance.getClass(), Subscribe.class, true, true);
+    for (Method method : methods) {
+      SimpleSubscriber subscriber = new SimpleSubscriber(instance, method);
+      subscribers.add(subscriber);
+    }
+    return subscribers;
+  }
+
+  @Override
+  public void register(Object instance) {
+    subscribersMap.computeIfAbsent(instance, this::collectSubscribers);
+    // even ignored cause of duplicate register
+    // still reset cache
+    // this makes logic simpler
+    subscribersCache = new ConcurrentHashMapEx<>();
+  }
+
+  @Override
+  public void unregister(Object instance) {
+    if (subscribersMap.remove(instance) != null) {
+      subscribersCache = new ConcurrentHashMapEx<>();
+    }
+  }
+
+  public void post(Object event) {
+    // cache always reset after register/unregister
+    // so cache always match latest subscribersMap at last
+    // te worst scenes is invoke collectSubscriberForEvent multiple times, no problem
+    List<SimpleSubscriber> subscribers = subscribersCache
+        .computeIfAbsent(event.getClass(), this::collectSubscriberForEvent);
+    for (SimpleSubscriber subscriber : subscribers) {
+      subscriber.dispatchEvent(event);
+    }
+  }
+
+  /**
+   * subscribersMap almost stable<br>
+   * so we not care for performance of collectSubscriberForEvent
+   * @param eventClass
+   */
+  private List<SimpleSubscriber> collectSubscriberForEvent(Class<?> eventClass) {
+    List<SimpleSubscriber> subscribersForEvent = new ArrayList<>();
+    for (List<SimpleSubscriber> subscribers : subscribersMap.values()) {
+      for (SimpleSubscriber subscriber : subscribers) {
+        if (subscriber.getMethod().getParameterTypes()[0].isAssignableFrom(eventClass)) {
+          subscribersForEvent.add(subscriber);
+        }
+      }
+    }
+    return subscribersForEvent;
+  }
+}
diff --git a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/event/SimpleSubscriber.java b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/event/SimpleSubscriber.java
new file mode 100644
index 000000000..e83a6bd21
--- /dev/null
+++ b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/event/SimpleSubscriber.java
@@ -0,0 +1,85 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.servicecomb.foundation.common.event;
+
+import java.lang.reflect.Method;
+import java.util.function.Consumer;
+
+import org.apache.servicecomb.foundation.common.utils.LambdaMetafactoryUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.eventbus.AllowConcurrentEvents;
+
+public class SimpleSubscriber {
+  private static final Logger LOGGER = LoggerFactory.getLogger(SimpleSubscriber.class);
+
+  private Object instance;
+
+  private Method method;
+
+  // generated from method
+  private Consumer<Object> lambda;
+
+  private Consumer<Object> dispatcher;
+
+  public SimpleSubscriber(Object instance, Method method) {
+    this.instance = instance;
+    this.method = method;
+
+    method.setAccessible(true);
+    try {
+      lambda = LambdaMetafactoryUtils.createLambda(instance, method, Consumer.class);
+    } catch (Throwable throwable) {
+      LOGGER.warn("Failed to create lambda for method: {}, fallback to reflect.", method);
+      lambda = event -> {
+        try {
+          method.invoke(instance, event);
+        } catch (Throwable e) {
+          throw new IllegalStateException(e);
+        }
+      };
+    }
+
+    dispatcher = this::syncDispatch;
+    if (method.getAnnotation(AllowConcurrentEvents.class) != null) {
+      dispatcher = this::concurrentDispatch;
+    }
+  }
+
+  public Object getInstance() {
+    return instance;
+  }
+
+  public Method getMethod() {
+    return method;
+  }
+
+  public void dispatchEvent(Object event) {
+    dispatcher.accept(event);
+  }
+
+  private void syncDispatch(Object event) {
+    synchronized (this) {
+      lambda.accept(event);
+    }
+  }
+
+  private void concurrentDispatch(Object event) {
+    lambda.accept(event);
+  }
+}
diff --git a/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/event/TestEventBus.java b/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/event/TestEventBus.java
deleted file mode 100644
index 77264adea..000000000
--- a/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/event/TestEventBus.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.foundation.common.event;
-
-import static org.awaitility.Awaitility.await;
-
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-
-public class TestEventBus {
-
-  private AtomicBoolean eventReceived = new AtomicBoolean(false);
-
-  private EventListener<String> listener = new EventListener<String>() {
-    @Override
-    public Class<String> getEventClass() {
-      return String.class;
-    }
-
-    @Override
-    public void process(String data) {
-      eventReceived.set(true);
-    }
-  };
-
-  @Before
-  public void reset() {
-    EventBus.getInstance().unregisterEventListener(listener);
-  }
-
-  @Test
-  public void checkEventReceivedAndProcessed() {
-    EventBus.getInstance().registerEventListener(listener);
-
-    EventBus.getInstance().triggerEvent("xxx");
-    await().atMost(1, TimeUnit.SECONDS)
-        .until(eventReceived::get);
-    Assert.assertTrue(eventReceived.get());
-  }
-
-  @Test
-  public void checkEventCanNotReceivedAfterUnregister() {
-    EventBus.getInstance().registerEventListener(listener);
-
-    EventBus.getInstance().triggerEvent("xxx");
-    await().atMost(1, TimeUnit.SECONDS)
-        .until(eventReceived::get);
-    Assert.assertTrue(eventReceived.get());
-
-    eventReceived.set(false);
-
-    EventBus.getInstance().unregisterEventListener(listener);
-    EventBus.getInstance().triggerEvent("xxx");
-    Assert.assertFalse(eventReceived.get());
-  }
-
-  @Test
-  public void checkUnmatchTypeWillNotReceived() {
-    EventBus.getInstance().registerEventListener(listener);
-
-    //trigger a Integer type event object
-    EventBus.getInstance().triggerEvent(1);
-    Assert.assertFalse(eventReceived.get());
-  }
-}
diff --git a/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/event/TestEventManager.java b/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/event/TestEventManager.java
index 192d97c2d..6073a41f4 100644
--- a/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/event/TestEventManager.java
+++ b/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/event/TestEventManager.java
@@ -17,34 +17,74 @@
 
 package org.apache.servicecomb.foundation.common.event;
 
+import java.util.stream.Collectors;
+
+import org.apache.servicecomb.foundation.test.scaffolding.log.LogCollector;
+import org.hamcrest.Matchers;
 import org.junit.Assert;
 import org.junit.Test;
 
 import com.google.common.eventbus.Subscribe;
 
 public class TestEventManager {
+  private int objCount = 0;
+
+  private int iCount = 0;
 
-  private int i = 0;
+  public void test(Object listener) {
+    EventManager.register(listener);
+    EventManager.post("a");
+    EventManager.post(1);
+    Assert.assertEquals(2, objCount);
+    Assert.assertEquals(1, iCount);
+
+    EventManager.unregister(listener);
+    EventManager.post("a");
+    EventManager.post(1);
+    Assert.assertEquals(2, objCount);
+    Assert.assertEquals(1, iCount);
+  }
 
   @Test
-  public void testRegister() {
-    EventManager.register(this);
-    EventManager.post(this);
-    EventManager.unregister(this);
-    Assert.assertEquals(1, i);
+  public void lambda() {
+    LogCollector collector = new LogCollector();
+
+    test(this);
+    Assert.assertTrue(collector.getEvents().isEmpty());
+    collector.teardown();
   }
 
   @Test
-  public void testUnregister() {
-    EventManager.register(this);
-    EventManager.unregister(this);
-    EventManager.post(this);
-    Assert.assertEquals(0, i);
+  public void reflect() {
+    LogCollector collector = new LogCollector();
+    Object listener = new Object() {
+      @Subscribe
+      public void onObject(Object obj) {
+        objCount++;
+      }
+
+      @Subscribe
+      public void onInt(Integer obj) {
+        iCount++;
+      }
+    };
+    test(listener);
+    Assert.assertThat(collector.getEvents().stream().map(e -> e.getMessage()).collect(Collectors.toList()),
+        Matchers.containsInAnyOrder(
+            "Failed to create lambda for method: public void org.apache.servicecomb.foundation.common.event.TestEventManager$1.onObject(java.lang.Object), fallback to reflect.",
+            "Failed to create lambda for method: public void org.apache.servicecomb.foundation.common.event.TestEventManager$1.onInt(java.lang.Integer), fallback to reflect."));
+
+    collector.teardown();
+  }
+
+  @Subscribe
+  public void onObject(Object obj) {
+    objCount++;
   }
 
   @Subscribe
-  public void eventCallBack(TestEventManager lTestEventManager) {
-    i++;
+  public void onInt(Integer obj) {
+    iCount++;
   }
 }
 
diff --git a/foundations/foundation-test-scaffolding/src/main/java/com/netflix/spectator/api/SpectatorUtils.java b/foundations/foundation-metrics/src/main/java/com/netflix/spectator/api/SpectatorUtils.java
similarity index 55%
rename from foundations/foundation-test-scaffolding/src/main/java/com/netflix/spectator/api/SpectatorUtils.java
rename to foundations/foundation-metrics/src/main/java/com/netflix/spectator/api/SpectatorUtils.java
index 7a2f78514..cccc7107f 100644
--- a/foundations/foundation-test-scaffolding/src/main/java/com/netflix/spectator/api/SpectatorUtils.java
+++ b/foundations/foundation-metrics/src/main/java/com/netflix/spectator/api/SpectatorUtils.java
@@ -16,8 +16,24 @@
  */
 package com.netflix.spectator.api;
 
-public class SpectatorUtils {
-  public static CompositeRegistry createCompositeRegistry(Clock clock) {
-    return new CompositeRegistry(clock);
+public final class SpectatorUtils {
+  private SpectatorUtils() {
+  }
+
+  public static Id createDefaultId(String name) {
+    return new DefaultId(name);
+  }
+
+  public static void removeExpiredMeters(Registry registry) {
+    if (registry instanceof AbstractRegistry) {
+      ((AbstractRegistry) registry).removeExpiredMeters();
+    }
+  }
+
+  public static void registerMeter(Registry registry, Meter meter) {
+    if (!(registry instanceof AbstractRegistry)) {
+      throw new IllegalStateException("registry must be a AbstractRegistry, class=" + registry.getClass().getName());
+    }
+    ((AbstractRegistry) registry).getOrCreate(meter.id(), Meter.class, null, _id -> meter);
   }
 }
diff --git a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/MetricsBootstrap.java b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/MetricsBootstrap.java
index 318097313..d2647f082 100644
--- a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/MetricsBootstrap.java
+++ b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/MetricsBootstrap.java
@@ -24,17 +24,13 @@
 import java.util.concurrent.TimeUnit;
 
 import org.apache.servicecomb.foundation.common.utils.SPIServiceUtils;
+import org.apache.servicecomb.foundation.metrics.registry.GlobalRegistry;
 
-import com.google.common.collect.Lists;
 import com.google.common.eventbus.EventBus;
 import com.google.common.util.concurrent.ThreadFactoryBuilder;
-import com.netflix.spectator.api.CompositeRegistry;
-import com.netflix.spectator.api.Measurement;
-import com.netflix.spectator.api.Meter;
 
 public class MetricsBootstrap {
-
-  private CompositeRegistry globalRegistry;
+  private GlobalRegistry globalRegistry;
 
   private EventBus eventBus;
 
@@ -42,7 +38,7 @@
 
   private ScheduledExecutorService executorService;
 
-  public void start(CompositeRegistry globalRegistry, EventBus eventBus) {
+  public void start(GlobalRegistry globalRegistry, EventBus eventBus) {
     this.globalRegistry = globalRegistry;
     this.eventBus = eventBus;
     this.executorService = Executors.newScheduledThreadPool(1,
@@ -61,36 +57,24 @@ public void shutdown() {
 
     List<MetricsInitializer> initializers = new ArrayList<>(SPIServiceUtils.getSortedService(MetricsInitializer.class));
     Collections.reverse(initializers);
-    initializers.forEach(initializer -> {
-      initializer.destroy();
-    });
+    initializers.forEach(initializer -> initializer.destroy());
   }
 
   protected void loadMetricsInitializers() {
-    SPIServiceUtils.getSortedService(MetricsInitializer.class).forEach(initializer -> {
-      initializer.init(globalRegistry, eventBus, config);
-    });
+    SPIServiceUtils.getSortedService(MetricsInitializer.class)
+        .forEach(initializer -> initializer.init(globalRegistry, eventBus, config));
   }
 
   protected void startPoll() {
     executorService.scheduleAtFixedRate(this::pollMeters,
-        config.getMsPollInterval(),
+        0,
         config.getMsPollInterval(),
         TimeUnit.MILLISECONDS);
   }
 
-  protected void pollMeters() {
-    eventBus.post(new PollEvent(config.getMsPollInterval()));
-    List<Meter> meters = Lists.newArrayList(globalRegistry.iterator());
-    // must collect measurements
-    // otherwise if there is no any period publisher, normal publisher maybe get NaN values 
-    List<Measurement> measurements = new ArrayList<>();
-    for (Meter meter : meters) {
-      meter.measure().forEach(measurements::add);
-    }
-
-    PolledEvent event = new PolledEvent(meters, measurements);
-
-    eventBus.post(event);
+  public synchronized void pollMeters() {
+    long secondInterval = TimeUnit.MILLISECONDS.toSeconds(config.getMsPollInterval());
+    PolledEvent polledEvent = globalRegistry.poll(secondInterval);
+    eventBus.post(polledEvent);
   }
 }
diff --git a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/MetricsBootstrapConfig.java b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/MetricsBootstrapConfig.java
index d1b6be72f..09322ca34 100644
--- a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/MetricsBootstrapConfig.java
+++ b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/MetricsBootstrapConfig.java
@@ -28,6 +28,9 @@
   public MetricsBootstrapConfig() {
     msPollInterval =
         DynamicPropertyFactory.getInstance().getIntProperty(METRICS_WINDOW_TIME, DEFAULT_METRICS_WINDOW_TIME).get();
+    if (msPollInterval < 1000) {
+      msPollInterval = 1000;
+    }
   }
 
   public long getMsPollInterval() {
diff --git a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/MetricsInitializer.java b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/MetricsInitializer.java
index b232f4815..88201dcb2 100644
--- a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/MetricsInitializer.java
+++ b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/MetricsInitializer.java
@@ -16,8 +16,9 @@
  */
 package org.apache.servicecomb.foundation.metrics;
 
+import org.apache.servicecomb.foundation.metrics.registry.GlobalRegistry;
+
 import com.google.common.eventbus.EventBus;
-import com.netflix.spectator.api.CompositeRegistry;
 
 public interface MetricsInitializer {
   default int getOrder() {
@@ -27,7 +28,7 @@ default int getOrder() {
   /**
    * if create new registry, must add to globalRegistry
    */
-  void init(CompositeRegistry globalRegistry, EventBus eventBus, MetricsBootstrapConfig config);
+  void init(GlobalRegistry globalRegistry, EventBus eventBus, MetricsBootstrapConfig config);
 
   default void destroy() {
 
diff --git a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/PollEvent.java b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/meter/AbstractPeriodMeter.java
similarity index 60%
rename from foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/PollEvent.java
rename to foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/meter/AbstractPeriodMeter.java
index 80a2055b5..d9e2f46d5 100644
--- a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/PollEvent.java
+++ b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/meter/AbstractPeriodMeter.java
@@ -14,19 +14,29 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.servicecomb.foundation.metrics;
+package org.apache.servicecomb.foundation.metrics.meter;
 
-/**
- * give not standard meters to calc measurement , eg : cpu usage, net throughput, and so on
- */
-public class PollEvent {
-  private final long msPollInterval;
+import java.util.Collections;
+import java.util.List;
+
+import com.netflix.spectator.api.Id;
+import com.netflix.spectator.api.Measurement;
+
+public abstract class AbstractPeriodMeter implements PeriodMeter {
+  protected Id id;
+
+  protected List<Measurement> allMeasurements = Collections.emptyList();
+
+  public Id id() {
+    return id;
+  }
 
-  public PollEvent(long msPollInterval) {
-    this.msPollInterval = msPollInterval;
+  @Override
+  public Iterable<Measurement> measure() {
+    return allMeasurements;
   }
 
-  public long getMsPollInterval() {
-    return msPollInterval;
+  public boolean hasExpired() {
+    return false;
   }
 }
diff --git a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/event/EventListener.java b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/meter/PeriodMeter.java
similarity index 69%
rename from foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/event/EventListener.java
rename to foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/meter/PeriodMeter.java
index 7924e1d69..f91d781e1 100644
--- a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/event/EventListener.java
+++ b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/meter/PeriodMeter.java
@@ -14,13 +14,15 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+package org.apache.servicecomb.foundation.metrics.meter;
 
-package org.apache.servicecomb.foundation.common.event;
+import java.util.List;
 
-//Common event listener interface,java chassis component can trigger event let high level component perceive data change.
-public interface EventListener<T> {
-  Class<T> getEventClass();
+import com.netflix.spectator.api.Measurement;
+import com.netflix.spectator.api.Meter;
 
-  //process event data
-  void process(T data);
+public interface PeriodMeter extends Meter {
+  void calcMeasurements(long msNow, long secondInterval);
+
+  void calcMeasurements(List<Measurement> measurements, long msNow, long secondInterval);
 }
diff --git a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/meter/SimpleTimer.java b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/meter/SimpleTimer.java
new file mode 100644
index 000000000..09803a471
--- /dev/null
+++ b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/meter/SimpleTimer.java
@@ -0,0 +1,93 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.servicecomb.foundation.metrics.meter;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.LongAdder;
+
+import com.netflix.spectator.api.Id;
+import com.netflix.spectator.api.Measurement;
+import com.netflix.spectator.api.Statistic;
+import com.netflix.spectator.impl.AtomicDouble;
+
+/**
+ * ServoTimer is too slow
+ * this is a faster timer
+ */
+public class SimpleTimer extends AbstractPeriodMeter {
+  private static final double CNV_SECONDS = 1.0 / TimeUnit.SECONDS.toNanos(1L);
+
+  private final Id idCount;
+
+  private final Id idTotalTime;
+
+  private final Id idMax;
+
+  private final LongAdder count = new LongAdder();
+
+  private final LongAdder totalTime = new LongAdder();
+
+  private final AtomicDouble max = new AtomicDouble();
+
+  private long lastCount = 0;
+
+  private long lastTotalTime = 0;
+
+  public SimpleTimer(Id id) {
+    this.id = id;
+    this.idCount = id.withTag(Statistic.count);
+    this.idTotalTime = id.withTag(Statistic.totalTime);
+    this.idMax = id.withTag(Statistic.max);
+  }
+
+  public void record(long nanoAmount) {
+    if (nanoAmount >= 0) {
+      totalTime.add(nanoAmount);
+      count.increment();
+      max.max(nanoAmount);
+    }
+  }
+
+  private Measurement newMeasurement(Id id, long msNow, Number n) {
+    return new Measurement(id, msNow, n.doubleValue());
+  }
+
+  @Override
+  public void calcMeasurements(long msNow, long secondInterval) {
+    List<Measurement> measurements = new ArrayList<>(3);
+    calcMeasurements(measurements, msNow, secondInterval);
+    allMeasurements = measurements;
+  }
+
+  @Override
+  public void calcMeasurements(List<Measurement> measurements, long msNow, long secondInterval) {
+    long currentCount = count.longValue();
+    long currentTotalTime = totalTime.longValue();
+
+    measurements.add(newMeasurement(idCount, msNow, (double) (currentCount - lastCount) / secondInterval));
+    measurements
+        .add(newMeasurement(idTotalTime, msNow, (currentTotalTime - lastTotalTime) / secondInterval * CNV_SECONDS));
+    measurements.add(newMeasurement(idMax, msNow, max.get() * CNV_SECONDS));
+
+    lastCount = currentCount;
+    lastTotalTime = currentTotalTime;
+    // maybe lost some max value, but not so important?
+    max.set(0);
+  }
+}
diff --git a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/spectator/MeasurementTree.java b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/spectator/MeasurementTree.java
index a342f34fc..79101fa16 100644
--- a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/spectator/MeasurementTree.java
+++ b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/spectator/MeasurementTree.java
@@ -56,7 +56,7 @@ public void from(Iterable<Measurement> measurements, MeasurementGroupConfig grou
         Tag tag = tagFinder.find(id.tags());
         if (tag == null) {
           if (tagFinder.skipOnNull()) {
-            return;
+            break;
           }
           throw new IllegalStateException(
               String.format("tag key \"%s\" not exist in %s",
diff --git a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/registry/GlobalRegistry.java b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/registry/GlobalRegistry.java
new file mode 100644
index 000000000..9af39d02d
--- /dev/null
+++ b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/registry/GlobalRegistry.java
@@ -0,0 +1,114 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.servicecomb.foundation.metrics.registry;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+import org.apache.servicecomb.foundation.metrics.PolledEvent;
+import org.apache.servicecomb.foundation.metrics.meter.PeriodMeter;
+
+import com.netflix.spectator.api.Clock;
+import com.netflix.spectator.api.Measurement;
+import com.netflix.spectator.api.Meter;
+import com.netflix.spectator.api.Registry;
+import com.netflix.spectator.api.SpectatorUtils;
+
+public class GlobalRegistry {
+  private Clock clock;
+
+  private List<Registry> registries = new CopyOnWriteArrayList<>();
+
+  private Registry defaultRegistry;
+
+  public GlobalRegistry() {
+    this(Clock.SYSTEM);
+  }
+
+  public GlobalRegistry(Clock clock) {
+    this.clock = clock;
+  }
+
+  public Clock getClock() {
+    return clock;
+  }
+
+  public List<Registry> getRegistries() {
+    return registries;
+  }
+
+  public Registry getDefaultRegistry() {
+    return defaultRegistry;
+  }
+
+  public synchronized void add(Registry registry) {
+    if (registries.isEmpty()) {
+      defaultRegistry = registry;
+    }
+    registries.add(registry);
+  }
+
+  public synchronized void remove(Registry registry) {
+    registries.remove(registry);
+    if (registry != defaultRegistry) {
+      return;
+    }
+
+    if (registries.isEmpty()) {
+      defaultRegistry = null;
+      return;
+    }
+
+    defaultRegistry = registries.get(0);
+  }
+
+  public synchronized void removeAll() {
+    registries.clear();
+    defaultRegistry = null;
+  }
+
+  @SuppressWarnings("unchecked")
+  public <T extends Registry> T find(Class<T> cls) {
+    for (Registry registry : registries) {
+      if (cls.isAssignableFrom(registry.getClass())) {
+        return (T) registry;
+      }
+    }
+    return null;
+  }
+
+  public PolledEvent poll(long secondInterval) {
+    long msNow = clock.wallTime();
+    List<Meter> meters = new ArrayList<>();
+    List<Measurement> measurements = new ArrayList<>();
+    for (Registry registry : registries) {
+      SpectatorUtils.removeExpiredMeters(registry);
+
+      for (Meter meter : registry) {
+        if (meter instanceof PeriodMeter) {
+          ((PeriodMeter) meter).calcMeasurements(msNow, secondInterval);
+        }
+
+        meters.add(meter);
+        meter.measure().forEach(measurements::add);
+      }
+    }
+
+    return new PolledEvent(meters, measurements);
+  }
+}
diff --git a/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/TestMetricsBootstrap.java b/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/TestMetricsBootstrap.java
index c22315a07..748774578 100644
--- a/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/TestMetricsBootstrap.java
+++ b/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/TestMetricsBootstrap.java
@@ -24,15 +24,16 @@
 import java.util.concurrent.ThreadFactory;
 
 import org.apache.servicecomb.foundation.common.utils.SPIServiceUtils;
+import org.apache.servicecomb.foundation.metrics.registry.GlobalRegistry;
 import org.hamcrest.Matchers;
 import org.junit.Assert;
 import org.junit.Test;
 
 import com.google.common.eventbus.EventBus;
 import com.google.common.eventbus.Subscribe;
-import com.netflix.spectator.api.CompositeRegistry;
 import com.netflix.spectator.api.Measurement;
 import com.netflix.spectator.api.Meter;
+import com.netflix.spectator.api.Registry;
 
 import mockit.Deencapsulation;
 import mockit.Expectations;
@@ -41,8 +42,7 @@
 public class TestMetricsBootstrap {
   MetricsBootstrap bootstrap = new MetricsBootstrap();
 
-  @Mocked
-  CompositeRegistry globalRegistry;
+  GlobalRegistry globalRegistry = new GlobalRegistry();
 
   EventBus eventBus = new EventBus();
 
@@ -51,7 +51,7 @@ public void loadMetricsInitializers() {
     List<MetricsInitializer> initList = new ArrayList<>();
     MetricsInitializer metricsInitializer = new MetricsInitializer() {
       @Override
-      public void init(CompositeRegistry globalRegistry, EventBus eventBus, MetricsBootstrapConfig config) {
+      public void init(GlobalRegistry globalRegistry, EventBus eventBus, MetricsBootstrapConfig config) {
         initList.add(this);
       }
     };
@@ -69,14 +69,15 @@ public void init(CompositeRegistry globalRegistry, EventBus eventBus, MetricsBoo
   }
 
   @Test
-  public void pollMeters(@Mocked Meter meter, @Mocked Measurement measurement,
+  public void pollMeters(@Mocked Registry registry, @Mocked Meter meter, @Mocked Measurement measurement,
       @Mocked ScheduledExecutorService executor) {
     List<Meter> meters = Arrays.asList(meter);
+    globalRegistry.add(registry);
     new Expectations(Executors.class) {
       {
         Executors.newScheduledThreadPool(1, (ThreadFactory) any);
         result = executor;
-        globalRegistry.iterator();
+        registry.iterator();
         result = meters.iterator();
         meter.measure();
         result = Arrays.asList(measurement);
@@ -85,13 +86,7 @@ public void pollMeters(@Mocked Meter meter, @Mocked Measurement measurement,
     bootstrap.start(globalRegistry, eventBus);
 
     PolledEvent result = new PolledEvent(null, null);
-    List<PollEvent> events = new ArrayList<>();
     eventBus.register(new Object() {
-      @Subscribe
-      public void onPollEvent(PollEvent pollEvent) {
-        events.add(pollEvent);
-      }
-
       @Subscribe
       public void onEvent(PolledEvent event) {
         result.setMeters(event.getMeters());
@@ -101,7 +96,6 @@ public void onEvent(PolledEvent event) {
 
     bootstrap.pollMeters();
     bootstrap.shutdown();
-    Assert.assertEquals(1, events.size());
     Assert.assertEquals(meters, result.getMeters());
     Assert.assertThat(result.getMeasurements(), Matchers.contains(measurement));
   }
@@ -116,7 +110,7 @@ public int getOrder() {
       }
 
       @Override
-      public void init(CompositeRegistry globalRegistry, EventBus eventBus, MetricsBootstrapConfig config) {
+      public void init(GlobalRegistry globalRegistry, EventBus eventBus, MetricsBootstrapConfig config) {
       }
 
       @Override
@@ -132,7 +126,7 @@ public int getOrder() {
       }
 
       @Override
-      public void init(CompositeRegistry globalRegistry, EventBus eventBus, MetricsBootstrapConfig config) {
+      public void init(GlobalRegistry globalRegistry, EventBus eventBus, MetricsBootstrapConfig config) {
       }
 
       @Override
diff --git a/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/meter/TestSimpleTimer.java b/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/meter/TestSimpleTimer.java
new file mode 100644
index 000000000..1d344973e
--- /dev/null
+++ b/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/meter/TestSimpleTimer.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.servicecomb.foundation.metrics.meter;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.netflix.spectator.api.SpectatorUtils;
+
+public class TestSimpleTimer {
+  SimpleTimer timer = new SimpleTimer(SpectatorUtils.createDefaultId("name"));
+
+  @Test
+  public void measure() {
+    timer.record(2);
+    timer.record(4);
+
+    Assert.assertFalse(timer.measure().iterator().hasNext());
+
+    timer.calcMeasurements(1, 2);
+    Assert.assertEquals(
+        "[Measurement(name:statistic=count,1,1.0), Measurement(name:statistic=totalTime,1,3.0000000000000004E-9), Measurement(name:statistic=max,1,4.0E-9)]",
+        timer.measure().toString());
+    Assert.assertFalse(timer.hasExpired());
+    Assert.assertEquals("name", timer.id().name());
+  }
+}
diff --git a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/metrics/metric/DefaultEndpointMetric.java b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/metrics/metric/DefaultEndpointMetric.java
index f25ca64e4..86590ce89 100644
--- a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/metrics/metric/DefaultEndpointMetric.java
+++ b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/metrics/metric/DefaultEndpointMetric.java
@@ -16,7 +16,7 @@
  */
 package org.apache.servicecomb.foundation.vertx.metrics.metric;
 
-import java.util.concurrent.atomic.AtomicLong;
+import java.util.concurrent.atomic.LongAdder;
 
 import io.vertx.core.net.SocketAddress;
 
@@ -28,15 +28,15 @@
 
   // summary of connect times from boot
   // by this, we can know how many new connections connected recently
-  private AtomicLong connectCount = new AtomicLong();
+  private LongAdder connectCount = new LongAdder();
 
   // summary of disconnect times from boot
   // by this, we can know how many connections disconnected recently
-  private AtomicLong disconnectCount = new AtomicLong();
+  private LongAdder disconnectCount = new LongAdder();
 
-  private AtomicLong bytesRead = new AtomicLong();
+  private LongAdder bytesRead = new LongAdder();
 
-  private AtomicLong bytesWritten = new AtomicLong();
+  private LongAdder bytesWritten = new LongAdder();
 
   public DefaultEndpointMetric(SocketAddress address) {
     this.address = address;
@@ -47,38 +47,38 @@ public SocketAddress getAddress() {
   }
 
   public long getConnectCount() {
-    return connectCount.get();
+    return connectCount.longValue();
   }
 
   public long getDisconnectCount() {
-    return disconnectCount.get();
+    return disconnectCount.longValue();
   }
 
   public long getCurrentConnectionCount() {
-    return connectCount.get() - disconnectCount.get();
+    return connectCount.longValue() - disconnectCount.longValue();
   }
 
   public void onConnect() {
-    connectCount.incrementAndGet();
+    connectCount.increment();
   }
 
   public void onDisconnect() {
-    disconnectCount.incrementAndGet();
+    disconnectCount.increment();
   }
 
   public long getBytesRead() {
-    return bytesRead.get();
+    return bytesRead.longValue();
   }
 
-  public long addBytesRead(long bytes) {
-    return bytesRead.addAndGet(bytes);
+  public void addBytesRead(long bytes) {
+    bytesRead.add(bytes);
   }
 
   public long getBytesWritten() {
-    return bytesWritten.get();
+    return bytesWritten.longValue();
   }
 
-  public long addBytesWritten(long bytes) {
-    return bytesWritten.addAndGet(bytes);
+  public void addBytesWritten(long bytes) {
+    bytesWritten.add(bytes);
   }
 }
diff --git a/handlers/handler-publickey-auth/src/main/java/org/apache/servicecomb/authentication/consumer/RSAConsumerTokenManager.java b/handlers/handler-publickey-auth/src/main/java/org/apache/servicecomb/authentication/consumer/RSAConsumerTokenManager.java
index 6679415c4..d3c610cca 100644
--- a/handlers/handler-publickey-auth/src/main/java/org/apache/servicecomb/authentication/consumer/RSAConsumerTokenManager.java
+++ b/handlers/handler-publickey-auth/src/main/java/org/apache/servicecomb/authentication/consumer/RSAConsumerTokenManager.java
@@ -22,7 +22,6 @@
 import java.security.SignatureException;
 import java.security.spec.InvalidKeySpecException;
 
-import org.apache.commons.lang3.RandomStringUtils;
 import org.apache.servicecomb.authentication.RSAAuthenticationToken;
 import org.apache.servicecomb.foundation.common.utils.RSAUtils;
 import org.apache.servicecomb.foundation.token.RSAKeypair4Auth;
@@ -54,7 +53,8 @@ public String createToken() {
     PrivateKey privateKey = RSAKeypair4Auth.INSTANCE.getPrivateKey();
     String instanceId = RegistryUtils.getMicroserviceInstance().getInstanceId();
     String serviceId = RegistryUtils.getMicroservice().getServiceId();
-    String randomCode = RandomStringUtils.randomAlphanumeric(128);
+    @SuppressWarnings("deprecation")
+    String randomCode = org.apache.commons.lang3.RandomStringUtils.randomAlphanumeric(128);
     long generateTime = System.currentTimeMillis();
     try {
       String plain = String.format("%s@%s@%s@%s", instanceId, serviceId, generateTime, randomCode);
diff --git a/java-chassis-dependencies/pom.xml b/java-chassis-dependencies/pom.xml
index 50a0778db..343900e2d 100644
--- a/java-chassis-dependencies/pom.xml
+++ b/java-chassis-dependencies/pom.xml
@@ -335,7 +335,7 @@
       <dependency>
         <groupId>org.apache.commons</groupId>
         <artifactId>commons-lang3</artifactId>
-        <version>3.3.2</version>
+        <version>3.6</version>
       </dependency>
       <dependency>
         <groupId>commons-beanutils</groupId>
@@ -366,7 +366,7 @@
       <dependency>
         <groupId>com.netflix.spectator</groupId>
         <artifactId>spectator-reg-servo</artifactId>
-        <version>0.63.0</version>
+        <version>0.71.0</version>
       </dependency>
       <dependency>
         <groupId>com.google.inject</groupId>
diff --git a/java-chassis-distribution/src/release/LICENSE b/java-chassis-distribution/src/release/LICENSE
index 31051f3e2..d9a3abd88 100644
--- a/java-chassis-distribution/src/release/LICENSE
+++ b/java-chassis-distribution/src/release/LICENSE
@@ -347,7 +347,7 @@ Apache Commons BeanUtils (http://commons.apache.org/proper/commons-beanutils/) c
 Apache Commons Codec (http://commons.apache.org/proper/commons-codec/) commons-codec:commons-codec:jar:1.10
 Apache Commons Collections (http://commons.apache.org/collections/) commons-collections:commons-collections:jar:3.2.2
 Apache Commons Configuration (http://commons.apache.org/configuration/) commons-configuration:commons-configuration:jar:1.10
-Apache Commons Lang (http://commons.apache.org/proper/commons-lang/) org.apache.commons:commons-lang3:jar:3.3.2
+Apache Commons Lang (http://commons.apache.org/proper/commons-lang/) org.apache.commons:commons-lang3:jar:3.6
 Apache Commons Logging (http://commons.apache.org/proper/commons-logging/) commons-logging:commons-logging:jar:1.2
 Apache HttpClient (http://hc.apache.org/httpcomponents-client) org.apache.httpcomponents:httpclient:jar:4.5.2
 Apache HttpCore (http://hc.apache.org/httpcomponents-core-ga) org.apache.httpcomponents:httpcore:jar:4.4.9
@@ -422,8 +422,8 @@ rxnetty-servo (https://github.com/ReactiveX/RxNetty) io.reactivex:rxnetty-servo:
 servo-core (https://github.com/Netflix/servo) com.netflix.servo:servo-core:jar:0.10.1
 servo-internal (https://github.com/Netflix/servo) com.netflix.servo:servo-internal:jar:0.10.1
 SnakeYAML (http://www.snakeyaml.org) org.yaml:snakeyaml:bundle:1.16
-spectator-api (https://github.com/Netflix/spectator) com.netflix.spectator:spectator-api:0.63.0
-spectator-reg-servo (https://github.com/Netflix/spectator) com.netflix.spectator:spectator-reg-servo:0.63.0
+spectator-api (https://github.com/Netflix/spectator) com.netflix.spectator:spectator-api:0.71.0
+spectator-reg-servo (https://github.com/Netflix/spectator) com.netflix.spectator:spectator-reg-servo:0.71.0
 Spring AOP (https://github.com/spring-projects/spring-framework) org.springframework:spring-aop:jar:4.3.16.RELEASE
 Spring Aspects (https://github.com/spring-projects/spring-framework) org.springframework:spring-aspects:jar:4.3.16.RELEASE
 Spring Beans (https://github.com/spring-projects/spring-framework) org.springframework:spring-beans:jar:4.3.16.RELEASE
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/DefaultRegistryInitializer.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/DefaultRegistryInitializer.java
index 586da6bb2..a01675fba 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/DefaultRegistryInitializer.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/DefaultRegistryInitializer.java
@@ -16,19 +16,20 @@
  */
 package org.apache.servicecomb.metrics.core;
 
+import java.time.Duration;
+
 import org.apache.servicecomb.foundation.metrics.MetricsBootstrapConfig;
 import org.apache.servicecomb.foundation.metrics.MetricsInitializer;
+import org.apache.servicecomb.foundation.metrics.registry.GlobalRegistry;
 
 import com.google.common.eventbus.EventBus;
 import com.netflix.servo.DefaultMonitorRegistry;
-import com.netflix.spectator.api.CompositeRegistry;
-import com.netflix.spectator.api.Registry;
 import com.netflix.spectator.servo.ServoRegistry;
 
 public class DefaultRegistryInitializer implements MetricsInitializer {
   public static final String SERVO_POLLERS = "servo.pollers";
 
-  private CompositeRegistry globalRegistry;
+  private GlobalRegistry globalRegistry;
 
   private ServoRegistry registry;
 
@@ -39,12 +40,15 @@ public int getOrder() {
   }
 
   @Override
-  public void init(CompositeRegistry globalRegistry, EventBus eventBus, MetricsBootstrapConfig config) {
+  public void init(GlobalRegistry globalRegistry, EventBus eventBus, MetricsBootstrapConfig config) {
     this.globalRegistry = globalRegistry;
 
-    System.getProperties().setProperty(SERVO_POLLERS, String.valueOf(config.getMsPollInterval()));
-    registry = new ServoRegistry();
+    // spectator move poll gauges from inline to background executor
+    // we need to set the interval to unify value
+    System.setProperty("spectator.api.gaugePollingFrequency", Duration.ofMillis(config.getMsPollInterval()).toString());
 
+    System.setProperty(SERVO_POLLERS, String.valueOf(config.getMsPollInterval()));
+    registry = new ServoRegistry();
     globalRegistry.add(registry);
   }
 
@@ -55,8 +59,4 @@ public void destroy() {
       globalRegistry.remove(registry);
     }
   }
-
-  public Registry getRegistry() {
-    return registry;
-  }
 }
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/InvocationMetersInitializer.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/InvocationMetersInitializer.java
index 72a05ef72..d26543467 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/InvocationMetersInitializer.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/InvocationMetersInitializer.java
@@ -19,9 +19,9 @@
 import org.apache.servicecomb.core.Invocation;
 import org.apache.servicecomb.core.event.InvocationFinishEvent;
 import org.apache.servicecomb.core.event.InvocationStartEvent;
-import org.apache.servicecomb.foundation.common.utils.SPIServiceUtils;
 import org.apache.servicecomb.foundation.metrics.MetricsBootstrapConfig;
 import org.apache.servicecomb.foundation.metrics.MetricsInitializer;
+import org.apache.servicecomb.foundation.metrics.registry.GlobalRegistry;
 import org.apache.servicecomb.metrics.core.meter.ConsumerMeters;
 import org.apache.servicecomb.metrics.core.meter.EdgeMeters;
 import org.apache.servicecomb.metrics.core.meter.ProducerMeters;
@@ -30,7 +30,6 @@
 import com.google.common.eventbus.AllowConcurrentEvents;
 import com.google.common.eventbus.EventBus;
 import com.google.common.eventbus.Subscribe;
-import com.netflix.spectator.api.CompositeRegistry;
 import com.netflix.spectator.api.Registry;
 
 public class InvocationMetersInitializer implements MetricsInitializer {
@@ -41,10 +40,8 @@
   private EdgeMeters edgeMeters;
 
   @Override
-  public void init(CompositeRegistry globalRegistry, EventBus eventBus, MetricsBootstrapConfig config) {
-    DefaultRegistryInitializer defaultRegistryInitializer =
-        SPIServiceUtils.getTargetService(MetricsInitializer.class, DefaultRegistryInitializer.class);
-    Registry registry = defaultRegistryInitializer.getRegistry();
+  public void init(GlobalRegistry globalRegistry, EventBus eventBus, MetricsBootstrapConfig config) {
+    Registry registry = globalRegistry.getDefaultRegistry();
 
     consumerMeters = new ConsumerMeters(registry);
     producerMeters = new ProducerMeters(registry);
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/MetricsBootListener.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/MetricsBootListener.java
index d5725065a..376c502bc 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/MetricsBootListener.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/MetricsBootListener.java
@@ -24,12 +24,11 @@
 import org.apache.servicecomb.foundation.common.utils.SPIServiceUtils;
 import org.apache.servicecomb.foundation.metrics.MetricsBootstrap;
 import org.apache.servicecomb.foundation.metrics.MetricsInitializer;
+import org.apache.servicecomb.foundation.metrics.registry.GlobalRegistry;
 import org.apache.servicecomb.metrics.core.publish.HealthCheckerRestPublisher;
 import org.apache.servicecomb.metrics.core.publish.MetricsRestPublisher;
 import org.springframework.stereotype.Component;
 
-import com.netflix.spectator.api.Spectator;
-
 @Component
 public class MetricsBootListener implements BootListener {
   private MetricsBootstrap metricsBootstrap = new MetricsBootstrap();
@@ -37,6 +36,10 @@
   @Inject
   private ProducerSchemaFactory producerSchemaFactory;
 
+  public MetricsBootstrap getMetricsBootstrap() {
+    return metricsBootstrap;
+  }
+
   @Override
   public void onBootEvent(BootEvent event) {
     switch (event.getEventType()) {
@@ -44,7 +47,7 @@ public void onBootEvent(BootEvent event) {
         registerSchemas();
         break;
       case AFTER_REGISTRY:
-        metricsBootstrap.start(Spectator.globalRegistry(), EventManager.getEventBus());
+        metricsBootstrap.start(new GlobalRegistry(), EventManager.getEventBus());
         break;
       case BEFORE_CLOSE:
         metricsBootstrap.shutdown();
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/OsMetersInitializer.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/OsMetersInitializer.java
index f94cf1888..783d0cce6 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/OsMetersInitializer.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/OsMetersInitializer.java
@@ -17,16 +17,16 @@
 package org.apache.servicecomb.metrics.core;
 
 import org.apache.commons.lang3.SystemUtils;
-import org.apache.servicecomb.foundation.common.utils.SPIServiceUtils;
 import org.apache.servicecomb.foundation.metrics.MetricsBootstrapConfig;
 import org.apache.servicecomb.foundation.metrics.MetricsInitializer;
+import org.apache.servicecomb.foundation.metrics.registry.GlobalRegistry;
 import org.apache.servicecomb.metrics.core.meter.os.OsMeter;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import com.google.common.eventbus.EventBus;
-import com.netflix.spectator.api.CompositeRegistry;
 import com.netflix.spectator.api.Registry;
+import com.netflix.spectator.api.SpectatorUtils;
 
 public class OsMetersInitializer implements MetricsInitializer {
   private static final Logger LOGGER = LoggerFactory.getLogger(OsMetersInitializer.class);
@@ -34,16 +34,15 @@
   private OsMeter osMeter;
 
   @Override
-  public void init(CompositeRegistry globalRegistry, EventBus eventBus, MetricsBootstrapConfig config) {
+  public void init(GlobalRegistry globalRegistry, EventBus eventBus, MetricsBootstrapConfig config) {
     if (!SystemUtils.IS_OS_LINUX) {
       LOGGER.info("only support linux os to collect cpu and net info");
       return;
     }
-    DefaultRegistryInitializer defaultRegistryInitializer = SPIServiceUtils
-        .getTargetService(MetricsInitializer.class, DefaultRegistryInitializer.class);
-    Registry registry = defaultRegistryInitializer.getRegistry();
-    osMeter = new OsMeter(registry, eventBus);
-    registry.register(osMeter);
+
+    Registry registry = globalRegistry.getDefaultRegistry();
+    osMeter = new OsMeter(registry);
+    SpectatorUtils.registerMeter(registry, osMeter);
   }
 
   public OsMeter getOsMeter() {
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/ThreadPoolMetersInitializer.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/ThreadPoolMetersInitializer.java
index 1637cfba9..621fd0fe2 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/ThreadPoolMetersInitializer.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/ThreadPoolMetersInitializer.java
@@ -27,12 +27,11 @@
 import org.apache.servicecomb.core.definition.OperationMeta;
 import org.apache.servicecomb.core.executor.FixedThreadExecutor;
 import org.apache.servicecomb.foundation.common.utils.BeanUtils;
-import org.apache.servicecomb.foundation.common.utils.SPIServiceUtils;
 import org.apache.servicecomb.foundation.metrics.MetricsBootstrapConfig;
 import org.apache.servicecomb.foundation.metrics.MetricsInitializer;
+import org.apache.servicecomb.foundation.metrics.registry.GlobalRegistry;
 
 import com.google.common.eventbus.EventBus;
-import com.netflix.spectator.api.CompositeRegistry;
 import com.netflix.spectator.api.Registry;
 import com.netflix.spectator.api.patterns.ThreadPoolMonitor;
 
@@ -40,10 +39,8 @@
   private Registry registry;
 
   @Override
-  public void init(CompositeRegistry globalRegistry, EventBus eventBus, MetricsBootstrapConfig config) {
-    DefaultRegistryInitializer defaultRegistryInitializer =
-        SPIServiceUtils.getTargetService(MetricsInitializer.class, DefaultRegistryInitializer.class);
-    registry = defaultRegistryInitializer.getRegistry();
+  public void init(GlobalRegistry globalRegistry, EventBus eventBus, MetricsBootstrapConfig config) {
+    registry = globalRegistry.getDefaultRegistry();
 
     createThreadPoolMeters();
   }
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/AbstractInvocationMeter.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/AbstractInvocationMeter.java
index dd0851e3f..3023602bc 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/AbstractInvocationMeter.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/AbstractInvocationMeter.java
@@ -16,52 +16,84 @@
  */
 package org.apache.servicecomb.metrics.core.meter.invocation;
 
-import java.util.concurrent.TimeUnit;
+import java.util.ArrayList;
+import java.util.List;
 
-import org.apache.servicecomb.core.Invocation;
 import org.apache.servicecomb.core.event.InvocationFinishEvent;
-import org.apache.servicecomb.swagger.invocation.Response;
+import org.apache.servicecomb.core.invocation.InvocationStageTrace;
+import org.apache.servicecomb.foundation.metrics.meter.AbstractPeriodMeter;
+import org.apache.servicecomb.foundation.metrics.meter.SimpleTimer;
 
 import com.netflix.spectator.api.Id;
+import com.netflix.spectator.api.Measurement;
 import com.netflix.spectator.api.Registry;
-import com.netflix.spectator.api.Timer;
 
-public abstract class AbstractInvocationMeter {
+public abstract class AbstractInvocationMeter extends AbstractPeriodMeter {
+  private final Registry registry;
+
   //total time
-  private Timer totalTimer;
+  private SimpleTimer totalTimer;
 
   // prepare time
-  private Timer prepareTimer;
+  private SimpleTimer prepareTimer;
 
   // handler request
-  private Timer handlersRequestTimer;
+  private SimpleTimer handlersRequestTimer;
 
   // handler response
-  private Timer handlersResponseTimer;
+  private SimpleTimer handlersResponseTimer;
+
+  private long lastUpdated;
+
+  public AbstractInvocationMeter(Registry registry, Id id) {
+    this.registry = registry;
+    this.id = id;
+
+    totalTimer = creatStageTimer(MeterInvocationConst.STAGE_TOTAL);
+    prepareTimer = creatStageTimer(MeterInvocationConst.STAGE_PREPARE);
+    handlersRequestTimer = creatStageTimer(MeterInvocationConst.STAGE_HANDLERS_REQUEST);
+    handlersResponseTimer = creatStageTimer(MeterInvocationConst.STAGE_HANDLERS_RESPONSE);
+  }
+
+  protected SimpleTimer creatStageTimer(String stageValue) {
+    return createTimer(id.withTag(MeterInvocationConst.TAG_STAGE, stageValue));
+  }
 
-  public AbstractInvocationMeter(Registry registry, Id id, Invocation invocation, Response response) {
+  protected SimpleTimer createTimer(String tagKey, String tagValue) {
+    return createTimer(id.withTag(tagKey, tagValue));
+  }
 
-    totalTimer = registry.timer(id.withTag(MeterInvocationConst.TAG_STAGE, MeterInvocationConst.STAGE_TOTAL));
-    prepareTimer = registry.timer(id.withTag(MeterInvocationConst.TAG_STAGE, MeterInvocationConst.STAGE_PREPARE));
-    handlersRequestTimer =
-        registry.timer(id.withTag(MeterInvocationConst.TAG_STAGE, MeterInvocationConst.STAGE_HANDLERS_REQUEST));
-    handlersResponseTimer =
-        registry.timer(id.withTag(MeterInvocationConst.TAG_STAGE, MeterInvocationConst.STAGE_HANDLERS_RESPONSE));
+  protected SimpleTimer createTimer(Id timerId) {
+    return new SimpleTimer(timerId);
   }
 
   public void onInvocationFinish(InvocationFinishEvent event) {
+    lastUpdated = registry.clock().wallTime();
+
+    InvocationStageTrace stageTrace = event.getInvocation().getInvocationStageTrace();
+    totalTimer.record((long) stageTrace.calcTotalTime());
+    handlersRequestTimer.record((long) stageTrace.calcHandlersRequestTime());
+    handlersResponseTimer.record((long) stageTrace.calcHandlersResponseTime());
+    prepareTimer.record((long) stageTrace.calcInvocationPrepareTime());
+  }
+
+  @Override
+  public void calcMeasurements(long msNow, long secondInterval) {
+    List<Measurement> measurements = new ArrayList<>(3);
+    calcMeasurements(measurements, msNow, secondInterval);
+    allMeasurements = measurements;
+  }
+
+  @Override
+  public void calcMeasurements(List<Measurement> measurements, long msNow, long secondInterval) {
+    totalTimer.calcMeasurements(measurements, msNow, secondInterval);
+    handlersRequestTimer.calcMeasurements(measurements, msNow, secondInterval);
+    handlersResponseTimer.calcMeasurements(measurements, msNow, secondInterval);
+    prepareTimer.calcMeasurements(measurements, msNow, secondInterval);
+  }
 
-    totalTimer.record((long) event.getInvocation().getInvocationStageTrace().calcTotalTime(),
-        TimeUnit.NANOSECONDS);
-
-    handlersRequestTimer
-        .record((long) event.getInvocation().getInvocationStageTrace().calcHandlersRequestTime(),
-            TimeUnit.NANOSECONDS);
-    handlersResponseTimer
-        .record((long) event.getInvocation().getInvocationStageTrace().calcHandlersResponseTime(),
-            TimeUnit.NANOSECONDS);
-    prepareTimer
-        .record((long) event.getInvocation().getInvocationStageTrace().calcInvocationPrepareTime(),
-            TimeUnit.NANOSECONDS);
+  @Override
+  public boolean hasExpired() {
+    return super.hasExpired();
   }
 }
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/AbstractInvocationMeters.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/AbstractInvocationMeters.java
index 179cd5a4e..e9114804b 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/AbstractInvocationMeters.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/AbstractInvocationMeters.java
@@ -26,6 +26,7 @@
 
 import com.netflix.spectator.api.Id;
 import com.netflix.spectator.api.Registry;
+import com.netflix.spectator.api.SpectatorUtils;
 
 public abstract class AbstractInvocationMeters {
   protected Registry registry;
@@ -70,14 +71,13 @@ protected AbstractInvocationMeter getOrCreateMeters(Invocation invocation, Respo
           MeterInvocationConst.TAG_STATUS,
           String.valueOf(response.getStatusCode()));
 
-      return createMeter(id, invocation, response);
+      AbstractInvocationMeter meter = createMeter(id);
+      SpectatorUtils.registerMeter(registry, meter);
+      return meter;
     });
   }
 
-
-
-  protected abstract AbstractInvocationMeter createMeter(Id id, Invocation invocation,
-      Response response);
+  protected abstract AbstractInvocationMeter createMeter(Id id);
 
   public void onInvocationStart(InvocationStartEvent event) {
   }
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/ConsumerInvocationMeter.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/ConsumerInvocationMeter.java
index e8e0d3802..a82624fe9 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/ConsumerInvocationMeter.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/ConsumerInvocationMeter.java
@@ -16,70 +16,66 @@
  */
 package org.apache.servicecomb.metrics.core.meter.invocation;
 
-import java.util.concurrent.TimeUnit;
+import java.util.List;
 
-import org.apache.servicecomb.core.Invocation;
 import org.apache.servicecomb.core.event.InvocationFinishEvent;
 import org.apache.servicecomb.core.invocation.InvocationStageTrace;
-import org.apache.servicecomb.swagger.invocation.Response;
+import org.apache.servicecomb.foundation.metrics.meter.SimpleTimer;
 
 import com.netflix.spectator.api.Id;
+import com.netflix.spectator.api.Measurement;
 import com.netflix.spectator.api.Registry;
-import com.netflix.spectator.api.Timer;
 
 public class ConsumerInvocationMeter extends AbstractInvocationMeter {
+  private SimpleTimer clientFiltersRequestTimer;
 
-  private Timer clientFiltersRequestTimer;
+  private SimpleTimer consumerSendRequestTimer;
 
-  private Timer consumerSendRequestTimer;
+  private SimpleTimer consumerGetConnectionTimer;
 
-  private Timer consumerGetConnectionTimer;
+  private SimpleTimer consumerWriteToBufTimer;
 
-  private Timer consumerWriteToBufTimer;
+  private SimpleTimer consumerWaitResponseTimer;
 
-  private Timer consumerWaitResponseTimer;
+  private SimpleTimer consumerWakeConsumerTimer;
 
-  private Timer consumerWakeConsumerTimer;
+  private SimpleTimer clientFiltersResponseTimer;
 
-  private Timer clientFiltersResponseTimer;
-
-
-  public ConsumerInvocationMeter(Registry registry, Id id, Invocation invocation, Response response) {
-    super(registry, id, invocation, response);
-    clientFiltersRequestTimer =
-        registry.timer(id.withTag(MeterInvocationConst.TAG_STAGE, MeterInvocationConst.STAGE_CLIENT_FILTERS_REQUEST));
-    consumerSendRequestTimer =
-        registry.timer(id.withTag(MeterInvocationConst.TAG_STAGE, MeterInvocationConst.STAGE_CONSUMER_SEND_REQUEST));
-    consumerGetConnectionTimer =
-        registry.timer(id.withTag(MeterInvocationConst.TAG_STAGE, MeterInvocationConst.STAGE_CONSUMER_GET_CONNECTION));
-    consumerWriteToBufTimer =
-        registry.timer(id.withTag(MeterInvocationConst.TAG_STAGE, MeterInvocationConst.STAGE_CONSUMER_WRITE_TO_BUF));
-    consumerWakeConsumerTimer =
-        registry.timer(id.withTag(MeterInvocationConst.TAG_STAGE, MeterInvocationConst.STAGE_CONSUMER_WAKE_CONSUMER));
-    clientFiltersResponseTimer =
-        registry.timer(id.withTag(MeterInvocationConst.TAG_STAGE, MeterInvocationConst.STAGE_CLIENT_FILTERS_RESPONSE));
-    consumerWaitResponseTimer =
-        registry.timer(id.withTag(MeterInvocationConst.TAG_STAGE, MeterInvocationConst.STAGE_CONSUMER_WAIT_RESPONSE));
+  public ConsumerInvocationMeter(Registry registry, Id id) {
+    super(registry, id);
+    clientFiltersRequestTimer = creatStageTimer(MeterInvocationConst.STAGE_CLIENT_FILTERS_REQUEST);
+    consumerSendRequestTimer = creatStageTimer(MeterInvocationConst.STAGE_CONSUMER_SEND_REQUEST);
+    consumerGetConnectionTimer = creatStageTimer(MeterInvocationConst.STAGE_CONSUMER_GET_CONNECTION);
+    consumerWriteToBufTimer = creatStageTimer(MeterInvocationConst.STAGE_CONSUMER_WRITE_TO_BUF);
+    consumerWakeConsumerTimer = creatStageTimer(MeterInvocationConst.STAGE_CONSUMER_WAKE_CONSUMER);
+    clientFiltersResponseTimer = creatStageTimer(MeterInvocationConst.STAGE_CLIENT_FILTERS_RESPONSE);
+    consumerWaitResponseTimer = creatStageTimer(MeterInvocationConst.STAGE_CONSUMER_WAIT_RESPONSE);
   }
 
   @Override
   public void onInvocationFinish(InvocationFinishEvent event) {
     super.onInvocationFinish(event);
+
     InvocationStageTrace invocationStageTrace = event.getInvocation().getInvocationStageTrace();
+    clientFiltersRequestTimer.record((long) invocationStageTrace.calcClientFiltersRequestTime());
+    consumerSendRequestTimer.record((long) invocationStageTrace.calcSendRequestTime());
+    consumerGetConnectionTimer.record((long) invocationStageTrace.calcGetConnectionTime());
+    consumerWriteToBufTimer.record((long) invocationStageTrace.calcWriteToBufferTime());
+    consumerWaitResponseTimer.record((long) invocationStageTrace.calcReceiveResponseTime());
+    consumerWakeConsumerTimer.record((long) invocationStageTrace.calcWakeConsumer());
+    clientFiltersResponseTimer.record((long) invocationStageTrace.calcClientFiltersResponseTime());
+  }
+
+  @Override
+  public void calcMeasurements(List<Measurement> measurements, long msNow, long secondInterval) {
+    super.calcMeasurements(measurements, msNow, secondInterval);
 
-    clientFiltersRequestTimer.record((long) invocationStageTrace.calcClientFiltersRequestTime(),
-        TimeUnit.NANOSECONDS);
-    consumerSendRequestTimer.record((long) invocationStageTrace.calcSendRequestTime(),
-        TimeUnit.NANOSECONDS);
-    consumerGetConnectionTimer.record((long) invocationStageTrace.calcGetConnectionTime(),
-        TimeUnit.NANOSECONDS);
-    consumerWriteToBufTimer.record((long) invocationStageTrace.calcWriteToBufferTime(),
-        TimeUnit.NANOSECONDS);
-    consumerWaitResponseTimer.record((long) invocationStageTrace.calcReceiveResponseTime(),
-        TimeUnit.NANOSECONDS);
-    consumerWakeConsumerTimer.record((long) invocationStageTrace.calcWakeConsumer(),
-        TimeUnit.NANOSECONDS);
-    clientFiltersResponseTimer.record((long) invocationStageTrace.calcClientFiltersResponseTime(),
-        TimeUnit.NANOSECONDS);
+    clientFiltersRequestTimer.calcMeasurements(measurements, msNow, secondInterval);
+    consumerSendRequestTimer.calcMeasurements(measurements, msNow, secondInterval);
+    consumerGetConnectionTimer.calcMeasurements(measurements, msNow, secondInterval);
+    consumerWriteToBufTimer.calcMeasurements(measurements, msNow, secondInterval);
+    consumerWaitResponseTimer.calcMeasurements(measurements, msNow, secondInterval);
+    consumerWakeConsumerTimer.calcMeasurements(measurements, msNow, secondInterval);
+    clientFiltersResponseTimer.calcMeasurements(measurements, msNow, secondInterval);
   }
 }
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/ConsumerInvocationMeters.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/ConsumerInvocationMeters.java
index dd24ecb71..5543c9f54 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/ConsumerInvocationMeters.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/ConsumerInvocationMeters.java
@@ -16,9 +16,6 @@
  */
 package org.apache.servicecomb.metrics.core.meter.invocation;
 
-import org.apache.servicecomb.core.Invocation;
-import org.apache.servicecomb.swagger.invocation.Response;
-
 import com.netflix.spectator.api.Id;
 import com.netflix.spectator.api.Registry;
 
@@ -28,7 +25,7 @@ public ConsumerInvocationMeters(Registry registry) {
   }
 
   @Override
-  protected AbstractInvocationMeter createMeter(Id id, Invocation invocation, Response response) {
-    return new ConsumerInvocationMeter(registry, id, invocation, response);
+  protected AbstractInvocationMeter createMeter(Id id) {
+    return new ConsumerInvocationMeter(registry, id);
   }
 }
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/EdgeInvocationMeter.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/EdgeInvocationMeter.java
index ac9716757..ca41a2f6b 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/EdgeInvocationMeter.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/EdgeInvocationMeter.java
@@ -17,38 +17,31 @@
 
 package org.apache.servicecomb.metrics.core.meter.invocation;
 
-import java.util.concurrent.TimeUnit;
+import java.util.List;
 
-import org.apache.servicecomb.core.Invocation;
 import org.apache.servicecomb.core.event.InvocationFinishEvent;
 import org.apache.servicecomb.core.invocation.InvocationStageTrace;
-import org.apache.servicecomb.swagger.invocation.Response;
+import org.apache.servicecomb.foundation.metrics.meter.SimpleTimer;
 
 import com.netflix.spectator.api.Id;
+import com.netflix.spectator.api.Measurement;
 import com.netflix.spectator.api.Registry;
-import com.netflix.spectator.api.Timer;
 
 public class EdgeInvocationMeter extends ConsumerInvocationMeter {
+  private SimpleTimer executorQueueTimer;
 
-  private Timer executorQueueTimer;
+  private SimpleTimer serverFiltersRequestTimer;
 
-  private Timer serverFiltersRequestTimer;
+  private SimpleTimer serverFiltersResponseTimer;
 
-  private Timer serverFiltersResponseTimer;
+  private SimpleTimer sendResponseTimer;
 
-  private Timer sendResponseTimer;
-
-  public EdgeInvocationMeter(Registry registry, Id id, Invocation invocation, Response response) {
-    super(registry, id, invocation, response);
-    executorQueueTimer =
-        registry.timer(id.withTag(MeterInvocationConst.TAG_STAGE, MeterInvocationConst.STAGE_EXECUTOR_QUEUE));
-
-    serverFiltersRequestTimer =
-        registry.timer(id.withTag(MeterInvocationConst.TAG_STAGE, MeterInvocationConst.STAGE_SERVER_FILTERS_REQUEST));
-    serverFiltersResponseTimer =
-        registry.timer(id.withTag(MeterInvocationConst.TAG_STAGE, MeterInvocationConst.STAGE_SERVER_FILTERS_RESPONSE));
-    sendResponseTimer =
-        registry.timer(id.withTag(MeterInvocationConst.TAG_STAGE, MeterInvocationConst.STAGE_PRODUCER_SEND_RESPONSE));
+  public EdgeInvocationMeter(Registry registry, Id id) {
+    super(registry, id);
+    executorQueueTimer = creatStageTimer(MeterInvocationConst.STAGE_EXECUTOR_QUEUE);
+    serverFiltersRequestTimer = creatStageTimer(MeterInvocationConst.STAGE_SERVER_FILTERS_REQUEST);
+    serverFiltersResponseTimer = creatStageTimer(MeterInvocationConst.STAGE_SERVER_FILTERS_RESPONSE);
+    sendResponseTimer = creatStageTimer(MeterInvocationConst.STAGE_PRODUCER_SEND_RESPONSE);
   }
 
   @Override
@@ -56,12 +49,19 @@ public void onInvocationFinish(InvocationFinishEvent event) {
     super.onInvocationFinish(event);
     InvocationStageTrace invocationStageTrace = event.getInvocation().getInvocationStageTrace();
 
-    executorQueueTimer.record((long) invocationStageTrace.calcThreadPoolQueueTime(),
-        TimeUnit.NANOSECONDS);
+    executorQueueTimer.record((long) invocationStageTrace.calcThreadPoolQueueTime());
+    serverFiltersRequestTimer.record((long) invocationStageTrace.calcServerFiltersRequestTime());
+    serverFiltersResponseTimer.record((long) invocationStageTrace.calcServerFiltersResponseTime());
+    sendResponseTimer.record((long) invocationStageTrace.calcSendResponseTime());
+  }
+
+  @Override
+  public void calcMeasurements(List<Measurement> measurements, long msNow, long secondInterval) {
+    super.calcMeasurements(measurements, msNow, secondInterval);
 
-    serverFiltersRequestTimer.record((long) invocationStageTrace.calcServerFiltersRequestTime(), TimeUnit.NANOSECONDS);
-    serverFiltersResponseTimer
-        .record((long) invocationStageTrace.calcServerFiltersResponseTime(), TimeUnit.NANOSECONDS);
-    sendResponseTimer.record((long) invocationStageTrace.calcSendResponseTime(), TimeUnit.NANOSECONDS);
+    executorQueueTimer.calcMeasurements(measurements, msNow, secondInterval);
+    serverFiltersRequestTimer.calcMeasurements(measurements, msNow, secondInterval);
+    serverFiltersResponseTimer.calcMeasurements(measurements, msNow, secondInterval);
+    sendResponseTimer.calcMeasurements(measurements, msNow, secondInterval);
   }
 }
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/EdgeInvocationMeters.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/EdgeInvocationMeters.java
index 70c5c203c..b7db74c27 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/EdgeInvocationMeters.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/EdgeInvocationMeters.java
@@ -17,9 +17,6 @@
 
 package org.apache.servicecomb.metrics.core.meter.invocation;
 
-import org.apache.servicecomb.core.Invocation;
-import org.apache.servicecomb.swagger.invocation.Response;
-
 import com.netflix.spectator.api.Id;
 import com.netflix.spectator.api.Registry;
 
@@ -29,7 +26,7 @@ public EdgeInvocationMeters(Registry registry) {
   }
 
   @Override
-  protected AbstractInvocationMeter createMeter(Id id, Invocation invocation, Response response) {
-    return new EdgeInvocationMeter(registry, id, invocation, response);
+  protected AbstractInvocationMeter createMeter(Id id) {
+    return new EdgeInvocationMeter(registry, id);
   }
 }
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/MeterInvocationConst.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/MeterInvocationConst.java
index b4e12d2ae..e09da9b5e 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/MeterInvocationConst.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/MeterInvocationConst.java
@@ -19,56 +19,55 @@
 import com.netflix.spectator.api.Statistic;
 
 public interface MeterInvocationConst {
-  final String INVOCATION_NAME = "servicecomb.invocation";
+  String INVOCATION_NAME = "servicecomb.invocation";
 
   // consumer or producer
-  final String TAG_ROLE = "role";
+  String TAG_ROLE = "role";
 
-  final String TAG_OPERATION = "operation";
+  String TAG_OPERATION = "operation";
 
-  final String TAG_TRANSPORT = "transport";
+  String TAG_TRANSPORT = "transport";
 
-  final String TAG_STAGE = "stage";
+  String TAG_STAGE = "stage";
 
-  final String TAG_STATUS = "status";
+  String TAG_STATUS = "status";
 
-  final String TAG_STATISTIC = Statistic.count.key();
+  String TAG_STATISTIC = Statistic.count.key();
 
-  final String STAGE_TOTAL = "total";
+  String STAGE_TOTAL = "total";
 
-  final String STAGE_PREPARE = "prepare";
+  String STAGE_PREPARE = "prepare";
 
-  final String STAGE_EXECUTOR_QUEUE = "queue";
+  String STAGE_EXECUTOR_QUEUE = "queue";
 
-  final String STAGE_EXECUTION = "execution";
+  String STAGE_EXECUTION = "execution";
 
-  final String EDGE_INVOCATION_NAME = "EDGE";
+  String EDGE_INVOCATION_NAME = "EDGE";
 
-  final String STAGE_HANDLERS_REQUEST = "handlers_request";
+  String STAGE_HANDLERS_REQUEST = "handlers_request";
 
-  final String STAGE_HANDLERS_RESPONSE = "handlers_response";
+  String STAGE_HANDLERS_RESPONSE = "handlers_response";
 
   // producer only
-  final String STAGE_SERVER_FILTERS_REQUEST = "server_filters_request";
+  String STAGE_SERVER_FILTERS_REQUEST = "server_filters_request";
 
-  final String STAGE_SERVER_FILTERS_RESPONSE = "server_filters_response";
+  String STAGE_SERVER_FILTERS_RESPONSE = "server_filters_response";
 
-  final String STAGE_PRODUCER_SEND_RESPONSE = "producer_send_response";
+  String STAGE_PRODUCER_SEND_RESPONSE = "producer_send_response";
 
   //consumer only
 
-  final String STAGE_CLIENT_FILTERS_REQUEST = "client_filters_request";
+  String STAGE_CLIENT_FILTERS_REQUEST = "client_filters_request";
 
-  final String STAGE_CONSUMER_SEND_REQUEST = "consumer_send_request";
+  String STAGE_CONSUMER_SEND_REQUEST = "consumer_send_request";
 
-  final String STAGE_CONSUMER_GET_CONNECTION = "consumer_get_connection";
+  String STAGE_CONSUMER_GET_CONNECTION = "consumer_get_connection";
 
-  final String STAGE_CONSUMER_WRITE_TO_BUF = "consumer_write_to_buf";
+  String STAGE_CONSUMER_WRITE_TO_BUF = "consumer_write_to_buf";
 
-  final String STAGE_CONSUMER_WAIT_RESPONSE = "consumer_wait_response";
+  String STAGE_CONSUMER_WAIT_RESPONSE = "consumer_wait_response";
 
-  final String STAGE_CONSUMER_WAKE_CONSUMER = "consumer_wake_consumer";
-
-  final String STAGE_CLIENT_FILTERS_RESPONSE = "client_filters_response";
+  String STAGE_CONSUMER_WAKE_CONSUMER = "consumer_wake_consumer";
 
+  String STAGE_CLIENT_FILTERS_RESPONSE = "client_filters_response";
 }
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/ProducerInvocationMeter.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/ProducerInvocationMeter.java
index cb525d73c..79b89e51f 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/ProducerInvocationMeter.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/ProducerInvocationMeter.java
@@ -16,42 +16,35 @@
  */
 package org.apache.servicecomb.metrics.core.meter.invocation;
 
-import java.util.concurrent.TimeUnit;
+import java.util.List;
 
-import org.apache.servicecomb.core.Invocation;
 import org.apache.servicecomb.core.event.InvocationFinishEvent;
 import org.apache.servicecomb.core.invocation.InvocationStageTrace;
-import org.apache.servicecomb.swagger.invocation.Response;
+import org.apache.servicecomb.foundation.metrics.meter.SimpleTimer;
 
 import com.netflix.spectator.api.Id;
+import com.netflix.spectator.api.Measurement;
 import com.netflix.spectator.api.Registry;
-import com.netflix.spectator.api.Timer;
 
 public class ProducerInvocationMeter extends AbstractInvocationMeter {
-  private Timer executorQueueTimer;
+  private SimpleTimer executorQueueTimer;
 
-  private Timer executionTimer;
+  private SimpleTimer executionTimer;
 
-  private Timer serverFiltersRequestTimer;
+  private SimpleTimer serverFiltersRequestTimer;
 
-  private Timer serverFiltersResponseTimer;
+  private SimpleTimer serverFiltersResponseTimer;
 
-  private Timer sendResponseTimer;
+  private SimpleTimer sendResponseTimer;
 
+  public ProducerInvocationMeter(Registry registry, Id id) {
+    super(registry, id);
 
-  public ProducerInvocationMeter(Registry registry, Id id, Invocation invocation, Response response) {
-    super(registry, id, invocation, response);
-
-    executorQueueTimer =
-        registry.timer(id.withTag(MeterInvocationConst.TAG_STAGE, MeterInvocationConst.STAGE_EXECUTOR_QUEUE));
-    executionTimer =
-        registry.timer(id.withTag(MeterInvocationConst.TAG_STAGE, MeterInvocationConst.STAGE_EXECUTION));
-    serverFiltersRequestTimer =
-        registry.timer(id.withTag(MeterInvocationConst.TAG_STAGE, MeterInvocationConst.STAGE_SERVER_FILTERS_REQUEST));
-    serverFiltersResponseTimer =
-        registry.timer(id.withTag(MeterInvocationConst.TAG_STAGE, MeterInvocationConst.STAGE_SERVER_FILTERS_RESPONSE));
-    sendResponseTimer =
-        registry.timer(id.withTag(MeterInvocationConst.TAG_STAGE, MeterInvocationConst.STAGE_PRODUCER_SEND_RESPONSE));
+    executorQueueTimer = creatStageTimer(MeterInvocationConst.STAGE_EXECUTOR_QUEUE);
+    executionTimer = creatStageTimer(MeterInvocationConst.STAGE_EXECUTION);
+    serverFiltersRequestTimer = creatStageTimer(MeterInvocationConst.STAGE_SERVER_FILTERS_REQUEST);
+    serverFiltersResponseTimer = creatStageTimer(MeterInvocationConst.STAGE_SERVER_FILTERS_RESPONSE);
+    sendResponseTimer = creatStageTimer(MeterInvocationConst.STAGE_PRODUCER_SEND_RESPONSE);
   }
 
   @Override
@@ -59,14 +52,21 @@ public void onInvocationFinish(InvocationFinishEvent event) {
     super.onInvocationFinish(event);
 
     InvocationStageTrace invocationStageTrace = event.getInvocation().getInvocationStageTrace();
+    executorQueueTimer.record((long) invocationStageTrace.calcThreadPoolQueueTime());
+    executionTimer.record((long) invocationStageTrace.calcBusinessTime());
+    serverFiltersRequestTimer.record((long) invocationStageTrace.calcServerFiltersRequestTime());
+    serverFiltersResponseTimer.record((long) invocationStageTrace.calcServerFiltersResponseTime());
+    sendResponseTimer.record((long) invocationStageTrace.calcSendResponseTime());
+  }
 
-    executorQueueTimer.record((long) invocationStageTrace.calcThreadPoolQueueTime(),
-        TimeUnit.NANOSECONDS);
-    executionTimer.record((long) invocationStageTrace.calcBusinessTime(), TimeUnit.NANOSECONDS);
+  @Override
+  public void calcMeasurements(List<Measurement> measurements, long msNow, long secondInterval) {
+    super.calcMeasurements(measurements, msNow, secondInterval);
 
-    serverFiltersRequestTimer.record((long) invocationStageTrace.calcServerFiltersRequestTime(), TimeUnit.NANOSECONDS);
-    serverFiltersResponseTimer
-        .record((long) invocationStageTrace.calcServerFiltersResponseTime(), TimeUnit.NANOSECONDS);
-    sendResponseTimer.record((long) invocationStageTrace.calcSendResponseTime(), TimeUnit.NANOSECONDS);
+    executorQueueTimer.calcMeasurements(measurements, msNow, secondInterval);
+    executionTimer.calcMeasurements(measurements, msNow, secondInterval);
+    serverFiltersRequestTimer.calcMeasurements(measurements, msNow, secondInterval);
+    serverFiltersResponseTimer.calcMeasurements(measurements, msNow, secondInterval);
+    sendResponseTimer.calcMeasurements(measurements, msNow, secondInterval);
   }
 }
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/ProducerInvocationMeters.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/ProducerInvocationMeters.java
index 56031d0d3..f8e88148a 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/ProducerInvocationMeters.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/ProducerInvocationMeters.java
@@ -16,9 +16,6 @@
  */
 package org.apache.servicecomb.metrics.core.meter.invocation;
 
-import org.apache.servicecomb.core.Invocation;
-import org.apache.servicecomb.swagger.invocation.Response;
-
 import com.netflix.spectator.api.Id;
 import com.netflix.spectator.api.Registry;
 
@@ -28,7 +25,7 @@ public ProducerInvocationMeters(Registry registry) {
   }
 
   @Override
-  protected AbstractInvocationMeter createMeter(Id id, Invocation invocation, Response response) {
-    return new ProducerInvocationMeter(registry, id, invocation, response);
+  protected AbstractInvocationMeter createMeter(Id id) {
+    return new ProducerInvocationMeter(registry, id);
   }
 }
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/os/CpuMeter.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/os/CpuMeter.java
index d6e916e65..60f6cd25a 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/os/CpuMeter.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/os/CpuMeter.java
@@ -48,9 +48,9 @@ public CpuMeter(Id id) {
     rate = 0.0;
   }
 
-  public void calcMeasurements(List<Measurement> measurements, long timestap) {
+  public void calcMeasurements(List<Measurement> measurements, long msNow) {
     refreshCpu();
-    measurements.add(new Measurement(id, timestap, rate));
+    measurements.add(new Measurement(id, msNow, rate));
   }
 
   /*
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/os/NetMeter.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/os/NetMeter.java
index 1c1d59da9..839661941 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/os/NetMeter.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/os/NetMeter.java
@@ -26,7 +26,6 @@
 import java.util.concurrent.ConcurrentHashMap;
 
 import org.apache.commons.io.FileUtils;
-import org.apache.servicecomb.foundation.metrics.PollEvent;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -51,7 +50,6 @@
   private Map<String, InterfaceInfo> interfaceInfoMap = new ConcurrentHashMap<>();
 
   public static class InterfaceInfo {
-
     private final String name;
 
     private Id sendId;
@@ -76,12 +74,12 @@
       this.receiveId = id.withTag(TAG_RECEIVE);
     }
 
-    public void update(String interfaceData, long interval) {
+    public void update(String interfaceData, long secondInterval) {
       String[] netInfo = interfaceData.trim().split("\\s+");
       long rxBytes = Long.parseLong(netInfo[0]);
       long txBytes = Long.parseLong(netInfo[8]);
-      sendRate = (double) (txBytes - lastTxBytes) * 1000 / interval;
-      receiveRate = (double) (rxBytes - lastRxBytes) * 1000 / interval;
+      sendRate = (double) (txBytes - lastTxBytes) / secondInterval;
+      receiveRate = (double) (rxBytes - lastRxBytes) / secondInterval;
       lastRxBytes = rxBytes;
       lastTxBytes = txBytes;
     }
@@ -109,6 +107,8 @@ public double getReceiveRate() {
 
   public NetMeter(Id id) {
     this.id = id;
+
+    // init lastRxBytes and lastTxBytes
     refreshNet(1);
     for (InterfaceInfo interfaceInfo : interfaceInfoMap.values()) {
       interfaceInfo.sendRate = 0;
@@ -116,12 +116,12 @@ public NetMeter(Id id) {
     }
   }
 
-  public void calcMeasurements(List<Measurement> measurements, long timestap, PollEvent pollEvent) {
-    refreshNet(pollEvent.getMsPollInterval());
+  public void calcMeasurements(List<Measurement> measurements, long msNow, long secondInterval) {
+    refreshNet(secondInterval);
 
     for (InterfaceInfo interfaceInfo : interfaceInfoMap.values()) {
-      measurements.add(new Measurement(interfaceInfo.sendId, timestap, interfaceInfo.sendRate));
-      measurements.add(new Measurement(interfaceInfo.receiveId, timestap, interfaceInfo.receiveRate));
+      measurements.add(new Measurement(interfaceInfo.sendId, msNow, interfaceInfo.sendRate));
+      measurements.add(new Measurement(interfaceInfo.receiveId, msNow, interfaceInfo.receiveRate));
     }
   }
 
@@ -131,7 +131,7 @@ public void calcMeasurements(List<Measurement> measurements, long timestap, Poll
    *  eth0: 2615248100 32148518    0    0    0     0          0          0         87333034794 21420267    0      0     0     0    0    0
    *        0          1           2    3    4     5          6          7          8
    */
-  protected void refreshNet(long interval) {
+  protected void refreshNet(long secondInterval) {
     try {
       File file = new File("/proc/net/dev");
       List<String> netInfo = FileUtils.readLines(file, StandardCharsets.UTF_8);
@@ -150,7 +150,7 @@ protected void refreshNet(long interval) {
         nameSet.add(name);
 
         InterfaceInfo interfaceInfo = interfaceInfoMap.computeIfAbsent(name, key -> new InterfaceInfo(id, key));
-        interfaceInfo.update(strings[1], interval);
+        interfaceInfo.update(strings[1], secondInterval);
       }
 
       // clear deleted interfaces
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/os/OsMeter.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/os/OsMeter.java
index 961dbe047..257f8d9ff 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/os/OsMeter.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/os/OsMeter.java
@@ -19,13 +19,10 @@
 import java.util.ArrayList;
 import java.util.List;
 
-import org.apache.servicecomb.foundation.metrics.PollEvent;
+import org.apache.servicecomb.foundation.metrics.meter.AbstractPeriodMeter;
 
-import com.google.common.eventbus.EventBus;
-import com.google.common.eventbus.Subscribe;
-import com.netflix.spectator.api.Id;
+import com.google.common.annotations.VisibleForTesting;
 import com.netflix.spectator.api.Measurement;
-import com.netflix.spectator.api.Meter;
 import com.netflix.spectator.api.Registry;
 
 /**
@@ -33,7 +30,7 @@
  * name=os type=net interface=eth0 statistic=send value=100
  * name=os type=net interface=eth0 statistic=receive value=100
  */
-public class OsMeter implements Meter {
+public class OsMeter extends AbstractPeriodMeter {
   public static final String OS_NAME = "os";
 
   public static final String OS_TYPE = "type";
@@ -42,56 +39,36 @@
 
   public static final String OS_TYPE_NET = "net";
 
-  private List<Measurement> measurements = new ArrayList<>();
-
-  private Id id;
-
-  private Registry registry;
-
   private CpuMeter cpuMeter;
 
   private NetMeter netMeter;
 
-  public OsMeter(Registry registry, EventBus eventBus) {
-    this.registry = registry;
+  public OsMeter(Registry registry) {
     this.id = registry.createId(OS_NAME);
 
     cpuMeter = new CpuMeter(id.withTag(OS_TYPE, OS_TYPE_CPU));
     netMeter = new NetMeter(id.withTag(OS_TYPE, OS_TYPE_NET));
-
-    eventBus.register(this);
-  }
-
-  @Subscribe
-  public void calcMeasurements(PollEvent pollEvent) {
-    final long now = registry.clock().wallTime();
-
-    final List<Measurement> tmpCpuMeasurements = new ArrayList<>();
-    cpuMeter.calcMeasurements(tmpCpuMeasurements, now);
-    netMeter.calcMeasurements(tmpCpuMeasurements, now, pollEvent);
-
-    measurements = tmpCpuMeasurements;
-  }
-
-  @Override
-  public Id id() {
-    return id;
   }
 
   @Override
-  public Iterable<Measurement> measure() {
-    return measurements;
+  public void calcMeasurements(long msNow, long secondInterval) {
+    List<Measurement> measurements = new ArrayList<>();
+    calcMeasurements(measurements, msNow, secondInterval);
+    allMeasurements = measurements;
   }
 
   @Override
-  public boolean hasExpired() {
-    return false;
+  public void calcMeasurements(List<Measurement> measurements, long msNow, long secondInterval) {
+    cpuMeter.calcMeasurements(measurements, msNow);
+    netMeter.calcMeasurements(measurements, msNow, secondInterval);
   }
 
+  @VisibleForTesting
   public CpuMeter getCpuMeter() {
     return cpuMeter;
   }
 
+  @VisibleForTesting
   public NetMeter getNetMeter() {
     return netMeter;
   }
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/DefaultLogPublisher.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/DefaultLogPublisher.java
index 6052f7eb9..8259ff988 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/DefaultLogPublisher.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/DefaultLogPublisher.java
@@ -28,6 +28,7 @@
 import org.apache.servicecomb.foundation.metrics.PolledEvent;
 import org.apache.servicecomb.foundation.metrics.publish.spectator.MeasurementNode;
 import org.apache.servicecomb.foundation.metrics.publish.spectator.MeasurementTree;
+import org.apache.servicecomb.foundation.metrics.registry.GlobalRegistry;
 import org.apache.servicecomb.foundation.vertx.VertxUtils;
 import org.apache.servicecomb.metrics.core.meter.invocation.MeterInvocationConst;
 import org.apache.servicecomb.metrics.core.meter.os.NetMeter;
@@ -44,7 +45,6 @@
 import com.google.common.eventbus.EventBus;
 import com.google.common.eventbus.Subscribe;
 import com.netflix.config.DynamicPropertyFactory;
-import com.netflix.spectator.api.CompositeRegistry;
 import com.netflix.spectator.api.Meter;
 
 import io.vertx.core.impl.VertxImplEx;
@@ -56,30 +56,30 @@
 
   //sample
   private static final String SIMPLE_HEADER = "%s:\n  simple:\n"
-      + "    status          tps           latency                                    operation\n";
+      + "    status          tps      latency             operation\n";
 
-  private static final String FIRST_LINE_SIMPLE_FORMAT = "    %-15s %-13s %-42s %s\n";
+  private static final String FIRST_LINE_SIMPLE_FORMAT = "    %-15s %-8s %-19s %s\n";
 
-  private static final String SIMPLE_FORMAT = "                    %-13s %-42s %s\n";
+  private static final String SIMPLE_FORMAT = "                    %-8s %-19s %s\n";
 
   //details
-  private static final String PRODUCER_DETAILS_FORMAT =
-      "        prepare: %-22s queue       : %-22s filtersReq : %-22s handlersReq: %s\n"
-          + "        execute: %-22s handlersResp: %-22s filtersResp: %-22s sendResp   : %s\n";
+  private static final String PRODUCER_DETAILS_FORMAT = ""
+      + "        prepare: %-19s queue       : %-19s filtersReq : %-19s handlersReq: %s\n"
+      + "        execute: %-19s handlersResp: %-19s filtersResp: %-19s sendResp   : %s\n";
 
-  private static final String CONSUMER_DETAILS_FORMAT =
-      "        prepare          : %-22s handlersReq : %-22s clientFiltersReq: %-22s sendReq     : %s\n"
-          + "        getConnect       : %-22s writeBuf    : %-22s waitResp        : %-22s wakeConsumer: %s\n"
-          + "        clientFiltersResp: %-22s handlersResp: %s\n";
+  private static final String CONSUMER_DETAILS_FORMAT = ""
+      + "        prepare     : %-19s handlersReq : %-19s cFiltersReq: %-19s sendReq     : %s\n"
+      + "        getConnect  : %-19s writeBuf    : %-19s waitResp   : %-19s wakeConsumer: %s\n"
+      + "        cFiltersResp: %-19s handlersResp: %s\n";
 
-  private static final String EDGE_DETAILS_FORMAT =
-      "        prepare          : %-22s queue       : %-22s serverFiltersReq : %-22s handlersReq : %s\n"
-          + "        clientFiltersReq : %-22s sendReq     : %-22s getConnect       : %-22s writeBuf    : %s\n"
-          + "        waitResp         : %-22s wakeConsumer: %-22s clientFiltersResp: %-22s handlersResp: %s\n"
-          + "        serverFiltersResp: %-22s sendResp    : %s\n";
+  private static final String EDGE_DETAILS_FORMAT = ""
+      + "        prepare     : %-19s queue       : %-19s sFiltersReq : %-19s handlersReq : %s\n"
+      + "        cFiltersReq : %-19s sendReq     : %-19s getConnect  : %-19s writeBuf    : %s\n"
+      + "        waitResp    : %-19s wakeConsumer: %-19s cFiltersResp: %-19s handlersResp: %s\n"
+      + "        sFiltersResp: %-19s sendResp    : %s\n";
 
   @Override
-  public void init(CompositeRegistry globalRegistry, EventBus eventBus, MetricsBootstrapConfig config) {
+  public void init(GlobalRegistry globalRegistry, EventBus eventBus, MetricsBootstrapConfig config) {
     if (!DynamicPropertyFactory.getInstance()
         .getBooleanProperty(ENABLED, false)
         .get()) {
@@ -100,17 +100,16 @@ public void onPolledEvent(PolledEvent event) {
   }
 
   protected void printLog(List<Meter> meters) {
-
     StringBuilder sb = new StringBuilder();
     sb.append("\n");
 
-    printVertxMetrics(sb);
-
     PublishModelFactory factory = new PublishModelFactory(meters);
     DefaultPublishModel model = factory.createDefaultPublishModel();
 
-    printThreadPoolMetrics(model, sb);
     printOsLog(factory.getTree(), sb);
+    printVertxMetrics(sb);
+    printThreadPoolMetrics(model, sb);
+
     printConsumerLog(model, sb);
     printProducerLog(model, sb);
     printEdgeLog(model, sb);
@@ -152,7 +151,7 @@ private void printNetLog(StringBuilder sb, MeasurementNode osNode) {
           interfaceNode.getName());
     }
     if (tmpSb.length() != 0) {
-      appendLine(sb, tmpSb.toString());
+      sb.append(tmpSb.toString());
     }
   }
 
@@ -372,7 +371,6 @@ private StringBuilder printEdgeDetailsPerf(OperationPerfGroup perfGroup) {
     PerfInfo prepare, queue, serverFiltersReq, handlersReq, clientFiltersReq, sendReq, getConnect, writeBuf,
         waitResp, wakeConsumer, clientFiltersResp, handlersResp, serverFiltersResp, sendResp;
     for (OperationPerf operationPerf : perfGroup.getOperationPerfs()) {
-
       prepare = operationPerf.findStage(MeterInvocationConst.STAGE_PREPARE);
       queue = operationPerf.findStage(MeterInvocationConst.STAGE_EXECUTOR_QUEUE);
       serverFiltersReq = operationPerf.findStage(MeterInvocationConst.STAGE_SERVER_FILTERS_REQUEST);
@@ -413,12 +411,14 @@ private StringBuilder printEdgeDetailsPerf(OperationPerfGroup perfGroup) {
   }
 
   protected void printVertxMetrics(StringBuilder sb) {
-    sb.append("vertx:\n")
-        .append("  name       eventLoopContext-created\n");
+    appendLine(sb, "vertx:");
+
+    appendLine(sb, "  instances:");
+    appendLine(sb, "    name       eventLoopContext-created");
     for (Entry<String, VertxImplEx> entry : VertxUtils.getVertxMap().entrySet()) {
-      sb.append(String.format("  %-10s %d\n",
+      appendLine(sb, "    %-10s %d",
           entry.getKey(),
-          entry.getValue().getEventLoopContextCreatedCount()));
+          entry.getValue().getEventLoopContextCreatedCount());
     }
   }
 
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/MetricsRestPublisher.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/MetricsRestPublisher.java
index 2669b375f..629b171b7 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/MetricsRestPublisher.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/MetricsRestPublisher.java
@@ -27,20 +27,22 @@
 
 import org.apache.servicecomb.foundation.metrics.MetricsBootstrapConfig;
 import org.apache.servicecomb.foundation.metrics.MetricsInitializer;
+import org.apache.servicecomb.foundation.metrics.registry.GlobalRegistry;
 
 import com.google.common.eventbus.EventBus;
-import com.netflix.spectator.api.CompositeRegistry;
 import com.netflix.spectator.api.Id;
+import com.netflix.spectator.api.Meter;
+import com.netflix.spectator.api.Registry;
 
 import io.swagger.annotations.ApiResponse;
 import io.swagger.annotations.ApiResponses;
 
 @Path("/metrics")
 public class MetricsRestPublisher implements MetricsInitializer {
-  private CompositeRegistry globalRegistry;
+  private GlobalRegistry globalRegistry;
 
   @Override
-  public void init(CompositeRegistry globalRegistry, EventBus eventBus, MetricsBootstrapConfig config) {
+  public void init(GlobalRegistry globalRegistry, EventBus eventBus, MetricsBootstrapConfig config) {
     this.globalRegistry = globalRegistry;
   }
 
@@ -56,14 +58,14 @@ public void init(CompositeRegistry globalRegistry, EventBus eventBus, MetricsBoo
     }
 
     StringBuilder sb = new StringBuilder();
-    globalRegistry
-        .iterator()
-        .forEachRemaining(meter -> {
-          meter.measure().forEach(measurement -> {
-            String key = idToString(measurement.id(), sb);
-            measurements.put(key, measurement.value());
-          });
+    for (Registry registry : globalRegistry.getRegistries()) {
+      for (Meter meter : registry) {
+        meter.measure().forEach(measurement -> {
+          String key = idToString(measurement.id(), sb);
+          measurements.put(key, measurement.value());
         });
+      }
+    }
 
     return measurements;
   }
diff --git a/metrics/metrics-core/src/main/resources/META-INF/services/org.apache.servicecomb.foundation.common.event.EventListener b/metrics/metrics-core/src/main/resources/META-INF/services/org.apache.servicecomb.foundation.common.event.EventListener
deleted file mode 100644
index b63d2988c..000000000
--- a/metrics/metrics-core/src/main/resources/META-INF/services/org.apache.servicecomb.foundation.common.event.EventListener
+++ /dev/null
@@ -1,37 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-#
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-org.apache.servicecomb.metrics.core.event.InvocationStartExecutionEventListener
-org.apache.servicecomb.metrics.core.event.InvocationStartedEventListener
-org.apache.servicecomb.metrics.core.event.InvocationFinishedEventListener
\ No newline at end of file
diff --git a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/TestDefaultRegistryInitializer.java b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/TestDefaultRegistryInitializer.java
index f5e77b092..c18aed91b 100644
--- a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/TestDefaultRegistryInitializer.java
+++ b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/TestDefaultRegistryInitializer.java
@@ -19,22 +19,20 @@
 import java.util.List;
 
 import org.apache.servicecomb.foundation.metrics.MetricsBootstrapConfig;
+import org.apache.servicecomb.foundation.metrics.registry.GlobalRegistry;
 import org.hamcrest.Matchers;
 import org.junit.Assert;
 import org.junit.Test;
 
 import com.google.common.eventbus.EventBus;
 import com.netflix.servo.DefaultMonitorRegistry;
-import com.netflix.spectator.api.CompositeRegistry;
-import com.netflix.spectator.api.ManualClock;
 import com.netflix.spectator.api.Registry;
-import com.netflix.spectator.api.SpectatorUtils;
 import com.netflix.spectator.servo.ServoRegistry;
 
 import mockit.Deencapsulation;
 
 public class TestDefaultRegistryInitializer {
-  CompositeRegistry globalRegistry = SpectatorUtils.createCompositeRegistry(new ManualClock());
+  GlobalRegistry globalRegistry = new GlobalRegistry();
 
   List<Registry> registries = Deencapsulation.getField(globalRegistry, "registries");
 
@@ -45,7 +43,7 @@ public void init() {
     registryInitializer.init(globalRegistry, new EventBus(), new MetricsBootstrapConfig());
 
     Assert.assertEquals(-10, registryInitializer.getOrder());
-    Assert.assertThat(registryInitializer.getRegistry(), Matchers.instanceOf(ServoRegistry.class));
+    Assert.assertThat(globalRegistry.getDefaultRegistry(), Matchers.instanceOf(ServoRegistry.class));
     Assert.assertEquals(1, registries.size());
     Assert.assertEquals(1, DefaultMonitorRegistry.getInstance().getRegisteredMonitors().size());
 
diff --git a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/TestInvocationMetersInitializer.java b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/TestInvocationMetersInitializer.java
index 4bc556eb0..6bb57ad54 100644
--- a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/TestInvocationMetersInitializer.java
+++ b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/TestInvocationMetersInitializer.java
@@ -21,10 +21,9 @@
 import org.apache.servicecomb.core.Const;
 import org.apache.servicecomb.core.Invocation;
 import org.apache.servicecomb.core.event.InvocationFinishEvent;
-import org.apache.servicecomb.foundation.common.utils.SPIServiceUtils;
-import org.apache.servicecomb.foundation.metrics.MetricsInitializer;
 import org.apache.servicecomb.foundation.metrics.publish.spectator.MeasurementGroupConfig;
 import org.apache.servicecomb.foundation.metrics.publish.spectator.MeasurementTree;
+import org.apache.servicecomb.foundation.metrics.registry.GlobalRegistry;
 import org.apache.servicecomb.metrics.core.meter.invocation.MeterInvocationConst;
 import org.apache.servicecomb.swagger.invocation.InvocationType;
 import org.apache.servicecomb.swagger.invocation.Response;
@@ -42,7 +41,9 @@
 public class TestInvocationMetersInitializer {
   EventBus eventBus = new EventBus();
 
-  Registry registry = new DefaultRegistry(new ManualClock());
+  GlobalRegistry globalRegistry = new GlobalRegistry(new ManualClock());
+
+  Registry registry = new DefaultRegistry(globalRegistry.getClock());
 
   InvocationMetersInitializer invocationMetersInitializer = new InvocationMetersInitializer();
 
@@ -52,20 +53,10 @@
   @Mocked
   Response response;
 
-  @Mocked
-  DefaultRegistryInitializer defaultRegistryInitializer;
-
   @Before
   public void setup() {
-    new Expectations(SPIServiceUtils.class) {
-      {
-        SPIServiceUtils.getTargetService(MetricsInitializer.class, DefaultRegistryInitializer.class);
-        result = defaultRegistryInitializer;
-        defaultRegistryInitializer.getRegistry();
-        result = registry;
-      }
-    };
-    invocationMetersInitializer.init(null, eventBus, null);
+    globalRegistry.add(registry);
+    invocationMetersInitializer.init(globalRegistry, eventBus, null);
   }
 
   @Test
@@ -111,32 +102,44 @@ public void consumerInvocation(@Mocked InvocationFinishEvent event) {
     eventBus.post(event);
     eventBus.post(event);
 
+    globalRegistry.poll(1);
+
     MeasurementTree tree = new MeasurementTree();
     tree.from(registry.iterator(), new MeasurementGroupConfig(MeterInvocationConst.INVOCATION_NAME));
-    assertEquals(
-        "[Measurement(servicecomb.invocation:operation=m.s.o:role=CONSUMER:stage=consumer_wait_response:statistic=count:status=0:transport=rest,0,2.0), "
-            + "Measurement(servicecomb.invocation:operation=m.s.o:role=CONSUMER:stage=consumer_wait_response:statistic=totalTime:status=0:transport=rest,0,18.0), "
-            + "Measurement(servicecomb.invocation:operation=m.s.o:role=CONSUMER:stage=consumer_write_to_buf:statistic=count:status=0:transport=rest,0,2.0), "
-            + "Measurement(servicecomb.invocation:operation=m.s.o:role=CONSUMER:stage=consumer_write_to_buf:statistic=totalTime:status=0:transport=rest,0,10.0), "
-            + "Measurement(servicecomb.invocation:operation=m.s.o:role=CONSUMER:stage=client_filters_request:statistic=count:status=0:transport=rest,0,2.0), "
-            + "Measurement(servicecomb.invocation:operation=m.s.o:role=CONSUMER:stage=client_filters_request:statistic=totalTime:status=0:transport=rest,0,18.0), "
-            + "Measurement(servicecomb.invocation:operation=m.s.o:role=CONSUMER:stage=total:statistic=count:status=0:transport=rest,0,2.0), "
-            + "Measurement(servicecomb.invocation:operation=m.s.o:role=CONSUMER:stage=total:statistic=totalTime:status=0:transport=rest,0,18.0), "
-            + "Measurement(servicecomb.invocation:operation=m.s.o:role=CONSUMER:stage=client_filters_response:statistic=count:status=0:transport=rest,0,2.0), "
-            + "Measurement(servicecomb.invocation:operation=m.s.o:role=CONSUMER:stage=client_filters_response:statistic=totalTime:status=0:transport=rest,0,18.0), "
-            + "Measurement(servicecomb.invocation:operation=m.s.o:role=CONSUMER:stage=consumer_send_request:statistic=count:status=0:transport=rest,0,2.0), "
-            + "Measurement(servicecomb.invocation:operation=m.s.o:role=CONSUMER:stage=consumer_send_request:statistic=totalTime:status=0:transport=rest,0,18.0), "
+    assertEquals(""
+            + "[Measurement(servicecomb.invocation:operation=m.s.o:role=CONSUMER:stage=total:statistic=count:status=0:transport=rest,0,2.0), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=CONSUMER:stage=total:statistic=totalTime:status=0:transport=rest,0,1.8000000000000002E-8), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=CONSUMER:stage=total:statistic=max:status=0:transport=rest,0,9.000000000000001E-9), "
             + "Measurement(servicecomb.invocation:operation=m.s.o:role=CONSUMER:stage=handlers_request:statistic=count:status=0:transport=rest,0,2.0), "
-            + "Measurement(servicecomb.invocation:operation=m.s.o:role=CONSUMER:stage=handlers_request:statistic=totalTime:status=0:transport=rest,0,18.0), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=CONSUMER:stage=handlers_request:statistic=totalTime:status=0:transport=rest,0,1.8000000000000002E-8), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=CONSUMER:stage=handlers_request:statistic=max:status=0:transport=rest,0,9.000000000000001E-9), "
             + "Measurement(servicecomb.invocation:operation=m.s.o:role=CONSUMER:stage=handlers_response:statistic=count:status=0:transport=rest,0,2.0), "
-            + "Measurement(servicecomb.invocation:operation=m.s.o:role=CONSUMER:stage=handlers_response:statistic=totalTime:status=0:transport=rest,0,18.0), "
-            + "Measurement(servicecomb.invocation:operation=m.s.o:role=CONSUMER:stage=consumer_wake_consumer:statistic=count:status=0:transport=rest,0,2.0), "
-            + "Measurement(servicecomb.invocation:operation=m.s.o:role=CONSUMER:stage=consumer_wake_consumer:statistic=totalTime:status=0:transport=rest,0,18.0), "
-            + "Measurement(servicecomb.invocation:operation=m.s.o:role=CONSUMER:stage=consumer_get_connection:statistic=count:status=0:transport=rest,0,2.0), "
-            + "Measurement(servicecomb.invocation:operation=m.s.o:role=CONSUMER:stage=consumer_get_connection:statistic=totalTime:status=0:transport=rest,0,8.0), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=CONSUMER:stage=handlers_response:statistic=totalTime:status=0:transport=rest,0,1.8000000000000002E-8), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=CONSUMER:stage=handlers_response:statistic=max:status=0:transport=rest,0,9.000000000000001E-9), "
             + "Measurement(servicecomb.invocation:operation=m.s.o:role=CONSUMER:stage=prepare:statistic=count:status=0:transport=rest,0,2.0), "
-            + "Measurement(servicecomb.invocation:operation=m.s.o:role=CONSUMER:stage=prepare:statistic=totalTime:status=0:transport=rest,0,18.0)]"
-        ,
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=CONSUMER:stage=prepare:statistic=totalTime:status=0:transport=rest,0,1.8000000000000002E-8), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=CONSUMER:stage=prepare:statistic=max:status=0:transport=rest,0,9.000000000000001E-9), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=CONSUMER:stage=client_filters_request:statistic=count:status=0:transport=rest,0,2.0), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=CONSUMER:stage=client_filters_request:statistic=totalTime:status=0:transport=rest,0,1.8000000000000002E-8), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=CONSUMER:stage=client_filters_request:statistic=max:status=0:transport=rest,0,9.000000000000001E-9), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=CONSUMER:stage=consumer_send_request:statistic=count:status=0:transport=rest,0,2.0), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=CONSUMER:stage=consumer_send_request:statistic=totalTime:status=0:transport=rest,0,1.8000000000000002E-8), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=CONSUMER:stage=consumer_send_request:statistic=max:status=0:transport=rest,0,9.000000000000001E-9), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=CONSUMER:stage=consumer_get_connection:statistic=count:status=0:transport=rest,0,2.0), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=CONSUMER:stage=consumer_get_connection:statistic=totalTime:status=0:transport=rest,0,8.0E-9), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=CONSUMER:stage=consumer_get_connection:statistic=max:status=0:transport=rest,0,4.0E-9), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=CONSUMER:stage=consumer_write_to_buf:statistic=count:status=0:transport=rest,0,2.0), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=CONSUMER:stage=consumer_write_to_buf:statistic=totalTime:status=0:transport=rest,0,1.0E-8), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=CONSUMER:stage=consumer_write_to_buf:statistic=max:status=0:transport=rest,0,5.0E-9), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=CONSUMER:stage=consumer_wait_response:statistic=count:status=0:transport=rest,0,2.0), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=CONSUMER:stage=consumer_wait_response:statistic=totalTime:status=0:transport=rest,0,1.8000000000000002E-8), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=CONSUMER:stage=consumer_wait_response:statistic=max:status=0:transport=rest,0,9.000000000000001E-9), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=CONSUMER:stage=consumer_wake_consumer:statistic=count:status=0:transport=rest,0,2.0), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=CONSUMER:stage=consumer_wake_consumer:statistic=totalTime:status=0:transport=rest,0,1.8000000000000002E-8), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=CONSUMER:stage=consumer_wake_consumer:statistic=max:status=0:transport=rest,0,9.000000000000001E-9), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=CONSUMER:stage=client_filters_response:statistic=count:status=0:transport=rest,0,2.0), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=CONSUMER:stage=client_filters_response:statistic=totalTime:status=0:transport=rest,0,1.8000000000000002E-8), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=CONSUMER:stage=client_filters_response:statistic=max:status=0:transport=rest,0,9.000000000000001E-9)]",
         tree.findChild(MeterInvocationConst.INVOCATION_NAME).getMeasurements().toString());
   }
 
@@ -190,40 +193,56 @@ public void edgeInvocation(@Mocked InvocationFinishEvent event) {
     eventBus.post(event);
     eventBus.post(event);
 
+    globalRegistry.poll(1);
+
     MeasurementTree tree = new MeasurementTree();
     tree.from(registry.iterator(), new MeasurementGroupConfig(MeterInvocationConst.INVOCATION_NAME));
-    assertEquals(
-        "[Measurement(servicecomb.invocation:operation=m.s.o:role=EDGE:stage=consumer_send_request:statistic=count:status=0:transport=rest,0,2.0), "
-            + "Measurement(servicecomb.invocation:operation=m.s.o:role=EDGE:stage=consumer_send_request:statistic=totalTime:status=0:transport=rest,0,18.0), "
-            + "Measurement(servicecomb.invocation:operation=m.s.o:role=EDGE:stage=server_filters_response:statistic=count:status=0:transport=rest,0,2.0), "
-            + "Measurement(servicecomb.invocation:operation=m.s.o:role=EDGE:stage=server_filters_response:statistic=totalTime:status=0:transport=rest,0,18.0), "
-            + "Measurement(servicecomb.invocation:operation=m.s.o:role=EDGE:stage=total:statistic=count:status=0:transport=rest,0,2.0), "
-            + "Measurement(servicecomb.invocation:operation=m.s.o:role=EDGE:stage=total:statistic=totalTime:status=0:transport=rest,0,18.0), "
+    assertEquals(""
+            + "[Measurement(servicecomb.invocation:operation=m.s.o:role=EDGE:stage=total:statistic=count:status=0:transport=rest,0,2.0), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=EDGE:stage=total:statistic=totalTime:status=0:transport=rest,0,1.8000000000000002E-8), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=EDGE:stage=total:statistic=max:status=0:transport=rest,0,9.000000000000001E-9), "
             + "Measurement(servicecomb.invocation:operation=m.s.o:role=EDGE:stage=handlers_request:statistic=count:status=0:transport=rest,0,2.0), "
-            + "Measurement(servicecomb.invocation:operation=m.s.o:role=EDGE:stage=handlers_request:statistic=totalTime:status=0:transport=rest,0,18.0), "
-            + "Measurement(servicecomb.invocation:operation=m.s.o:role=EDGE:stage=consumer_wake_consumer:statistic=count:status=0:transport=rest,0,2.0), "
-            + "Measurement(servicecomb.invocation:operation=m.s.o:role=EDGE:stage=consumer_wake_consumer:statistic=totalTime:status=0:transport=rest,0,18.0), "
-            + "Measurement(servicecomb.invocation:operation=m.s.o:role=EDGE:stage=client_filters_response:statistic=count:status=0:transport=rest,0,2.0), "
-            + "Measurement(servicecomb.invocation:operation=m.s.o:role=EDGE:stage=client_filters_response:statistic=totalTime:status=0:transport=rest,0,18.0), "
-            + "Measurement(servicecomb.invocation:operation=m.s.o:role=EDGE:stage=producer_send_response:statistic=count:status=0:transport=rest,0,2.0), "
-            + "Measurement(servicecomb.invocation:operation=m.s.o:role=EDGE:stage=producer_send_response:statistic=totalTime:status=0:transport=rest,0,18.0), "
-            + "Measurement(servicecomb.invocation:operation=m.s.o:role=EDGE:stage=consumer_write_to_buf:statistic=count:status=0:transport=rest,0,2.0), "
-            + "Measurement(servicecomb.invocation:operation=m.s.o:role=EDGE:stage=consumer_write_to_buf:statistic=totalTime:status=0:transport=rest,0,10.0), "
-            + "Measurement(servicecomb.invocation:operation=m.s.o:role=EDGE:stage=server_filters_request:statistic=count:status=0:transport=rest,0,2.0), "
-            + "Measurement(servicecomb.invocation:operation=m.s.o:role=EDGE:stage=server_filters_request:statistic=totalTime:status=0:transport=rest,0,18.0), "
-            + "Measurement(servicecomb.invocation:operation=m.s.o:role=EDGE:stage=queue:statistic=count:status=0:transport=rest,0,2.0), "
-            + "Measurement(servicecomb.invocation:operation=m.s.o:role=EDGE:stage=queue:statistic=totalTime:status=0:transport=rest,0,18.0), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=EDGE:stage=handlers_request:statistic=totalTime:status=0:transport=rest,0,1.8000000000000002E-8), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=EDGE:stage=handlers_request:statistic=max:status=0:transport=rest,0,9.000000000000001E-9), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=EDGE:stage=handlers_response:statistic=count:status=0:transport=rest,0,2.0), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=EDGE:stage=handlers_response:statistic=totalTime:status=0:transport=rest,0,1.8000000000000002E-8), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=EDGE:stage=handlers_response:statistic=max:status=0:transport=rest,0,9.000000000000001E-9), "
             + "Measurement(servicecomb.invocation:operation=m.s.o:role=EDGE:stage=prepare:statistic=count:status=0:transport=rest,0,2.0), "
-            + "Measurement(servicecomb.invocation:operation=m.s.o:role=EDGE:stage=prepare:statistic=totalTime:status=0:transport=rest,0,18.0), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=EDGE:stage=prepare:statistic=totalTime:status=0:transport=rest,0,1.8000000000000002E-8), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=EDGE:stage=prepare:statistic=max:status=0:transport=rest,0,9.000000000000001E-9), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=EDGE:stage=client_filters_request:statistic=count:status=0:transport=rest,0,2.0), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=EDGE:stage=client_filters_request:statistic=totalTime:status=0:transport=rest,0,1.8000000000000002E-8), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=EDGE:stage=client_filters_request:statistic=max:status=0:transport=rest,0,9.000000000000001E-9), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=EDGE:stage=consumer_send_request:statistic=count:status=0:transport=rest,0,2.0), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=EDGE:stage=consumer_send_request:statistic=totalTime:status=0:transport=rest,0,1.8000000000000002E-8), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=EDGE:stage=consumer_send_request:statistic=max:status=0:transport=rest,0,9.000000000000001E-9), "
             + "Measurement(servicecomb.invocation:operation=m.s.o:role=EDGE:stage=consumer_get_connection:statistic=count:status=0:transport=rest,0,2.0), "
-            + "Measurement(servicecomb.invocation:operation=m.s.o:role=EDGE:stage=consumer_get_connection:statistic=totalTime:status=0:transport=rest,0,8.0), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=EDGE:stage=consumer_get_connection:statistic=totalTime:status=0:transport=rest,0,8.0E-9), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=EDGE:stage=consumer_get_connection:statistic=max:status=0:transport=rest,0,4.0E-9), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=EDGE:stage=consumer_write_to_buf:statistic=count:status=0:transport=rest,0,2.0), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=EDGE:stage=consumer_write_to_buf:statistic=totalTime:status=0:transport=rest,0,1.0E-8), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=EDGE:stage=consumer_write_to_buf:statistic=max:status=0:transport=rest,0,5.0E-9), "
             + "Measurement(servicecomb.invocation:operation=m.s.o:role=EDGE:stage=consumer_wait_response:statistic=count:status=0:transport=rest,0,2.0), "
-            + "Measurement(servicecomb.invocation:operation=m.s.o:role=EDGE:stage=consumer_wait_response:statistic=totalTime:status=0:transport=rest,0,18.0), "
-            + "Measurement(servicecomb.invocation:operation=m.s.o:role=EDGE:stage=handlers_response:statistic=count:status=0:transport=rest,0,2.0), "
-            + "Measurement(servicecomb.invocation:operation=m.s.o:role=EDGE:stage=handlers_response:statistic=totalTime:status=0:transport=rest,0,18.0), "
-            + "Measurement(servicecomb.invocation:operation=m.s.o:role=EDGE:stage=client_filters_request:statistic=count:status=0:transport=rest,0,2.0), "
-            + "Measurement(servicecomb.invocation:operation=m.s.o:role=EDGE:stage=client_filters_request:statistic=totalTime:status=0:transport=rest,0,18.0)]"
-        ,
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=EDGE:stage=consumer_wait_response:statistic=totalTime:status=0:transport=rest,0,1.8000000000000002E-8), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=EDGE:stage=consumer_wait_response:statistic=max:status=0:transport=rest,0,9.000000000000001E-9), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=EDGE:stage=consumer_wake_consumer:statistic=count:status=0:transport=rest,0,2.0), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=EDGE:stage=consumer_wake_consumer:statistic=totalTime:status=0:transport=rest,0,1.8000000000000002E-8), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=EDGE:stage=consumer_wake_consumer:statistic=max:status=0:transport=rest,0,9.000000000000001E-9), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=EDGE:stage=client_filters_response:statistic=count:status=0:transport=rest,0,2.0), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=EDGE:stage=client_filters_response:statistic=totalTime:status=0:transport=rest,0,1.8000000000000002E-8), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=EDGE:stage=client_filters_response:statistic=max:status=0:transport=rest,0,9.000000000000001E-9), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=EDGE:stage=queue:statistic=count:status=0:transport=rest,0,2.0), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=EDGE:stage=queue:statistic=totalTime:status=0:transport=rest,0,1.8000000000000002E-8), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=EDGE:stage=queue:statistic=max:status=0:transport=rest,0,9.000000000000001E-9), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=EDGE:stage=server_filters_request:statistic=count:status=0:transport=rest,0,2.0), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=EDGE:stage=server_filters_request:statistic=totalTime:status=0:transport=rest,0,1.8000000000000002E-8), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=EDGE:stage=server_filters_request:statistic=max:status=0:transport=rest,0,9.000000000000001E-9), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=EDGE:stage=server_filters_response:statistic=count:status=0:transport=rest,0,2.0), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=EDGE:stage=server_filters_response:statistic=totalTime:status=0:transport=rest,0,1.8000000000000002E-8), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=EDGE:stage=server_filters_response:statistic=max:status=0:transport=rest,0,9.000000000000001E-9), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=EDGE:stage=producer_send_response:statistic=count:status=0:transport=rest,0,2.0), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=EDGE:stage=producer_send_response:statistic=totalTime:status=0:transport=rest,0,1.8000000000000002E-8), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=EDGE:stage=producer_send_response:statistic=max:status=0:transport=rest,0,9.000000000000001E-9)]",
         tree.findChild(MeterInvocationConst.INVOCATION_NAME).getMeasurements().toString());
   }
 
@@ -265,28 +284,38 @@ public void producerInvocation(@Mocked InvocationFinishEvent event) {
     eventBus.post(event);
     eventBus.post(event);
 
+    globalRegistry.poll(1);
+
     MeasurementTree tree = new MeasurementTree();
     tree.from(registry.iterator(), new MeasurementGroupConfig(MeterInvocationConst.INVOCATION_NAME));
-    assertEquals(
-        "[Measurement(servicecomb.invocation:operation=m.s.o:role=PRODUCER:stage=execution:statistic=count:status=0:transport=rest,0,2.0), "
-            + "Measurement(servicecomb.invocation:operation=m.s.o:role=PRODUCER:stage=execution:statistic=totalTime:status=0:transport=rest,0,18.0), "
-            + "Measurement(servicecomb.invocation:operation=m.s.o:role=PRODUCER:stage=prepare:statistic=count:status=0:transport=rest,0,2.0), "
-            + "Measurement(servicecomb.invocation:operation=m.s.o:role=PRODUCER:stage=prepare:statistic=totalTime:status=0:transport=rest,0,18.0), "
-            + "Measurement(servicecomb.invocation:operation=m.s.o:role=PRODUCER:stage=total:statistic=count:status=0:transport=rest,0,2.0), "
-            + "Measurement(servicecomb.invocation:operation=m.s.o:role=PRODUCER:stage=total:statistic=totalTime:status=0:transport=rest,0,18.0), "
+    assertEquals(""
+            + "[Measurement(servicecomb.invocation:operation=m.s.o:role=PRODUCER:stage=total:statistic=count:status=0:transport=rest,0,2.0), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=PRODUCER:stage=total:statistic=totalTime:status=0:transport=rest,0,1.8000000000000002E-8), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=PRODUCER:stage=total:statistic=max:status=0:transport=rest,0,9.000000000000001E-9), "
             + "Measurement(servicecomb.invocation:operation=m.s.o:role=PRODUCER:stage=handlers_request:statistic=count:status=0:transport=rest,0,2.0), "
-            + "Measurement(servicecomb.invocation:operation=m.s.o:role=PRODUCER:stage=handlers_request:statistic=totalTime:status=0:transport=rest,0,18.0), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=PRODUCER:stage=handlers_request:statistic=totalTime:status=0:transport=rest,0,1.8000000000000002E-8), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=PRODUCER:stage=handlers_request:statistic=max:status=0:transport=rest,0,9.000000000000001E-9), "
             + "Measurement(servicecomb.invocation:operation=m.s.o:role=PRODUCER:stage=handlers_response:statistic=count:status=0:transport=rest,0,2.0), "
-            + "Measurement(servicecomb.invocation:operation=m.s.o:role=PRODUCER:stage=handlers_response:statistic=totalTime:status=0:transport=rest,0,18.0), "
-            + "Measurement(servicecomb.invocation:operation=m.s.o:role=PRODUCER:stage=producer_send_response:statistic=count:status=0:transport=rest,0,2.0), "
-            + "Measurement(servicecomb.invocation:operation=m.s.o:role=PRODUCER:stage=producer_send_response:statistic=totalTime:status=0:transport=rest,0,18.0), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=PRODUCER:stage=handlers_response:statistic=totalTime:status=0:transport=rest,0,1.8000000000000002E-8), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=PRODUCER:stage=handlers_response:statistic=max:status=0:transport=rest,0,9.000000000000001E-9), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=PRODUCER:stage=prepare:statistic=count:status=0:transport=rest,0,2.0), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=PRODUCER:stage=prepare:statistic=totalTime:status=0:transport=rest,0,1.8000000000000002E-8), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=PRODUCER:stage=prepare:statistic=max:status=0:transport=rest,0,9.000000000000001E-9), "
             + "Measurement(servicecomb.invocation:operation=m.s.o:role=PRODUCER:stage=queue:statistic=count:status=0:transport=rest,0,2.0), "
-            + "Measurement(servicecomb.invocation:operation=m.s.o:role=PRODUCER:stage=queue:statistic=totalTime:status=0:transport=rest,0,18.0), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=PRODUCER:stage=queue:statistic=totalTime:status=0:transport=rest,0,1.8000000000000002E-8), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=PRODUCER:stage=queue:statistic=max:status=0:transport=rest,0,9.000000000000001E-9), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=PRODUCER:stage=execution:statistic=count:status=0:transport=rest,0,2.0), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=PRODUCER:stage=execution:statistic=totalTime:status=0:transport=rest,0,1.8000000000000002E-8), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=PRODUCER:stage=execution:statistic=max:status=0:transport=rest,0,9.000000000000001E-9), "
             + "Measurement(servicecomb.invocation:operation=m.s.o:role=PRODUCER:stage=server_filters_request:statistic=count:status=0:transport=rest,0,2.0), "
-            + "Measurement(servicecomb.invocation:operation=m.s.o:role=PRODUCER:stage=server_filters_request:statistic=totalTime:status=0:transport=rest,0,18.0), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=PRODUCER:stage=server_filters_request:statistic=totalTime:status=0:transport=rest,0,1.8000000000000002E-8), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=PRODUCER:stage=server_filters_request:statistic=max:status=0:transport=rest,0,9.000000000000001E-9), "
             + "Measurement(servicecomb.invocation:operation=m.s.o:role=PRODUCER:stage=server_filters_response:statistic=count:status=0:transport=rest,0,2.0), "
-            + "Measurement(servicecomb.invocation:operation=m.s.o:role=PRODUCER:stage=server_filters_response:statistic=totalTime:status=0:transport=rest,0,18.0)]"
-        ,
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=PRODUCER:stage=server_filters_response:statistic=totalTime:status=0:transport=rest,0,1.8000000000000002E-8), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=PRODUCER:stage=server_filters_response:statistic=max:status=0:transport=rest,0,9.000000000000001E-9), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=PRODUCER:stage=producer_send_response:statistic=count:status=0:transport=rest,0,2.0), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=PRODUCER:stage=producer_send_response:statistic=totalTime:status=0:transport=rest,0,1.8000000000000002E-8), "
+            + "Measurement(servicecomb.invocation:operation=m.s.o:role=PRODUCER:stage=producer_send_response:statistic=max:status=0:transport=rest,0,9.000000000000001E-9)]",
         tree.findChild(MeterInvocationConst.INVOCATION_NAME).getMeasurements().toString());
   }
 }
diff --git a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/TestOsMeterInitializer.java b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/TestOsMeterInitializer.java
index db266af9b..bb73bd13e 100644
--- a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/TestOsMeterInitializer.java
+++ b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/TestOsMeterInitializer.java
@@ -25,8 +25,7 @@
 import org.apache.commons.io.FileUtils;
 import org.apache.commons.lang3.SystemUtils;
 import org.apache.servicecomb.foundation.common.utils.ReflectUtils;
-import org.apache.servicecomb.foundation.common.utils.SPIServiceUtils;
-import org.apache.servicecomb.foundation.metrics.MetricsInitializer;
+import org.apache.servicecomb.foundation.metrics.registry.GlobalRegistry;
 import org.apache.servicecomb.metrics.core.meter.os.CpuMeter;
 import org.apache.servicecomb.metrics.core.meter.os.NetMeter;
 import org.apache.servicecomb.metrics.core.meter.os.NetMeter.InterfaceInfo;
@@ -47,16 +46,15 @@
 import mockit.Mocked;
 
 public class TestOsMeterInitializer {
-  private Registry registry = new DefaultRegistry(new ManualClock());
+  GlobalRegistry globalRegistry = new GlobalRegistry(new ManualClock());
 
-  @Mocked
-  private DefaultRegistryInitializer defaultRegistryInitializer;
-
-  @Mocked
-  private EventBus eventBus;
+  Registry registry = new DefaultRegistry(globalRegistry.getClock());
 
   private boolean isLinux;
 
+  @Mocked
+  EventBus eventBus;
+
   @Before
   public void beforeTest() {
     isLinux = SystemUtils.IS_OS_LINUX;
@@ -65,14 +63,6 @@ public void beforeTest() {
   @Test
   public void init(@Mocked Runtime runtime) {
     ReflectUtils.setField(SystemUtils.class, null, "IS_OS_LINUX", true);
-    new Expectations(SPIServiceUtils.class) {
-      {
-        SPIServiceUtils.getTargetService(MetricsInitializer.class, DefaultRegistryInitializer.class);
-        result = defaultRegistryInitializer;
-        defaultRegistryInitializer.getRegistry();
-        result = registry;
-      }
-    };
     List<String> list = new ArrayList<>();
     list.add("cpu  1 1 1 1 1 1 1 1 0 0");
     list.add("useless");
@@ -95,8 +85,9 @@ public Runtime getRuntime() {
         result = 2;
       }
     };
+    globalRegistry.add(registry);
     OsMetersInitializer osMetersInitializer = new OsMetersInitializer();
-    osMetersInitializer.init(null, eventBus, null);
+    osMetersInitializer.init(globalRegistry, eventBus, null);
     OsMeter osMeter = osMetersInitializer.getOsMeter();
     Assert.assertNotNull(osMeter);
     Assert.assertNotNull(osMeter.getCpuMeter());
diff --git a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/TestThreadPoolMetersInitializer.java b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/TestThreadPoolMetersInitializer.java
index 378743de2..4942ccfbf 100644
--- a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/TestThreadPoolMetersInitializer.java
+++ b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/TestThreadPoolMetersInitializer.java
@@ -23,6 +23,7 @@
 import java.util.Map;
 import java.util.concurrent.BlockingQueue;
 import java.util.concurrent.Executor;
+import java.util.concurrent.ExecutorService;
 import java.util.concurrent.RunnableScheduledFuture;
 import java.util.concurrent.ScheduledThreadPoolExecutor;
 import java.util.concurrent.ThreadPoolExecutor;
@@ -33,31 +34,31 @@
 import org.apache.servicecomb.core.definition.OperationMeta;
 import org.apache.servicecomb.core.executor.FixedThreadExecutor;
 import org.apache.servicecomb.foundation.common.utils.BeanUtils;
-import org.apache.servicecomb.foundation.common.utils.SPIServiceUtils;
-import org.apache.servicecomb.foundation.metrics.MetricsInitializer;
+import org.apache.servicecomb.foundation.metrics.registry.GlobalRegistry;
 import org.hamcrest.Matchers;
 import org.junit.Assert;
 import org.junit.Test;
+import org.mockito.Mockito;
 import org.springframework.context.ApplicationContext;
 
 import com.netflix.spectator.api.DefaultRegistry;
 import com.netflix.spectator.api.ManualClock;
 import com.netflix.spectator.api.Registry;
+import com.netflix.spectator.api.patterns.PolledMeter;
+
 import mockit.Expectations;
 import mockit.Mock;
 import mockit.MockUp;
 import mockit.Mocked;
 
 public class TestThreadPoolMetersInitializer {
+  GlobalRegistry globalRegistry = new GlobalRegistry();
+
   Registry registry = new DefaultRegistry(new ManualClock());
 
   ThreadPoolMetersInitializer threadPoolMetersInitializer = new ThreadPoolMetersInitializer();
 
-  @Mocked
-  DefaultRegistryInitializer defaultRegistryInitializer;
-
-  @Mocked
-  ThreadPoolExecutor threadPoolExecutor;
+  ThreadPoolExecutor threadPoolExecutor = Mockito.mock(ThreadPoolExecutor.class);
 
   @Mocked
   BlockingQueue<Runnable> queue;
@@ -65,8 +66,7 @@
   @Mocked
   FixedThreadExecutor fixedThreadExecutor;
 
-  @Mocked
-  Executor executor;
+  ExecutorService executor = Mockito.mock(ExecutorService.class);
 
   @Mocked
   ApplicationContext applicationContext;
@@ -92,14 +92,6 @@ public void init() {
         result = microserviceMeta;
       }
     };
-    new Expectations(SPIServiceUtils.class) {
-      {
-        SPIServiceUtils.getTargetService(MetricsInitializer.class, DefaultRegistryInitializer.class);
-        result = defaultRegistryInitializer;
-        defaultRegistryInitializer.getRegistry();
-        result = registry;
-      }
-    };
     Map<String, Executor> beanExecutors = new HashMap<>();
     beanExecutors.put("executor", executor);
     beanExecutors.put("fixedThreadExecutor", fixedThreadExecutor);
@@ -113,6 +105,7 @@ public void init() {
       }
     };
 
+    Mockito.when(threadPoolExecutor.getQueue()).thenReturn(queue);
     new Expectations(CseContext.getInstance()) {
       {
         microserviceMeta.getOperations();
@@ -127,8 +120,6 @@ public void init() {
         fixedThreadExecutor.getExecutorList();
         result = Arrays.asList(threadPoolExecutor);
 
-        threadPoolExecutor.getQueue();
-        result = queue;
         queue.size();
         result = 10d;
       }
@@ -141,8 +132,10 @@ void delayedExecute(RunnableScheduledFuture<?> task) {
       }
     };
 
-    threadPoolMetersInitializer.init(null, null, null);
+    globalRegistry.add(registry);
+    threadPoolMetersInitializer.init(globalRegistry, null, null);
 
+    PolledMeter.update(registry);
     List<String> result = new ArrayList<>();
     registry.iterator().forEachRemaining(meter -> {
       result.add(meter.measure().toString());
diff --git a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/meter/os/TestNetMeter.java b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/meter/os/TestNetMeter.java
index 3995083cd..8caa14d5e 100644
--- a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/meter/os/TestNetMeter.java
+++ b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/meter/os/TestNetMeter.java
@@ -23,7 +23,6 @@
 import java.util.Map;
 
 import org.apache.commons.io.FileUtils;
-import org.apache.servicecomb.foundation.metrics.PollEvent;
 import org.apache.servicecomb.metrics.core.meter.os.NetMeter.InterfaceInfo;
 import org.junit.Assert;
 import org.junit.Test;
@@ -31,7 +30,6 @@
 import com.netflix.spectator.api.Id;
 import com.netflix.spectator.api.Measurement;
 
-import mockit.Expectations;
 import mockit.Mock;
 import mockit.MockUp;
 import mockit.Mocked;
@@ -52,7 +50,7 @@ public void testNetRefreshUnchanged(@Mocked Id id) {
     NetMeter netMeter = new NetMeter(id);
     list.remove(2);
     list.add("eth0: 1 1    0    0    0     0          0          1         1 1    1      0     0     0    0    0");
-    netMeter.refreshNet(1000);
+    netMeter.refreshNet(1);
     Map<String, InterfaceInfo> meterInterfaceInfoMap = netMeter.getInterfaceInfoMap();
     Assert.assertTrue(meterInterfaceInfoMap.containsKey("eth0"));
     InterfaceInfo eth0 = meterInterfaceInfoMap.get("eth0");
@@ -82,7 +80,7 @@ public void testNetRefreshAdd(@Mocked Id id) {
     list.remove(2);
     list.add("eth0: 1 1    0    0    0     0          0          1         1 1    1      0     0     0    0    0");
     list.add("lo: 0 0    0    0    0     0          0          0         0 0    0      0     0     0    0    0");
-    netMeter.refreshNet(1000);
+    netMeter.refreshNet(1);
     Assert.assertEquals(2, netMap.size());
     InterfaceInfo eth0 = netMap.get("eth0");
     Assert.assertEquals("eth0", eth0.getName());
@@ -130,7 +128,7 @@ public void testNetRefreshRemove(@Mocked Id id) {
     list.remove(2);
     list.remove(2);
     list.add("eth0: 1 1    0    0    0     0          0          1         1 1    1      0     0     0    0    0");
-    netMeter.refreshNet(1000);
+    netMeter.refreshNet(1);
     Assert.assertNull(netMap.get("lo"));
     Assert.assertEquals(1, netMap.size());
     Assert.assertEquals("eth0", eth0.getName());
@@ -142,18 +140,11 @@ public void testNetRefreshRemove(@Mocked Id id) {
 
 
   @Test
-  public void testCalcMeasurements(@Mocked Id id, @Mocked PollEvent pollEvent) {
-
+  public void testCalcMeasurements(@Mocked Id id) {
     List<String> list = new ArrayList<>();
     list.add("useless");
     list.add("useless");
     list.add("eth0: 0 0    0    0    0     0          0          0         0 0    0      0     0     0    0    0");
-    new Expectations() {
-      {
-        pollEvent.getMsPollInterval();
-        result = 1000;
-      }
-    };
     new MockUp<FileUtils>() {
       @Mock
       public List<String> readLines(File file, Charset encoding) {
@@ -164,7 +155,7 @@ public void testCalcMeasurements(@Mocked Id id, @Mocked PollEvent pollEvent) {
     list.remove(2);
     list.add("eth0: 1 1    0    0    0     0          0          1         1 1    1      0     0     0    0    0");
     List<Measurement> measurements = new ArrayList<>();
-    netMeter.calcMeasurements(measurements, 0L, pollEvent);
+    netMeter.calcMeasurements(measurements, 0L, 1);
     Assert.assertEquals(2, measurements.size());
     Measurement send = measurements.get(0);
     Measurement recv = measurements.get(1);
diff --git a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/meter/os/TestOsMeter.java b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/meter/os/TestOsMeter.java
index aa3c3ba6b..a07f22916 100644
--- a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/meter/os/TestOsMeter.java
+++ b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/meter/os/TestOsMeter.java
@@ -23,12 +23,10 @@
 import java.util.List;
 
 import org.apache.commons.io.FileUtils;
-import org.apache.servicecomb.foundation.metrics.PollEvent;
 import org.junit.Assert;
 import org.junit.Test;
 
 import com.google.common.collect.Lists;
-import com.google.common.eventbus.EventBus;
 import com.netflix.spectator.api.DefaultRegistry;
 import com.netflix.spectator.api.ManualClock;
 import com.netflix.spectator.api.Measurement;
@@ -40,12 +38,10 @@
 import mockit.Mocked;
 
 public class TestOsMeter {
-  EventBus eventBus = new EventBus();
-
   Registry registry = new DefaultRegistry(new ManualClock());
 
   @Test
-  public void testCalcMeasurement(@Mocked PollEvent pollEvent, @Mocked Runtime runtime) {
+  public void testCalcMeasurement(@Mocked Runtime runtime) {
     List<String> list = new ArrayList<>();
     list.add("cpu  1 1 1 1 1 1 1 1 0 0");
     list.add("useless");
@@ -66,16 +62,15 @@ public Runtime getRuntime() {
       {
         runtime.availableProcessors();
         result = 2;
-        pollEvent.getMsPollInterval();
-        result = 1000;
       }
     };
-    OsMeter osMeter = new OsMeter(registry, eventBus);
+    OsMeter osMeter = new OsMeter(registry);
     list.clear();
     list.add("cpu  2 2 2 2 2 2 2 2 0 0");
     list.add("useless");
     list.add("eth0: 1 1    0    0    0     0          0          1         1 1    1      0     0     0    0    0");
-    eventBus.post(pollEvent);
+
+    osMeter.calcMeasurements(1, 1);
     ArrayList<Measurement> measurements = Lists.newArrayList(osMeter.measure());
     Assert.assertEquals(3, measurements.size());
     Assert.assertEquals(1.75, measurements.get(0).value(), 0.0);
diff --git a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/TestDefaultLogPublisher.java b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/TestDefaultLogPublisher.java
index 2ad68a62a..81ab22c1f 100644
--- a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/TestDefaultLogPublisher.java
+++ b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/TestDefaultLogPublisher.java
@@ -30,6 +30,7 @@
 import org.apache.servicecomb.foundation.metrics.PolledEvent;
 import org.apache.servicecomb.foundation.metrics.publish.spectator.MeasurementNode;
 import org.apache.servicecomb.foundation.metrics.publish.spectator.MeasurementTree;
+import org.apache.servicecomb.foundation.metrics.registry.GlobalRegistry;
 import org.apache.servicecomb.foundation.test.scaffolding.config.ArchaiusUtils;
 import org.apache.servicecomb.foundation.test.scaffolding.log.LogCollector;
 import org.apache.servicecomb.foundation.vertx.VertxUtils;
@@ -47,7 +48,6 @@
 import org.junit.Test;
 
 import com.google.common.eventbus.EventBus;
-import com.netflix.spectator.api.CompositeRegistry;
 import com.netflix.spectator.api.Measurement;
 
 import io.vertx.core.impl.VertxImplEx;
@@ -57,7 +57,7 @@
 import mockit.Mocked;
 
 public class TestDefaultLogPublisher {
-  CompositeRegistry globalRegistry = null;
+  GlobalRegistry globalRegistry = new GlobalRegistry();
 
   EventBus eventBus = new EventBus();
 
@@ -145,8 +145,9 @@ public void onPolledEvent(@Mocked VertxImplEx vertxImplEx, @Mocked MeasurementTr
     DefaultPublishModel model = new DefaultPublishModel();
 
     PerfInfo perfTotal = new PerfInfo();
-    perfTotal.setTps(10);
-    perfTotal.setMsTotalTime(100);
+    perfTotal.setTps(100_0000);
+    perfTotal.setMsTotalTime(30000L * 100_0000);
+    perfTotal.setMsMaxLatency(30000);
 
     OperationPerf operationPerf = new OperationPerf();
     operationPerf.setOperation("op");
@@ -222,41 +223,42 @@ MeasurementTree getTree() {
     List<LoggingEvent> events = collector.getEvents().stream().filter(e -> {
       return DefaultLogPublisher.class.getName().equals(e.getLoggerName());
     }).collect(Collectors.toList());
+
     LoggingEvent event = events.get(0);
-    Assert.assertEquals("\n" +
-            "vertx:\n" +
-            "  name       eventLoopContext-created\n" +
-            "  v          1\n" +
-            "threadPool:\n" +
-            "  corePoolSize maxThreads poolSize currentThreadsBusy queueSize taskCount completedTaskCount name\n" +
-            "  0            0          0        0                  0         0.0       0.0                test\n" +
-            "os:\n"
+    Assert.assertEquals("\n"
+            + "os:\n"
             + "  cpu: 100.00%\n"
             + "  net:\n"
             + "    send         receive      interface\n"
-            + "    1 B          1 B          eth0\n" +
-            "\n" +
-            "consumer:\n" +
-            "  simple:\n"
-            + "    status          tps           latency                                    operation\n"
-            + "    rest.OK         10            10.000/0.000                               op\n"
-            + "                    10            10.000/0.000                               (summary)\n"
+            + "    1 B          1 B          eth0\n"
+            + "vertx:\n"
+            + "  instances:\n"
+            + "    name       eventLoopContext-created\n"
+            + "    v          1\n"
+            + "threadPool:\n"
+            + "  corePoolSize maxThreads poolSize currentThreadsBusy queueSize taskCount completedTaskCount name\n"
+            + "  0            0          0        0                  0         0.0       0.0                test\n"
+            + "consumer:\n"
+            + "  simple:\n"
+            + "    status          tps      latency             operation\n"
+            + "    rest.OK         1000000  30000.000/30000.000 op\n"
+            + "                    1000000  30000.000/30000.000 (summary)\n"
             + "  details:\n"
             + "    rest.OK:\n"
             + "      op:\n"
-            + "        prepare          : 10.000/0.000           handlersReq : 10.000/0.000           clientFiltersReq: 10.000/0.000           sendReq     : 10.000/0.000\n"
-            + "        getConnect       : 10.000/0.000           writeBuf    : 10.000/0.000           waitResp        : 10.000/0.000           wakeConsumer: 10.000/0.000\n"
-            + "        clientFiltersResp: 10.000/0.000           handlersResp: 10.000/0.000\n"
+            + "        prepare     : 30000.000/30000.000 handlersReq : 30000.000/30000.000 cFiltersReq: 30000.000/30000.000 sendReq     : 30000.000/30000.000\n"
+            + "        getConnect  : 30000.000/30000.000 writeBuf    : 30000.000/30000.000 waitResp   : 30000.000/30000.000 wakeConsumer: 30000.000/30000.000\n"
+            + "        cFiltersResp: 30000.000/30000.000 handlersResp: 30000.000/30000.000\n"
             + "producer:\n"
             + "  simple:\n"
-            + "    status          tps           latency                                    operation\n"
-            + "    rest.OK         10            10.000/0.000                               op\n"
-            + "                    10            10.000/0.000                               (summary)\n"
+            + "    status          tps      latency             operation\n"
+            + "    rest.OK         1000000  30000.000/30000.000 op\n"
+            + "                    1000000  30000.000/30000.000 (summary)\n"
             + "  details:\n"
             + "    rest.OK:\n"
             + "      op:\n"
-            + "        prepare: 10.000/0.000           queue       : 10.000/0.000           filtersReq : 10.000/0.000           handlersReq: 10.000/0.000\n"
-            + "        execute: 10.000/0.000           handlersResp: 10.000/0.000           filtersResp: 10.000/0.000           sendResp   : 10.000/0.000\n",
+            + "        prepare: 30000.000/30000.000 queue       : 30000.000/30000.000 filtersReq : 30000.000/30000.000 handlersReq: 30000.000/30000.000\n"
+            + "        execute: 30000.000/30000.000 handlersResp: 30000.000/30000.000 filtersResp: 30000.000/30000.000 sendResp   : 30000.000/30000.000\n",
         event.getMessage());
   }
 }
diff --git a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/TestInvocationPublishModelFactory.java b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/TestInvocationPublishModelFactory.java
index e284533fc..fadabdc11 100644
--- a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/TestInvocationPublishModelFactory.java
+++ b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/TestInvocationPublishModelFactory.java
@@ -20,10 +20,7 @@
 import org.apache.servicecomb.core.Invocation;
 import org.apache.servicecomb.core.event.InvocationFinishEvent;
 import org.apache.servicecomb.core.invocation.InvocationStageTrace;
-import org.apache.servicecomb.foundation.common.utils.JsonUtils;
-import org.apache.servicecomb.foundation.common.utils.SPIServiceUtils;
-import org.apache.servicecomb.foundation.metrics.MetricsInitializer;
-import org.apache.servicecomb.metrics.core.DefaultRegistryInitializer;
+import org.apache.servicecomb.foundation.metrics.registry.GlobalRegistry;
 import org.apache.servicecomb.metrics.core.InvocationMetersInitializer;
 import org.apache.servicecomb.metrics.core.publish.model.DefaultPublishModel;
 import org.apache.servicecomb.swagger.invocation.InvocationType;
@@ -31,13 +28,13 @@
 import org.junit.Assert;
 import org.junit.Test;
 
-import com.fasterxml.jackson.core.JsonProcessingException;
 import com.google.common.collect.Lists;
 import com.google.common.eventbus.EventBus;
 import com.netflix.spectator.api.DefaultRegistry;
 import com.netflix.spectator.api.ManualClock;
 import com.netflix.spectator.api.Registry;
 
+import io.vertx.core.json.Json;
 import mockit.Deencapsulation;
 import mockit.Expectations;
 import mockit.Mock;
@@ -47,10 +44,9 @@
 public class TestInvocationPublishModelFactory {
   EventBus eventBus = new EventBus();
 
-  Registry registry = new DefaultRegistry(new ManualClock());
+  GlobalRegistry globalRegistry = new GlobalRegistry();
 
-  @Mocked
-  DefaultRegistryInitializer defaultRegistryInitializer;
+  Registry registry = new DefaultRegistry(new ManualClock());
 
   InvocationMetersInitializer invocationMetersInitializer = new InvocationMetersInitializer();
 
@@ -65,27 +61,264 @@
   InvocationType invocationType;
 
   @Test
-  public void createDefaultPublishModel() throws JsonProcessingException {
-    new Expectations(SPIServiceUtils.class) {
-      {
-        SPIServiceUtils.getTargetService(MetricsInitializer.class, DefaultRegistryInitializer.class);
-        result = defaultRegistryInitializer;
-        defaultRegistryInitializer.getRegistry();
-        result = registry;
-      }
-    };
-    invocationMetersInitializer.init(null, eventBus, null);
+  public void createDefaultPublishModel() {
+    globalRegistry.add(registry);
+    invocationMetersInitializer.init(globalRegistry, eventBus, null);
     prepareInvocation();
 
+    globalRegistry.poll(1);
     PublishModelFactory factory = new PublishModelFactory(Lists.newArrayList(registry.iterator()));
     DefaultPublishModel model = factory.createDefaultPublishModel();
 
-    Assert.assertEquals(
-        "{\"operationPerfGroups\":{\"groups\":{\"rest\":{\"200\":{\"transport\":\"rest\",\"status\":\"200\",\"operationPerfs\":[{\"operation\":\"m.s.o\",\"stages\":{\"client_filters_request\":{\"tps\":1,\"msTotalTime\":1000.0,\"msMaxLatency\":0.0},\"prepare\":{\"tps\":1,\"msTotalTime\":1000.0,\"msMaxLatency\":0.0},\"consumer_send_request\":{\"tps\":1,\"msTotalTime\":2000.0,\"msMaxLatency\":0.0},\"total\":{\"tps\":1,\"msTotalTime\":14000.0,\"msMaxLatency\":0.0},\"handlers_request\":{\"tps\":1,\"msTotalTime\":1000.0,\"msMaxLatency\":0.0},\"consumer_wait_response\":{\"tps\":1,\"msTotalTime\":1000.0,\"msMaxLatency\":0.0},\"client_filters_response\":{\"tps\":1,\"msTotalTime\":1000.0,\"msMaxLatency\":0.0},\"handlers_response\":{\"tps\":1,\"msTotalTime\":3000.0,\"msMaxLatency\":0.0},\"consumer_get_connection\":{\"tps\":1,\"msTotalTime\":1000.0,\"msMaxLatency\":0.0},\"consumer_wake_consumer\":{\"tps\":1,\"msTotalTime\":1000.0,\"msMaxLatency\":0.0},\"consumer_write_to_buf\":{\"tps\":1,\"msTotalTime\":1000.0,\"msMaxLatency\":0.0}}}],\"summary\":{\"operation\":\"\",\"stages\":{\"prepare\":{\"tps\":1,\"msTotalTime\":1000.0,\"msMaxLatency\":0.0},\"client_filters_request\":{\"tps\":1,\"msTotalTime\":1000.0,\"msMaxLatency\":0.0},\"total\":{\"tps\":1,\"msTotalTime\":14000.0,\"msMaxLatency\":0.0},\"consumer_send_request\":{\"tps\":1,\"msTotalTime\":2000.0,\"msMaxLatency\":0.0},\"handlers_request\":{\"tps\":1,\"msTotalTime\":1000.0,\"msMaxLatency\":0.0},\"handlers_response\":{\"tps\":1,\"msTotalTime\":3000.0,\"msMaxLatency\":0.0},\"client_filters_response\":{\"tps\":1,\"msTotalTime\":1000.0,\"msMaxLatency\":0.0},\"consumer_wait_response\":{\"tps\":1,\"msTotalTime\":1000.0,\"msMaxLatency\":0.0},\"consumer_get_connection\":{\"tps\":1,\"msTotalTime\":1000.0,\"msMaxLatency\":0.0},\"consumer_write_to_buf\":{\"tps\":1,\"msTotalTime\":1000.0,\"msMaxLatency\":0.0},\"consumer_wake_consumer\":{\"tps\":1,\"msTotalTime\":1000.0,\"msMaxLatency\":0.0}}}}}}}}",
-        JsonUtils.writeValueAsString(model.getConsumer()));
-    Assert.assertEquals(
-        "{\"operationPerfGroups\":{\"groups\":{\"rest\":{\"200\":{\"transport\":\"rest\",\"status\":\"200\",\"operationPerfs\":[{\"operation\":\"m.s.o\",\"stages\":{\"server_filters_request\":{\"tps\":1,\"msTotalTime\":0.0,\"msMaxLatency\":0.0},\"prepare\":{\"tps\":1,\"msTotalTime\":5000.0,\"msMaxLatency\":0.0},\"execution\":{\"tps\":1,\"msTotalTime\":3000.0,\"msMaxLatency\":0.0},\"producer_send_response\":{\"tps\":1,\"msTotalTime\":2000.0,\"msMaxLatency\":0.0},\"total\":{\"tps\":1,\"msTotalTime\":14000.0,\"msMaxLatency\":0.0},\"handlers_request\":{\"tps\":1,\"msTotalTime\":6000.0,\"msMaxLatency\":0.0},\"handlers_response\":{\"tps\":1,\"msTotalTime\":1000.0,\"msMaxLatency\":0.0},\"queue\":{\"tps\":0,\"msTotalTime\":0.0,\"msMaxLatency\":0.0},\"server_filters_response\":{\"tps\":1,\"msTotalTime\":1000.0,\"msMaxLatency\":0.0}}}],\"summary\":{\"operation\":\"\",\"stages\":{\"server_filters_request\":{\"tps\":1,\"msTotalTime\":0.0,\"msMaxLatency\":0.0},\"execution\":{\"tps\":1,\"msTotalTime\":3000.0,\"msMaxLatency\":0.0},\"prepare\":{\"tps\":1,\"msTotalTime\":5000.0,\"msMaxLatency\":0.0},\"total\":{\"tps\":1,\"msTotalTime\":14000.0,\"msMaxLatency\":0.0},\"producer_send_response\":{\"tps\":1,\"msTotalTime\":2000.0,\"msMaxLatency\":0.0},\"handlers_request\":{\"tps\":1,\"msTotalTime\":6000.0,\"msMaxLatency\":0.0},\"handlers_response\":{\"tps\":1,\"msTotalTime\":1000.0,\"msMaxLatency\":0.0},\"queue\":{\"tps\":0,\"msTotalTime\":0.0,\"msMaxLatency\":0.0},\"server_filters_response\":{\"tps\":1,\"msTotalTime\":1000.0,\"msMaxLatency\":0.0}}}}}}}}",
-        JsonUtils.writeValueAsString(model.getProducer()));
+    String expect = "{\n"
+        + "  \"operationPerfGroups\" : {\n"
+        + "    \"groups\" : {\n"
+        + "      \"rest\" : {\n"
+        + "        \"200\" : {\n"
+        + "          \"transport\" : \"rest\",\n"
+        + "          \"status\" : \"200\",\n"
+        + "          \"operationPerfs\" : [ {\n"
+        + "            \"operation\" : \"m.s.o\",\n"
+        + "            \"stages\" : {\n"
+        + "              \"client_filters_request\" : {\n"
+        + "                \"tps\" : 1,\n"
+        + "                \"msTotalTime\" : 1.0000000000000002E-6,\n"
+        + "                \"msMaxLatency\" : 1.0000000000000002E-6\n"
+        + "              },\n"
+        + "              \"prepare\" : {\n"
+        + "                \"tps\" : 1,\n"
+        + "                \"msTotalTime\" : 1.0000000000000002E-6,\n"
+        + "                \"msMaxLatency\" : 1.0000000000000002E-6\n"
+        + "              },\n"
+        + "              \"consumer_send_request\" : {\n"
+        + "                \"tps\" : 1,\n"
+        + "                \"msTotalTime\" : 2.0000000000000003E-6,\n"
+        + "                \"msMaxLatency\" : 2.0000000000000003E-6\n"
+        + "              },\n"
+        + "              \"total\" : {\n"
+        + "                \"tps\" : 1,\n"
+        + "                \"msTotalTime\" : 1.4000000000000001E-5,\n"
+        + "                \"msMaxLatency\" : 1.4000000000000001E-5\n"
+        + "              },\n"
+        + "              \"handlers_request\" : {\n"
+        + "                \"tps\" : 1,\n"
+        + "                \"msTotalTime\" : 1.0000000000000002E-6,\n"
+        + "                \"msMaxLatency\" : 1.0000000000000002E-6\n"
+        + "              },\n"
+        + "              \"client_filters_response\" : {\n"
+        + "                \"tps\" : 1,\n"
+        + "                \"msTotalTime\" : 1.0000000000000002E-6,\n"
+        + "                \"msMaxLatency\" : 1.0000000000000002E-6\n"
+        + "              },\n"
+        + "              \"consumer_wait_response\" : {\n"
+        + "                \"tps\" : 1,\n"
+        + "                \"msTotalTime\" : 1.0000000000000002E-6,\n"
+        + "                \"msMaxLatency\" : 1.0000000000000002E-6\n"
+        + "              },\n"
+        + "              \"handlers_response\" : {\n"
+        + "                \"tps\" : 1,\n"
+        + "                \"msTotalTime\" : 3.0000000000000005E-6,\n"
+        + "                \"msMaxLatency\" : 3.0000000000000005E-6\n"
+        + "              },\n"
+        + "              \"consumer_get_connection\" : {\n"
+        + "                \"tps\" : 1,\n"
+        + "                \"msTotalTime\" : 1.0000000000000002E-6,\n"
+        + "                \"msMaxLatency\" : 1.0000000000000002E-6\n"
+        + "              },\n"
+        + "              \"consumer_wake_consumer\" : {\n"
+        + "                \"tps\" : 1,\n"
+        + "                \"msTotalTime\" : 1.0000000000000002E-6,\n"
+        + "                \"msMaxLatency\" : 1.0000000000000002E-6\n"
+        + "              },\n"
+        + "              \"consumer_write_to_buf\" : {\n"
+        + "                \"tps\" : 1,\n"
+        + "                \"msTotalTime\" : 1.0000000000000002E-6,\n"
+        + "                \"msMaxLatency\" : 1.0000000000000002E-6\n"
+        + "              }\n"
+        + "            }\n"
+        + "          } ],\n"
+        + "          \"summary\" : {\n"
+        + "            \"operation\" : \"\",\n"
+        + "            \"stages\" : {\n"
+        + "              \"prepare\" : {\n"
+        + "                \"tps\" : 1,\n"
+        + "                \"msTotalTime\" : 1.0000000000000002E-6,\n"
+        + "                \"msMaxLatency\" : 1.0000000000000002E-6\n"
+        + "              },\n"
+        + "              \"client_filters_request\" : {\n"
+        + "                \"tps\" : 1,\n"
+        + "                \"msTotalTime\" : 1.0000000000000002E-6,\n"
+        + "                \"msMaxLatency\" : 1.0000000000000002E-6\n"
+        + "              },\n"
+        + "              \"total\" : {\n"
+        + "                \"tps\" : 1,\n"
+        + "                \"msTotalTime\" : 1.4000000000000001E-5,\n"
+        + "                \"msMaxLatency\" : 1.4000000000000001E-5\n"
+        + "              },\n"
+        + "              \"consumer_send_request\" : {\n"
+        + "                \"tps\" : 1,\n"
+        + "                \"msTotalTime\" : 2.0000000000000003E-6,\n"
+        + "                \"msMaxLatency\" : 2.0000000000000003E-6\n"
+        + "              },\n"
+        + "              \"handlers_request\" : {\n"
+        + "                \"tps\" : 1,\n"
+        + "                \"msTotalTime\" : 1.0000000000000002E-6,\n"
+        + "                \"msMaxLatency\" : 1.0000000000000002E-6\n"
+        + "              },\n"
+        + "              \"handlers_response\" : {\n"
+        + "                \"tps\" : 1,\n"
+        + "                \"msTotalTime\" : 3.0000000000000005E-6,\n"
+        + "                \"msMaxLatency\" : 3.0000000000000005E-6\n"
+        + "              },\n"
+        + "              \"consumer_wait_response\" : {\n"
+        + "                \"tps\" : 1,\n"
+        + "                \"msTotalTime\" : 1.0000000000000002E-6,\n"
+        + "                \"msMaxLatency\" : 1.0000000000000002E-6\n"
+        + "              },\n"
+        + "              \"client_filters_response\" : {\n"
+        + "                \"tps\" : 1,\n"
+        + "                \"msTotalTime\" : 1.0000000000000002E-6,\n"
+        + "                \"msMaxLatency\" : 1.0000000000000002E-6\n"
+        + "              },\n"
+        + "              \"consumer_get_connection\" : {\n"
+        + "                \"tps\" : 1,\n"
+        + "                \"msTotalTime\" : 1.0000000000000002E-6,\n"
+        + "                \"msMaxLatency\" : 1.0000000000000002E-6\n"
+        + "              },\n"
+        + "              \"consumer_write_to_buf\" : {\n"
+        + "                \"tps\" : 1,\n"
+        + "                \"msTotalTime\" : 1.0000000000000002E-6,\n"
+        + "                \"msMaxLatency\" : 1.0000000000000002E-6\n"
+        + "              },\n"
+        + "              \"consumer_wake_consumer\" : {\n"
+        + "                \"tps\" : 1,\n"
+        + "                \"msTotalTime\" : 1.0000000000000002E-6,\n"
+        + "                \"msMaxLatency\" : 1.0000000000000002E-6\n"
+        + "              }\n"
+        + "            }\n"
+        + "          }\n"
+        + "        }\n"
+        + "      }\n"
+        + "    }\n"
+        + "  }\n"
+        + "}";
+    Assert.assertEquals(Json.encodePrettily(Json.decodeValue(expect, Object.class)),
+        Json.encodePrettily(model.getConsumer()));
+
+    expect = "{\n"
+        + "  \"operationPerfGroups\" : {\n"
+        + "    \"groups\" : {\n"
+        + "      \"rest\" : {\n"
+        + "        \"200\" : {\n"
+        + "          \"transport\" : \"rest\",\n"
+        + "          \"status\" : \"200\",\n"
+        + "          \"operationPerfs\" : [ {\n"
+        + "            \"operation\" : \"m.s.o\",\n"
+        + "            \"stages\" : {\n"
+        + "              \"server_filters_request\" : {\n"
+        + "                \"tps\" : 1,\n"
+        + "                \"msTotalTime\" : 0.0,\n"
+        + "                \"msMaxLatency\" : 0.0\n"
+        + "              },\n"
+        + "              \"execution\" : {\n"
+        + "                \"tps\" : 1,\n"
+        + "                \"msTotalTime\" : 3.0000000000000005E-6,\n"
+        + "                \"msMaxLatency\" : 3.0000000000000005E-6\n"
+        + "              },\n"
+        + "              \"prepare\" : {\n"
+        + "                \"tps\" : 1,\n"
+        + "                \"msTotalTime\" : 5.0E-6,\n"
+        + "                \"msMaxLatency\" : 5.0E-6\n"
+        + "              },\n"
+        + "              \"producer_send_response\" : {\n"
+        + "                \"tps\" : 1,\n"
+        + "                \"msTotalTime\" : 2.0000000000000003E-6,\n"
+        + "                \"msMaxLatency\" : 2.0000000000000003E-6\n"
+        + "              },\n"
+        + "              \"total\" : {\n"
+        + "                \"tps\" : 1,\n"
+        + "                \"msTotalTime\" : 1.4000000000000001E-5,\n"
+        + "                \"msMaxLatency\" : 1.4000000000000001E-5\n"
+        + "              },\n"
+        + "              \"handlers_request\" : {\n"
+        + "                \"tps\" : 1,\n"
+        + "                \"msTotalTime\" : 6.000000000000001E-6,\n"
+        + "                \"msMaxLatency\" : 6.000000000000001E-6\n"
+        + "              },\n"
+        + "              \"handlers_response\" : {\n"
+        + "                \"tps\" : 1,\n"
+        + "                \"msTotalTime\" : 1.0000000000000002E-6,\n"
+        + "                \"msMaxLatency\" : 1.0000000000000002E-6\n"
+        + "              },\n"
+        + "              \"queue\" : {\n"
+        + "                \"tps\" : 0,\n"
+        + "                \"msTotalTime\" : 0.0,\n"
+        + "                \"msMaxLatency\" : 0.0\n"
+        + "              },\n"
+        + "              \"server_filters_response\" : {\n"
+        + "                \"tps\" : 1,\n"
+        + "                \"msTotalTime\" : 1.0000000000000002E-6,\n"
+        + "                \"msMaxLatency\" : 1.0000000000000002E-6\n"
+        + "              }\n"
+        + "            }\n"
+        + "          } ],\n"
+        + "          \"summary\" : {\n"
+        + "            \"operation\" : \"\",\n"
+        + "            \"stages\" : {\n"
+        + "              \"server_filters_request\" : {\n"
+        + "                \"tps\" : 1,\n"
+        + "                \"msTotalTime\" : 0.0,\n"
+        + "                \"msMaxLatency\" : 0.0\n"
+        + "              },\n"
+        + "              \"prepare\" : {\n"
+        + "                \"tps\" : 1,\n"
+        + "                \"msTotalTime\" : 5.0E-6,\n"
+        + "                \"msMaxLatency\" : 5.0E-6\n"
+        + "              },\n"
+        + "              \"execution\" : {\n"
+        + "                \"tps\" : 1,\n"
+        + "                \"msTotalTime\" : 3.0000000000000005E-6,\n"
+        + "                \"msMaxLatency\" : 3.0000000000000005E-6\n"
+        + "              },\n"
+        + "              \"total\" : {\n"
+        + "                \"tps\" : 1,\n"
+        + "                \"msTotalTime\" : 1.4000000000000001E-5,\n"
+        + "                \"msMaxLatency\" : 1.4000000000000001E-5\n"
+        + "              },\n"
+        + "              \"producer_send_response\" : {\n"
+        + "                \"tps\" : 1,\n"
+        + "                \"msTotalTime\" : 2.0000000000000003E-6,\n"
+        + "                \"msMaxLatency\" : 2.0000000000000003E-6\n"
+        + "              },\n"
+        + "              \"handlers_request\" : {\n"
+        + "                \"tps\" : 1,\n"
+        + "                \"msTotalTime\" : 6.000000000000001E-6,\n"
+        + "                \"msMaxLatency\" : 6.000000000000001E-6\n"
+        + "              },\n"
+        + "              \"handlers_response\" : {\n"
+        + "                \"tps\" : 1,\n"
+        + "                \"msTotalTime\" : 1.0000000000000002E-6,\n"
+        + "                \"msMaxLatency\" : 1.0000000000000002E-6\n"
+        + "              },\n"
+        + "              \"queue\" : {\n"
+        + "                \"tps\" : 0,\n"
+        + "                \"msTotalTime\" : 0.0,\n"
+        + "                \"msMaxLatency\" : 0.0\n"
+        + "              },\n"
+        + "              \"server_filters_response\" : {\n"
+        + "                \"tps\" : 1,\n"
+        + "                \"msTotalTime\" : 1.0000000000000002E-6,\n"
+        + "                \"msMaxLatency\" : 1.0000000000000002E-6\n"
+        + "              }\n"
+        + "            }\n"
+        + "          }\n"
+        + "        }\n"
+        + "      }\n"
+        + "    }\n"
+        + "  }\n"
+        + "}";
+    Assert.assertEquals(Json.encodePrettily(Json.decodeValue(expect, Object.class)),
+        Json.encodePrettily(model.getProducer()));
   }
 
   protected void prepareInvocation() {
diff --git a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/TestMetricsRestPublisher.java b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/TestMetricsRestPublisher.java
index 83ed66db3..40b72f390 100644
--- a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/TestMetricsRestPublisher.java
+++ b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/TestMetricsRestPublisher.java
@@ -19,16 +19,15 @@
 import java.util.Map;
 
 import org.apache.servicecomb.foundation.metrics.MetricsBootstrapConfig;
+import org.apache.servicecomb.foundation.metrics.registry.GlobalRegistry;
 import org.junit.Assert;
 import org.junit.Test;
 
 import com.google.common.eventbus.EventBus;
 import com.netflix.spectator.api.Clock;
-import com.netflix.spectator.api.CompositeRegistry;
 import com.netflix.spectator.api.DefaultRegistry;
 import com.netflix.spectator.api.ManualClock;
 import com.netflix.spectator.api.Registry;
-import com.netflix.spectator.api.SpectatorUtils;
 
 public class TestMetricsRestPublisher {
   MetricsRestPublisher publisher = new MetricsRestPublisher();
@@ -43,7 +42,7 @@ public void measure_globalRegistryNull() {
   @Test
   public void measure_normal() {
     Clock clock = new ManualClock();
-    CompositeRegistry globalRegistry = SpectatorUtils.createCompositeRegistry(clock);
+    GlobalRegistry globalRegistry = new GlobalRegistry();
     Registry registry = new DefaultRegistry(clock);
     registry.timer(registry.createId("name", "t1", "v1", "t2", "v2"));
     globalRegistry.add(registry);
diff --git a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/TestThreadPoolPublishModelFactory.java b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/TestThreadPoolPublishModelFactory.java
index 7f000f089..ab8c89861 100644
--- a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/TestThreadPoolPublishModelFactory.java
+++ b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/TestThreadPoolPublishModelFactory.java
@@ -32,6 +32,7 @@
 import com.netflix.spectator.api.DefaultRegistry;
 import com.netflix.spectator.api.ManualClock;
 import com.netflix.spectator.api.Registry;
+import com.netflix.spectator.api.patterns.PolledMeter;
 import com.netflix.spectator.api.patterns.ThreadPoolMonitor;
 
 import mockit.Expectations;
@@ -68,6 +69,7 @@ void delayedExecute(RunnableScheduledFuture<?> task) {
     };
     ThreadPoolMonitor.attach(registry, threadPoolExecutor, "test");
 
+    PolledMeter.update(registry);
     PublishModelFactory factory = new PublishModelFactory(Lists.newArrayList(registry.iterator()));
     DefaultPublishModel model = factory.createDefaultPublishModel();
 
diff --git a/metrics/metrics-integration/metrics-prometheus/src/main/java/org/apache/servicecomb/metrics/prometheus/PrometheusPublisher.java b/metrics/metrics-integration/metrics-prometheus/src/main/java/org/apache/servicecomb/metrics/prometheus/PrometheusPublisher.java
index b1eb9c67c..af62c09fa 100644
--- a/metrics/metrics-integration/metrics-prometheus/src/main/java/org/apache/servicecomb/metrics/prometheus/PrometheusPublisher.java
+++ b/metrics/metrics-integration/metrics-prometheus/src/main/java/org/apache/servicecomb/metrics/prometheus/PrometheusPublisher.java
@@ -24,13 +24,15 @@
 import org.apache.servicecomb.foundation.common.exceptions.ServiceCombException;
 import org.apache.servicecomb.foundation.metrics.MetricsBootstrapConfig;
 import org.apache.servicecomb.foundation.metrics.MetricsInitializer;
+import org.apache.servicecomb.foundation.metrics.registry.GlobalRegistry;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import com.google.common.eventbus.EventBus;
 import com.netflix.config.DynamicPropertyFactory;
-import com.netflix.spectator.api.CompositeRegistry;
 import com.netflix.spectator.api.Measurement;
+import com.netflix.spectator.api.Meter;
+import com.netflix.spectator.api.Registry;
 import com.netflix.spectator.api.Tag;
 
 import io.prometheus.client.Collector;
@@ -45,10 +47,10 @@
 
   private HTTPServer httpServer;
 
-  private CompositeRegistry globalRegistry;
+  private GlobalRegistry globalRegistry;
 
   @Override
-  public void init(CompositeRegistry globalRegistry, EventBus eventBus, MetricsBootstrapConfig config) {
+  public void init(GlobalRegistry globalRegistry, EventBus eventBus, MetricsBootstrapConfig config) {
     this.globalRegistry = globalRegistry;
 
     //prometheus default port allocation is here : https://github.com/prometheus/prometheus/wiki/Default-port-allocations
@@ -82,14 +84,15 @@ private InetSocketAddress getSocketAddress(String address) {
     }
 
     List<Sample> samples = new ArrayList<>();
-    globalRegistry
-        .iterator()
-        .forEachRemaining(meter -> {
-          meter.measure().forEach(measurement -> {
-            Sample sample = convertMeasurementToSample(measurement);
-            samples.add(sample);
-          });
+    for (Registry registry : globalRegistry.getRegistries()) {
+      for (Meter meter : registry) {
+        meter.measure().forEach(measurement -> {
+          Sample sample = convertMeasurementToSample(measurement);
+          samples.add(sample);
         });
+      }
+    }
+
     familySamples.add(new MetricFamilySamples("ServiceComb Metrics", Type.UNTYPED, "ServiceComb Metrics", samples));
 
     return familySamples;
diff --git a/metrics/metrics-integration/metrics-prometheus/src/test/java/org/apache/servicecomb/metrics/prometheus/TestPrometheusPublisher.java b/metrics/metrics-integration/metrics-prometheus/src/test/java/org/apache/servicecomb/metrics/prometheus/TestPrometheusPublisher.java
index c953730f4..cc10b4e6b 100644
--- a/metrics/metrics-integration/metrics-prometheus/src/test/java/org/apache/servicecomb/metrics/prometheus/TestPrometheusPublisher.java
+++ b/metrics/metrics-integration/metrics-prometheus/src/test/java/org/apache/servicecomb/metrics/prometheus/TestPrometheusPublisher.java
@@ -25,6 +25,7 @@
 import org.apache.commons.io.IOUtils;
 import org.apache.commons.lang3.reflect.FieldUtils;
 import org.apache.servicecomb.foundation.common.exceptions.ServiceCombException;
+import org.apache.servicecomb.foundation.metrics.registry.GlobalRegistry;
 import org.apache.servicecomb.foundation.test.scaffolding.config.ArchaiusUtils;
 import org.junit.AfterClass;
 import org.junit.Assert;
@@ -32,19 +33,17 @@
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
 
-import com.netflix.spectator.api.CompositeRegistry;
 import com.netflix.spectator.api.Counter;
 import com.netflix.spectator.api.DefaultRegistry;
 import com.netflix.spectator.api.ManualClock;
 import com.netflix.spectator.api.Registry;
-import com.netflix.spectator.api.SpectatorUtils;
 import com.sun.net.httpserver.HttpServer;
 
 import io.prometheus.client.exporter.HTTPServer;
 
 @SuppressWarnings("restriction")
 public class TestPrometheusPublisher {
-  CompositeRegistry globalRegistry = SpectatorUtils.createCompositeRegistry(new ManualClock());
+  GlobalRegistry globalRegistry = new GlobalRegistry(new ManualClock());
 
   PrometheusPublisher publisher = new PrometheusPublisher();
 


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services