Performance opt (#12680)
This commit is contained in:
parent
35149ba694
commit
d2eb2ba3d7
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
metricsClusterFilter=org.apache.dubbo.rpc.cluster.filter.support.MetricsClusterFilter
|
||||
metricsConsumerFilter=org.apache.dubbo.rpc.cluster.filter.support.MetricsConsumerFilter
|
||||
|
|
|
|||
|
|
@ -514,8 +514,7 @@ public class ServiceConfig<T> extends ServiceConfigBase<T> {
|
|||
|
||||
List<URL> registryURLs = ConfigValidationUtils.loadRegistries(this, true);
|
||||
|
||||
MetricsEventBus.post(RegistryEvent.toRsEvent(module.getApplicationModel(), getUniqueServiceName(), protocols.size() * registryURLs.size()),
|
||||
() -> {
|
||||
MetricsEventBus.post(RegistryEvent.toRsEvent(getApplicationModel(), getUniqueServiceName(), protocols.size() * registryURLs.size()), () -> {
|
||||
for (ProtocolConfig protocolConfig : protocols) {
|
||||
String pathKey = URL.buildKey(getContextPath(protocolConfig)
|
||||
.map(p -> p + "/" + path)
|
||||
|
|
|
|||
|
|
@ -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";
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ public interface ApplicationMetricsCollector<E extends TimeCounterEvent> extends
|
|||
|
||||
void increment(MetricsKey metricsKey);
|
||||
|
||||
void addRt(String registryOpType, Long responseTime);
|
||||
void addApplicationRt(String registryOpType, Long responseTime);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ import org.apache.dubbo.metrics.data.BaseStatComposite;
|
|||
import org.apache.dubbo.metrics.event.MetricsEventMulticaster;
|
||||
import org.apache.dubbo.metrics.event.TimeCounterEvent;
|
||||
import org.apache.dubbo.metrics.listener.AbstractMetricsListener;
|
||||
import org.apache.dubbo.metrics.model.MethodMetric;
|
||||
import org.apache.dubbo.metrics.model.MetricsCategory;
|
||||
import org.apache.dubbo.metrics.model.key.MetricsKey;
|
||||
import org.apache.dubbo.metrics.model.key.MetricsKeyWrapper;
|
||||
|
|
@ -60,24 +61,30 @@ public abstract class CombMetricsCollector<E extends TimeCounterEvent> extends A
|
|||
}
|
||||
|
||||
@Override
|
||||
public void addRt(String registryOpType, Long responseTime) {
|
||||
public void addApplicationRt(String registryOpType, Long responseTime) {
|
||||
stats.calcApplicationRt(registryOpType, responseTime);
|
||||
}
|
||||
|
||||
public void addRt(String serviceKey, String registryOpType, Long responseTime) {
|
||||
@Override
|
||||
public void addServiceRt(String serviceKey, String registryOpType, Long responseTime) {
|
||||
stats.calcServiceKeyRt(serviceKey, registryOpType, responseTime);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void increment(Invocation invocation, MetricsKeyWrapper wrapper, int size) {
|
||||
this.stats.incrementMethodKey(wrapper, invocation, size);
|
||||
public void addServiceRt(Invocation invocation, String registryOpType, Long responseTime) {
|
||||
stats.calcServiceKeyRt(invocation, registryOpType, responseTime);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addRt(Invocation invocation, String registryOpType, Long responseTime) {
|
||||
public void addMethodRt(Invocation invocation, String registryOpType, Long responseTime) {
|
||||
stats.calcMethodKeyRt(invocation, registryOpType, responseTime);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void increment(MethodMetric methodMetric, MetricsKeyWrapper wrapper, int size) {
|
||||
this.stats.incrementMethodKey(wrapper, methodMetric, size);
|
||||
}
|
||||
|
||||
protected List<MetricSample> export(MetricsCategory category) {
|
||||
return stats.export(category);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
package org.apache.dubbo.metrics.collector;
|
||||
|
||||
import org.apache.dubbo.metrics.event.TimeCounterEvent;
|
||||
import org.apache.dubbo.metrics.model.MethodMetric;
|
||||
import org.apache.dubbo.metrics.model.key.MetricsKeyWrapper;
|
||||
import org.apache.dubbo.rpc.Invocation;
|
||||
|
||||
|
|
@ -26,8 +27,8 @@ import org.apache.dubbo.rpc.Invocation;
|
|||
*/
|
||||
public interface MethodMetricsCollector<E extends TimeCounterEvent> extends MetricsCollector<E> {
|
||||
|
||||
void increment(Invocation invocation, MetricsKeyWrapper wrapper, int size);
|
||||
void increment(MethodMetric methodMetric, MetricsKeyWrapper wrapper, int size);
|
||||
|
||||
void addRt(Invocation invocation, String registryOpType, Long responseTime);
|
||||
void addMethodRt(Invocation invocation, String registryOpType, Long responseTime);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ package org.apache.dubbo.metrics.collector;
|
|||
|
||||
import org.apache.dubbo.metrics.event.TimeCounterEvent;
|
||||
import org.apache.dubbo.metrics.model.key.MetricsKeyWrapper;
|
||||
import org.apache.dubbo.rpc.Invocation;
|
||||
|
||||
/**
|
||||
* Service-level collector.
|
||||
|
|
@ -30,6 +31,8 @@ public interface ServiceMetricsCollector<E extends TimeCounterEvent> extends Met
|
|||
|
||||
void setNum(MetricsKeyWrapper metricsKey, String serviceKey, int num);
|
||||
|
||||
void addRt(String serviceKey, String registryOpType, Long responseTime);
|
||||
void addServiceRt(String serviceKey, String registryOpType, Long responseTime);
|
||||
|
||||
void addServiceRt(Invocation invocation, String registryOpType, Long responseTime);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@
|
|||
|
||||
package org.apache.dubbo.metrics.data;
|
||||
|
||||
import org.apache.dubbo.common.utils.ConcurrentHashMapUtils;
|
||||
import org.apache.dubbo.metrics.model.ApplicationMetric;
|
||||
import org.apache.dubbo.metrics.model.MethodMetric;
|
||||
import org.apache.dubbo.metrics.model.Metric;
|
||||
|
|
@ -36,10 +35,13 @@ import org.apache.dubbo.rpc.Invocation;
|
|||
import org.apache.dubbo.rpc.model.ApplicationModel;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.concurrent.atomic.LongAccumulator;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
|
|
@ -54,13 +56,19 @@ public class RtStatComposite extends AbstractMetricsExport {
|
|||
super(applicationModel);
|
||||
}
|
||||
|
||||
private final List<LongContainer<? extends Number>> rtStats = new ArrayList<>();
|
||||
private final Map<String, List<LongContainer<? extends Number>>> rtStats = new ConcurrentHashMap<>();
|
||||
|
||||
public void init(MetricsPlaceValue... placeValues) {
|
||||
if (placeValues == null) {
|
||||
return;
|
||||
}
|
||||
Arrays.stream(placeValues).forEach(metricsPlaceType -> rtStats.addAll(initStats(metricsPlaceType)));
|
||||
for (MetricsPlaceValue placeValue : placeValues) {
|
||||
List<LongContainer<? extends Number>> containers = initStats(placeValue);
|
||||
for (LongContainer<? extends Number> container : containers) {
|
||||
rtStats.computeIfAbsent(container.getMetricsKeyWrapper().getType(), k -> new ArrayList<>())
|
||||
.add(container);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private List<LongContainer<? extends Number>> initStats(MetricsPlaceValue placeValue) {
|
||||
|
|
@ -72,7 +80,7 @@ public class RtStatComposite extends AbstractMetricsExport {
|
|||
// AvgContainer is a special counter that stores the number of times but outputs function of sum/times
|
||||
AtomicLongContainer avgContainer = new AtomicLongContainer(new MetricsKeyWrapper(MetricsKey.METRIC_RT_AVG, placeValue), (k, v) -> v.incrementAndGet());
|
||||
avgContainer.setValueSupplier(applicationName -> {
|
||||
LongContainer<? extends Number> totalContainer = rtStats.stream().filter(longContainer -> longContainer.isKeyWrapper(MetricsKey.METRIC_RT_SUM, placeValue.getType())).findFirst().get();
|
||||
LongContainer<? extends Number> totalContainer = rtStats.values().stream().flatMap(List::stream).filter(longContainer -> longContainer.isKeyWrapper(MetricsKey.METRIC_RT_SUM, placeValue.getType())).findFirst().get();
|
||||
AtomicLong totalRtTimes = avgContainer.get(applicationName);
|
||||
AtomicLong totalRtSum = (AtomicLong) totalContainer.get(applicationName);
|
||||
return totalRtSum.get() / totalRtTimes.get();
|
||||
|
|
@ -82,41 +90,144 @@ public class RtStatComposite extends AbstractMetricsExport {
|
|||
}
|
||||
|
||||
public void calcApplicationRt(String registryOpType, Long responseTime) {
|
||||
for (LongContainer container : rtStats.stream().filter(longContainer -> longContainer.specifyType(registryOpType)).collect(Collectors.toList())) {
|
||||
Number current = (Number) ConcurrentHashMapUtils.computeIfAbsent(container, new ApplicationMetric(getApplicationModel()), container.getInitFunc());
|
||||
ApplicationMetric key = new ApplicationMetric(getApplicationModel());
|
||||
for (LongContainer container : rtStats.get(registryOpType)) {
|
||||
Number current = (Number) container.get(key);
|
||||
if (current == null) {
|
||||
container.putIfAbsent(key, container.getInitFunc().apply(key));
|
||||
current = (Number) container.get(key);
|
||||
}
|
||||
container.getConsumerFunc().accept(responseTime, current);
|
||||
}
|
||||
}
|
||||
|
||||
public void calcServiceKeyRt(String serviceKey, String registryOpType, Long responseTime) {
|
||||
for (LongContainer container : rtStats.stream().filter(longContainer -> longContainer.specifyType(registryOpType)).collect(Collectors.toList())) {
|
||||
Number current = (Number) ConcurrentHashMapUtils.computeIfAbsent(container, new ServiceKeyMetric(getApplicationModel(), serviceKey), container.getInitFunc());
|
||||
ServiceKeyMetric key = new ServiceKeyMetric(getApplicationModel(), serviceKey);
|
||||
for (LongContainer container : rtStats.get(registryOpType)) {
|
||||
Number current = (Number) container.get(key);
|
||||
if (current == null) {
|
||||
container.putIfAbsent(key, container.getInitFunc().apply(key));
|
||||
current = (Number) container.get(key);
|
||||
}
|
||||
container.getConsumerFunc().accept(responseTime, current);
|
||||
}
|
||||
}
|
||||
|
||||
public void 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<Action> actions;
|
||||
if (invocation.getServiceModel() != null && invocation.getServiceModel().getServiceKey() != null) {
|
||||
Map<String, Object> attributeMap = invocation.getServiceModel().getServiceMetadata().getAttributeMap();
|
||||
Map<String, List<Action>> cache = (Map<String, List<Action>>) attributeMap.get("ServiceKeyRt");
|
||||
if (cache == null) {
|
||||
attributeMap.putIfAbsent("ServiceKeyRt", new ConcurrentHashMap<>(32));
|
||||
cache = (Map<String, List<Action>>) attributeMap.get("ServiceKeyRt");
|
||||
}
|
||||
actions = cache.get(registryOpType);
|
||||
if (actions == null) {
|
||||
actions = calServiceRtActions(invocation, registryOpType);
|
||||
cache.putIfAbsent(registryOpType, actions);
|
||||
actions = cache.get(registryOpType);
|
||||
}
|
||||
} else {
|
||||
actions = calServiceRtActions(invocation, registryOpType);
|
||||
}
|
||||
|
||||
for (Action action : actions) {
|
||||
action.run(responseTime);
|
||||
}
|
||||
}
|
||||
|
||||
private List<Action> calServiceRtActions(Invocation invocation, String registryOpType) {
|
||||
List<Action> actions;
|
||||
actions = new LinkedList<>();
|
||||
|
||||
ServiceKeyMetric key = new ServiceKeyMetric(getApplicationModel(), invocation.getTargetServiceUniqueName());
|
||||
for (LongContainer container : rtStats.get(registryOpType)) {
|
||||
Number current = (Number) container.get(key);
|
||||
if (current == null) {
|
||||
container.putIfAbsent(key, container.getInitFunc().apply(key));
|
||||
current = (Number) container.get(key);
|
||||
}
|
||||
actions.add(new Action(container.getConsumerFunc(), current));
|
||||
}
|
||||
return actions;
|
||||
}
|
||||
|
||||
public void calcMethodKeyRt(Invocation invocation, String registryOpType, Long responseTime) {
|
||||
List<Action> actions;
|
||||
|
||||
if (invocation.getServiceModel() != null && invocation.getServiceModel().getServiceMetadata() != null) {
|
||||
Map<String, Object> attributeMap = invocation.getServiceModel().getServiceMetadata().getAttributeMap();
|
||||
Map<String, List<Action>> cache = (Map<String, List<Action>>) attributeMap.get("MethodKeyRt");
|
||||
if (cache == null) {
|
||||
attributeMap.putIfAbsent("MethodKeyRt", new ConcurrentHashMap<>(32));
|
||||
cache = (Map<String, List<Action>>) attributeMap.get("MethodKeyRt");
|
||||
}
|
||||
actions = cache.get(registryOpType);
|
||||
if (actions == null) {
|
||||
actions = calMethodRtActions(invocation, registryOpType);
|
||||
cache.putIfAbsent(registryOpType, actions);
|
||||
actions = cache.get(registryOpType);
|
||||
}
|
||||
} else {
|
||||
actions = calMethodRtActions(invocation, registryOpType);
|
||||
}
|
||||
|
||||
for (Action action : actions) {
|
||||
action.run(responseTime);
|
||||
}
|
||||
}
|
||||
|
||||
private List<Action> calMethodRtActions(Invocation invocation, String registryOpType) {
|
||||
List<Action> actions;
|
||||
actions = new LinkedList<>();
|
||||
for (LongContainer container : rtStats.get(registryOpType)) {
|
||||
MethodMetric key = new MethodMetric(getApplicationModel(), invocation);
|
||||
Number current = (Number) container.get(key);
|
||||
if (current == null) {
|
||||
container.putIfAbsent(key, container.getInitFunc().apply(key));
|
||||
current = (Number) container.get(key);
|
||||
}
|
||||
actions.add(new Action(container.getConsumerFunc(), current));
|
||||
}
|
||||
return actions;
|
||||
}
|
||||
|
||||
public List<MetricSample> export(MetricsCategory category) {
|
||||
List<MetricSample> list = new ArrayList<>();
|
||||
for (LongContainer<? extends Number> rtContainer : rtStats) {
|
||||
MetricsKeyWrapper metricsKeyWrapper = rtContainer.getMetricsKeyWrapper();
|
||||
for (Metric key : rtContainer.keySet()) {
|
||||
// Use keySet to obtain the original key instance reference of ConcurrentHashMap to avoid early recycling of the micrometer
|
||||
list.add(new GaugeMetricSample<>(metricsKeyWrapper.targetKey(), metricsKeyWrapper.targetDesc(), key.getTags(), category, key, value -> rtContainer.getValueSupplier().apply(value)));
|
||||
for (List<LongContainer<? extends Number>> containers : rtStats.values()) {
|
||||
for (LongContainer<? extends Number> container : containers) {
|
||||
MetricsKeyWrapper metricsKeyWrapper = container.getMetricsKeyWrapper();
|
||||
for (Metric key : container.keySet()) {
|
||||
// Use keySet to obtain the original key instance reference of ConcurrentHashMap to avoid early recycling of the micrometer
|
||||
list.add(new GaugeMetricSample<>(metricsKeyWrapper.targetKey(),
|
||||
metricsKeyWrapper.targetDesc(),
|
||||
key.getTags(),
|
||||
category,
|
||||
key,
|
||||
value -> container.getValueSupplier().apply(value)));
|
||||
}
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public List<LongContainer<? extends Number>> getRtStats() {
|
||||
return rtStats;
|
||||
return rtStats.values().stream().flatMap(List::stream).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
|
||||
private static class Action {
|
||||
private final BiConsumer<Long, Number> consumerFunc;
|
||||
private final Number initValue;
|
||||
|
||||
public Action(BiConsumer<Long, Number> consumerFunc, Number initValue) {
|
||||
this.consumerFunc = consumerFunc;
|
||||
this.initValue = initValue;
|
||||
}
|
||||
|
||||
public void run(Long responseTime) {
|
||||
consumerFunc.accept(responseTime, initValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,12 +17,13 @@
|
|||
|
||||
package org.apache.dubbo.metrics.event;
|
||||
|
||||
import org.apache.dubbo.common.beans.factory.ScopeBeanFactory;
|
||||
import org.apache.dubbo.metrics.exception.MetricsNeverHappenException;
|
||||
import org.apache.dubbo.metrics.model.MethodMetric;
|
||||
import org.apache.dubbo.metrics.model.key.TypeWrapper;
|
||||
import org.apache.dubbo.rpc.model.ApplicationModel;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
|
|
@ -33,13 +34,19 @@ public abstract class MetricsEvent {
|
|||
/**
|
||||
* Metric object. (eg. {@link MethodMetric})
|
||||
*/
|
||||
protected transient ApplicationModel source;
|
||||
protected transient final ApplicationModel source;
|
||||
private boolean available = true;
|
||||
private final TypeWrapper typeWrapper;
|
||||
private final String appName;
|
||||
private final MetricsDispatcher metricsDispatcher;
|
||||
|
||||
private final Map<String, Object> attachment = new HashMap<>(8);
|
||||
private final Map<String, Object> attachment = new IdentityHashMap<>(8);
|
||||
|
||||
public MetricsEvent(ApplicationModel source, TypeWrapper typeWrapper) {
|
||||
this(source, null, null, typeWrapper);
|
||||
}
|
||||
|
||||
public MetricsEvent(ApplicationModel source, String appName, MetricsDispatcher metricsDispatcher, TypeWrapper typeWrapper) {
|
||||
this.typeWrapper = typeWrapper;
|
||||
if (source == null) {
|
||||
this.source = ApplicationModel.defaultModel();
|
||||
|
|
@ -48,6 +55,26 @@ public abstract class MetricsEvent {
|
|||
} else {
|
||||
this.source = source;
|
||||
}
|
||||
if (metricsDispatcher == null) {
|
||||
if (this.source.isDestroyed()) {
|
||||
this.metricsDispatcher = null;
|
||||
} else {
|
||||
ScopeBeanFactory beanFactory = this.source.getBeanFactory();
|
||||
if (beanFactory.isDestroyed()) {
|
||||
this.metricsDispatcher = null;
|
||||
} else {
|
||||
MetricsDispatcher dispatcher = beanFactory.getBean(MetricsDispatcher.class);
|
||||
this.metricsDispatcher = dispatcher;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this.metricsDispatcher = metricsDispatcher;
|
||||
}
|
||||
if (appName == null) {
|
||||
this.appName = this.source.tryGetApplicationName();
|
||||
} else {
|
||||
this.appName = appName;
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
|
|
@ -79,8 +106,12 @@ public abstract class MetricsEvent {
|
|||
return source;
|
||||
}
|
||||
|
||||
public MetricsDispatcher getMetricsDispatcher() {
|
||||
return metricsDispatcher;
|
||||
}
|
||||
|
||||
public String appName() {
|
||||
return getSource().getApplicationName();
|
||||
return appName;
|
||||
}
|
||||
|
||||
public TypeWrapper getTypeWrapper() {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,13 +25,17 @@ import java.util.concurrent.ConcurrentHashMap;
|
|||
|
||||
public abstract class AbstractMetricsListener<E extends MetricsEvent> implements MetricsListener<E> {
|
||||
|
||||
private final Map<Class<?>, Boolean> eventMatchCache = new ConcurrentHashMap<>();
|
||||
private final Map<Integer, Boolean> eventMatchCache = new ConcurrentHashMap<>();
|
||||
|
||||
/**
|
||||
* Whether to support the general determination of event points depends on the event type
|
||||
*/
|
||||
public boolean isSupport(MetricsEvent event) {
|
||||
Boolean eventMatch = eventMatchCache.computeIfAbsent(event.getClass(), clazz -> ReflectionUtils.match(getClass(), AbstractMetricsListener.class, event));
|
||||
Boolean eventMatch = eventMatchCache.get(System.identityHashCode(event.getClass()));
|
||||
if (eventMatch == null) {
|
||||
eventMatch = ReflectionUtils.match(getClass(), AbstractMetricsListener.class, event);
|
||||
eventMatchCache.put(System.identityHashCode(event.getClass()), eventMatch);
|
||||
}
|
||||
return event.isAvailable() && eventMatch;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
}
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -53,6 +53,7 @@ import static org.apache.dubbo.common.utils.NetUtils.getLocalHost;
|
|||
import static org.apache.dubbo.common.utils.NetUtils.getLocalHostName;
|
||||
import static org.apache.dubbo.metrics.MetricsConstants.ATTACHMENT_KEY_SERVICE;
|
||||
import static org.apache.dubbo.metrics.MetricsConstants.INVOCATION;
|
||||
import static org.apache.dubbo.metrics.MetricsConstants.METHOD_METRICS;
|
||||
import static org.apache.dubbo.metrics.MetricsConstants.SELF_INCREMENT_SIZE;
|
||||
|
||||
public class MetricsSupport {
|
||||
|
|
@ -145,38 +146,50 @@ public class MetricsSupport {
|
|||
|
||||
|
||||
public static String getInterfaceName(Invocation invocation) {
|
||||
String serviceUniqueName = invocation.getTargetServiceUniqueName();
|
||||
String interfaceAndVersion;
|
||||
String[] arr = serviceUniqueName.split(PATH_SEPARATOR);
|
||||
if (arr.length == 2) {
|
||||
interfaceAndVersion = arr[1];
|
||||
if (invocation.getServiceModel() != null && invocation.getServiceModel().getServiceMetadata() != null) {
|
||||
return invocation.getServiceModel().getServiceMetadata().getServiceInterfaceName();
|
||||
} else {
|
||||
interfaceAndVersion = arr[0];
|
||||
String serviceUniqueName = invocation.getTargetServiceUniqueName();
|
||||
String interfaceAndVersion;
|
||||
String[] arr = serviceUniqueName.split(PATH_SEPARATOR);
|
||||
if (arr.length == 2) {
|
||||
interfaceAndVersion = arr[1];
|
||||
} else {
|
||||
interfaceAndVersion = arr[0];
|
||||
}
|
||||
String[] ivArr = interfaceAndVersion.split(GROUP_CHAR_SEPARATOR);
|
||||
return ivArr[0];
|
||||
}
|
||||
String[] ivArr = interfaceAndVersion.split(GROUP_CHAR_SEPARATOR);
|
||||
return ivArr[0];
|
||||
}
|
||||
|
||||
public static String getGroup(Invocation invocation) {
|
||||
String serviceUniqueName = invocation.getTargetServiceUniqueName();
|
||||
String group = null;
|
||||
String[] arr = serviceUniqueName.split(PATH_SEPARATOR);
|
||||
if (arr.length == 2) {
|
||||
group = arr[0];
|
||||
if (invocation.getServiceModel() != null && invocation.getServiceModel().getServiceMetadata() != null) {
|
||||
return invocation.getServiceModel().getServiceMetadata().getGroup();
|
||||
} else {
|
||||
String serviceUniqueName = invocation.getTargetServiceUniqueName();
|
||||
String group = null;
|
||||
String[] arr = serviceUniqueName.split(PATH_SEPARATOR);
|
||||
if (arr.length == 2) {
|
||||
group = arr[0];
|
||||
}
|
||||
return group;
|
||||
}
|
||||
return group;
|
||||
}
|
||||
|
||||
public static String getVersion(Invocation invocation) {
|
||||
String interfaceAndVersion;
|
||||
String[] arr = invocation.getTargetServiceUniqueName().split(PATH_SEPARATOR);
|
||||
if (arr.length == 2) {
|
||||
interfaceAndVersion = arr[1];
|
||||
if (invocation.getServiceModel() != null && invocation.getServiceModel().getServiceMetadata() != null) {
|
||||
return invocation.getServiceModel().getServiceMetadata().getVersion();
|
||||
} else {
|
||||
interfaceAndVersion = arr[0];
|
||||
String interfaceAndVersion;
|
||||
String[] arr = invocation.getTargetServiceUniqueName().split(PATH_SEPARATOR);
|
||||
if (arr.length == 2) {
|
||||
interfaceAndVersion = arr[1];
|
||||
} else {
|
||||
interfaceAndVersion = arr[0];
|
||||
}
|
||||
String[] ivArr = interfaceAndVersion.split(GROUP_CHAR_SEPARATOR);
|
||||
return ivArr.length == 2 ? ivArr[1] : null;
|
||||
}
|
||||
String[] ivArr = interfaceAndVersion.split(GROUP_CHAR_SEPARATOR);
|
||||
return ivArr.length == 2 ? ivArr[1] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -191,29 +204,35 @@ public class MetricsSupport {
|
|||
*/
|
||||
public static void incrAndAddRt(MetricsKey metricsKey, MetricsPlaceValue placeType, ServiceMetricsCollector<TimeCounterEvent> collector, TimeCounterEvent event) {
|
||||
collector.increment(event.getAttachmentValue(ATTACHMENT_KEY_SERVICE), new MetricsKeyWrapper(metricsKey, placeType), SELF_INCREMENT_SIZE);
|
||||
collector.addRt(event.getAttachmentValue(ATTACHMENT_KEY_SERVICE), placeType.getType(), event.getTimePair().calc());
|
||||
Invocation invocation = event.getAttachmentValue(INVOCATION);
|
||||
if (invocation != null) {
|
||||
collector.addServiceRt(invocation, placeType.getType(), event.getTimePair().calc());
|
||||
return;
|
||||
} else {
|
||||
collector.addServiceRt((String) event.getAttachmentValue(ATTACHMENT_KEY_SERVICE), placeType.getType(), event.getTimePair().calc());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Incr method num
|
||||
*/
|
||||
public static void increment(MetricsKey metricsKey, MetricsPlaceValue placeType, MethodMetricsCollector<TimeCounterEvent> collector, MetricsEvent event) {
|
||||
collector.increment(event.getAttachmentValue(INVOCATION), new MetricsKeyWrapper(metricsKey, placeType), SELF_INCREMENT_SIZE);
|
||||
collector.increment(event.getAttachmentValue(METHOD_METRICS), new MetricsKeyWrapper(metricsKey, placeType), SELF_INCREMENT_SIZE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dec method num
|
||||
*/
|
||||
public static void dec(MetricsKey metricsKey, MetricsPlaceValue placeType, MethodMetricsCollector<TimeCounterEvent> collector, MetricsEvent event) {
|
||||
collector.increment(event.getAttachmentValue(INVOCATION), new MetricsKeyWrapper(metricsKey, placeType), -SELF_INCREMENT_SIZE);
|
||||
collector.increment(event.getAttachmentValue(METHOD_METRICS), new MetricsKeyWrapper(metricsKey, placeType), -SELF_INCREMENT_SIZE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Incr method num&&rt
|
||||
*/
|
||||
public static void incrAndAddRt(MetricsKey metricsKey, MetricsPlaceValue placeType, MethodMetricsCollector<TimeCounterEvent> collector, TimeCounterEvent event) {
|
||||
collector.increment(event.getAttachmentValue(INVOCATION), new MetricsKeyWrapper(metricsKey, placeType), SELF_INCREMENT_SIZE);
|
||||
collector.addRt(event.getAttachmentValue(INVOCATION), placeType.getType(), event.getTimePair().calc());
|
||||
collector.increment(event.getAttachmentValue(METHOD_METRICS), new MetricsKeyWrapper(metricsKey, placeType), SELF_INCREMENT_SIZE);
|
||||
collector.addMethodRt(event.getAttachmentValue(INVOCATION), placeType.getType(), event.getTimePair().calc());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -18,8 +18,8 @@
|
|||
package org.apache.dubbo.metrics.model.container;
|
||||
|
||||
import org.apache.dubbo.metrics.model.Metric;
|
||||
import org.apache.dubbo.metrics.model.key.MetricsKeyWrapper;
|
||||
import org.apache.dubbo.metrics.model.key.MetricsKey;
|
||||
import org.apache.dubbo.metrics.model.key.MetricsKeyWrapper;
|
||||
import org.apache.dubbo.metrics.model.sample.GaugeMetricSample;
|
||||
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
|
@ -52,6 +52,7 @@ public class LongContainer<N extends Number> extends ConcurrentHashMap<Metric, N
|
|||
|
||||
|
||||
public LongContainer(MetricsKeyWrapper metricsKeyWrapper, Supplier<N> initFunc, BiConsumer<Long, N> consumerFunc) {
|
||||
super(128, 0.5f);
|
||||
this.metricsKeyWrapper = metricsKeyWrapper;
|
||||
this.initFunc = s -> initFunc.get();
|
||||
this.consumerFunc = consumerFunc;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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()) {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,2 +1,2 @@
|
|||
metrics-beta=org.apache.dubbo.metrics.filter.MetricsFilter
|
||||
observationreceiver=org.apache.dubbo.metrics.observation.ObservationReceiverFilter
|
||||
metrics-provider=org.apache.dubbo.metrics.filter.MetricsProviderFilter
|
||||
observationreceiver=org.apache.dubbo.metrics.observation.ObservationReceiverFilter
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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()) {
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ import static org.apache.dubbo.metrics.MetricsConstants.ATTACHMENT_KEY_SIZE;
|
|||
*/
|
||||
public class RegistryEvent extends TimeCounterEvent {
|
||||
public RegistryEvent(ApplicationModel applicationModel, TypeWrapper typeWrapper) {
|
||||
super(applicationModel,typeWrapper);
|
||||
super(applicationModel, typeWrapper);
|
||||
ScopeBeanFactory beanFactory = getSource().getBeanFactory();
|
||||
RegistryMetricsCollector collector;
|
||||
if (!beanFactory.isDestroyed()) {
|
||||
|
|
@ -47,18 +47,21 @@ public class RegistryEvent extends TimeCounterEvent {
|
|||
}
|
||||
}
|
||||
|
||||
private static final TypeWrapper REGISTER_EVENT = new TypeWrapper(MetricsLevel.APP, MetricsKey.REGISTER_METRIC_REQUESTS, MetricsKey.REGISTER_METRIC_REQUESTS_SUCCEED, MetricsKey.REGISTER_METRIC_REQUESTS_FAILED);
|
||||
public static RegistryEvent toRegisterEvent(ApplicationModel applicationModel) {
|
||||
return new RegistryEvent(applicationModel, new TypeWrapper(MetricsLevel.APP, MetricsKey.REGISTER_METRIC_REQUESTS, MetricsKey.REGISTER_METRIC_REQUESTS_SUCCEED, MetricsKey.REGISTER_METRIC_REQUESTS_FAILED));
|
||||
return new RegistryEvent(applicationModel, REGISTER_EVENT);
|
||||
}
|
||||
|
||||
|
||||
private static final TypeWrapper SUBSCRIBE_EVENT = new TypeWrapper(MetricsLevel.APP, MetricsKey.SUBSCRIBE_METRIC_NUM, MetricsKey.SUBSCRIBE_METRIC_NUM_SUCCEED, MetricsKey.SUBSCRIBE_METRIC_NUM_FAILED);
|
||||
public static RegistryEvent toSubscribeEvent(ApplicationModel applicationModel) {
|
||||
return new RegistryEvent(applicationModel, new TypeWrapper(MetricsLevel.APP, MetricsKey.SUBSCRIBE_METRIC_NUM, MetricsKey.SUBSCRIBE_METRIC_NUM_SUCCEED, MetricsKey.SUBSCRIBE_METRIC_NUM_FAILED));
|
||||
return new RegistryEvent(applicationModel, SUBSCRIBE_EVENT);
|
||||
}
|
||||
|
||||
|
||||
private static final TypeWrapper NOTIFY_EVENT = new TypeWrapper(MetricsLevel.APP, MetricsKey.NOTIFY_METRIC_REQUESTS, MetricsKey.NOTIFY_METRIC_NUM_LAST, (MetricsKey) null);
|
||||
public static RegistryEvent toNotifyEvent(ApplicationModel applicationModel) {
|
||||
return new RegistryEvent(applicationModel, new TypeWrapper(MetricsLevel.APP, MetricsKey.NOTIFY_METRIC_REQUESTS, MetricsKey.NOTIFY_METRIC_NUM_LAST, (MetricsKey) null)) {
|
||||
return new RegistryEvent(applicationModel, NOTIFY_EVENT) {
|
||||
@Override
|
||||
public void customAfterPost(Object postResult) {
|
||||
super.putAttachment(ATTACHMENT_KEY_LAST_NUM_MAP, postResult);
|
||||
|
|
@ -66,21 +69,24 @@ public class RegistryEvent extends TimeCounterEvent {
|
|||
};
|
||||
}
|
||||
|
||||
private static final TypeWrapper RS_EVENT = new TypeWrapper(MetricsLevel.SERVICE, MetricsKey.SERVICE_REGISTER_METRIC_REQUESTS, MetricsKey.SERVICE_REGISTER_METRIC_REQUESTS_SUCCEED, MetricsKey.SERVICE_REGISTER_METRIC_REQUESTS_FAILED);
|
||||
public static RegistryEvent toRsEvent(ApplicationModel applicationModel, String serviceKey, int size) {
|
||||
RegistryEvent ddEvent = new RegistryEvent(applicationModel, new TypeWrapper(MetricsLevel.SERVICE, MetricsKey.SERVICE_REGISTER_METRIC_REQUESTS, MetricsKey.SERVICE_REGISTER_METRIC_REQUESTS_SUCCEED, MetricsKey.SERVICE_REGISTER_METRIC_REQUESTS_FAILED));
|
||||
RegistryEvent ddEvent = new RegistryEvent(applicationModel, RS_EVENT);
|
||||
ddEvent.putAttachment(ATTACHMENT_KEY_SERVICE, serviceKey);
|
||||
ddEvent.putAttachment(ATTACHMENT_KEY_SIZE, size);
|
||||
return ddEvent;
|
||||
}
|
||||
|
||||
private static final TypeWrapper SS_EVENT = new TypeWrapper(MetricsLevel.SERVICE, MetricsKey.SERVICE_SUBSCRIBE_METRIC_NUM, MetricsKey.SERVICE_SUBSCRIBE_METRIC_NUM_SUCCEED, MetricsKey.SERVICE_SUBSCRIBE_METRIC_NUM_FAILED);
|
||||
public static RegistryEvent toSsEvent(ApplicationModel applicationModel, String serviceKey) {
|
||||
RegistryEvent ddEvent = new RegistryEvent(applicationModel, new TypeWrapper(MetricsLevel.SERVICE, MetricsKey.SERVICE_SUBSCRIBE_METRIC_NUM, MetricsKey.SERVICE_SUBSCRIBE_METRIC_NUM_SUCCEED, MetricsKey.SERVICE_SUBSCRIBE_METRIC_NUM_FAILED));
|
||||
RegistryEvent ddEvent = new RegistryEvent(applicationModel, SS_EVENT);
|
||||
ddEvent.putAttachment(ATTACHMENT_KEY_SERVICE, serviceKey);
|
||||
return ddEvent;
|
||||
}
|
||||
|
||||
private static final TypeWrapper DIRECTORY_EVENT = new TypeWrapper(MetricsLevel.APP, MetricsKey.DIRECTORY_METRIC_NUM_VALID, null, null);
|
||||
public static RegistryEvent refreshDirectoryEvent(ApplicationModel applicationModel, Map<MetricsKey, Map<String, Integer>> summaryMap) {
|
||||
RegistryEvent registryEvent = new RegistryEvent(applicationModel, new TypeWrapper(MetricsLevel.APP, MetricsKey.DIRECTORY_METRIC_NUM_VALID, null, null));
|
||||
RegistryEvent registryEvent = new RegistryEvent(applicationModel, DIRECTORY_EVENT);
|
||||
registryEvent.putAttachment(ATTACHMENT_DIRECTORY_MAP, summaryMap);
|
||||
return registryEvent;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -93,7 +93,7 @@ public final class RegistrySubDispatcher extends SimpleMetricsEventMulticaster {
|
|||
MetricsCat APPLICATION_NOTIFY_FINISH = new MetricsCat(MetricsKey.NOTIFY_METRIC_NUM_LAST,
|
||||
(key, placeType, collector) -> AbstractMetricsKeyListener.onFinish(key,
|
||||
event -> {
|
||||
collector.addRt(event.appName(), placeType.getType(), event.getTimePair().calc());
|
||||
collector.addServiceRt(event.appName(), placeType.getType(), event.getTimePair().calc());
|
||||
Map<String, Integer> lastNumMap = Collections.unmodifiableMap(event.getAttachmentValue(ATTACHMENT_KEY_LAST_NUM_MAP));
|
||||
lastNumMap.forEach(
|
||||
(k, v) -> collector.setNum(new MetricsKeyWrapper(key, OP_TYPE_NOTIFY), k, v));
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ import org.apache.dubbo.metrics.model.sample.MetricSample;
|
|||
import org.apache.dubbo.metrics.registry.collector.RegistryMetricsCollector;
|
||||
import org.apache.dubbo.rpc.model.ApplicationModel;
|
||||
import org.apache.dubbo.rpc.model.FrameworkModel;
|
||||
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
|
|
@ -64,8 +65,8 @@ class RegistryMetricsSampleTest {
|
|||
RegistryMetricsCollector collector = new RegistryMetricsCollector(applicationModel);
|
||||
collector.setCollectEnabled(true);
|
||||
String applicationName = applicationModel.getApplicationName();
|
||||
collector.addRt(applicationName, OP_TYPE_REGISTER.getType(), 10L);
|
||||
collector.addRt(applicationName, OP_TYPE_REGISTER.getType(), 0L);
|
||||
collector.addServiceRt(applicationName, OP_TYPE_REGISTER.getType(), 10L);
|
||||
collector.addServiceRt(applicationName, OP_TYPE_REGISTER.getType(), 0L);
|
||||
|
||||
List<MetricSample> samples = collector.collect();
|
||||
for (MetricSample sample : samples) {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -93,7 +93,6 @@ public class ServiceInstancesChangedListener {
|
|||
private final Set<ServiceInstanceNotificationCustomizer> serviceInstanceNotificationCustomizers;
|
||||
private final ApplicationModel applicationModel;
|
||||
|
||||
|
||||
public ServiceInstancesChangedListener(Set<String> serviceNames, ServiceDiscovery serviceDiscovery) {
|
||||
this.serviceNames = serviceNames;
|
||||
this.serviceDiscovery = serviceDiscovery;
|
||||
|
|
|
|||
|
|
@ -114,7 +114,6 @@ public class RegistryDirectory<T> extends DynamicDirectory<T> {
|
|||
super(serviceType, url);
|
||||
moduleModel = getModuleModel(url.getScopeModel());
|
||||
consumerConfigurationListener = getConsumerConfigurationListener(moduleModel);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ import org.apache.dubbo.common.json.GsonUtils;
|
|||
import org.apache.dubbo.common.logger.ErrorTypeAwareLogger;
|
||||
import org.apache.dubbo.common.logger.LoggerFactory;
|
||||
import org.apache.dubbo.common.serialize.Serialization;
|
||||
import org.apache.dubbo.common.utils.ClassUtils;
|
||||
import org.apache.dubbo.common.utils.PojoUtils;
|
||||
import org.apache.dubbo.common.utils.ReflectUtils;
|
||||
import org.apache.dubbo.common.utils.StringUtils;
|
||||
|
|
@ -40,7 +41,9 @@ import org.apache.dubbo.rpc.RpcContext;
|
|||
import org.apache.dubbo.rpc.RpcException;
|
||||
import org.apache.dubbo.rpc.RpcInvocation;
|
||||
import org.apache.dubbo.rpc.model.ApplicationModel;
|
||||
import org.apache.dubbo.rpc.model.MethodDescriptor;
|
||||
import org.apache.dubbo.rpc.model.ScopeModelAware;
|
||||
import org.apache.dubbo.rpc.model.ServiceModel;
|
||||
import org.apache.dubbo.rpc.service.GenericException;
|
||||
import org.apache.dubbo.rpc.service.GenericService;
|
||||
import org.apache.dubbo.rpc.support.ProtocolUtils;
|
||||
|
|
@ -48,6 +51,10 @@ import org.apache.dubbo.rpc.support.ProtocolUtils;
|
|||
import java.io.IOException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
import static org.apache.dubbo.common.constants.CommonConstants.$INVOKE;
|
||||
|
|
@ -67,6 +74,8 @@ public class GenericFilter implements Filter, Filter.Listener, ScopeModelAware {
|
|||
|
||||
private ApplicationModel applicationModel;
|
||||
|
||||
private final Map<ClassLoader, Map<String, Class<?>>> classCache = new ConcurrentHashMap<>();
|
||||
|
||||
@Override
|
||||
public void setApplicationModel(ApplicationModel applicationModel) {
|
||||
this.applicationModel = applicationModel;
|
||||
|
|
@ -82,7 +91,7 @@ public class GenericFilter implements Filter, Filter.Listener, ScopeModelAware {
|
|||
String[] types = (String[]) inv.getArguments()[1];
|
||||
Object[] args = (Object[]) inv.getArguments()[2];
|
||||
try {
|
||||
Method method = ReflectUtils.findMethodByMethodSignature(invoker.getInterface(), name, types);
|
||||
Method method = findMethodByMethodSignature(invoker.getInterface(), name, types, inv.getServiceModel());
|
||||
Class<?>[] params = method.getParameterTypes();
|
||||
if (args == null) {
|
||||
args = new Object[params.length];
|
||||
|
|
@ -219,6 +228,54 @@ public class GenericFilter implements Filter, Filter.Listener, ScopeModelAware {
|
|||
return generic;
|
||||
}
|
||||
|
||||
public Method findMethodByMethodSignature(Class<?> clazz, String methodName, String[] parameterTypes, ServiceModel serviceModel)
|
||||
throws NoSuchMethodException, ClassNotFoundException {
|
||||
Method method;
|
||||
if (parameterTypes == null) {
|
||||
List<Method> finded = new ArrayList<>();
|
||||
for (Method m : clazz.getMethods()) {
|
||||
if (m.getName().equals(methodName)) {
|
||||
finded.add(m);
|
||||
}
|
||||
}
|
||||
if (finded.isEmpty()) {
|
||||
throw new NoSuchMethodException("No such method " + methodName + " in class " + clazz);
|
||||
}
|
||||
if (finded.size() > 1) {
|
||||
String msg = String.format("Not unique method for method name(%s) in class(%s), find %d methods.",
|
||||
methodName, clazz.getName(), finded.size());
|
||||
throw new IllegalStateException(msg);
|
||||
}
|
||||
method = finded.get(0);
|
||||
} else {
|
||||
Class<?>[] types = new Class<?>[parameterTypes.length];
|
||||
for (int i = 0; i < parameterTypes.length; i++) {
|
||||
ClassLoader classLoader = ClassUtils.getClassLoader();
|
||||
Map<String, Class<?>> cacheMap = classCache.get(classLoader);
|
||||
if (cacheMap == null) {
|
||||
cacheMap = new ConcurrentHashMap<>();
|
||||
classCache.putIfAbsent(classLoader, cacheMap);
|
||||
cacheMap = classCache.get(classLoader);
|
||||
}
|
||||
types[i] = cacheMap.get(parameterTypes[i]);
|
||||
if (types[i] == null) {
|
||||
types[i] = ReflectUtils.name2class(parameterTypes[i]);
|
||||
cacheMap.put(parameterTypes[i], types[i]);
|
||||
}
|
||||
}
|
||||
if (serviceModel != null) {
|
||||
MethodDescriptor methodDescriptor = serviceModel.getServiceModel().getMethod(methodName, types);
|
||||
if (methodDescriptor == null) {
|
||||
throw new NoSuchMethodException("No such method " + methodName + " in class " + clazz);
|
||||
}
|
||||
method = methodDescriptor.getMethod();
|
||||
} else {
|
||||
method = clazz.getMethod(methodName, types);
|
||||
}
|
||||
}
|
||||
return method;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResponse(Result appResponse, Invoker<?> invoker, Invocation inv) {
|
||||
if ((inv.getMethodName().equals($INVOKE) || inv.getMethodName().equals($INVOKE_ASYNC))
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -16,9 +16,6 @@
|
|||
*/
|
||||
package org.apache.dubbo.common.serialize.hessian2;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.apache.dubbo.common.utils.DefaultSerializeClassChecker;
|
||||
import org.apache.dubbo.common.utils.SerializeCheckStatus;
|
||||
import org.apache.dubbo.common.utils.SerializeSecurityManager;
|
||||
|
|
@ -27,12 +24,16 @@ import org.apache.dubbo.rpc.model.FrameworkModel;
|
|||
|
||||
import com.alibaba.com.caucho.hessian.io.SerializerFactory;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
|
||||
public class Hessian2FactoryManager {
|
||||
String WHITELIST = "dubbo.application.hessian2.whitelist";
|
||||
String ALLOW = "dubbo.application.hessian2.allow";
|
||||
String DENY = "dubbo.application.hessian2.deny";
|
||||
private volatile SerializerFactory SYSTEM_SERIALIZER_FACTORY;
|
||||
private volatile SerializerFactory stickySerializerFactory = null;
|
||||
private final Map<ClassLoader, SerializerFactory> CL_2_SERIALIZER_FACTORY = new ConcurrentHashMap<>();
|
||||
|
||||
private final SerializeSecurityManager serializeSecurityManager;
|
||||
|
|
@ -44,6 +45,11 @@ public class Hessian2FactoryManager {
|
|||
}
|
||||
|
||||
public SerializerFactory getSerializerFactory(ClassLoader classLoader) {
|
||||
SerializerFactory sticky = stickySerializerFactory;
|
||||
if (sticky != null && sticky.getClassLoader().equals(classLoader)) {
|
||||
return sticky;
|
||||
}
|
||||
|
||||
if (classLoader == null) {
|
||||
// system classloader
|
||||
if (SYSTEM_SERIALIZER_FACTORY == null) {
|
||||
|
|
@ -53,19 +59,23 @@ public class Hessian2FactoryManager {
|
|||
}
|
||||
}
|
||||
}
|
||||
stickySerializerFactory = SYSTEM_SERIALIZER_FACTORY;
|
||||
return SYSTEM_SERIALIZER_FACTORY;
|
||||
}
|
||||
|
||||
if (!CL_2_SERIALIZER_FACTORY.containsKey(classLoader)) {
|
||||
SerializerFactory factory = CL_2_SERIALIZER_FACTORY.get(classLoader);
|
||||
if (factory == null) {
|
||||
synchronized (this) {
|
||||
if (!CL_2_SERIALIZER_FACTORY.containsKey(classLoader)) {
|
||||
SerializerFactory serializerFactory = createSerializerFactory();
|
||||
CL_2_SERIALIZER_FACTORY.put(classLoader, serializerFactory);
|
||||
stickySerializerFactory = serializerFactory;
|
||||
return serializerFactory;
|
||||
}
|
||||
}
|
||||
}
|
||||
return CL_2_SERIALIZER_FACTORY.get(classLoader);
|
||||
stickySerializerFactory = factory;
|
||||
return factory;
|
||||
}
|
||||
|
||||
private SerializerFactory createSerializerFactory() {
|
||||
|
|
|
|||
Loading…
Reference in New Issue