From d2eb2ba3d74d9a23f728201b7a3a0ded6466185b Mon Sep 17 00:00:00 2001 From: Albumen Kevin Date: Tue, 11 Jul 2023 14:42:33 +0800 Subject: [PATCH] Performance opt (#12680) --- .../filter/support/MetricsClusterFilter.java | 8 +- .../filter/support/MetricsConsumerFilter.java | 49 ++++++ ...che.dubbo.rpc.cluster.filter.ClusterFilter | 3 +- .../apache/dubbo/config/ServiceConfig.java | 3 +- .../dubbo/metrics/MetricsConstants.java | 1 + .../ApplicationMetricsCollector.java | 2 +- .../collector/CombMetricsCollector.java | 17 +- .../collector/MethodMetricsCollector.java | 5 +- .../collector/ServiceMetricsCollector.java | 5 +- .../dubbo/metrics/data/BaseStatComposite.java | 9 +- .../metrics/data/MethodStatComposite.java | 10 +- .../dubbo/metrics/data/RtStatComposite.java | 149 +++++++++++++++--- .../dubbo/metrics/event/MetricsEvent.java | 39 ++++- .../dubbo/metrics/event/MetricsEventBus.java | 35 +--- .../event/SimpleMetricsEventMulticaster.java | 3 +- .../dubbo/metrics/event/TimeCounterEvent.java | 5 + .../listener/AbstractMetricsListener.java | 8 +- .../listener/MetricsApplicationListener.java | 4 +- .../metrics/model/ApplicationMetric.java | 7 +- .../dubbo/metrics/model/MethodMetric.java | 16 +- .../dubbo/metrics/model/MetricsSupport.java | 71 ++++++--- .../dubbo/metrics/model/ServiceKeyMetric.java | 11 +- .../model/container/LongContainer.java | 3 +- .../SimpleMetricsEventMulticasterTest.java | 1 + .../config/event/ConfigCenterEvent.java | 2 +- .../metrics/event/DefaultSubDispatcher.java | 3 +- .../metrics/event/RequestBeforeEvent.java | 13 +- .../dubbo/metrics/event/RequestEvent.java | 50 +++--- .../dubbo/metrics/filter/MetricsFilter.java | 36 +++-- .../metrics/filter/MetricsProviderFilter.java | 48 ++++++ .../internal/org.apache.dubbo.rpc.Filter | 4 +- .../AggregateMetricsCollectorTest.java | 11 +- .../collector/DefaultCollectorTest.java | 5 +- .../metrics/metadata/event/MetadataEvent.java | 2 +- .../MetadataMetricsCollectorTest.java | 2 +- .../metrics/registry/event/RegistryEvent.java | 20 ++- .../registry/event/RegistrySubDispatcher.java | 2 +- .../collector/RegistryMetricsSampleTest.java | 5 +- .../collector/RegistryMetricsTest.java | 7 +- .../ServiceInstancesChangedListener.java | 1 - .../integration/RegistryDirectory.java | 1 - .../dubbo/rpc/filter/GenericFilter.java | 59 ++++++- .../dubbo/DecodeableRpcInvocation.java | 8 +- .../dubbo/rpc/protocol/dubbo/DubboCodec.java | 2 + .../hessian2/Hessian2FactoryManager.java | 20 ++- 45 files changed, 574 insertions(+), 191 deletions(-) create mode 100644 dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/filter/support/MetricsConsumerFilter.java create mode 100644 dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/filter/MetricsProviderFilter.java 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 extends ServiceConfigBase { List 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 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 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 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 extends MetricsCollector { - 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 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> rtStats = new ArrayList<>(); + private final Map>> 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> containers = initStats(placeValue); + for (LongContainer container : containers) { + rtStats.computeIfAbsent(container.getMetricsKeyWrapper().getType(), k -> new ArrayList<>()) + .add(container); + } + } } private List> 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 totalContainer = rtStats.stream().filter(longContainer -> longContainer.isKeyWrapper(MetricsKey.METRIC_RT_SUM, placeValue.getType())).findFirst().get(); + LongContainer 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 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); + public void calcServiceKeyRt(Invocation invocation, String registryOpType, Long responseTime) { + List actions; + if (invocation.getServiceModel() != null && invocation.getServiceModel().getServiceKey() != null) { + Map attributeMap = invocation.getServiceModel().getServiceMetadata().getAttributeMap(); + Map> cache = (Map>) attributeMap.get("ServiceKeyRt"); + if (cache == null) { + attributeMap.putIfAbsent("ServiceKeyRt", new ConcurrentHashMap<>(32)); + cache = (Map>) 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 calServiceRtActions(Invocation invocation, String registryOpType) { + List 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) { + List actions; + + if (invocation.getServiceModel() != null && invocation.getServiceModel().getServiceMetadata() != null) { + Map attributeMap = invocation.getServiceModel().getServiceMetadata().getAttributeMap(); + Map> cache = (Map>) attributeMap.get("MethodKeyRt"); + if (cache == null) { + attributeMap.putIfAbsent("MethodKeyRt", new ConcurrentHashMap<>(32)); + cache = (Map>) 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 calMethodRtActions(Invocation invocation, String registryOpType) { + List 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 export(MetricsCategory category) { List list = new ArrayList<>(); - for (LongContainer 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> containers : rtStats.values()) { + for (LongContainer 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> getRtStats() { - return rtStats; + return rtStats.values().stream().flatMap(List::stream).collect(Collectors.toList()); } + private static class Action { + private final BiConsumer consumerFunc; + private final Number initValue; + + public Action(BiConsumer 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 attachment = new HashMap<>(8); + private final Map 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 implements MetricsListener { - private final Map, Boolean> eventMatchCache = new ConcurrentHashMap<>(); + private final Map 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 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 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 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 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 extends ConcurrentHashMap initFunc, BiConsumer 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> 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 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 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 serviceInstanceNotificationCustomizers; private final ApplicationModel applicationModel; - public ServiceInstancesChangedListener(Set 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 extends DynamicDirectory { 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>> 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 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> 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 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() {