You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@dubbo.apache.org by li...@apache.org on 2023/07/11 06:42:39 UTC

[dubbo] branch 3.2 updated: Performance opt (#12680)

This is an automated email from the ASF dual-hosted git repository.

liujun pushed a commit to branch 3.2
in repository https://gitbox.apache.org/repos/asf/dubbo.git


The following commit(s) were added to refs/heads/3.2 by this push:
     new d2eb2ba3d7 Performance opt (#12680)
d2eb2ba3d7 is described below

commit d2eb2ba3d74d9a23f728201b7a3a0ded6466185b
Author: Albumen Kevin <jh...@gmail.com>
AuthorDate: Tue Jul 11 14:42:33 2023 +0800

    Performance opt (#12680)
---
 .../filter/support/MetricsClusterFilter.java       |   8 +-
 .../filter/support/MetricsConsumerFilter.java      |  49 +++++++
 ...g.apache.dubbo.rpc.cluster.filter.ClusterFilter |   3 +-
 .../org/apache/dubbo/config/ServiceConfig.java     |   3 +-
 .../org/apache/dubbo/metrics/MetricsConstants.java |   1 +
 .../collector/ApplicationMetricsCollector.java     |   2 +-
 .../metrics/collector/CombMetricsCollector.java    |  17 ++-
 .../metrics/collector/MethodMetricsCollector.java  |   5 +-
 .../metrics/collector/ServiceMetricsCollector.java |   5 +-
 .../dubbo/metrics/data/BaseStatComposite.java      |   9 +-
 .../dubbo/metrics/data/MethodStatComposite.java    |  10 +-
 .../apache/dubbo/metrics/data/RtStatComposite.java | 147 ++++++++++++++++++---
 .../apache/dubbo/metrics/event/MetricsEvent.java   |  39 +++++-
 .../dubbo/metrics/event/MetricsEventBus.java       |  35 +----
 .../event/SimpleMetricsEventMulticaster.java       |   3 +-
 .../dubbo/metrics/event/TimeCounterEvent.java      |   5 +
 .../metrics/listener/AbstractMetricsListener.java  |   8 +-
 .../listener/MetricsApplicationListener.java       |   4 +-
 .../dubbo/metrics/model/ApplicationMetric.java     |   7 +-
 .../apache/dubbo/metrics/model/MethodMetric.java   |  16 +--
 .../apache/dubbo/metrics/model/MetricsSupport.java |  71 ++++++----
 .../dubbo/metrics/model/ServiceKeyMetric.java      |  11 +-
 .../metrics/model/container/LongContainer.java     |   3 +-
 .../event/SimpleMetricsEventMulticasterTest.java   |   1 +
 .../metrics/config/event/ConfigCenterEvent.java    |   2 +-
 .../dubbo/metrics/event/DefaultSubDispatcher.java  |   3 +-
 .../dubbo/metrics/event/RequestBeforeEvent.java    |  13 +-
 .../apache/dubbo/metrics/event/RequestEvent.java   |  50 ++++---
 .../apache/dubbo/metrics/filter/MetricsFilter.java |  36 +++--
 .../metrics/filter/MetricsProviderFilter.java      |  48 +++++++
 .../dubbo/internal/org.apache.dubbo.rpc.Filter     |   4 +-
 .../collector/AggregateMetricsCollectorTest.java   |  11 +-
 .../metrics/collector/DefaultCollectorTest.java    |   5 +-
 .../metrics/metadata/event/MetadataEvent.java      |   2 +-
 .../metadata/MetadataMetricsCollectorTest.java     |   2 +-
 .../metrics/registry/event/RegistryEvent.java      |  20 ++-
 .../registry/event/RegistrySubDispatcher.java      |   2 +-
 .../collector/RegistryMetricsSampleTest.java       |   5 +-
 .../metrics/collector/RegistryMetricsTest.java     |   7 +-
 .../listener/ServiceInstancesChangedListener.java  |   1 -
 .../registry/integration/RegistryDirectory.java    |   1 -
 .../org/apache/dubbo/rpc/filter/GenericFilter.java |  59 ++++++++-
 .../protocol/dubbo/DecodeableRpcInvocation.java    |   8 +-
 .../dubbo/rpc/protocol/dubbo/DubboCodec.java       |   2 +
 .../serialize/hessian2/Hessian2FactoryManager.java |  20 ++-
 45 files changed, 573 insertions(+), 190 deletions(-)

diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/filter/support/MetricsClusterFilter.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/filter/support/MetricsClusterFilter.java
index 9cc8f19535..03c9018517 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/filter/support/MetricsClusterFilter.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/filter/support/MetricsClusterFilter.java
@@ -20,6 +20,7 @@ package org.apache.dubbo.rpc.cluster.filter.support;
 
 import org.apache.dubbo.common.extension.Activate;
 import org.apache.dubbo.metrics.collector.DefaultMetricsCollector;
+import org.apache.dubbo.metrics.event.MetricsDispatcher;
 import org.apache.dubbo.metrics.event.MetricsEventBus;
 import org.apache.dubbo.metrics.event.RequestBeforeEvent;
 import org.apache.dubbo.rpc.BaseFilter;
@@ -32,17 +33,22 @@ import org.apache.dubbo.rpc.model.ApplicationModel;
 import org.apache.dubbo.rpc.model.ScopeModelAware;
 
 import static org.apache.dubbo.common.constants.CommonConstants.CONSUMER;
+import static org.apache.dubbo.common.constants.CommonConstants.CONSUMER_SIDE;
 
 @Activate(group = CONSUMER, onClass = "org.apache.dubbo.metrics.collector.DefaultMetricsCollector")
 public class MetricsClusterFilter implements ClusterFilter, BaseFilter.Listener, ScopeModelAware {
 
     private ApplicationModel applicationModel;
     private DefaultMetricsCollector collector;
+    private String appName;
+    private MetricsDispatcher metricsDispatcher;
 
     @Override
     public void setApplicationModel(ApplicationModel applicationModel) {
         this.applicationModel = applicationModel;
         this.collector = applicationModel.getBeanFactory().getBean(DefaultMetricsCollector.class);
+        this.appName = applicationModel.tryGetApplicationName();
+        this.metricsDispatcher = applicationModel.getBeanFactory().getBean(MetricsDispatcher.class);
     }
 
     @Override
@@ -67,7 +73,7 @@ public class MetricsClusterFilter implements ClusterFilter, BaseFilter.Listener,
         if (t instanceof RpcException) {
             RpcException e = (RpcException) t;
             if (e.isForbidden()) {
-                MetricsEventBus.publish(RequestBeforeEvent.toEvent(applicationModel, invocation));
+                MetricsEventBus.publish(RequestBeforeEvent.toEvent(applicationModel, appName, metricsDispatcher, invocation, CONSUMER_SIDE));
             }
         }
     }
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/filter/support/MetricsConsumerFilter.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/filter/support/MetricsConsumerFilter.java
new file mode 100644
index 0000000000..10136c17d8
--- /dev/null
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/filter/support/MetricsConsumerFilter.java
@@ -0,0 +1,49 @@
+/*
+ * 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.dubbo.rpc.cluster.filter.support;
+
+import org.apache.dubbo.common.extension.Activate;
+import org.apache.dubbo.metrics.filter.MetricsFilter;
+import org.apache.dubbo.rpc.BaseFilter;
+import org.apache.dubbo.rpc.Invocation;
+import org.apache.dubbo.rpc.Invoker;
+import org.apache.dubbo.rpc.Result;
+import org.apache.dubbo.rpc.RpcException;
+import org.apache.dubbo.rpc.cluster.filter.ClusterFilter;
+
+import static org.apache.dubbo.common.constants.CommonConstants.CONSUMER;
+
+@Activate(group = {CONSUMER}, order = Integer.MIN_VALUE + 100)
+public class MetricsConsumerFilter extends MetricsFilter implements ClusterFilter, BaseFilter.Listener {
+    public MetricsConsumerFilter() {
+    }
+
+    @Override
+    public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
+        return super.invoke(invoker, invocation, false);
+    }
+
+    @Override
+    public void onResponse(Result appResponse, Invoker<?> invoker, Invocation invocation) {
+        super.onResponse(appResponse, invoker, invocation, false);
+    }
+
+    @Override
+    public void onError(Throwable t, Invoker<?> invoker, Invocation invocation) {
+        super.onError(t, invoker, invocation, false);
+    }
+}
diff --git a/dubbo-cluster/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.cluster.filter.ClusterFilter b/dubbo-cluster/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.cluster.filter.ClusterFilter
index cd0a2f44e8..5c2632a7c6 100644
--- a/dubbo-cluster/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.cluster.filter.ClusterFilter
+++ b/dubbo-cluster/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.cluster.filter.ClusterFilter
@@ -2,4 +2,5 @@ consumercontext=org.apache.dubbo.rpc.cluster.filter.support.ConsumerContextFilte
 consumer-classloader=org.apache.dubbo.rpc.cluster.filter.support.ConsumerClassLoaderFilter
 router-snapshot=org.apache.dubbo.rpc.cluster.router.RouterSnapshotFilter
 observationsender=org.apache.dubbo.rpc.cluster.filter.support.ObservationSenderFilter
-metricsClusterFilter=org.apache.dubbo.rpc.cluster.filter.support.MetricsClusterFilter
\ No newline at end of file
+metricsClusterFilter=org.apache.dubbo.rpc.cluster.filter.support.MetricsClusterFilter
+metricsConsumerFilter=org.apache.dubbo.rpc.cluster.filter.support.MetricsConsumerFilter
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ServiceConfig.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ServiceConfig.java
index e3d3028a44..98aab862d2 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ServiceConfig.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ServiceConfig.java
@@ -514,8 +514,7 @@ public class ServiceConfig<T> extends ServiceConfigBase<T> {
 
         List<URL> registryURLs = ConfigValidationUtils.loadRegistries(this, true);
 
-        MetricsEventBus.post(RegistryEvent.toRsEvent(module.getApplicationModel(), getUniqueServiceName(), protocols.size() * registryURLs.size()),
-            () -> {
+        MetricsEventBus.post(RegistryEvent.toRsEvent(getApplicationModel(), getUniqueServiceName(), protocols.size() * registryURLs.size()),            () -> {
                 for (ProtocolConfig protocolConfig : protocols) {
                     String pathKey = URL.buildKey(getContextPath(protocolConfig)
                         .map(p -> p + "/" + path)
diff --git a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/MetricsConstants.java b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/MetricsConstants.java
index 3c3871c0d7..a99e4c6657 100644
--- a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/MetricsConstants.java
+++ b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/MetricsConstants.java
@@ -20,6 +20,7 @@ package org.apache.dubbo.metrics;
 public interface MetricsConstants {
 
     String INVOCATION = "metric_filter_invocation";
+    String METHOD_METRICS = "metric_filter_method_metrics";
     String INVOCATION_METRICS_COUNTER = "metric_filter_invocation_counter";
 
     String INVOCATION_SIDE = "metric_filter_side";
diff --git a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/collector/ApplicationMetricsCollector.java b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/collector/ApplicationMetricsCollector.java
index 3f2427cf8c..cac0635f6f 100644
--- a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/collector/ApplicationMetricsCollector.java
+++ b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/collector/ApplicationMetricsCollector.java
@@ -30,7 +30,7 @@ public interface ApplicationMetricsCollector<E extends TimeCounterEvent> extends
 
     void increment(MetricsKey metricsKey);
 
-    void addRt(String registryOpType, Long responseTime);
+    void addApplicationRt(String registryOpType, Long responseTime);
 
 }
 
diff --git a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/collector/CombMetricsCollector.java b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/collector/CombMetricsCollector.java
index d8c6e07e04..81ae03eb40 100644
--- a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/collector/CombMetricsCollector.java
+++ b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/collector/CombMetricsCollector.java
@@ -21,6 +21,7 @@ import org.apache.dubbo.metrics.data.BaseStatComposite;
 import org.apache.dubbo.metrics.event.MetricsEventMulticaster;
 import org.apache.dubbo.metrics.event.TimeCounterEvent;
 import org.apache.dubbo.metrics.listener.AbstractMetricsListener;
+import org.apache.dubbo.metrics.model.MethodMetric;
 import org.apache.dubbo.metrics.model.MetricsCategory;
 import org.apache.dubbo.metrics.model.key.MetricsKey;
 import org.apache.dubbo.metrics.model.key.MetricsKeyWrapper;
@@ -60,24 +61,30 @@ public abstract class CombMetricsCollector<E extends TimeCounterEvent> extends A
     }
 
     @Override
-    public void addRt(String registryOpType, Long responseTime) {
+    public void addApplicationRt(String registryOpType, Long responseTime) {
         stats.calcApplicationRt(registryOpType, responseTime);
     }
 
-    public void addRt(String serviceKey, String registryOpType, Long responseTime) {
+    @Override
+    public void addServiceRt(String serviceKey, String registryOpType, Long responseTime) {
         stats.calcServiceKeyRt(serviceKey, registryOpType, responseTime);
     }
 
     @Override
-    public void increment(Invocation invocation, MetricsKeyWrapper wrapper, int size) {
-        this.stats.incrementMethodKey(wrapper, invocation, size);
+    public void addServiceRt(Invocation invocation, String registryOpType, Long responseTime) {
+        stats.calcServiceKeyRt(invocation, registryOpType, responseTime);
     }
 
     @Override
-    public void addRt(Invocation invocation, String registryOpType, Long responseTime) {
+    public void addMethodRt(Invocation invocation, String registryOpType, Long responseTime) {
         stats.calcMethodKeyRt(invocation, registryOpType, responseTime);
     }
 
+    @Override
+    public void increment(MethodMetric methodMetric, MetricsKeyWrapper wrapper, int size) {
+        this.stats.incrementMethodKey(wrapper, methodMetric, size);
+    }
+
     protected List<MetricSample> export(MetricsCategory category) {
         return stats.export(category);
     }
diff --git a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/collector/MethodMetricsCollector.java b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/collector/MethodMetricsCollector.java
index 836de4dcd3..d62bab1820 100644
--- a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/collector/MethodMetricsCollector.java
+++ b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/collector/MethodMetricsCollector.java
@@ -18,6 +18,7 @@
 package org.apache.dubbo.metrics.collector;
 
 import org.apache.dubbo.metrics.event.TimeCounterEvent;
+import org.apache.dubbo.metrics.model.MethodMetric;
 import org.apache.dubbo.metrics.model.key.MetricsKeyWrapper;
 import org.apache.dubbo.rpc.Invocation;
 
@@ -26,8 +27,8 @@ import org.apache.dubbo.rpc.Invocation;
  */
 public interface MethodMetricsCollector<E extends TimeCounterEvent> extends MetricsCollector<E> {
 
-    void increment(Invocation invocation, MetricsKeyWrapper wrapper, int size);
+    void increment(MethodMetric methodMetric, MetricsKeyWrapper wrapper, int size);
 
-    void addRt(Invocation invocation, String registryOpType, Long responseTime);
+    void addMethodRt(Invocation invocation, String registryOpType, Long responseTime);
 }
 
diff --git a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/collector/ServiceMetricsCollector.java b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/collector/ServiceMetricsCollector.java
index 37cd96ce82..fc269b87ab 100644
--- a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/collector/ServiceMetricsCollector.java
+++ b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/collector/ServiceMetricsCollector.java
@@ -19,6 +19,7 @@ package org.apache.dubbo.metrics.collector;
 
 import org.apache.dubbo.metrics.event.TimeCounterEvent;
 import org.apache.dubbo.metrics.model.key.MetricsKeyWrapper;
+import org.apache.dubbo.rpc.Invocation;
 
 /**
  * Service-level collector.
@@ -30,6 +31,8 @@ public interface ServiceMetricsCollector<E extends TimeCounterEvent> extends Met
 
     void setNum(MetricsKeyWrapper metricsKey, String serviceKey, int num);
 
-    void addRt(String serviceKey, String registryOpType, Long responseTime);
+    void addServiceRt(String serviceKey, String registryOpType, Long responseTime);
+
+    void addServiceRt(Invocation invocation, String registryOpType, Long responseTime);
 }
 
diff --git a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/data/BaseStatComposite.java b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/data/BaseStatComposite.java
index b4798b83ef..c7ddd9dee0 100644
--- a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/data/BaseStatComposite.java
+++ b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/data/BaseStatComposite.java
@@ -18,6 +18,7 @@
 package org.apache.dubbo.metrics.data;
 
 import org.apache.dubbo.metrics.collector.MetricsCollector;
+import org.apache.dubbo.metrics.model.MethodMetric;
 import org.apache.dubbo.metrics.model.MetricsCategory;
 import org.apache.dubbo.metrics.model.key.MetricsKey;
 import org.apache.dubbo.metrics.model.key.MetricsKeyWrapper;
@@ -76,6 +77,10 @@ public abstract class BaseStatComposite implements MetricsExport {
         rtStatComposite.calcServiceKeyRt(serviceKey, registryOpType, responseTime);
     }
 
+    public void calcServiceKeyRt(Invocation invocation, String registryOpType, Long responseTime) {
+        rtStatComposite.calcServiceKeyRt(invocation, registryOpType, responseTime);
+    }
+
     public void calcMethodKeyRt(Invocation invocation, String registryOpType, Long responseTime) {
         rtStatComposite.calcMethodKeyRt(invocation, registryOpType, responseTime);
     }
@@ -92,8 +97,8 @@ public abstract class BaseStatComposite implements MetricsExport {
         serviceStatComposite.incrementServiceKey(metricsKeyWrapper, attServiceKey, size);
     }
 
-    public void incrementMethodKey(MetricsKeyWrapper metricsKeyWrapper, Invocation invocation, int size) {
-        methodStatComposite.incrementMethodKey(metricsKeyWrapper, invocation, size);
+    public void incrementMethodKey(MetricsKeyWrapper metricsKeyWrapper, MethodMetric methodMetric, int size) {
+        methodStatComposite.incrementMethodKey(metricsKeyWrapper, methodMetric, size);
     }
 
     @Override
diff --git a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/data/MethodStatComposite.java b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/data/MethodStatComposite.java
index bfd08d27a3..527fb31bf3 100644
--- a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/data/MethodStatComposite.java
+++ b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/data/MethodStatComposite.java
@@ -26,7 +26,6 @@ import org.apache.dubbo.metrics.model.sample.CounterMetricSample;
 import org.apache.dubbo.metrics.model.sample.GaugeMetricSample;
 import org.apache.dubbo.metrics.model.sample.MetricSample;
 import org.apache.dubbo.metrics.report.AbstractMetricsExport;
-import org.apache.dubbo.rpc.Invocation;
 import org.apache.dubbo.rpc.model.ApplicationModel;
 
 import java.util.ArrayList;
@@ -55,11 +54,16 @@ public class MethodStatComposite extends AbstractMetricsExport {
         metricsKeyWrappers.forEach(appKey -> methodNumStats.put(appKey, new ConcurrentHashMap<>()));
     }
 
-    public void incrementMethodKey(MetricsKeyWrapper wrapper, Invocation invocation, int size) {
+    public void incrementMethodKey(MetricsKeyWrapper wrapper, MethodMetric methodMetric, int size) {
         if (!methodNumStats.containsKey(wrapper)) {
             return;
         }
-        methodNumStats.get(wrapper).computeIfAbsent(new MethodMetric(getApplicationModel(), invocation), k -> new AtomicLong(0L)).getAndAdd(size);
+        AtomicLong stat = methodNumStats.get(wrapper).get(methodMetric);
+        if (stat == null) {
+            methodNumStats.get(wrapper).putIfAbsent(methodMetric, new AtomicLong(0L));
+            stat = methodNumStats.get(wrapper).get(methodMetric);
+        }
+        stat.getAndAdd(size);
 //        MetricsSupport.fillZero(methodNumStats);
     }
 
diff --git a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/data/RtStatComposite.java b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/data/RtStatComposite.java
index 0a739c7d0f..5a3d96c9b3 100644
--- a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/data/RtStatComposite.java
+++ b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/data/RtStatComposite.java
@@ -17,7 +17,6 @@
 
 package org.apache.dubbo.metrics.data;
 
-import org.apache.dubbo.common.utils.ConcurrentHashMapUtils;
 import org.apache.dubbo.metrics.model.ApplicationMetric;
 import org.apache.dubbo.metrics.model.MethodMetric;
 import org.apache.dubbo.metrics.model.Metric;
@@ -36,10 +35,13 @@ import org.apache.dubbo.rpc.Invocation;
 import org.apache.dubbo.rpc.model.ApplicationModel;
 
 import java.util.ArrayList;
-import java.util.Arrays;
+import java.util.LinkedList;
 import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.atomic.AtomicLong;
 import java.util.concurrent.atomic.LongAccumulator;
+import java.util.function.BiConsumer;
 import java.util.stream.Collectors;
 
 /**
@@ -54,13 +56,19 @@ public class RtStatComposite extends AbstractMetricsExport {
         super(applicationModel);
     }
 
-    private final List<LongContainer<? extends Number>> rtStats = new ArrayList<>();
+    private final Map<String, List<LongContainer<? extends Number>>> rtStats = new ConcurrentHashMap<>();
 
     public void init(MetricsPlaceValue... placeValues) {
         if (placeValues == null) {
             return;
         }
-        Arrays.stream(placeValues).forEach(metricsPlaceType -> rtStats.addAll(initStats(metricsPlaceType)));
+        for (MetricsPlaceValue placeValue : placeValues) {
+            List<LongContainer<? extends Number>> containers = initStats(placeValue);
+            for (LongContainer<? extends Number> container : containers) {
+                rtStats.computeIfAbsent(container.getMetricsKeyWrapper().getType(), k -> new ArrayList<>())
+                    .add(container);
+            }
+        }
     }
 
     private List<LongContainer<? extends Number>> initStats(MetricsPlaceValue placeValue) {
@@ -72,7 +80,7 @@ public class RtStatComposite extends AbstractMetricsExport {
         // AvgContainer is a special counter that stores the number of times but outputs function of sum/times
         AtomicLongContainer avgContainer = new AtomicLongContainer(new MetricsKeyWrapper(MetricsKey.METRIC_RT_AVG, placeValue), (k, v) -> v.incrementAndGet());
         avgContainer.setValueSupplier(applicationName -> {
-            LongContainer<? extends Number> totalContainer = rtStats.stream().filter(longContainer -> longContainer.isKeyWrapper(MetricsKey.METRIC_RT_SUM, placeValue.getType())).findFirst().get();
+            LongContainer<? extends Number> totalContainer = rtStats.values().stream().flatMap(List::stream).filter(longContainer -> longContainer.isKeyWrapper(MetricsKey.METRIC_RT_SUM, placeValue.getType())).findFirst().get();
             AtomicLong totalRtTimes = avgContainer.get(applicationName);
             AtomicLong totalRtSum = (AtomicLong) totalContainer.get(applicationName);
             return totalRtSum.get() / totalRtTimes.get();
@@ -82,41 +90,144 @@ public class RtStatComposite extends AbstractMetricsExport {
     }
 
     public void calcApplicationRt(String registryOpType, Long responseTime) {
-        for (LongContainer container : rtStats.stream().filter(longContainer -> longContainer.specifyType(registryOpType)).collect(Collectors.toList())) {
-            Number current = (Number) ConcurrentHashMapUtils.computeIfAbsent(container, new ApplicationMetric(getApplicationModel()), container.getInitFunc());
+        ApplicationMetric key = new ApplicationMetric(getApplicationModel());
+        for (LongContainer container : rtStats.get(registryOpType)) {
+            Number current = (Number) container.get(key);
+            if (current == null) {
+                container.putIfAbsent(key, container.getInitFunc().apply(key));
+                current = (Number) container.get(key);
+            }
             container.getConsumerFunc().accept(responseTime, current);
         }
     }
 
     public void calcServiceKeyRt(String serviceKey, String registryOpType, Long responseTime) {
-        for (LongContainer container : rtStats.stream().filter(longContainer -> longContainer.specifyType(registryOpType)).collect(Collectors.toList())) {
-            Number current = (Number) ConcurrentHashMapUtils.computeIfAbsent(container, new ServiceKeyMetric(getApplicationModel(), serviceKey), container.getInitFunc());
+        ServiceKeyMetric key = new ServiceKeyMetric(getApplicationModel(), serviceKey);
+        for (LongContainer container : rtStats.get(registryOpType)) {
+            Number current = (Number) container.get(key);
+            if (current == null) {
+                container.putIfAbsent(key, container.getInitFunc().apply(key));
+                current = (Number) container.get(key);
+            }
             container.getConsumerFunc().accept(responseTime, current);
         }
     }
 
+    public void calcServiceKeyRt(Invocation invocation, String registryOpType, Long responseTime) {
+        List<Action> actions;
+        if (invocation.getServiceModel() != null && invocation.getServiceModel().getServiceKey() != null) {
+            Map<String, Object> attributeMap = invocation.getServiceModel().getServiceMetadata().getAttributeMap();
+            Map<String, List<Action>> cache = (Map<String, List<Action>>) attributeMap.get("ServiceKeyRt");
+            if (cache == null) {
+                attributeMap.putIfAbsent("ServiceKeyRt", new ConcurrentHashMap<>(32));
+                cache = (Map<String, List<Action>>) attributeMap.get("ServiceKeyRt");
+            }
+            actions = cache.get(registryOpType);
+            if (actions == null) {
+                actions = calServiceRtActions(invocation, registryOpType);
+                cache.putIfAbsent(registryOpType, actions);
+                actions = cache.get(registryOpType);
+            }
+        } else {
+            actions = calServiceRtActions(invocation, registryOpType);
+        }
+
+        for (Action action : actions) {
+            action.run(responseTime);
+        }
+    }
+
+    private List<Action> calServiceRtActions(Invocation invocation, String registryOpType) {
+        List<Action> actions;
+        actions = new LinkedList<>();
+
+        ServiceKeyMetric key = new ServiceKeyMetric(getApplicationModel(), invocation.getTargetServiceUniqueName());
+        for (LongContainer container : rtStats.get(registryOpType)) {
+            Number current = (Number) container.get(key);
+            if (current == null) {
+                container.putIfAbsent(key, container.getInitFunc().apply(key));
+                current = (Number) container.get(key);
+            }
+            actions.add(new Action(container.getConsumerFunc(), current));
+        }
+        return actions;
+    }
+
     public void calcMethodKeyRt(Invocation invocation, String registryOpType, Long responseTime) {
-        for (LongContainer container : rtStats.stream().filter(longContainer -> longContainer.specifyType(registryOpType)).collect(Collectors.toList())) {
-            Number current = (Number) ConcurrentHashMapUtils.computeIfAbsent(container, new MethodMetric(getApplicationModel(), invocation), container.getInitFunc());
-            container.getConsumerFunc().accept(responseTime, current);
+        List<Action> actions;
+
+        if (invocation.getServiceModel() != null && invocation.getServiceModel().getServiceMetadata() != null) {
+            Map<String, Object> attributeMap = invocation.getServiceModel().getServiceMetadata().getAttributeMap();
+            Map<String, List<Action>> cache = (Map<String, List<Action>>) attributeMap.get("MethodKeyRt");
+            if (cache == null) {
+                attributeMap.putIfAbsent("MethodKeyRt", new ConcurrentHashMap<>(32));
+                cache = (Map<String, List<Action>>) attributeMap.get("MethodKeyRt");
+            }
+            actions = cache.get(registryOpType);
+            if (actions == null) {
+                actions = calMethodRtActions(invocation, registryOpType);
+                cache.putIfAbsent(registryOpType, actions);
+                actions = cache.get(registryOpType);
+            }
+        } else {
+            actions = calMethodRtActions(invocation, registryOpType);
+        }
+
+        for (Action action : actions) {
+            action.run(responseTime);
         }
     }
 
+    private List<Action> calMethodRtActions(Invocation invocation, String registryOpType) {
+        List<Action> actions;
+        actions = new LinkedList<>();
+        for (LongContainer container : rtStats.get(registryOpType)) {
+            MethodMetric key = new MethodMetric(getApplicationModel(), invocation);
+            Number current = (Number) container.get(key);
+            if (current == null) {
+                container.putIfAbsent(key, container.getInitFunc().apply(key));
+                current = (Number) container.get(key);
+            }
+            actions.add(new Action(container.getConsumerFunc(), current));
+        }
+        return actions;
+    }
+
     public List<MetricSample> export(MetricsCategory category) {
         List<MetricSample> list = new ArrayList<>();
-        for (LongContainer<? extends Number> rtContainer : rtStats) {
-            MetricsKeyWrapper metricsKeyWrapper = rtContainer.getMetricsKeyWrapper();
-            for (Metric key : rtContainer.keySet()) {
-                // Use keySet to obtain the original key instance reference of ConcurrentHashMap to avoid early recycling of the micrometer
-                list.add(new GaugeMetricSample<>(metricsKeyWrapper.targetKey(), metricsKeyWrapper.targetDesc(), key.getTags(), category, key, value -> rtContainer.getValueSupplier().apply(value)));
+        for (List<LongContainer<? extends Number>> containers : rtStats.values()) {
+            for (LongContainer<? extends Number> container : containers) {
+                MetricsKeyWrapper metricsKeyWrapper = container.getMetricsKeyWrapper();
+                for (Metric key : container.keySet()) {
+                    // Use keySet to obtain the original key instance reference of ConcurrentHashMap to avoid early recycling of the micrometer
+                    list.add(new GaugeMetricSample<>(metricsKeyWrapper.targetKey(),
+                        metricsKeyWrapper.targetDesc(),
+                        key.getTags(),
+                        category,
+                        key,
+                        value -> container.getValueSupplier().apply(value)));
+                }
             }
         }
         return list;
     }
 
     public List<LongContainer<? extends Number>> getRtStats() {
-        return rtStats;
+        return rtStats.values().stream().flatMap(List::stream).collect(Collectors.toList());
     }
 
 
+    private static class Action {
+        private final BiConsumer<Long, Number> consumerFunc;
+        private final Number initValue;
+
+        public Action(BiConsumer<Long, Number> consumerFunc, Number initValue) {
+            this.consumerFunc = consumerFunc;
+            this.initValue = initValue;
+        }
+
+        public void run(Long responseTime) {
+            consumerFunc.accept(responseTime, initValue);
+        }
+    }
 }
diff --git a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/event/MetricsEvent.java b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/event/MetricsEvent.java
index baa5d812fd..4203d81a63 100644
--- a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/event/MetricsEvent.java
+++ b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/event/MetricsEvent.java
@@ -17,12 +17,13 @@
 
 package org.apache.dubbo.metrics.event;
 
+import org.apache.dubbo.common.beans.factory.ScopeBeanFactory;
 import org.apache.dubbo.metrics.exception.MetricsNeverHappenException;
 import org.apache.dubbo.metrics.model.MethodMetric;
 import org.apache.dubbo.metrics.model.key.TypeWrapper;
 import org.apache.dubbo.rpc.model.ApplicationModel;
 
-import java.util.HashMap;
+import java.util.IdentityHashMap;
 import java.util.Map;
 
 /**
@@ -33,13 +34,19 @@ public abstract class MetricsEvent {
     /**
      * Metric object. (eg. {@link MethodMetric})
      */
-    protected transient ApplicationModel source;
+    protected transient final ApplicationModel source;
     private boolean available = true;
     private final TypeWrapper typeWrapper;
+    private final String appName;
+    private final MetricsDispatcher metricsDispatcher;
 
-    private final Map<String, Object> attachment = new HashMap<>(8);
+    private final Map<String, Object> attachment = new IdentityHashMap<>(8);
 
     public MetricsEvent(ApplicationModel source, TypeWrapper typeWrapper) {
+        this(source, null, null, typeWrapper);
+    }
+
+    public MetricsEvent(ApplicationModel source, String appName, MetricsDispatcher metricsDispatcher, TypeWrapper typeWrapper) {
         this.typeWrapper = typeWrapper;
         if (source == null) {
             this.source = ApplicationModel.defaultModel();
@@ -48,6 +55,26 @@ public abstract class MetricsEvent {
         } else {
             this.source = source;
         }
+        if (metricsDispatcher == null) {
+            if (this.source.isDestroyed()) {
+                this.metricsDispatcher = null;
+            } else {
+                ScopeBeanFactory beanFactory = this.source.getBeanFactory();
+                if (beanFactory.isDestroyed()) {
+                    this.metricsDispatcher = null;
+                } else {
+                    MetricsDispatcher dispatcher = beanFactory.getBean(MetricsDispatcher.class);
+                    this.metricsDispatcher = dispatcher;
+                }
+            }
+        } else {
+            this.metricsDispatcher = metricsDispatcher;
+        }
+        if (appName == null) {
+            this.appName = this.source.tryGetApplicationName();
+        } else {
+            this.appName = appName;
+        }
     }
 
     @SuppressWarnings("unchecked")
@@ -79,8 +106,12 @@ public abstract class MetricsEvent {
         return source;
     }
 
+    public MetricsDispatcher getMetricsDispatcher() {
+        return metricsDispatcher;
+    }
+
     public String appName() {
-        return getSource().getApplicationName();
+        return appName;
     }
 
     public TypeWrapper getTypeWrapper() {
diff --git a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/event/MetricsEventBus.java b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/event/MetricsEventBus.java
index 8a4121baa6..6c514bafda 100644
--- a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/event/MetricsEventBus.java
+++ b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/event/MetricsEventBus.java
@@ -17,9 +17,6 @@
 
 package org.apache.dubbo.metrics.event;
 
-import org.apache.dubbo.common.beans.factory.ScopeBeanFactory;
-import org.apache.dubbo.rpc.model.ApplicationModel;
-
 import java.util.Optional;
 import java.util.function.Function;
 import java.util.function.Supplier;
@@ -38,15 +35,7 @@ public class MetricsEventBus {
         if (event.getSource() == null) {
             return;
         }
-        ApplicationModel applicationModel = event.getSource();
-        if (applicationModel.isDestroyed()) {
-            return;
-        }
-        ScopeBeanFactory beanFactory = applicationModel.getBeanFactory();
-        if (beanFactory.isDestroyed()) {
-            return;
-        }
-        MetricsDispatcher dispatcher = beanFactory.getBean(MetricsDispatcher.class);
+        MetricsDispatcher dispatcher = event.getMetricsDispatcher();
         Optional.ofNullable(dispatcher).ifPresent(d -> d.publishEvent(event));
     }
 
@@ -95,21 +84,14 @@ public class MetricsEventBus {
         return result;
     }
 
-    public static void before(MetricsEvent event) {
-        before(event, null);
-    }
-
     /**
      * Applicable to the scene where execution and return are separated,
      * eventSaveRunner saves the event, so that the calculation rt is introverted
      */
-    public static void before(MetricsEvent event, Runnable eventSaveRunner) {
+    public static void before(MetricsEvent event) {
         MetricsDispatcher dispatcher = validate(event);
         if (dispatcher == null) return;
         dispatcher.publishEvent(event);
-        if (eventSaveRunner != null) {
-            eventSaveRunner.run();
-        }
     }
 
     public static void after(MetricsEvent event, Object result) {
@@ -126,18 +108,7 @@ public class MetricsEventBus {
     }
 
     private static MetricsDispatcher validate(MetricsEvent event) {
-        if (event.getSource() == null) {
-            return null;
-        }
-        ApplicationModel applicationModel = event.getSource();
-        if (applicationModel.isDestroyed()) {
-            return null;
-        }
-        ScopeBeanFactory beanFactory = applicationModel.getBeanFactory();
-        if (beanFactory.isDestroyed()) {
-            return null;
-        }
-        MetricsDispatcher dispatcher = beanFactory.getBean(MetricsDispatcher.class);
+        MetricsDispatcher dispatcher = event.getMetricsDispatcher();
         if (dispatcher == null) {
             return null;
         }
diff --git a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/event/SimpleMetricsEventMulticaster.java b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/event/SimpleMetricsEventMulticaster.java
index 57b12cd6dd..e89483f8c6 100644
--- a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/event/SimpleMetricsEventMulticaster.java
+++ b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/event/SimpleMetricsEventMulticaster.java
@@ -17,6 +17,7 @@
 
 package org.apache.dubbo.metrics.event;
 
+import org.apache.dubbo.common.utils.StringUtils;
 import org.apache.dubbo.metrics.listener.MetricsLifeListener;
 import org.apache.dubbo.metrics.listener.MetricsListener;
 
@@ -53,7 +54,7 @@ public class SimpleMetricsEventMulticaster implements MetricsEventMulticaster {
     private boolean validateIfApplicationConfigExist(MetricsEvent event) {
         if (event.getSource() != null) {
             // Check if exist application config
-            return event.getSource().NotExistApplicationConfig();
+            return StringUtils.isEmpty(event.appName());
         }
         return false;
     }
diff --git a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/event/TimeCounterEvent.java b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/event/TimeCounterEvent.java
index c8f91df47e..69e7e42925 100644
--- a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/event/TimeCounterEvent.java
+++ b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/event/TimeCounterEvent.java
@@ -33,6 +33,11 @@ public abstract class TimeCounterEvent extends MetricsEvent {
         this.timePair = TimePair.start();
     }
 
+    public TimeCounterEvent(ApplicationModel source, String appName, MetricsDispatcher metricsDispatcher, TypeWrapper typeWrapper) {
+        super(source, appName, metricsDispatcher, typeWrapper);
+        this.timePair = TimePair.start();
+    }
+
     public TimePair getTimePair() {
         return timePair;
     }
diff --git a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/listener/AbstractMetricsListener.java b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/listener/AbstractMetricsListener.java
index 491cffbbda..63ac20b877 100644
--- a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/listener/AbstractMetricsListener.java
+++ b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/listener/AbstractMetricsListener.java
@@ -25,13 +25,17 @@ import java.util.concurrent.ConcurrentHashMap;
 
 public abstract class AbstractMetricsListener<E extends MetricsEvent> implements MetricsListener<E> {
 
-    private final Map<Class<?>, Boolean> eventMatchCache = new ConcurrentHashMap<>();
+    private final Map<Integer, Boolean> eventMatchCache = new ConcurrentHashMap<>();
 
     /**
      * Whether to support the general determination of event points depends on the event type
      */
     public boolean isSupport(MetricsEvent event) {
-        Boolean eventMatch = eventMatchCache.computeIfAbsent(event.getClass(), clazz -> ReflectionUtils.match(getClass(), AbstractMetricsListener.class, event));
+        Boolean eventMatch = eventMatchCache.get(System.identityHashCode(event.getClass()));
+        if (eventMatch == null) {
+            eventMatch = ReflectionUtils.match(getClass(), AbstractMetricsListener.class, event);
+            eventMatchCache.put(System.identityHashCode(event.getClass()), eventMatch);
+        }
         return event.isAvailable() && eventMatch;
     }
 
diff --git a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/listener/MetricsApplicationListener.java b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/listener/MetricsApplicationListener.java
index 27835e59eb..57d52ccb29 100644
--- a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/listener/MetricsApplicationListener.java
+++ b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/listener/MetricsApplicationListener.java
@@ -37,7 +37,7 @@ public class MetricsApplicationListener extends AbstractMetricsKeyListener {
         return AbstractMetricsKeyListener.onFinish(metricsKey,
                 event -> {
                     collector.increment(metricsKey);
-                    collector.addRt(placeType.getType(), event.getTimePair().calc());
+                    collector.addApplicationRt(placeType.getType(), event.getTimePair().calc());
                 }
         );
     }
@@ -46,7 +46,7 @@ public class MetricsApplicationListener extends AbstractMetricsKeyListener {
         return AbstractMetricsKeyListener.onError(metricsKey,
                 event -> {
                     collector.increment(metricsKey);
-                    collector.addRt(placeType.getType(), event.getTimePair().calc());
+                    collector.addApplicationRt(placeType.getType(), event.getTimePair().calc());
                 }
         );
     }
diff --git a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/model/ApplicationMetric.java b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/model/ApplicationMetric.java
index 4b7d0a8cc5..6752139e89 100644
--- a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/model/ApplicationMetric.java
+++ b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/model/ApplicationMetric.java
@@ -72,8 +72,13 @@ public class ApplicationMetric implements Metric {
         return Objects.equals(getApplicationName(), that.applicationModel.getApplicationName());
     }
 
+    private volatile int hashCode;
+
     @Override
     public int hashCode() {
-        return Objects.hash(getApplicationName());
+        if (hashCode == 0) {
+            hashCode = Objects.hash(getApplicationName());
+        }
+        return hashCode;
     }
 }
diff --git a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/model/MethodMetric.java b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/model/MethodMetric.java
index 86195f6e8e..c376fdd57d 100644
--- a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/model/MethodMetric.java
+++ b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/model/MethodMetric.java
@@ -17,7 +17,6 @@
 
 package org.apache.dubbo.metrics.model;
 
-import org.apache.dubbo.metrics.model.sample.MetricSample;
 import org.apache.dubbo.rpc.Invocation;
 import org.apache.dubbo.rpc.model.ApplicationModel;
 import org.apache.dubbo.rpc.support.RpcUtils;
@@ -27,7 +26,6 @@ import java.util.Objects;
 
 import static org.apache.dubbo.common.constants.MetricsConstants.TAG_GROUP_KEY;
 import static org.apache.dubbo.common.constants.MetricsConstants.TAG_VERSION_KEY;
-import static org.apache.dubbo.metrics.MetricsConstants.INVOCATION_METRICS_COUNTER;
 
 /**
  * Metric class for method.
@@ -37,7 +35,6 @@ public class MethodMetric extends ServiceKeyMetric {
     private final String methodName;
     private String group;
     private String version;
-    private final MetricSample.Type sampleType;
 
     public MethodMetric(ApplicationModel applicationModel, Invocation invocation) {
         super(applicationModel, MetricsSupport.getInterfaceName(invocation));
@@ -45,11 +42,6 @@ public class MethodMetric extends ServiceKeyMetric {
         this.side = MetricsSupport.getSide(invocation);
         this.group = MetricsSupport.getGroup(invocation);
         this.version = MetricsSupport.getVersion(invocation);
-        this.sampleType = (MetricSample.Type) invocation.get(INVOCATION_METRICS_COUNTER);
-    }
-
-    public MetricSample.Type getSampleType() {
-        return sampleType;
     }
 
     public String getGroup() {
@@ -104,11 +96,15 @@ public class MethodMetric extends ServiceKeyMetric {
         if (this == o) return true;
         if (o == null || getClass() != o.getClass()) return false;
         MethodMetric that = (MethodMetric) o;
-        return Objects.equals(getApplicationName(), that.getApplicationName()) && Objects.equals(side, that.side) && Objects.equals(getServiceKey(), that.getServiceKey()) && Objects.equals(methodName, that.methodName) && Objects.equals(group, that.group) && Objects.equals(version, that.version);
+        return Objects.equals(getApplicationModel(), that.getApplicationModel()) && Objects.equals(side, that.side) && Objects.equals(getServiceKey(), that.getServiceKey()) && Objects.equals(methodName, that.methodName) && Objects.equals(group, that.group) && Objects.equals(version, that.version);
     }
 
+    private volatile int hashCode = 0;
     @Override
     public int hashCode() {
-        return Objects.hash(getApplicationName(), side, getServiceKey(), methodName, group, version);
+        if (hashCode == 0) {
+            hashCode = Objects.hash(getApplicationModel(), side, getServiceKey(), methodName, group, version);
+        }
+        return hashCode;
     }
 }
diff --git a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/model/MetricsSupport.java b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/model/MetricsSupport.java
index b444f7a4a7..5025926596 100644
--- a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/model/MetricsSupport.java
+++ b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/model/MetricsSupport.java
@@ -53,6 +53,7 @@ import static org.apache.dubbo.common.utils.NetUtils.getLocalHost;
 import static org.apache.dubbo.common.utils.NetUtils.getLocalHostName;
 import static org.apache.dubbo.metrics.MetricsConstants.ATTACHMENT_KEY_SERVICE;
 import static org.apache.dubbo.metrics.MetricsConstants.INVOCATION;
+import static org.apache.dubbo.metrics.MetricsConstants.METHOD_METRICS;
 import static org.apache.dubbo.metrics.MetricsConstants.SELF_INCREMENT_SIZE;
 
 public class MetricsSupport {
@@ -145,38 +146,50 @@ public class MetricsSupport {
 
 
     public static String getInterfaceName(Invocation invocation) {
-        String serviceUniqueName = invocation.getTargetServiceUniqueName();
-        String interfaceAndVersion;
-        String[] arr = serviceUniqueName.split(PATH_SEPARATOR);
-        if (arr.length == 2) {
-            interfaceAndVersion = arr[1];
+        if (invocation.getServiceModel() != null && invocation.getServiceModel().getServiceMetadata() != null) {
+            return invocation.getServiceModel().getServiceMetadata().getServiceInterfaceName();
         } else {
-            interfaceAndVersion = arr[0];
+            String serviceUniqueName = invocation.getTargetServiceUniqueName();
+            String interfaceAndVersion;
+            String[] arr = serviceUniqueName.split(PATH_SEPARATOR);
+            if (arr.length == 2) {
+                interfaceAndVersion = arr[1];
+            } else {
+                interfaceAndVersion = arr[0];
+            }
+            String[] ivArr = interfaceAndVersion.split(GROUP_CHAR_SEPARATOR);
+            return ivArr[0];
         }
-        String[] ivArr = interfaceAndVersion.split(GROUP_CHAR_SEPARATOR);
-        return ivArr[0];
     }
 
     public static String getGroup(Invocation invocation) {
-        String serviceUniqueName = invocation.getTargetServiceUniqueName();
-        String group = null;
-        String[] arr = serviceUniqueName.split(PATH_SEPARATOR);
-        if (arr.length == 2) {
-            group = arr[0];
+        if (invocation.getServiceModel() != null && invocation.getServiceModel().getServiceMetadata() != null) {
+            return invocation.getServiceModel().getServiceMetadata().getGroup();
+        } else {
+            String serviceUniqueName = invocation.getTargetServiceUniqueName();
+            String group = null;
+            String[] arr = serviceUniqueName.split(PATH_SEPARATOR);
+            if (arr.length == 2) {
+                group = arr[0];
+            }
+            return group;
         }
-        return group;
     }
 
     public static String getVersion(Invocation invocation) {
-        String interfaceAndVersion;
-        String[] arr = invocation.getTargetServiceUniqueName().split(PATH_SEPARATOR);
-        if (arr.length == 2) {
-            interfaceAndVersion = arr[1];
+        if (invocation.getServiceModel() != null && invocation.getServiceModel().getServiceMetadata() != null) {
+            return invocation.getServiceModel().getServiceMetadata().getVersion();
         } else {
-            interfaceAndVersion = arr[0];
+            String interfaceAndVersion;
+            String[] arr = invocation.getTargetServiceUniqueName().split(PATH_SEPARATOR);
+            if (arr.length == 2) {
+                interfaceAndVersion = arr[1];
+            } else {
+                interfaceAndVersion = arr[0];
+            }
+            String[] ivArr = interfaceAndVersion.split(GROUP_CHAR_SEPARATOR);
+            return ivArr.length == 2 ? ivArr[1] : null;
         }
-        String[] ivArr = interfaceAndVersion.split(GROUP_CHAR_SEPARATOR);
-        return ivArr.length == 2 ? ivArr[1] : null;
     }
 
     /**
@@ -191,29 +204,35 @@ public class MetricsSupport {
      */
     public static void incrAndAddRt(MetricsKey metricsKey, MetricsPlaceValue placeType, ServiceMetricsCollector<TimeCounterEvent> collector, TimeCounterEvent event) {
         collector.increment(event.getAttachmentValue(ATTACHMENT_KEY_SERVICE), new MetricsKeyWrapper(metricsKey, placeType), SELF_INCREMENT_SIZE);
-        collector.addRt(event.getAttachmentValue(ATTACHMENT_KEY_SERVICE), placeType.getType(), event.getTimePair().calc());
+        Invocation invocation = event.getAttachmentValue(INVOCATION);
+        if (invocation != null) {
+            collector.addServiceRt(invocation, placeType.getType(), event.getTimePair().calc());
+            return;
+        } else {
+            collector.addServiceRt((String) event.getAttachmentValue(ATTACHMENT_KEY_SERVICE), placeType.getType(), event.getTimePair().calc());
+        }
     }
 
     /**
      * Incr method num
      */
     public static void increment(MetricsKey metricsKey, MetricsPlaceValue placeType, MethodMetricsCollector<TimeCounterEvent> collector, MetricsEvent event) {
-        collector.increment(event.getAttachmentValue(INVOCATION), new MetricsKeyWrapper(metricsKey, placeType), SELF_INCREMENT_SIZE);
+        collector.increment(event.getAttachmentValue(METHOD_METRICS), new MetricsKeyWrapper(metricsKey, placeType), SELF_INCREMENT_SIZE);
     }
 
     /**
      * Dec method num
      */
     public static void dec(MetricsKey metricsKey, MetricsPlaceValue placeType, MethodMetricsCollector<TimeCounterEvent> collector, MetricsEvent event) {
-        collector.increment(event.getAttachmentValue(INVOCATION), new MetricsKeyWrapper(metricsKey, placeType), -SELF_INCREMENT_SIZE);
+        collector.increment(event.getAttachmentValue(METHOD_METRICS), new MetricsKeyWrapper(metricsKey, placeType), -SELF_INCREMENT_SIZE);
     }
 
     /**
      * Incr method num&&rt
      */
     public static void incrAndAddRt(MetricsKey metricsKey, MetricsPlaceValue placeType, MethodMetricsCollector<TimeCounterEvent> collector, TimeCounterEvent event) {
-        collector.increment(event.getAttachmentValue(INVOCATION), new MetricsKeyWrapper(metricsKey, placeType), SELF_INCREMENT_SIZE);
-        collector.addRt(event.getAttachmentValue(INVOCATION), placeType.getType(), event.getTimePair().calc());
+        collector.increment(event.getAttachmentValue(METHOD_METRICS), new MetricsKeyWrapper(metricsKey, placeType), SELF_INCREMENT_SIZE);
+        collector.addMethodRt(event.getAttachmentValue(INVOCATION), placeType.getType(), event.getTimePair().calc());
     }
 
     /**
diff --git a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/model/ServiceKeyMetric.java b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/model/ServiceKeyMetric.java
index ae3ff0df24..1b1d220cea 100644
--- a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/model/ServiceKeyMetric.java
+++ b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/model/ServiceKeyMetric.java
@@ -20,6 +20,7 @@ package org.apache.dubbo.metrics.model;
 import org.apache.dubbo.rpc.model.ApplicationModel;
 
 import java.util.Map;
+import java.util.Objects;
 
 /**
  * Metric class for service.
@@ -58,11 +59,15 @@ public class ServiceKeyMetric extends ApplicationMetric {
         return serviceKey.equals(that.serviceKey);
     }
 
+
+    private volatile int hashCode = 0;
+
     @Override
     public int hashCode() {
-        int result = getApplicationName().hashCode();
-        result = 31 * result + serviceKey.hashCode();
-        return result;
+        if (hashCode == 0) {
+            hashCode = Objects.hash(getApplicationName(), serviceKey);
+        }
+        return hashCode;
     }
 
     @Override
diff --git a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/model/container/LongContainer.java b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/model/container/LongContainer.java
index fd7b10e81f..dad8fce4bf 100644
--- a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/model/container/LongContainer.java
+++ b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/model/container/LongContainer.java
@@ -18,8 +18,8 @@
 package org.apache.dubbo.metrics.model.container;
 
 import org.apache.dubbo.metrics.model.Metric;
-import org.apache.dubbo.metrics.model.key.MetricsKeyWrapper;
 import org.apache.dubbo.metrics.model.key.MetricsKey;
+import org.apache.dubbo.metrics.model.key.MetricsKeyWrapper;
 import org.apache.dubbo.metrics.model.sample.GaugeMetricSample;
 
 import java.util.concurrent.ConcurrentHashMap;
@@ -52,6 +52,7 @@ public class LongContainer<N extends Number> extends ConcurrentHashMap<Metric, N
 
 
     public LongContainer(MetricsKeyWrapper metricsKeyWrapper, Supplier<N> initFunc, BiConsumer<Long, N> consumerFunc) {
+        super(128, 0.5f);
         this.metricsKeyWrapper = metricsKeyWrapper;
         this.initFunc = s -> initFunc.get();
         this.consumerFunc = consumerFunc;
diff --git a/dubbo-metrics/dubbo-metrics-api/src/test/java/org/apache/dubbo/metrics/event/SimpleMetricsEventMulticasterTest.java b/dubbo-metrics/dubbo-metrics-api/src/test/java/org/apache/dubbo/metrics/event/SimpleMetricsEventMulticasterTest.java
index c18627b584..1e3b2f4c56 100644
--- a/dubbo-metrics/dubbo-metrics-api/src/test/java/org/apache/dubbo/metrics/event/SimpleMetricsEventMulticasterTest.java
+++ b/dubbo-metrics/dubbo-metrics-api/src/test/java/org/apache/dubbo/metrics/event/SimpleMetricsEventMulticasterTest.java
@@ -22,6 +22,7 @@ import org.apache.dubbo.config.context.ConfigManager;
 import org.apache.dubbo.metrics.listener.AbstractMetricsListener;
 import org.apache.dubbo.metrics.listener.MetricsLifeListener;
 import org.apache.dubbo.rpc.model.ApplicationModel;
+
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
diff --git a/dubbo-metrics/dubbo-metrics-config-center/src/main/java/org/apache/dubbo/metrics/config/event/ConfigCenterEvent.java b/dubbo-metrics/dubbo-metrics-config-center/src/main/java/org/apache/dubbo/metrics/config/event/ConfigCenterEvent.java
index 3c1577a700..ddf4f88fdb 100644
--- a/dubbo-metrics/dubbo-metrics-config-center/src/main/java/org/apache/dubbo/metrics/config/event/ConfigCenterEvent.java
+++ b/dubbo-metrics/dubbo-metrics-config-center/src/main/java/org/apache/dubbo/metrics/config/event/ConfigCenterEvent.java
@@ -44,7 +44,7 @@ public class ConfigCenterEvent extends TimeCounterEvent {
 
 
     public ConfigCenterEvent(ApplicationModel applicationModel, TypeWrapper typeWrapper) {
-        super(applicationModel,typeWrapper);
+        super(applicationModel, typeWrapper);
         ScopeBeanFactory beanFactory = applicationModel.getBeanFactory();
         ConfigCenterMetricsCollector collector;
         if (!beanFactory.isDestroyed()) {
diff --git a/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/event/DefaultSubDispatcher.java b/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/event/DefaultSubDispatcher.java
index 5bcbc20469..94228172fc 100644
--- a/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/event/DefaultSubDispatcher.java
+++ b/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/event/DefaultSubDispatcher.java
@@ -50,9 +50,10 @@ public final class DefaultSubDispatcher extends SimpleMetricsEventMulticaster {
                 return event instanceof RequestBeforeEvent;
             }
 
+
+            private final MetricsPlaceValue dynamicPlaceType = MetricsPlaceValue.of(CommonConstants.CONSUMER, MetricsLevel.METHOD);
             @Override
             public void onEvent(RequestBeforeEvent event) {
-                MetricsPlaceValue dynamicPlaceType = MetricsPlaceValue.of(CommonConstants.CONSUMER, MetricsLevel.METHOD);
                 MetricsSupport.increment(METRIC_REQUESTS_SERVICE_UNAVAILABLE_FAILED, dynamicPlaceType, (MethodMetricsCollector) collector, event);
             }
         });
diff --git a/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/event/RequestBeforeEvent.java b/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/event/RequestBeforeEvent.java
index cad2de5e5a..5b7d7c64da 100644
--- a/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/event/RequestBeforeEvent.java
+++ b/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/event/RequestBeforeEvent.java
@@ -18,6 +18,7 @@
 package org.apache.dubbo.metrics.event;
 
 import org.apache.dubbo.metrics.MetricsConstants;
+import org.apache.dubbo.metrics.model.MethodMetric;
 import org.apache.dubbo.metrics.model.MetricsSupport;
 import org.apache.dubbo.metrics.model.key.MetricsKey;
 import org.apache.dubbo.metrics.model.key.MetricsLevel;
@@ -32,16 +33,18 @@ import static org.apache.dubbo.metrics.MetricsConstants.ATTACHMENT_KEY_SERVICE;
  */
 public class RequestBeforeEvent extends TimeCounterEvent {
 
-    public RequestBeforeEvent(ApplicationModel source, TypeWrapper typeWrapper) {
-        super(source, typeWrapper);
+    public RequestBeforeEvent(ApplicationModel source, String appName, MetricsDispatcher metricsDispatcher, TypeWrapper typeWrapper) {
+        super(source, appName, metricsDispatcher, typeWrapper);
 
     }
 
-    public static RequestBeforeEvent toEvent(ApplicationModel applicationModel, Invocation invocation) {
-        RequestBeforeEvent event = new RequestBeforeEvent(applicationModel, new TypeWrapper(MetricsLevel.METHOD, MetricsKey.METRIC_REQUESTS));
+    private static final TypeWrapper REQUEST_BEFORE_EVENT = new TypeWrapper(MetricsLevel.METHOD, MetricsKey.METRIC_REQUESTS);
+    public static RequestBeforeEvent toEvent(ApplicationModel applicationModel, String appName, MetricsDispatcher metricsDispatcher, Invocation invocation, String side) {
+        RequestBeforeEvent event = new RequestBeforeEvent(applicationModel, appName, metricsDispatcher, REQUEST_BEFORE_EVENT);
         event.putAttachment(ATTACHMENT_KEY_SERVICE, MetricsSupport.getInterfaceName(invocation));
-        event.putAttachment(MetricsConstants.INVOCATION_SIDE, MetricsSupport.getSide(invocation));
+        event.putAttachment(MetricsConstants.INVOCATION_SIDE, side);
         event.putAttachment(MetricsConstants.INVOCATION, invocation);
+        event.putAttachment(MetricsConstants.METHOD_METRICS, new MethodMetric(applicationModel, invocation));
         return event;
     }
 
diff --git a/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/event/RequestEvent.java b/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/event/RequestEvent.java
index 13eafa48a1..acb0aad159 100644
--- a/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/event/RequestEvent.java
+++ b/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/event/RequestEvent.java
@@ -21,6 +21,7 @@ import org.apache.dubbo.common.beans.factory.ScopeBeanFactory;
 import org.apache.dubbo.metrics.MetricsConstants;
 import org.apache.dubbo.metrics.collector.DefaultMetricsCollector;
 import org.apache.dubbo.metrics.exception.MetricsNeverHappenException;
+import org.apache.dubbo.metrics.model.MethodMetric;
 import org.apache.dubbo.metrics.model.MetricsSupport;
 import org.apache.dubbo.metrics.model.key.MetricsLevel;
 import org.apache.dubbo.metrics.model.key.TypeWrapper;
@@ -38,34 +39,39 @@ import static org.apache.dubbo.metrics.model.key.MetricsKey.METRIC_REQUEST_BUSIN
  * Request related events
  */
 public class RequestEvent extends TimeCounterEvent {
-    public RequestEvent(ApplicationModel applicationModel, TypeWrapper typeWrapper) {
-        super(applicationModel,typeWrapper);
-        ScopeBeanFactory beanFactory = applicationModel.getBeanFactory();
-        DefaultMetricsCollector collector;
-        if (!beanFactory.isDestroyed()) {
-            collector = beanFactory.getBean(DefaultMetricsCollector.class);
-            super.setAvailable(collector != null && collector.isCollectEnabled());
+    private static final TypeWrapper TYPE_WRAPPER = new TypeWrapper(MetricsLevel.SERVICE, METRIC_REQUESTS, METRIC_REQUESTS_SUCCEED, METRIC_REQUEST_BUSINESS_FAILED);
+
+    public RequestEvent(ApplicationModel applicationModel, String appName, MetricsDispatcher metricsDispatcher, DefaultMetricsCollector collector, TypeWrapper TYPE_WRAPPER) {
+        super(applicationModel, appName, metricsDispatcher, TYPE_WRAPPER);
+        if (collector == null) {
+            ScopeBeanFactory beanFactory = applicationModel.getBeanFactory();
+            if (!beanFactory.isDestroyed()) {
+                collector = beanFactory.getBean(DefaultMetricsCollector.class);
+            }
         }
+        super.setAvailable(collector != null && collector.isCollectEnabled());
     }
 
-    public static RequestEvent toRequestEvent(ApplicationModel applicationModel, Invocation invocation) {
-        RequestEvent requestEvent = new RequestEvent(applicationModel, new TypeWrapper(MetricsLevel.SERVICE, METRIC_REQUESTS, METRIC_REQUESTS_SUCCEED, METRIC_REQUEST_BUSINESS_FAILED)) {
-            @Override
-            public void customAfterPost(Object postResult) {
-                if (postResult == null) {
-                    return;
-                }
-                if (!(postResult instanceof Result)) {
-                    throw new MetricsNeverHappenException("Result type error, postResult:" + postResult.getClass().getName());
-                }
-                super.putAttachment(METRIC_THROWABLE, ((Result) postResult).getException());
-            }
-        };
+    public static RequestEvent toRequestEvent(ApplicationModel applicationModel, String appName,
+                                              MetricsDispatcher metricsDispatcher, DefaultMetricsCollector collector,
+                                              Invocation invocation, String side) {
+        MethodMetric methodMetric = new MethodMetric(applicationModel, invocation);
+        RequestEvent requestEvent = new RequestEvent(applicationModel, appName, metricsDispatcher, collector, TYPE_WRAPPER);
         requestEvent.putAttachment(MetricsConstants.INVOCATION, invocation);
+        requestEvent.putAttachment(MetricsConstants.METHOD_METRICS, methodMetric);
         requestEvent.putAttachment(ATTACHMENT_KEY_SERVICE, MetricsSupport.getInterfaceName(invocation));
-        requestEvent.putAttachment(MetricsConstants.INVOCATION_SIDE, MetricsSupport.getSide(invocation));
+        requestEvent.putAttachment(MetricsConstants.INVOCATION_SIDE, side);
         return requestEvent;
     }
 
-
+    @Override
+    public void customAfterPost(Object postResult) {
+        if (postResult == null) {
+            return;
+        }
+        if (!(postResult instanceof Result)) {
+            throw new MetricsNeverHappenException("Result type error, postResult:" + postResult.getClass().getName());
+        }
+        super.putAttachment(METRIC_THROWABLE, ((Result) postResult).getException());
+    }
 }
diff --git a/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/filter/MetricsFilter.java b/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/filter/MetricsFilter.java
index 7b92276f33..2492b78b70 100644
--- a/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/filter/MetricsFilter.java
+++ b/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/filter/MetricsFilter.java
@@ -16,14 +16,14 @@
  */
 package org.apache.dubbo.metrics.filter;
 
-import org.apache.dubbo.common.extension.Activate;
 import org.apache.dubbo.common.logger.ErrorTypeAwareLogger;
 import org.apache.dubbo.common.logger.LoggerFactory;
 import org.apache.dubbo.config.MetricsConfig;
+import org.apache.dubbo.metrics.collector.DefaultMetricsCollector;
+import org.apache.dubbo.metrics.event.MetricsDispatcher;
 import org.apache.dubbo.metrics.event.MetricsEventBus;
 import org.apache.dubbo.metrics.event.RequestEvent;
-import org.apache.dubbo.rpc.BaseFilter;
-import org.apache.dubbo.rpc.Filter;
+import org.apache.dubbo.metrics.model.MetricsSupport;
 import org.apache.dubbo.rpc.Invocation;
 import org.apache.dubbo.rpc.Invoker;
 import org.apache.dubbo.rpc.Result;
@@ -37,25 +37,35 @@ import static org.apache.dubbo.common.constants.LoggerCodeConstants.INTERNAL_ERR
 import static org.apache.dubbo.metrics.DefaultConstants.METRIC_FILTER_EVENT;
 import static org.apache.dubbo.metrics.DefaultConstants.METRIC_THROWABLE;
 
-@Activate(group = {CONSUMER, PROVIDER}, order = Integer.MIN_VALUE + 100)
-public class MetricsFilter implements Filter, BaseFilter.Listener, ScopeModelAware {
+public class MetricsFilter implements ScopeModelAware {
 
     private ApplicationModel applicationModel;
     private static final ErrorTypeAwareLogger LOGGER = LoggerFactory.getErrorTypeAwareLogger(MetricsFilter.class);
     private boolean rpcMetricsEnable;
+    private String appName;
+    private MetricsDispatcher metricsDispatcher;
+    private DefaultMetricsCollector defaultMetricsCollector;
 
     @Override
     public void setApplicationModel(ApplicationModel applicationModel) {
         this.applicationModel = applicationModel;
         this.rpcMetricsEnable = applicationModel.getApplicationConfigManager().getMetrics().map(MetricsConfig::getEnableRpc).orElse(true);
+        this.appName = applicationModel.tryGetApplicationName();
+        this.metricsDispatcher = applicationModel.getBeanFactory().getBean(MetricsDispatcher.class);
+        this.defaultMetricsCollector = applicationModel.getBeanFactory().getBean(DefaultMetricsCollector.class);
     }
 
-    @Override
     public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
+        return invoke(invoker, invocation, PROVIDER.equals(MetricsSupport.getSide(invocation)));
+    }
+
+    public Result invoke(Invoker<?> invoker, Invocation invocation, boolean isProvider) throws RpcException {
         if (rpcMetricsEnable) {
             try {
-                RequestEvent requestEvent = RequestEvent.toRequestEvent(applicationModel, invocation);
-                MetricsEventBus.before(requestEvent, () -> invocation.put(METRIC_FILTER_EVENT, requestEvent));
+                RequestEvent requestEvent = RequestEvent.toRequestEvent(applicationModel, appName, metricsDispatcher,
+                    defaultMetricsCollector, invocation, isProvider ? PROVIDER : CONSUMER);
+                MetricsEventBus.before(requestEvent);
+                invocation.put(METRIC_FILTER_EVENT, requestEvent);
             } catch (Throwable t) {
                 LOGGER.warn(INTERNAL_ERROR, "", "", "Error occurred when invoke.", t);
             }
@@ -63,8 +73,11 @@ public class MetricsFilter implements Filter, BaseFilter.Listener, ScopeModelAwa
         return invoker.invoke(invocation);
     }
 
-    @Override
     public void onResponse(Result result, Invoker<?> invoker, Invocation invocation) {
+        onResponse(result, invoker, invocation, PROVIDER.equals(MetricsSupport.getSide(invocation)));
+    }
+
+    public void onResponse(Result result, Invoker<?> invoker, Invocation invocation, boolean isProvider) {
         Object eventObj = invocation.get(METRIC_FILTER_EVENT);
         if (eventObj != null) {
             try {
@@ -75,8 +88,11 @@ public class MetricsFilter implements Filter, BaseFilter.Listener, ScopeModelAwa
         }
     }
 
-    @Override
     public void onError(Throwable t, Invoker<?> invoker, Invocation invocation) {
+        onError(t, invoker, invocation, PROVIDER.equals(MetricsSupport.getSide(invocation)));
+    }
+
+    public void onError(Throwable t, Invoker<?> invoker, Invocation invocation, boolean isProvider) {
         Object eventObj = invocation.get(METRIC_FILTER_EVENT);
         if (eventObj != null) {
             try {
diff --git a/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/filter/MetricsProviderFilter.java b/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/filter/MetricsProviderFilter.java
new file mode 100644
index 0000000000..68502bdfba
--- /dev/null
+++ b/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/filter/MetricsProviderFilter.java
@@ -0,0 +1,48 @@
+/*
+ * 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.dubbo.metrics.filter;
+
+import org.apache.dubbo.common.extension.Activate;
+import org.apache.dubbo.rpc.BaseFilter;
+import org.apache.dubbo.rpc.Filter;
+import org.apache.dubbo.rpc.Invocation;
+import org.apache.dubbo.rpc.Invoker;
+import org.apache.dubbo.rpc.Result;
+import org.apache.dubbo.rpc.RpcException;
+
+import static org.apache.dubbo.common.constants.CommonConstants.PROVIDER;
+
+@Activate(group = {PROVIDER}, order = Integer.MIN_VALUE + 100)
+public class MetricsProviderFilter extends MetricsFilter implements Filter, BaseFilter.Listener {
+    public MetricsProviderFilter() {
+    }
+
+    @Override
+    public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
+        return super.invoke(invoker, invocation, true);
+    }
+
+    @Override
+    public void onResponse(Result appResponse, Invoker<?> invoker, Invocation invocation) {
+        super.onResponse(appResponse, invoker, invocation, true);
+    }
+
+    @Override
+    public void onError(Throwable t, Invoker<?> invoker, Invocation invocation) {
+        super.onError(t, invoker, invocation, true);
+    }
+}
diff --git a/dubbo-metrics/dubbo-metrics-default/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.Filter b/dubbo-metrics/dubbo-metrics-default/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.Filter
index 5ee6c1d455..68097181d6 100644
--- a/dubbo-metrics/dubbo-metrics-default/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.Filter
+++ b/dubbo-metrics/dubbo-metrics-default/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.Filter
@@ -1,2 +1,2 @@
-metrics-beta=org.apache.dubbo.metrics.filter.MetricsFilter
-observationreceiver=org.apache.dubbo.metrics.observation.ObservationReceiverFilter
\ No newline at end of file
+metrics-provider=org.apache.dubbo.metrics.filter.MetricsProviderFilter
+observationreceiver=org.apache.dubbo.metrics.observation.ObservationReceiverFilter
diff --git a/dubbo-metrics/dubbo-metrics-default/src/test/java/org/apache/dubbo/metrics/collector/AggregateMetricsCollectorTest.java b/dubbo-metrics/dubbo-metrics-default/src/test/java/org/apache/dubbo/metrics/collector/AggregateMetricsCollectorTest.java
index 383dac76f9..a99be4735d 100644
--- a/dubbo-metrics/dubbo-metrics-default/src/test/java/org/apache/dubbo/metrics/collector/AggregateMetricsCollectorTest.java
+++ b/dubbo-metrics/dubbo-metrics-default/src/test/java/org/apache/dubbo/metrics/collector/AggregateMetricsCollectorTest.java
@@ -50,6 +50,7 @@ import org.apache.dubbo.rpc.RpcContext;
 import org.apache.dubbo.rpc.RpcException;
 import org.apache.dubbo.rpc.RpcInvocation;
 import org.apache.dubbo.rpc.model.ApplicationModel;
+
 import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.BeforeEach;
@@ -141,8 +142,8 @@ class AggregateMetricsCollectorTest {
     @Test
     void testListener() {
         AggregateMetricsCollector metricsCollector = new AggregateMetricsCollector(applicationModel);
-        RequestEvent event = RequestEvent.toRequestEvent(applicationModel, invocation);
-        RequestBeforeEvent beforeEvent = new RequestBeforeEvent(applicationModel, new TypeWrapper(MetricsLevel.METHOD, MetricsKey.METRIC_REQUESTS));
+        RequestEvent event = RequestEvent.toRequestEvent(applicationModel, null, null, null, invocation, MetricsSupport.getSide(invocation));
+        RequestBeforeEvent beforeEvent = new RequestBeforeEvent(applicationModel, null, null, new TypeWrapper(MetricsLevel.METHOD, MetricsKey.METRIC_REQUESTS));
         Assertions.assertTrue(metricsCollector.isSupport(event));
         Assertions.assertFalse(metricsCollector.isSupport(beforeEvent));
     }
@@ -248,7 +249,7 @@ class AggregateMetricsCollectorTest {
         rtList.add(30L);
 
         for (Long requestTime: rtList) {
-            RequestEvent requestEvent = RequestEvent.toRequestEvent(applicationModel, invocation);
+            RequestEvent requestEvent = RequestEvent.toRequestEvent(applicationModel, null, null, null, invocation, MetricsSupport.getSide(invocation));
             TestRequestEvent testRequestEvent = new TestRequestEvent(requestEvent.getSource(), requestEvent.getTypeWrapper());
             testRequestEvent.putAttachment(MetricsConstants.INVOCATION, invocation);
             testRequestEvent.putAttachment(ATTACHMENT_KEY_SERVICE, MetricsSupport.getInterfaceName(invocation));
@@ -298,7 +299,7 @@ class AggregateMetricsCollectorTest {
         double manualP99 = requestTimes.get((int) Math.round(p99Index));
 
         for (Long requestTime : requestTimes) {
-            RequestEvent requestEvent = RequestEvent.toRequestEvent(applicationModel, invocation);
+            RequestEvent requestEvent = RequestEvent.toRequestEvent(applicationModel, null, null, null, invocation, MetricsSupport.getSide(invocation));
             TestRequestEvent testRequestEvent = new TestRequestEvent(requestEvent.getSource(), requestEvent.getTypeWrapper());
             testRequestEvent.putAttachment(MetricsConstants.INVOCATION, invocation);
             testRequestEvent.putAttachment(ATTACHMENT_KEY_SERVICE, MetricsSupport.getInterfaceName(invocation));
@@ -345,7 +346,7 @@ class AggregateMetricsCollectorTest {
         private long rt;
 
         public TestRequestEvent(ApplicationModel applicationModel, TypeWrapper typeWrapper) {
-            super(applicationModel, typeWrapper);
+            super(applicationModel, null, null, null, typeWrapper);
         }
 
         public void setRt(long rt) {
diff --git a/dubbo-metrics/dubbo-metrics-default/src/test/java/org/apache/dubbo/metrics/collector/DefaultCollectorTest.java b/dubbo-metrics/dubbo-metrics-default/src/test/java/org/apache/dubbo/metrics/collector/DefaultCollectorTest.java
index 0ebe6596f9..6113908990 100644
--- a/dubbo-metrics/dubbo-metrics-default/src/test/java/org/apache/dubbo/metrics/collector/DefaultCollectorTest.java
+++ b/dubbo-metrics/dubbo-metrics-default/src/test/java/org/apache/dubbo/metrics/collector/DefaultCollectorTest.java
@@ -25,6 +25,7 @@ import org.apache.dubbo.metrics.event.MetricsDispatcher;
 import org.apache.dubbo.metrics.event.RequestBeforeEvent;
 import org.apache.dubbo.metrics.event.RequestEvent;
 import org.apache.dubbo.metrics.filter.MetricsFilter;
+import org.apache.dubbo.metrics.model.MetricsSupport;
 import org.apache.dubbo.metrics.model.ServiceKeyMetric;
 import org.apache.dubbo.metrics.model.key.MetricsKey;
 import org.apache.dubbo.metrics.model.key.MetricsKeyWrapper;
@@ -112,8 +113,8 @@ class DefaultCollectorTest {
     @Test
     void testListener() {
         DefaultMetricsCollector metricsCollector = new DefaultMetricsCollector(applicationModel);
-        RequestEvent event = RequestEvent.toRequestEvent(applicationModel, invocation);
-        RequestBeforeEvent beforeEvent = new RequestBeforeEvent(applicationModel, new TypeWrapper(MetricsLevel.METHOD, MetricsKey.METRIC_REQUESTS));
+        RequestEvent event = RequestEvent.toRequestEvent(applicationModel, null, null, null, invocation, MetricsSupport.getSide(invocation));
+        RequestBeforeEvent beforeEvent = new RequestBeforeEvent(applicationModel, null, null, new TypeWrapper(MetricsLevel.METHOD, MetricsKey.METRIC_REQUESTS));
         Assertions.assertTrue(metricsCollector.isSupport(event));
         Assertions.assertTrue(metricsCollector.isSupport(beforeEvent));
     }
diff --git a/dubbo-metrics/dubbo-metrics-metadata/src/main/java/org/apache/dubbo/metrics/metadata/event/MetadataEvent.java b/dubbo-metrics/dubbo-metrics-metadata/src/main/java/org/apache/dubbo/metrics/metadata/event/MetadataEvent.java
index 95af81c33f..2222bda162 100644
--- a/dubbo-metrics/dubbo-metrics-metadata/src/main/java/org/apache/dubbo/metrics/metadata/event/MetadataEvent.java
+++ b/dubbo-metrics/dubbo-metrics-metadata/src/main/java/org/apache/dubbo/metrics/metadata/event/MetadataEvent.java
@@ -40,7 +40,7 @@ import static org.apache.dubbo.metrics.model.key.MetricsKey.STORE_PROVIDER_METAD
  */
 public class MetadataEvent extends TimeCounterEvent {
     public MetadataEvent(ApplicationModel applicationModel, TypeWrapper typeWrapper) {
-        super(applicationModel,typeWrapper);
+        super(applicationModel, typeWrapper);
         ScopeBeanFactory beanFactory = applicationModel.getBeanFactory();
         MetadataMetricsCollector collector;
         if (!beanFactory.isDestroyed()) {
diff --git a/dubbo-metrics/dubbo-metrics-metadata/src/test/java/org/apache/dubbo/metrics/metadata/MetadataMetricsCollectorTest.java b/dubbo-metrics/dubbo-metrics-metadata/src/test/java/org/apache/dubbo/metrics/metadata/MetadataMetricsCollectorTest.java
index bce692123c..564b0ba9c5 100644
--- a/dubbo-metrics/dubbo-metrics-metadata/src/test/java/org/apache/dubbo/metrics/metadata/MetadataMetricsCollectorTest.java
+++ b/dubbo-metrics/dubbo-metrics-metadata/src/test/java/org/apache/dubbo/metrics/metadata/MetadataMetricsCollectorTest.java
@@ -71,7 +71,7 @@ class MetadataMetricsCollectorTest {
     @Test
     void testListener() {
         MetadataEvent event = MetadataEvent.toPushEvent(applicationModel);
-        MetricsEvent otherEvent = new MetricsEvent(applicationModel,null){
+        MetricsEvent otherEvent = new MetricsEvent(applicationModel,null, null, null){
         };
         Assertions.assertTrue(collector.isSupport(event));
         Assertions.assertFalse(collector.isSupport(otherEvent));
diff --git a/dubbo-metrics/dubbo-metrics-registry/src/main/java/org/apache/dubbo/metrics/registry/event/RegistryEvent.java b/dubbo-metrics/dubbo-metrics-registry/src/main/java/org/apache/dubbo/metrics/registry/event/RegistryEvent.java
index 5aa49bfcae..5ed721c695 100644
--- a/dubbo-metrics/dubbo-metrics-registry/src/main/java/org/apache/dubbo/metrics/registry/event/RegistryEvent.java
+++ b/dubbo-metrics/dubbo-metrics-registry/src/main/java/org/apache/dubbo/metrics/registry/event/RegistryEvent.java
@@ -38,7 +38,7 @@ import static org.apache.dubbo.metrics.MetricsConstants.ATTACHMENT_KEY_SIZE;
  */
 public class RegistryEvent extends TimeCounterEvent {
     public RegistryEvent(ApplicationModel applicationModel, TypeWrapper typeWrapper) {
-        super(applicationModel,typeWrapper);
+        super(applicationModel, typeWrapper);
         ScopeBeanFactory beanFactory = getSource().getBeanFactory();
         RegistryMetricsCollector collector;
         if (!beanFactory.isDestroyed()) {
@@ -47,18 +47,21 @@ public class RegistryEvent extends TimeCounterEvent {
         }
     }
 
+    private static final TypeWrapper REGISTER_EVENT = new TypeWrapper(MetricsLevel.APP, MetricsKey.REGISTER_METRIC_REQUESTS, MetricsKey.REGISTER_METRIC_REQUESTS_SUCCEED, MetricsKey.REGISTER_METRIC_REQUESTS_FAILED);
     public static RegistryEvent toRegisterEvent(ApplicationModel applicationModel) {
-        return new RegistryEvent(applicationModel, new TypeWrapper(MetricsLevel.APP, MetricsKey.REGISTER_METRIC_REQUESTS, MetricsKey.REGISTER_METRIC_REQUESTS_SUCCEED, MetricsKey.REGISTER_METRIC_REQUESTS_FAILED));
+        return new RegistryEvent(applicationModel, REGISTER_EVENT);
     }
 
 
+    private static final TypeWrapper SUBSCRIBE_EVENT = new TypeWrapper(MetricsLevel.APP, MetricsKey.SUBSCRIBE_METRIC_NUM, MetricsKey.SUBSCRIBE_METRIC_NUM_SUCCEED, MetricsKey.SUBSCRIBE_METRIC_NUM_FAILED);
     public static RegistryEvent toSubscribeEvent(ApplicationModel applicationModel) {
-        return new RegistryEvent(applicationModel, new TypeWrapper(MetricsLevel.APP, MetricsKey.SUBSCRIBE_METRIC_NUM, MetricsKey.SUBSCRIBE_METRIC_NUM_SUCCEED, MetricsKey.SUBSCRIBE_METRIC_NUM_FAILED));
+        return new RegistryEvent(applicationModel, SUBSCRIBE_EVENT);
     }
 
 
+    private static final TypeWrapper NOTIFY_EVENT = new TypeWrapper(MetricsLevel.APP, MetricsKey.NOTIFY_METRIC_REQUESTS, MetricsKey.NOTIFY_METRIC_NUM_LAST, (MetricsKey) null);
     public static RegistryEvent toNotifyEvent(ApplicationModel applicationModel) {
-        return new RegistryEvent(applicationModel, new TypeWrapper(MetricsLevel.APP, MetricsKey.NOTIFY_METRIC_REQUESTS, MetricsKey.NOTIFY_METRIC_NUM_LAST, (MetricsKey) null)) {
+        return new RegistryEvent(applicationModel, NOTIFY_EVENT) {
             @Override
             public void customAfterPost(Object postResult) {
                 super.putAttachment(ATTACHMENT_KEY_LAST_NUM_MAP, postResult);
@@ -66,21 +69,24 @@ public class RegistryEvent extends TimeCounterEvent {
         };
     }
 
+    private static final TypeWrapper RS_EVENT = new TypeWrapper(MetricsLevel.SERVICE, MetricsKey.SERVICE_REGISTER_METRIC_REQUESTS, MetricsKey.SERVICE_REGISTER_METRIC_REQUESTS_SUCCEED, MetricsKey.SERVICE_REGISTER_METRIC_REQUESTS_FAILED);
     public static RegistryEvent toRsEvent(ApplicationModel applicationModel, String serviceKey, int size) {
-        RegistryEvent ddEvent = new RegistryEvent(applicationModel, new TypeWrapper(MetricsLevel.SERVICE, MetricsKey.SERVICE_REGISTER_METRIC_REQUESTS, MetricsKey.SERVICE_REGISTER_METRIC_REQUESTS_SUCCEED, MetricsKey.SERVICE_REGISTER_METRIC_REQUESTS_FAILED));
+        RegistryEvent ddEvent = new RegistryEvent(applicationModel, RS_EVENT);
         ddEvent.putAttachment(ATTACHMENT_KEY_SERVICE, serviceKey);
         ddEvent.putAttachment(ATTACHMENT_KEY_SIZE, size);
         return ddEvent;
     }
 
+    private static final TypeWrapper SS_EVENT = new TypeWrapper(MetricsLevel.SERVICE, MetricsKey.SERVICE_SUBSCRIBE_METRIC_NUM, MetricsKey.SERVICE_SUBSCRIBE_METRIC_NUM_SUCCEED, MetricsKey.SERVICE_SUBSCRIBE_METRIC_NUM_FAILED);
     public static RegistryEvent toSsEvent(ApplicationModel applicationModel, String serviceKey) {
-        RegistryEvent ddEvent = new RegistryEvent(applicationModel, new TypeWrapper(MetricsLevel.SERVICE, MetricsKey.SERVICE_SUBSCRIBE_METRIC_NUM, MetricsKey.SERVICE_SUBSCRIBE_METRIC_NUM_SUCCEED, MetricsKey.SERVICE_SUBSCRIBE_METRIC_NUM_FAILED));
+        RegistryEvent ddEvent = new RegistryEvent(applicationModel, SS_EVENT);
         ddEvent.putAttachment(ATTACHMENT_KEY_SERVICE, serviceKey);
         return ddEvent;
     }
 
+    private static final TypeWrapper DIRECTORY_EVENT = new TypeWrapper(MetricsLevel.APP, MetricsKey.DIRECTORY_METRIC_NUM_VALID, null, null);
     public static RegistryEvent refreshDirectoryEvent(ApplicationModel applicationModel, Map<MetricsKey, Map<String, Integer>> summaryMap) {
-        RegistryEvent registryEvent = new RegistryEvent(applicationModel, new TypeWrapper(MetricsLevel.APP, MetricsKey.DIRECTORY_METRIC_NUM_VALID, null, null));
+        RegistryEvent registryEvent = new RegistryEvent(applicationModel, DIRECTORY_EVENT);
         registryEvent.putAttachment(ATTACHMENT_DIRECTORY_MAP, summaryMap);
         return registryEvent;
     }
diff --git a/dubbo-metrics/dubbo-metrics-registry/src/main/java/org/apache/dubbo/metrics/registry/event/RegistrySubDispatcher.java b/dubbo-metrics/dubbo-metrics-registry/src/main/java/org/apache/dubbo/metrics/registry/event/RegistrySubDispatcher.java
index f0d8c74f41..fd314443db 100644
--- a/dubbo-metrics/dubbo-metrics-registry/src/main/java/org/apache/dubbo/metrics/registry/event/RegistrySubDispatcher.java
+++ b/dubbo-metrics/dubbo-metrics-registry/src/main/java/org/apache/dubbo/metrics/registry/event/RegistrySubDispatcher.java
@@ -93,7 +93,7 @@ public final class RegistrySubDispatcher extends SimpleMetricsEventMulticaster {
         MetricsCat APPLICATION_NOTIFY_FINISH = new MetricsCat(MetricsKey.NOTIFY_METRIC_NUM_LAST,
             (key, placeType, collector) -> AbstractMetricsKeyListener.onFinish(key,
                 event -> {
-                    collector.addRt(event.appName(), placeType.getType(), event.getTimePair().calc());
+                    collector.addServiceRt(event.appName(), placeType.getType(), event.getTimePair().calc());
                     Map<String, Integer> lastNumMap = Collections.unmodifiableMap(event.getAttachmentValue(ATTACHMENT_KEY_LAST_NUM_MAP));
                     lastNumMap.forEach(
                         (k, v) -> collector.setNum(new MetricsKeyWrapper(key, OP_TYPE_NOTIFY), k, v));
diff --git a/dubbo-metrics/dubbo-metrics-registry/src/test/java/org/apache/dubbo/metrics/registry/metrics/collector/RegistryMetricsSampleTest.java b/dubbo-metrics/dubbo-metrics-registry/src/test/java/org/apache/dubbo/metrics/registry/metrics/collector/RegistryMetricsSampleTest.java
index 73d5815948..bd59ab5dae 100644
--- a/dubbo-metrics/dubbo-metrics-registry/src/test/java/org/apache/dubbo/metrics/registry/metrics/collector/RegistryMetricsSampleTest.java
+++ b/dubbo-metrics/dubbo-metrics-registry/src/test/java/org/apache/dubbo/metrics/registry/metrics/collector/RegistryMetricsSampleTest.java
@@ -25,6 +25,7 @@ import org.apache.dubbo.metrics.model.sample.MetricSample;
 import org.apache.dubbo.metrics.registry.collector.RegistryMetricsCollector;
 import org.apache.dubbo.rpc.model.ApplicationModel;
 import org.apache.dubbo.rpc.model.FrameworkModel;
+
 import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.BeforeEach;
@@ -64,8 +65,8 @@ class RegistryMetricsSampleTest {
         RegistryMetricsCollector collector = new RegistryMetricsCollector(applicationModel);
         collector.setCollectEnabled(true);
         String applicationName = applicationModel.getApplicationName();
-        collector.addRt(applicationName, OP_TYPE_REGISTER.getType(), 10L);
-        collector.addRt(applicationName, OP_TYPE_REGISTER.getType(), 0L);
+        collector.addServiceRt(applicationName, OP_TYPE_REGISTER.getType(), 10L);
+        collector.addServiceRt(applicationName, OP_TYPE_REGISTER.getType(), 0L);
 
         List<MetricSample> samples = collector.collect();
         for (MetricSample sample : samples) {
diff --git a/dubbo-metrics/dubbo-metrics-registry/src/test/java/org/apache/dubbo/metrics/registry/metrics/collector/RegistryMetricsTest.java b/dubbo-metrics/dubbo-metrics-registry/src/test/java/org/apache/dubbo/metrics/registry/metrics/collector/RegistryMetricsTest.java
index 553283c672..0e1bf07346 100644
--- a/dubbo-metrics/dubbo-metrics-registry/src/test/java/org/apache/dubbo/metrics/registry/metrics/collector/RegistryMetricsTest.java
+++ b/dubbo-metrics/dubbo-metrics-registry/src/test/java/org/apache/dubbo/metrics/registry/metrics/collector/RegistryMetricsTest.java
@@ -28,6 +28,7 @@ import org.apache.dubbo.metrics.registry.collector.RegistryMetricsCollector;
 import org.apache.dubbo.metrics.registry.event.RegistryEvent;
 import org.apache.dubbo.rpc.model.ApplicationModel;
 import org.apache.dubbo.rpc.model.FrameworkModel;
+
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
@@ -35,7 +36,11 @@ import org.junit.jupiter.api.Test;
 import java.util.List;
 import java.util.NoSuchElementException;
 import java.util.Optional;
-import java.util.concurrent.*;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.TimeUnit;
 
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.when;
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/listener/ServiceInstancesChangedListener.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/listener/ServiceInstancesChangedListener.java
index e069ead88c..f12d7912ca 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/listener/ServiceInstancesChangedListener.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/listener/ServiceInstancesChangedListener.java
@@ -93,7 +93,6 @@ public class ServiceInstancesChangedListener {
     private final Set<ServiceInstanceNotificationCustomizer> serviceInstanceNotificationCustomizers;
     private final ApplicationModel applicationModel;
 
-
     public ServiceInstancesChangedListener(Set<String> serviceNames, ServiceDiscovery serviceDiscovery) {
         this.serviceNames = serviceNames;
         this.serviceDiscovery = serviceDiscovery;
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryDirectory.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryDirectory.java
index 192cc4650d..86c8717d6e 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryDirectory.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryDirectory.java
@@ -114,7 +114,6 @@ public class RegistryDirectory<T> extends DynamicDirectory<T> {
         super(serviceType, url);
         moduleModel = getModuleModel(url.getScopeModel());
         consumerConfigurationListener = getConsumerConfigurationListener(moduleModel);
-
     }
 
     @Override
diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/GenericFilter.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/GenericFilter.java
index 8375298508..a63ef57eb8 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/GenericFilter.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/GenericFilter.java
@@ -29,6 +29,7 @@ import org.apache.dubbo.common.json.GsonUtils;
 import org.apache.dubbo.common.logger.ErrorTypeAwareLogger;
 import org.apache.dubbo.common.logger.LoggerFactory;
 import org.apache.dubbo.common.serialize.Serialization;
+import org.apache.dubbo.common.utils.ClassUtils;
 import org.apache.dubbo.common.utils.PojoUtils;
 import org.apache.dubbo.common.utils.ReflectUtils;
 import org.apache.dubbo.common.utils.StringUtils;
@@ -40,7 +41,9 @@ import org.apache.dubbo.rpc.RpcContext;
 import org.apache.dubbo.rpc.RpcException;
 import org.apache.dubbo.rpc.RpcInvocation;
 import org.apache.dubbo.rpc.model.ApplicationModel;
+import org.apache.dubbo.rpc.model.MethodDescriptor;
 import org.apache.dubbo.rpc.model.ScopeModelAware;
+import org.apache.dubbo.rpc.model.ServiceModel;
 import org.apache.dubbo.rpc.service.GenericException;
 import org.apache.dubbo.rpc.service.GenericService;
 import org.apache.dubbo.rpc.support.ProtocolUtils;
@@ -48,6 +51,10 @@ import org.apache.dubbo.rpc.support.ProtocolUtils;
 import java.io.IOException;
 import java.lang.reflect.Method;
 import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
 import java.util.stream.IntStream;
 
 import static org.apache.dubbo.common.constants.CommonConstants.$INVOKE;
@@ -67,6 +74,8 @@ public class GenericFilter implements Filter, Filter.Listener, ScopeModelAware {
 
     private ApplicationModel applicationModel;
 
+    private final Map<ClassLoader, Map<String, Class<?>>> classCache = new ConcurrentHashMap<>();
+
     @Override
     public void setApplicationModel(ApplicationModel applicationModel) {
         this.applicationModel = applicationModel;
@@ -82,7 +91,7 @@ public class GenericFilter implements Filter, Filter.Listener, ScopeModelAware {
             String[] types = (String[]) inv.getArguments()[1];
             Object[] args = (Object[]) inv.getArguments()[2];
             try {
-                Method method = ReflectUtils.findMethodByMethodSignature(invoker.getInterface(), name, types);
+                Method method = findMethodByMethodSignature(invoker.getInterface(), name, types, inv.getServiceModel());
                 Class<?>[] params = method.getParameterTypes();
                 if (args == null) {
                     args = new Object[params.length];
@@ -219,6 +228,54 @@ public class GenericFilter implements Filter, Filter.Listener, ScopeModelAware {
         return generic;
     }
 
+    public Method findMethodByMethodSignature(Class<?> clazz, String methodName, String[] parameterTypes, ServiceModel serviceModel)
+        throws NoSuchMethodException, ClassNotFoundException {
+        Method method;
+        if (parameterTypes == null) {
+            List<Method> finded = new ArrayList<>();
+            for (Method m : clazz.getMethods()) {
+                if (m.getName().equals(methodName)) {
+                    finded.add(m);
+                }
+            }
+            if (finded.isEmpty()) {
+                throw new NoSuchMethodException("No such method " + methodName + " in class " + clazz);
+            }
+            if (finded.size() > 1) {
+                String msg = String.format("Not unique method for method name(%s) in class(%s), find %d methods.",
+                    methodName, clazz.getName(), finded.size());
+                throw new IllegalStateException(msg);
+            }
+            method = finded.get(0);
+        } else {
+            Class<?>[] types = new Class<?>[parameterTypes.length];
+            for (int i = 0; i < parameterTypes.length; i++) {
+                ClassLoader classLoader = ClassUtils.getClassLoader();
+                Map<String, Class<?>> cacheMap = classCache.get(classLoader);
+                if (cacheMap == null) {
+                    cacheMap = new ConcurrentHashMap<>();
+                    classCache.putIfAbsent(classLoader, cacheMap);
+                    cacheMap = classCache.get(classLoader);
+                }
+                types[i] = cacheMap.get(parameterTypes[i]);
+                if (types[i] == null) {
+                    types[i] = ReflectUtils.name2class(parameterTypes[i]);
+                    cacheMap.put(parameterTypes[i], types[i]);
+                }
+            }
+            if (serviceModel != null) {
+                MethodDescriptor methodDescriptor = serviceModel.getServiceModel().getMethod(methodName, types);
+                if (methodDescriptor == null) {
+                    throw new NoSuchMethodException("No such method " + methodName + " in class " + clazz);
+                }
+                method = methodDescriptor.getMethod();
+            } else {
+                method = clazz.getMethod(methodName, types);
+            }
+        }
+        return method;
+    }
+
     @Override
     public void onResponse(Result appResponse, Invoker<?> invoker, Invocation inv) {
         if ((inv.getMethodName().equals($INVOKE) || inv.getMethodName().equals($INVOKE_ASYNC))
diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DecodeableRpcInvocation.java b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DecodeableRpcInvocation.java
index f23a7a9345..e677462e01 100644
--- a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DecodeableRpcInvocation.java
+++ b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DecodeableRpcInvocation.java
@@ -23,7 +23,6 @@ import org.apache.dubbo.common.serialize.ObjectInput;
 import org.apache.dubbo.common.utils.Assert;
 import org.apache.dubbo.common.utils.CacheableSupplier;
 import org.apache.dubbo.common.utils.CollectionUtils;
-import org.apache.dubbo.common.utils.ReflectUtils;
 import org.apache.dubbo.common.utils.StringUtils;
 import org.apache.dubbo.remoting.Channel;
 import org.apache.dubbo.remoting.Codec;
@@ -158,10 +157,13 @@ public class DecodeableRpcInvocation extends RpcInvocation implements Codec, Dec
             if (desc.length() > 0) {
                 pts = drawPts(path, version, desc, pts);
                 if (pts == DubboCodec.EMPTY_CLASS_ARRAY) {
-                    if (!RpcUtils.isGenericCall(desc, getMethodName()) && !RpcUtils.isEcho(desc, getMethodName())) {
+                    if (RpcUtils.isGenericCall(desc, getMethodName())) {
+                        pts = DubboCodec.GENERIC_PTS_ARRAY;
+                    } else if (RpcUtils.isEcho(desc, getMethodName())) {
+                        pts = DubboCodec.ECHO_PTS_ARRAY;
+                    } else {
                         throw new IllegalArgumentException("Service not found:" + path + ", " + getMethodName());
                     }
-                    pts = ReflectUtils.desc2classArray(desc);
                 }
                 args = drawArgs(in, pts);
             }
diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboCodec.java b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboCodec.java
index c775ae50a0..169722e112 100644
--- a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboCodec.java
+++ b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboCodec.java
@@ -69,6 +69,8 @@ public class DubboCodec extends ExchangeCodec {
     public static final byte RESPONSE_NULL_VALUE_WITH_ATTACHMENTS = 5;
     public static final Object[] EMPTY_OBJECT_ARRAY = new Object[0];
     public static final Class<?>[] EMPTY_CLASS_ARRAY = new Class<?>[0];
+    public static final Class<?>[] GENERIC_PTS_ARRAY = new Class<?>[]{String.class, String[].class, Object[].class};
+    public static final Class<?>[] ECHO_PTS_ARRAY = new Class<?>[]{Object.class};
     private static final ErrorTypeAwareLogger log = LoggerFactory.getErrorTypeAwareLogger(DubboCodec.class);
 
     private static final AtomicBoolean decodeInUserThreadLogged = new AtomicBoolean(false);
diff --git a/dubbo-serialization/dubbo-serialization-hessian2/src/main/java/org/apache/dubbo/common/serialize/hessian2/Hessian2FactoryManager.java b/dubbo-serialization/dubbo-serialization-hessian2/src/main/java/org/apache/dubbo/common/serialize/hessian2/Hessian2FactoryManager.java
index 60f9dfe2fe..8391ff2f09 100644
--- a/dubbo-serialization/dubbo-serialization-hessian2/src/main/java/org/apache/dubbo/common/serialize/hessian2/Hessian2FactoryManager.java
+++ b/dubbo-serialization/dubbo-serialization-hessian2/src/main/java/org/apache/dubbo/common/serialize/hessian2/Hessian2FactoryManager.java
@@ -16,9 +16,6 @@
  */
 package org.apache.dubbo.common.serialize.hessian2;
 
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-
 import org.apache.dubbo.common.utils.DefaultSerializeClassChecker;
 import org.apache.dubbo.common.utils.SerializeCheckStatus;
 import org.apache.dubbo.common.utils.SerializeSecurityManager;
@@ -27,12 +24,16 @@ import org.apache.dubbo.rpc.model.FrameworkModel;
 
 import com.alibaba.com.caucho.hessian.io.SerializerFactory;
 
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
 
 public class Hessian2FactoryManager {
     String WHITELIST = "dubbo.application.hessian2.whitelist";
     String ALLOW = "dubbo.application.hessian2.allow";
     String DENY = "dubbo.application.hessian2.deny";
     private volatile SerializerFactory SYSTEM_SERIALIZER_FACTORY;
+    private volatile SerializerFactory stickySerializerFactory = null;
     private final Map<ClassLoader, SerializerFactory> CL_2_SERIALIZER_FACTORY = new ConcurrentHashMap<>();
 
     private final SerializeSecurityManager serializeSecurityManager;
@@ -44,6 +45,11 @@ public class Hessian2FactoryManager {
     }
 
     public SerializerFactory getSerializerFactory(ClassLoader classLoader) {
+        SerializerFactory sticky = stickySerializerFactory;
+        if (sticky != null && sticky.getClassLoader().equals(classLoader)) {
+            return sticky;
+        }
+
         if (classLoader == null) {
             // system classloader
             if (SYSTEM_SERIALIZER_FACTORY == null) {
@@ -53,19 +59,23 @@ public class Hessian2FactoryManager {
                     }
                 }
             }
+            stickySerializerFactory = SYSTEM_SERIALIZER_FACTORY;
             return SYSTEM_SERIALIZER_FACTORY;
         }
 
-        if (!CL_2_SERIALIZER_FACTORY.containsKey(classLoader)) {
+        SerializerFactory factory = CL_2_SERIALIZER_FACTORY.get(classLoader);
+        if (factory == null) {
             synchronized (this) {
                 if (!CL_2_SERIALIZER_FACTORY.containsKey(classLoader)) {
                     SerializerFactory serializerFactory = createSerializerFactory();
                     CL_2_SERIALIZER_FACTORY.put(classLoader, serializerFactory);
+                    stickySerializerFactory = serializerFactory;
                     return serializerFactory;
                 }
             }
         }
-        return CL_2_SERIALIZER_FACTORY.get(classLoader);
+        stickySerializerFactory = factory;
+        return factory;
     }
 
     private SerializerFactory createSerializerFactory() {