diff --git a/.artifacts b/.artifacts index 9664530db0..5de1b0aa5b 100644 --- a/.artifacts +++ b/.artifacts @@ -61,6 +61,7 @@ dubbo-metrics-default dubbo-metrics-metadata dubbo-metrics-prometheus dubbo-metrics-registry +dubbo-metrics-config-center dubbo-monitor dubbo-monitor-api dubbo-monitor-default @@ -102,6 +103,10 @@ dubbo-spring-boot-actuator-compatible dubbo-spring-boot-autoconfigure dubbo-spring-boot-autoconfigure-compatible dubbo-spring-boot-compatible +dubbo-spring-boot-observability-starters +dubbo-spring-boot-observability-autoconfigure +dubbo-spring-boot-tracing-brave-zipkin-starter +dubbo-spring-boot-tracing-otel-zipkin-starter dubbo-spring-boot-observability-starter dubbo-spring-boot-starter dubbo-spring-security diff --git a/.licenserc.yaml b/.licenserc.yaml index 297e243e12..246f8b2db8 100644 --- a/.licenserc.yaml +++ b/.licenserc.yaml @@ -68,6 +68,7 @@ header: - 'Jenkinsfile' - '**/vendor/**' - '**/src/test/resources/certs/**' + - '**/src/test/resources/definition/**' - 'dubbo-common/src/main/java/org/apache/dubbo/common/threadlocal/InternalThreadLocal.java' - 'dubbo-common/src/main/java/org/apache/dubbo/common/threadlocal/InternalThreadLocalMap.java' - 'dubbo-common/src/main/java/org/apache/dubbo/common/timer/HashedWheelTimer.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 2a4d36dcfc..9cc8f19535 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,7 +20,8 @@ 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.MetricsEvent; +import org.apache.dubbo.metrics.event.MetricsEventBus; +import org.apache.dubbo.metrics.event.RequestBeforeEvent; import org.apache.dubbo.rpc.BaseFilter; import org.apache.dubbo.rpc.Invocation; import org.apache.dubbo.rpc.Invoker; @@ -30,19 +31,17 @@ import org.apache.dubbo.rpc.cluster.filter.ClusterFilter; import org.apache.dubbo.rpc.model.ApplicationModel; import org.apache.dubbo.rpc.model.ScopeModelAware; - -import java.util.Optional; - import static org.apache.dubbo.common.constants.CommonConstants.CONSUMER; -import static org.apache.dubbo.common.constants.CommonConstants.PROVIDER_SIDE; -@Activate(group = CONSUMER,onClass = "org.apache.dubbo.metrics.collector.DefaultMetricsCollector") +@Activate(group = CONSUMER, onClass = "org.apache.dubbo.metrics.collector.DefaultMetricsCollector") public class MetricsClusterFilter implements ClusterFilter, BaseFilter.Listener, ScopeModelAware { + private ApplicationModel applicationModel; private DefaultMetricsCollector collector; @Override public void setApplicationModel(ApplicationModel applicationModel) { + this.applicationModel = applicationModel; this.collector = applicationModel.getBeanFactory().getBean(DefaultMetricsCollector.class); } @@ -65,18 +64,12 @@ public class MetricsClusterFilter implements ClusterFilter, BaseFilter.Listener, if (collector == null || !collector.isCollectEnabled()) { return; } - if (t != null && t instanceof RpcException) { + if (t instanceof RpcException) { RpcException e = (RpcException) t; if (e.isForbidden()) { - collector.getMethodSampler().incOnEvent(invocation, - MetricsEvent.Type.SERVICE_UNAVAILABLE.getNameByType(getSide(invocation))); + MetricsEventBus.publish(RequestBeforeEvent.toEvent(applicationModel, invocation)); } } } - private String getSide(Invocation invocation) { - Optional> invoker = Optional.ofNullable(invocation.getInvoker()); - String side = invoker.isPresent() ? invoker.get().getUrl().getSide() : PROVIDER_SIDE; - return side; - } } diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/AbstractClusterInvoker.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/AbstractClusterInvoker.java index b03447676d..43c9e9b294 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/AbstractClusterInvoker.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/AbstractClusterInvoker.java @@ -333,6 +333,8 @@ public abstract class AbstractClusterInvoker implements ClusterInvoker { List> invokers = list(invocation); InvocationProfilerUtils.releaseDetailProfiler(invocation); + checkInvokers(invokers, invocation); + LoadBalance loadbalance = initLoadBalance(invokers, invocation); RpcUtils.attachInvocationIdIfAsync(getUrl(), invocation); diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/BroadcastClusterInvoker.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/BroadcastClusterInvoker.java index 02b8f6d2d0..bdf8f6f02e 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/BroadcastClusterInvoker.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/BroadcastClusterInvoker.java @@ -51,7 +51,6 @@ public class BroadcastClusterInvoker extends AbstractClusterInvoker { @Override @SuppressWarnings({"unchecked", "rawtypes"}) public Result doInvoke(final Invocation invocation, List> invokers, LoadBalance loadbalance) throws RpcException { - checkInvokers(invokers, invocation); RpcContext.getServiceContext().setInvokers((List) invokers); RpcException exception = null; Result result = null; diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailbackClusterInvoker.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailbackClusterInvoker.java index 608b00ef1f..368244a1df 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailbackClusterInvoker.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailbackClusterInvoker.java @@ -104,7 +104,6 @@ public class FailbackClusterInvoker extends AbstractClusterInvoker { Invoker invoker = null; URL consumerUrl = RpcContext.getServiceContext().getConsumerUrl(); try { - checkInvokers(invokers, invocation); invoker = select(loadbalance, invocation, invokers, null); // Asynchronous call method must be used here, because failback will retry in the background. // Then the serviceContext will be cleared after the call is completed. diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailfastClusterInvoker.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailfastClusterInvoker.java index 0b9f6bd2dc..22c708f824 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailfastClusterInvoker.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailfastClusterInvoker.java @@ -41,7 +41,6 @@ public class FailfastClusterInvoker extends AbstractClusterInvoker { @Override public Result doInvoke(Invocation invocation, List> invokers, LoadBalance loadbalance) throws RpcException { - checkInvokers(invokers, invocation); Invoker invoker = select(loadbalance, invocation, invokers, null); try { return invokeWithContext(invoker, invocation); diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailoverClusterInvoker.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailoverClusterInvoker.java index 18583742ba..b0cdb8ff53 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailoverClusterInvoker.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailoverClusterInvoker.java @@ -57,7 +57,6 @@ public class FailoverClusterInvoker extends AbstractClusterInvoker { @SuppressWarnings({"unchecked", "rawtypes"}) public Result doInvoke(Invocation invocation, final List> invokers, LoadBalance loadbalance) throws RpcException { List> copyInvokers = invokers; - checkInvokers(copyInvokers, invocation); String methodName = RpcUtils.getMethodName(invocation); int len = calculateInvokeTimes(methodName); // retry loop. diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailsafeClusterInvoker.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailsafeClusterInvoker.java index c09205bdbd..78c3540895 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailsafeClusterInvoker.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailsafeClusterInvoker.java @@ -47,7 +47,6 @@ public class FailsafeClusterInvoker extends AbstractClusterInvoker { @Override public Result doInvoke(Invocation invocation, List> invokers, LoadBalance loadbalance) throws RpcException { try { - checkInvokers(invokers, invocation); Invoker invoker = select(loadbalance, invocation, invokers, null); return invokeWithContext(invoker, invocation); } catch (Throwable e) { diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/ForkingClusterInvoker.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/ForkingClusterInvoker.java index a1334aab07..b2f0d2e095 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/ForkingClusterInvoker.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/ForkingClusterInvoker.java @@ -67,7 +67,6 @@ public class ForkingClusterInvoker extends AbstractClusterInvoker { @SuppressWarnings({"unchecked", "rawtypes"}) public Result doInvoke(final Invocation invocation, List> invokers, LoadBalance loadbalance) throws RpcException { try { - checkInvokers(invokers, invocation); final List> selected; final int forks = getUrl().getParameter(FORKS_KEY, DEFAULT_FORKS); final int timeout = getUrl().getParameter(TIMEOUT_KEY, DEFAULT_TIMEOUT); diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/MergeableClusterInvoker.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/MergeableClusterInvoker.java index bdd2ddd6d2..6d61eb2194 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/MergeableClusterInvoker.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/MergeableClusterInvoker.java @@ -59,7 +59,6 @@ public class MergeableClusterInvoker extends AbstractClusterInvoker { @Override protected Result doInvoke(Invocation invocation, List> invokers, LoadBalance loadbalance) throws RpcException { - checkInvokers(invokers, invocation); String merger = getUrl().getMethodParameter(invocation.getMethodName(), MERGER_KEY); if (ConfigUtils.isEmpty(merger)) { // If a method doesn't have a merger, only invoke one Group for (final Invoker invoker : invokers) { diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/AvailableClusterInvokerTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/AvailableClusterInvokerTest.java index 4218bd72d8..b3357e9ba4 100644 --- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/AvailableClusterInvokerTest.java +++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/AvailableClusterInvokerTest.java @@ -107,7 +107,7 @@ class AvailableClusterInvokerTest { invoker.invoke(invocation); fail(); } catch (RpcException e) { - Assertions.assertTrue(e.getMessage().contains("No provider available in")); + Assertions.assertTrue(e.getMessage().contains("No provider available")); assertFalse(e.getCause() instanceof RpcException); } } diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/FailSafeClusterInvokerTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/FailSafeClusterInvokerTest.java index 8887154a6c..dc05557f20 100644 --- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/FailSafeClusterInvokerTest.java +++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/FailSafeClusterInvokerTest.java @@ -17,7 +17,6 @@ package org.apache.dubbo.rpc.cluster.support; import org.apache.dubbo.common.URL; -import org.apache.dubbo.common.utils.LogUtil; import org.apache.dubbo.rpc.AppResponse; import org.apache.dubbo.rpc.Invoker; import org.apache.dubbo.rpc.Result; @@ -25,6 +24,7 @@ import org.apache.dubbo.rpc.RpcContext; import org.apache.dubbo.rpc.RpcInvocation; import org.apache.dubbo.rpc.cluster.Directory; import org.apache.dubbo.rpc.cluster.filter.DemoService; +import org.apache.dubbo.rpc.RpcException; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; @@ -33,7 +33,7 @@ import org.junit.jupiter.api.Test; import java.util.ArrayList; import java.util.List; -import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.assertFalse; import static org.mockito.BDDMockito.given; import static org.mockito.Mockito.mock; @@ -113,10 +113,13 @@ class FailSafeClusterInvokerTest { resetInvokerToNoException(); FailsafeClusterInvoker invoker = new FailsafeClusterInvoker(dic); - LogUtil.start(); - invoker.invoke(invocation); - assertTrue(LogUtil.findMessage("No provider") > 0); - LogUtil.stop(); + + try{ + invoker.invoke(invocation); + } catch (RpcException e){ + Assertions.assertTrue(e.getMessage().contains("No provider available")); + assertFalse(e.getCause() instanceof RpcException); + } } } diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/FailbackClusterInvokerTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/FailbackClusterInvokerTest.java index d7e48afef6..ed161d7c79 100644 --- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/FailbackClusterInvokerTest.java +++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/FailbackClusterInvokerTest.java @@ -24,9 +24,10 @@ import org.apache.dubbo.common.utils.LogUtil; import org.apache.dubbo.rpc.AppResponse; import org.apache.dubbo.rpc.Invoker; import org.apache.dubbo.rpc.Result; -import org.apache.dubbo.rpc.RpcContext; import org.apache.dubbo.rpc.RpcInvocation; +import org.apache.dubbo.rpc.RpcContext; import org.apache.dubbo.rpc.cluster.Directory; +import org.apache.dubbo.rpc.RpcException; import org.apache.log4j.Level; import org.junit.jupiter.api.AfterEach; @@ -37,6 +38,7 @@ import org.junit.jupiter.api.MethodOrderer; import org.junit.jupiter.api.Order; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestMethodOrder; +import org.junit.jupiter.api.function.Executable; import java.lang.reflect.Field; import java.util.ArrayList; @@ -45,7 +47,7 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import static org.apache.dubbo.common.constants.CommonConstants.RETRIES_KEY; -import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.*; import static org.mockito.BDDMockito.given; import static org.mockito.Mockito.mock; @@ -110,6 +112,9 @@ class FailbackClusterInvokerTest { given(dic.getUrl()).willReturn(url); given(dic.getConsumerUrl()).willReturn(url); given(dic.getInterface()).willReturn(FailbackClusterInvokerTest.class); + given(dic.list(invocation)).willReturn(invokers); + given(invoker.getUrl()).willReturn(url); + FailbackClusterInvoker invoker = new FailbackClusterInvoker<>(dic); invoker.invoke(invocation); Assertions.assertNull(RpcContext.getServiceContext().getInvoker()); @@ -123,6 +128,9 @@ class FailbackClusterInvokerTest { given(dic.getUrl()).willReturn(url); given(dic.getConsumerUrl()).willReturn(url); given(dic.getInterface()).willReturn(FailbackClusterInvokerTest.class); + given(dic.list(invocation)).willReturn(invokers); + given(invoker.getUrl()).willReturn(url); + FailbackClusterInvoker invoker = new FailbackClusterInvoker<>(dic); invoker.invoke(invocation); Assertions.assertNull(RpcContext.getServiceContext().getInvoker()); @@ -161,17 +169,15 @@ class FailbackClusterInvokerTest { given(dic.getInterface()).willReturn(FailbackClusterInvokerTest.class); invocation.setMethodName("method1"); - invokers.add(invoker); - resetInvokerToNoException(); - FailbackClusterInvoker invoker = new FailbackClusterInvoker<>(dic); - LogUtil.start(); - DubboAppender.clear(); - invoker.invoke(invocation); - assertEquals(1, LogUtil.findMessage("Failback to invoke")); - LogUtil.stop(); + try{ + invoker.invoke(invocation); + } catch (RpcException e){ + Assertions.assertTrue(e.getMessage().contains("No provider available")); + assertFalse(e.getCause() instanceof RpcException); + } } @Disabled diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/registry/ZoneAwareClusterInvokerTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/registry/ZoneAwareClusterInvokerTest.java index 021f6facb4..9a20078935 100644 --- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/registry/ZoneAwareClusterInvokerTest.java +++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/registry/ZoneAwareClusterInvokerTest.java @@ -24,6 +24,7 @@ import org.apache.dubbo.rpc.RpcException; import org.apache.dubbo.rpc.cluster.ClusterInvoker; import org.apache.dubbo.rpc.cluster.Directory; +import org.apache.dubbo.rpc.cluster.support.AbstractClusterInvoker; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; @@ -174,6 +175,7 @@ class ZoneAwareClusterInvokerTest { given(directory.getUrl()).willReturn(url); given(directory.getConsumerUrl()).willReturn(url); given(directory.list(invocation)).willReturn(new ArrayList<>(0)); + given(directory.getInterface()).willReturn(ZoneAwareClusterInvokerTest.class); zoneAwareClusterInvoker = new ZoneAwareClusterInvoker<>(directory); diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/constants/CommonConstants.java b/dubbo-common/src/main/java/org/apache/dubbo/common/constants/CommonConstants.java index 625ddfb2f8..266cacc7a5 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/constants/CommonConstants.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/constants/CommonConstants.java @@ -275,6 +275,7 @@ public interface CommonConstants { int MAX_PROXY_COUNT = 65535; String MONITOR_KEY = "monitor"; + String BACKGROUND_KEY = "background"; String CLUSTER_KEY = "cluster"; String USERNAME_KEY = "username"; String PASSWORD_KEY = "password"; @@ -313,6 +314,7 @@ public interface CommonConstants { String HEARTBEAT_EVENT = null; String MOCK_HEARTBEAT_EVENT = "H"; String READONLY_EVENT = "R"; + String WRITEABLE_EVENT = "W"; String REFERENCE_FILTER_KEY = "reference.filter"; @@ -628,4 +630,9 @@ public interface CommonConstants { String DUBBO_METRICS_CONFIGCENTER_ENABLE = "dubbo.metrics.configcenter.enable"; Integer TRI_EXCEPTION_CODE_NOT_EXISTS = 0; + + String PACKABLE_METHOD_FACTORY_KEY = "serialize.packable.factory"; + + String DUBBO_PACKABLE_METHOD_FACTORY = "dubbo.application.parameters." + PACKABLE_METHOD_FACTORY_KEY; + } diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/constants/QosConstants.java b/dubbo-common/src/main/java/org/apache/dubbo/common/constants/QosConstants.java index e02ec74a65..29b1993ca6 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/constants/QosConstants.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/constants/QosConstants.java @@ -34,6 +34,8 @@ public interface QosConstants { String ANONYMOUS_ACCESS_PERMISSION_LEVEL = "qos.anonymous.access.permission.level"; + String ANONYMOUS_ACCESS_ALLOW_COMMANDS = "qos.anonymous.access.allow.commands"; + String QOS_ENABLE_COMPATIBLE = "qos-enable"; String QOS_HOST_COMPATIBLE = "qos-host"; diff --git a/dubbo-spring-boot/dubbo-spring-boot-observability-starter/src/main/java/org/apache/dubbo/spring/boot/observability/annotation/ConditionalOnDubboTracingEnable.java b/dubbo-common/src/main/java/org/apache/dubbo/common/lang/Nullable.java similarity index 73% rename from dubbo-spring-boot/dubbo-spring-boot-observability-starter/src/main/java/org/apache/dubbo/spring/boot/observability/annotation/ConditionalOnDubboTracingEnable.java rename to dubbo-common/src/main/java/org/apache/dubbo/common/lang/Nullable.java index 5e6d05f9ce..1114492cc1 100644 --- a/dubbo-spring-boot/dubbo-spring-boot-observability-starter/src/main/java/org/apache/dubbo/spring/boot/observability/annotation/ConditionalOnDubboTracingEnable.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/lang/Nullable.java @@ -14,21 +14,18 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.dubbo.spring.boot.observability.annotation; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +package org.apache.dubbo.common.lang; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; -import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -@Target({ElementType.TYPE,ElementType.METHOD}) + +@Target({ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD}) @Retention(RetentionPolicy.RUNTIME) -@Inherited @Documented -@ConditionalOnProperty(prefix = "dubbo.tracing", name = "enabled", matchIfMissing = true) -public @interface ConditionalOnDubboTracingEnable { +public @interface Nullable { } diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/ReflectionUtils.java b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/ReflectionUtils.java new file mode 100644 index 0000000000..b6b686e50b --- /dev/null +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/ReflectionUtils.java @@ -0,0 +1,150 @@ +/* + * 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.common.utils; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +/** + * A utility class that provides methods for accessing and manipulating private fields and methods of an object. + * This is useful for white-box testing, where the internal workings of a class need to be tested directly. + *

+ * Note: Usage of this class should be limited to testing purposes only, as it violates the encapsulation principle. + */ +public class ReflectionUtils { + + private ReflectionUtils() { + } + + /** + * Retrieves the value of the specified field from the given object. + * + * @param source The object from which to retrieve the field value. + * @param fieldName The name of the field to retrieve. + * @return The value of the specified field in the given object. + * @throws RuntimeException If the specified field does not exist. + */ + public static Object getField(Object source, String fieldName) { + try { + Field f = source.getClass().getDeclaredField(fieldName); + f.setAccessible(true); + return f.get(source); + } catch (Exception e) { + throw new ReflectionException(e); + } + } + + /** + * Invokes the specified method on the given object with the provided parameters. + * + * @param source The object on which to invoke the method. + * @param methodName The name of the method to invoke. + * @param params The parameters to pass to the method. + * @return The result of invoking the specified method on the given object. + */ + public static Object invoke(Object source, String methodName, Object... params) { + try { + Class[] classes = Arrays.stream(params) + .map(param -> param != null ? param.getClass() : null) + .toArray(Class[]::new); + + for (Method method : source.getClass().getDeclaredMethods()) { + if (method.getName().equals(methodName) && matchParameters(method.getParameterTypes(), classes)) { + method.setAccessible(true); + return method.invoke(source, params); + } + } + throw new NoSuchMethodException("No method found with the specified name and parameter types"); + } catch (Exception e) { + throw new ReflectionException(e); + } + } + + private static boolean matchParameters(Class[] methodParamTypes, Class[] givenParamTypes) { + if (methodParamTypes.length != givenParamTypes.length) { + return false; + } + + for (int i = 0; i < methodParamTypes.length; i++) { + if (givenParamTypes[i] == null) { + if (methodParamTypes[i].isPrimitive()) { + return false; + } + } else if (!methodParamTypes[i].isAssignableFrom(givenParamTypes[i])) { + return false; + } + } + + return true; + } + + /** + * Returns a list of distinct {@link Class} objects representing the generics of the given class that implement the + * given interface. + * + * @param clazz the class to retrieve the generics for + * @param interfaceClass the interface to retrieve the generics for + * @return a list of distinct {@link Class} objects representing the generics of the given class that implement the + * given interface + */ + public static List> getClassGenerics(Class clazz, Class interfaceClass) { + List> generics = new ArrayList<>(); + Type[] genericInterfaces = clazz.getGenericInterfaces(); + for (Type genericInterface : genericInterfaces) { + if (genericInterface instanceof ParameterizedType) { + ParameterizedType parameterizedType = (ParameterizedType) genericInterface; + Type rawType = parameterizedType.getRawType(); + if (rawType instanceof Class && interfaceClass.isAssignableFrom((Class) rawType)) { + Type[] actualTypeArguments = parameterizedType.getActualTypeArguments(); + for (Type actualTypeArgument : actualTypeArguments) { + if (actualTypeArgument instanceof Class) { + generics.add((Class) actualTypeArgument); + } + } + } + } + } + Type genericSuperclass = clazz.getGenericSuperclass(); + if (genericSuperclass instanceof ParameterizedType) { + ParameterizedType parameterizedType = (ParameterizedType) genericSuperclass; + Type[] actualTypeArguments = parameterizedType.getActualTypeArguments(); + for (Type actualTypeArgument : actualTypeArguments) { + if (actualTypeArgument instanceof Class) { + generics.add((Class) actualTypeArgument); + } + } + } + Class superclass = clazz.getSuperclass(); + if (superclass != null) { + generics.addAll(getClassGenerics(superclass, interfaceClass)); + } + return generics.stream().distinct().collect(Collectors.toList()); + } + + public static class ReflectionException extends RuntimeException { + public ReflectionException(Throwable cause) { + super(cause); + } + } + +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/config/AbstractInterfaceConfig.java b/dubbo-common/src/main/java/org/apache/dubbo/config/AbstractInterfaceConfig.java index 023dea6e60..f4f397d574 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/config/AbstractInterfaceConfig.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/config/AbstractInterfaceConfig.java @@ -313,7 +313,8 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig { // There may be no interface class when generic call return; } - if (!interfaceClass.isInterface()) { + + if (!interfaceClass.isInterface() && !canSkipInterfaceCheck()) { throw new IllegalStateException(interfaceName + " is not an interface"); } @@ -373,6 +374,15 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig { } + /** + * it is used for skipping the check of interface since dubbo 3.2 + * rest protocol allow the service is implement class + * @return + */ + protected boolean canSkipInterfaceCheck() { + return false; + } + protected boolean verifyMethodConfig(MethodConfig methodConfig, Class interfaceClass, boolean ignoreInvalidMethodConfig) { String methodName = methodConfig.getName(); if (StringUtils.isEmpty(methodName)) { @@ -687,7 +697,7 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig { } public void setRegistry(RegistryConfig registry) { - List registries = new ArrayList(1); + List registries = new ArrayList<>(1); registries.add(registry); setRegistries(registries); } @@ -715,7 +725,6 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig { return methods; } - @SuppressWarnings("unchecked") public void setMethods(List methods) { this.methods = (methods != null) ? new ArrayList<>(methods) : null; } @@ -922,4 +931,5 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig { public void setInterfaceClassLoader(ClassLoader interfaceClassLoader) { this.interfaceClassLoader = interfaceClassLoader; } + } diff --git a/dubbo-common/src/main/java/org/apache/dubbo/config/ApplicationConfig.java b/dubbo-common/src/main/java/org/apache/dubbo/config/ApplicationConfig.java index 63dcfb5375..7336c6d144 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/config/ApplicationConfig.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/config/ApplicationConfig.java @@ -55,6 +55,7 @@ import static org.apache.dubbo.common.constants.QosConstants.ACCEPT_FOREIGN_IP; import static org.apache.dubbo.common.constants.QosConstants.ACCEPT_FOREIGN_IP_COMPATIBLE; import static org.apache.dubbo.common.constants.QosConstants.ACCEPT_FOREIGN_IP_WHITELIST; import static org.apache.dubbo.common.constants.QosConstants.ACCEPT_FOREIGN_IP_WHITELIST_COMPATIBLE; +import static org.apache.dubbo.common.constants.QosConstants.ANONYMOUS_ACCESS_ALLOW_COMMANDS; import static org.apache.dubbo.common.constants.QosConstants.ANONYMOUS_ACCESS_PERMISSION_LEVEL; import static org.apache.dubbo.common.constants.QosConstants.ANONYMOUS_ACCESS_PERMISSION_LEVEL_COMPATIBLE; import static org.apache.dubbo.common.constants.QosConstants.QOS_ENABLE; @@ -170,6 +171,11 @@ public class ApplicationConfig extends AbstractConfig { */ private String qosAnonymousAccessPermissionLevel; + /** + * the anonymous(any foreign ip) allow commands, default is empty, can not access any cmd + */ + private String qosAnonymousAllowCommands; + /** * Customized parameters */ @@ -472,6 +478,15 @@ public class ApplicationConfig extends AbstractConfig { this.qosAnonymousAccessPermissionLevel = qosAnonymousAccessPermissionLevel; } + @Parameter(key = ANONYMOUS_ACCESS_ALLOW_COMMANDS) + public String getQosAnonymousAllowCommands() { + return qosAnonymousAllowCommands; + } + + public void setQosAnonymousAllowCommands(String qosAnonymousAllowCommands) { + this.qosAnonymousAllowCommands = qosAnonymousAllowCommands; + } + /** * The format is the same as the springboot, including: getQosEnableCompatible(), getQosPortCompatible(), getQosAcceptForeignIpCompatible(). * diff --git a/dubbo-common/src/main/java/org/apache/dubbo/config/Constants.java b/dubbo-common/src/main/java/org/apache/dubbo/config/Constants.java index cd65fc4119..ed2e821368 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/config/Constants.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/config/Constants.java @@ -150,4 +150,6 @@ public interface Constants { String SERVER_THREAD_POOL_NAME = "DubboServerHandler"; String CLIENT_THREAD_POOL_NAME = "DubboClientHandler"; + + String REST_PROTOCOL="rest"; } diff --git a/dubbo-common/src/main/java/org/apache/dubbo/config/ProtocolConfig.java b/dubbo-common/src/main/java/org/apache/dubbo/config/ProtocolConfig.java index 5586f9c64b..c6be90b3db 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/config/ProtocolConfig.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/config/ProtocolConfig.java @@ -273,7 +273,7 @@ public class ProtocolConfig extends AbstractConfig { return name; } - public final void setName(String name) { + public void setName(String name) { this.name = name; } @@ -291,7 +291,7 @@ public class ProtocolConfig extends AbstractConfig { return port; } - public final void setPort(Integer port) { + public void setPort(Integer port) { this.port = port; } diff --git a/dubbo-common/src/main/java/org/apache/dubbo/config/ServiceConfigBase.java b/dubbo-common/src/main/java/org/apache/dubbo/config/ServiceConfigBase.java index 57f850c18c..78e6bf1c16 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/config/ServiceConfigBase.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/config/ServiceConfigBase.java @@ -51,7 +51,6 @@ public abstract class ServiceConfigBase extends AbstractServiceConfig { private static final long serialVersionUID = 3033787999037024738L; - /** * The interface class of the exported service */ @@ -173,8 +172,8 @@ public abstract class ServiceConfigBase extends AbstractServiceConfig { convertProviderIdToProvider(); if (provider == null) { provider = getModuleConfigManager() - .getDefaultProvider() - .orElseThrow(() -> new IllegalStateException("Default provider is not initialized")); + .getDefaultProvider() + .orElseThrow(() -> new IllegalStateException("Default provider is not initialized")); } // try set properties from `dubbo.service` if not set in current config refreshWithPrefixes(super.getPrefixes(), ConfigMode.OVERRIDE_IF_ABSENT); @@ -228,7 +227,7 @@ public abstract class ServiceConfigBase extends AbstractServiceConfig { protected void convertProviderIdToProvider() { if (provider == null && StringUtils.hasText(providerIds)) { provider = getModuleConfigManager().getProvider(providerIds) - .orElseThrow(() -> new IllegalStateException("Provider config not found: " + providerIds)); + .orElseThrow(() -> new IllegalStateException("Provider config not found: " + providerIds)); } } @@ -250,7 +249,7 @@ public abstract class ServiceConfigBase extends AbstractServiceConfig { if (globalProtocol.isPresent()) { tmpProtocols.add(globalProtocol.get()); } else { - throw new IllegalStateException("Protocol not found: "+id); + throw new IllegalStateException("Protocol not found: " + id); } } setProtocols(tmpProtocols); @@ -267,7 +266,7 @@ public abstract class ServiceConfigBase extends AbstractServiceConfig { try { if (StringUtils.isNotEmpty(interfaceName)) { this.interfaceClass = Class.forName(interfaceName, true, Thread.currentThread() - .getContextClassLoader()); + .getContextClassLoader()); } } catch (ClassNotFoundException t) { throw new IllegalStateException(t.getMessage(), t); @@ -285,9 +284,9 @@ public abstract class ServiceConfigBase extends AbstractServiceConfig { } - public void setInterface(Class interfaceClass) { - if (interfaceClass != null && !interfaceClass.isInterface()) { + // rest protocol allow set impl class + if (interfaceClass != null && !interfaceClass.isInterface() && !canSkipInterfaceCheck()) { throw new IllegalStateException("The interface class " + interfaceClass + " is not a interface!"); } this.interfaceClass = interfaceClass; @@ -297,6 +296,23 @@ public abstract class ServiceConfigBase extends AbstractServiceConfig { } } + @Override + public boolean canSkipInterfaceCheck() { + // for multipart protocol so for each contain + List protocols = getProtocols(); + + if (protocols == null) { + return false; + } + + for (ProtocolConfig protocol : protocols) { + if (Constants.REST_PROTOCOL.equals(protocol.getName())) { + return true; + } + } + return false; + } + @Transient public T getRef() { return ref; diff --git a/dubbo-common/src/main/java/org/apache/dubbo/config/TracingConfig.java b/dubbo-common/src/main/java/org/apache/dubbo/config/TracingConfig.java index 62b134f35c..3a7e4e3b91 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/config/TracingConfig.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/config/TracingConfig.java @@ -14,9 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.dubbo.config; import org.apache.dubbo.config.nested.BaggageConfig; +import org.apache.dubbo.config.nested.ExporterConfig; import org.apache.dubbo.config.nested.PropagationConfig; import org.apache.dubbo.config.nested.SamplingConfig; import org.apache.dubbo.config.support.Nested; @@ -49,6 +51,12 @@ public class TracingConfig extends AbstractConfig { @Nested private PropagationConfig propagation = new PropagationConfig(); + /** + * Exporter configuration. + */ + @Nested + private ExporterConfig tracingExporter = new ExporterConfig(); + public TracingConfig() { } @@ -87,4 +95,12 @@ public class TracingConfig extends AbstractConfig { public void setPropagation(PropagationConfig propagation) { this.propagation = propagation; } + + public ExporterConfig getTracingExporter() { + return tracingExporter; + } + + public void setTracingExporter(ExporterConfig tracingExporter) { + this.tracingExporter = tracingExporter; + } } diff --git a/dubbo-common/src/main/java/org/apache/dubbo/config/nested/ExporterConfig.java b/dubbo-common/src/main/java/org/apache/dubbo/config/nested/ExporterConfig.java new file mode 100644 index 0000000000..076daa9287 --- /dev/null +++ b/dubbo-common/src/main/java/org/apache/dubbo/config/nested/ExporterConfig.java @@ -0,0 +1,79 @@ +/* + * 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.config.nested; + +import org.apache.dubbo.config.support.Nested; + +import java.io.Serializable; +import java.time.Duration; + +public class ExporterConfig implements Serializable { + + @Nested + private ZipkinConfig zipkinConfig; + + public ZipkinConfig getZipkinConfig() { + return zipkinConfig; + } + + public void setZipkinConfig(ZipkinConfig zipkinConfig) { + this.zipkinConfig = zipkinConfig; + } + + public static class ZipkinConfig implements Serializable { + + /** + * URL to the Zipkin API. + */ + private String endpoint; + + /** + * Connection timeout for requests to Zipkin. + */ + private Duration connectTimeout = Duration.ofSeconds(1); + + /** + * Read timeout for requests to Zipkin. + */ + private Duration readTimeout = Duration.ofSeconds(10); + + public String getEndpoint() { + return endpoint; + } + + public void setEndpoint(String endpoint) { + this.endpoint = endpoint; + } + + public Duration getConnectTimeout() { + return connectTimeout; + } + + public void setConnectTimeout(Duration connectTimeout) { + this.connectTimeout = connectTimeout; + } + + public Duration getReadTimeout() { + return readTimeout; + } + + public void setReadTimeout(Duration readTimeout) { + this.readTimeout = readTimeout; + } + } +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/Pack.java b/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/Pack.java new file mode 100644 index 0000000000..50f46c5f8b --- /dev/null +++ b/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/Pack.java @@ -0,0 +1,29 @@ +/* + * 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.model; + +public interface Pack { + + /** + * @param obj instance + * @return byte array + * @throws Exception when error occurs + */ + byte[] pack(Object obj) throws Exception; + +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/PackableMethod.java b/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/PackableMethod.java index f21cc4d690..a9707bc073 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/PackableMethod.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/PackableMethod.java @@ -17,56 +17,21 @@ package org.apache.dubbo.rpc.model; -import java.io.IOException; - /** * A packable method is used to customize serialization for methods. It can provide a common wrapper * for RESP / Protobuf. */ public interface PackableMethod { - interface Pack { - - /** - * @param obj instance - * @return byte array - * @throws IOException when error occurs - */ - byte[] pack(Object obj) throws IOException; - } - - interface WrapperUnPack extends UnPack { - - default Object unpack(byte[] data) throws IOException, ClassNotFoundException { - return unpack(data, false); - } - - Object unpack(byte[] data, boolean isReturnTriException) throws IOException, ClassNotFoundException; - - - } - - interface UnPack { - - /** - * @param data byte array - * @return object instance - * @throws IOException IOException - * @throws ClassNotFoundException when no class found - */ - Object unpack(byte[] data) throws IOException, ClassNotFoundException; - - } - - default Object parseRequest(byte[] data) throws IOException, ClassNotFoundException { + default Object parseRequest(byte[] data) throws Exception { return getRequestUnpack().unpack(data); } - default Object parseResponse(byte[] data) throws IOException, ClassNotFoundException { + default Object parseResponse(byte[] data) throws Exception { return parseResponse(data, false); } - default Object parseResponse(byte[] data, boolean isReturnTriException) throws IOException, ClassNotFoundException { + default Object parseResponse(byte[] data, boolean isReturnTriException) throws Exception { UnPack unPack = getResponseUnpack(); if (unPack instanceof WrapperUnPack) { return ((WrapperUnPack) unPack).unpack(data, isReturnTriException); @@ -74,11 +39,11 @@ public interface PackableMethod { return unPack.unpack(data); } - default byte[] packRequest(Object request) throws IOException { + default byte[] packRequest(Object request) throws Exception { return getRequestPack().pack(request); } - default byte[] packResponse(Object response) throws IOException { + default byte[] packResponse(Object response) throws Exception { return getResponsePack().pack(response); } diff --git a/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/PackableMethodFactory.java b/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/PackableMethodFactory.java new file mode 100644 index 0000000000..c3961a78c5 --- /dev/null +++ b/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/PackableMethodFactory.java @@ -0,0 +1,29 @@ +/* + * 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.model; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.extension.ExtensionScope; +import org.apache.dubbo.common.extension.SPI; + +@SPI(scope = ExtensionScope.FRAMEWORK) +public interface PackableMethodFactory { + + PackableMethod create(MethodDescriptor methodDescriptor, URL url, String contentType); + +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ProviderModel.java b/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ProviderModel.java index 775d5c93c6..d578cef6fe 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ProviderModel.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ProviderModel.java @@ -40,6 +40,8 @@ public class ProviderModel extends ServiceModel { */ private List serviceUrls = new ArrayList<>(); + private volatile long lastInvokeTime = 0; + public ProviderModel(String serviceKey, Object serviceInstance, ServiceDescriptor serviceDescriptor, @@ -176,6 +178,14 @@ public class ProviderModel extends ServiceModel { } + public long getLastInvokeTime() { + return lastInvokeTime; + } + + public void updateLastInvokeTime() { + this.lastInvokeTime = System.currentTimeMillis(); + } + @Override public boolean equals(Object o) { if (this == o) { diff --git a/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/UnPack.java b/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/UnPack.java new file mode 100644 index 0000000000..b214e50ce0 --- /dev/null +++ b/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/UnPack.java @@ -0,0 +1,29 @@ +/* + * 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.model; + +public interface UnPack { + + /** + * @param data byte array + * @return object instance + * @throws Exception exception + */ + Object unpack(byte[] data) throws Exception; + +} diff --git a/dubbo-metrics/dubbo-metrics-default/src/test/java/org/apache/dubbo/metrics/metrics/event/RTEventTest.java b/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/WrapperUnPack.java similarity index 56% rename from dubbo-metrics/dubbo-metrics-default/src/test/java/org/apache/dubbo/metrics/metrics/event/RTEventTest.java rename to dubbo-common/src/main/java/org/apache/dubbo/rpc/model/WrapperUnPack.java index a69c166318..444309689e 100644 --- a/dubbo-metrics/dubbo-metrics-default/src/test/java/org/apache/dubbo/metrics/metrics/event/RTEventTest.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/WrapperUnPack.java @@ -15,23 +15,14 @@ * limitations under the License. */ -package org.apache.dubbo.metrics.metrics.event; +package org.apache.dubbo.rpc.model; -import org.apache.dubbo.metrics.event.RTEvent; -import org.apache.dubbo.metrics.model.MethodMetric; -import org.apache.dubbo.rpc.model.ApplicationModel; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; +public interface WrapperUnPack extends UnPack { -class RTEventTest { - - @Test - void testNewEvent() { - MethodMetric metric = new MethodMetric(); - Long rt = 5L; - RTEvent event = new RTEvent(ApplicationModel.defaultModel(), metric, rt); - - Assertions.assertEquals(event.getSource(), ApplicationModel.defaultModel()); - Assertions.assertEquals(event.getRt(), rt); + default Object unpack(byte[] data) throws Exception { + return unpack(data, false); } + + Object unpack(byte[] data, boolean isReturnTriException) throws Exception; + } diff --git a/dubbo-compatible/src/main/java/com/alibaba/dubbo/config/ApplicationConfig.java b/dubbo-compatible/src/main/java/com/alibaba/dubbo/config/ApplicationConfig.java index f17e7ed516..ab5f8c2fa8 100644 --- a/dubbo-compatible/src/main/java/com/alibaba/dubbo/config/ApplicationConfig.java +++ b/dubbo-compatible/src/main/java/com/alibaba/dubbo/config/ApplicationConfig.java @@ -27,4 +27,17 @@ public class ApplicationConfig extends org.apache.dubbo.config.ApplicationConfig public ApplicationConfig(String name) { super(name); } + + public void setRegistry(com.alibaba.dubbo.config.RegistryConfig registry) { + super.setRegistry(registry); + } + + public void setMonitor(com.alibaba.dubbo.config.MonitorConfig monitor) { + super.setMonitor(monitor); + } + + @Override + public void setMonitor(String monitor) { + setMonitor(new com.alibaba.dubbo.config.MonitorConfig(monitor)); + } } diff --git a/dubbo-compatible/src/main/java/com/alibaba/dubbo/config/ConsumerConfig.java b/dubbo-compatible/src/main/java/com/alibaba/dubbo/config/ConsumerConfig.java index 320ec47ec6..3c24db1d2a 100644 --- a/dubbo-compatible/src/main/java/com/alibaba/dubbo/config/ConsumerConfig.java +++ b/dubbo-compatible/src/main/java/com/alibaba/dubbo/config/ConsumerConfig.java @@ -19,4 +19,32 @@ package com.alibaba.dubbo.config; @Deprecated public class ConsumerConfig extends org.apache.dubbo.config.ConsumerConfig { + + public void setApplication(com.alibaba.dubbo.config.ApplicationConfig application) { + super.setApplication(application); + } + + public void setModule(com.alibaba.dubbo.config.ModuleConfig module) { + super.setModule(module); + } + + public void setRegistry(com.alibaba.dubbo.config.RegistryConfig registry) { + super.setRegistry(registry); + } + + public void addMethod(com.alibaba.dubbo.config.MethodConfig methodConfig) { + super.addMethod(methodConfig); + } + + public void setMonitor(com.alibaba.dubbo.config.MonitorConfig monitor) { + super.setMonitor(monitor); + } + + public void setMock(Boolean mock) { + if (mock == null) { + setMock((String) null); + } else { + setMock(String.valueOf(mock)); + } + } } diff --git a/dubbo-compatible/src/main/java/com/alibaba/dubbo/config/MethodConfig.java b/dubbo-compatible/src/main/java/com/alibaba/dubbo/config/MethodConfig.java index c3d13e9216..ff368c7011 100644 --- a/dubbo-compatible/src/main/java/com/alibaba/dubbo/config/MethodConfig.java +++ b/dubbo-compatible/src/main/java/com/alibaba/dubbo/config/MethodConfig.java @@ -19,5 +19,15 @@ package com.alibaba.dubbo.config; @Deprecated public class MethodConfig extends org.apache.dubbo.config.MethodConfig { + public void addArgument(com.alibaba.dubbo.config.ArgumentConfig argumentConfig) { + super.addArgument(argumentConfig); + } + public void setMock(Boolean mock) { + if (mock == null) { + setMock((String) null); + } else { + setMock(String.valueOf(mock)); + } + } } diff --git a/dubbo-compatible/src/main/java/com/alibaba/dubbo/config/ModuleConfig.java b/dubbo-compatible/src/main/java/com/alibaba/dubbo/config/ModuleConfig.java index 8b75279f8c..3b122efc56 100644 --- a/dubbo-compatible/src/main/java/com/alibaba/dubbo/config/ModuleConfig.java +++ b/dubbo-compatible/src/main/java/com/alibaba/dubbo/config/ModuleConfig.java @@ -26,4 +26,17 @@ public class ModuleConfig extends org.apache.dubbo.config.ModuleConfig { public ModuleConfig(String name) { super(name); } + + public void setRegistry(com.alibaba.dubbo.config.RegistryConfig registry) { + super.setRegistry(registry); + } + + public void setMonitor(com.alibaba.dubbo.config.MonitorConfig monitor) { + super.setMonitor(monitor); + } + + @Override + public void setMonitor(String monitor) { + setMonitor(new com.alibaba.dubbo.config.MonitorConfig(monitor)); + } } diff --git a/dubbo-compatible/src/main/java/com/alibaba/dubbo/config/ProtocolConfig.java b/dubbo-compatible/src/main/java/com/alibaba/dubbo/config/ProtocolConfig.java index 0835ef0cb8..3f716c3480 100644 --- a/dubbo-compatible/src/main/java/com/alibaba/dubbo/config/ProtocolConfig.java +++ b/dubbo-compatible/src/main/java/com/alibaba/dubbo/config/ProtocolConfig.java @@ -30,4 +30,10 @@ public class ProtocolConfig extends org.apache.dubbo.config.ProtocolConfig { public ProtocolConfig(String name, int port) { super(name, port); } + + public void mergeProtocol(ProtocolConfig sourceConfig) { + super.mergeProtocol(sourceConfig); + } + + } diff --git a/dubbo-compatible/src/main/java/com/alibaba/dubbo/config/ProviderConfig.java b/dubbo-compatible/src/main/java/com/alibaba/dubbo/config/ProviderConfig.java index fb353bf2f0..f7ff0c345c 100644 --- a/dubbo-compatible/src/main/java/com/alibaba/dubbo/config/ProviderConfig.java +++ b/dubbo-compatible/src/main/java/com/alibaba/dubbo/config/ProviderConfig.java @@ -19,4 +19,40 @@ package com.alibaba.dubbo.config; @Deprecated public class ProviderConfig extends org.apache.dubbo.config.ProviderConfig { + public void setApplication(com.alibaba.dubbo.config.ApplicationConfig application) { + super.setApplication(application); + } + + public void setModule(com.alibaba.dubbo.config.ModuleConfig module) { + super.setModule(module); + } + + public void setRegistry(com.alibaba.dubbo.config.RegistryConfig registry) { + super.setRegistry(registry); + } + + public void addMethod(com.alibaba.dubbo.config.MethodConfig methodConfig) { + super.addMethod(methodConfig); + } + + public void setMonitor(com.alibaba.dubbo.config.MonitorConfig monitor) { + super.setMonitor(monitor); + } + + public void setProtocol(com.alibaba.dubbo.config.ProtocolConfig protocol) { + super.setProtocol(protocol); + } + + @Override + public void setProtocol(String protocol) { + setProtocol(new com.alibaba.dubbo.config.ProtocolConfig(protocol)); + } + + public void setMock(Boolean mock) { + if (mock == null) { + setMock((String) null); + } else { + setMock(String.valueOf(mock)); + } + } } diff --git a/dubbo-compatible/src/main/java/com/alibaba/dubbo/config/ReferenceConfig.java b/dubbo-compatible/src/main/java/com/alibaba/dubbo/config/ReferenceConfig.java index 73f6819577..1e40b6f4c9 100644 --- a/dubbo-compatible/src/main/java/com/alibaba/dubbo/config/ReferenceConfig.java +++ b/dubbo-compatible/src/main/java/com/alibaba/dubbo/config/ReferenceConfig.java @@ -29,5 +29,39 @@ public class ReferenceConfig extends org.apache.dubbo.config.ReferenceConfig< super(reference); } + public void setConsumer(com.alibaba.dubbo.config.ConsumerConfig consumer) { + super.setConsumer(consumer); + } + public void setApplication(com.alibaba.dubbo.config.ApplicationConfig application) { + super.setApplication(application); + } + + public void setModule(com.alibaba.dubbo.config.ModuleConfig module) { + super.setModule(module); + } + + public void setRegistry(com.alibaba.dubbo.config.RegistryConfig registry) { + super.setRegistry(registry); + } + + public void addMethod(com.alibaba.dubbo.config.MethodConfig methodConfig) { + super.addMethod(methodConfig); + } + + public void setMonitor(com.alibaba.dubbo.config.MonitorConfig monitor) { + super.setMonitor(monitor); + } + + public void setMock(Boolean mock) { + if (mock == null) { + setMock((String) null); + } else { + setMock(String.valueOf(mock)); + } + } + + public void setInterfaceClass(Class interfaceClass) { + setInterface(interfaceClass); + } } diff --git a/dubbo-compatible/src/main/java/com/alibaba/dubbo/config/ServiceConfig.java b/dubbo-compatible/src/main/java/com/alibaba/dubbo/config/ServiceConfig.java index f0f22d76cb..e874a59798 100644 --- a/dubbo-compatible/src/main/java/com/alibaba/dubbo/config/ServiceConfig.java +++ b/dubbo-compatible/src/main/java/com/alibaba/dubbo/config/ServiceConfig.java @@ -19,6 +19,9 @@ package com.alibaba.dubbo.config; import org.apache.dubbo.config.annotation.Service; +import java.util.ArrayList; +import java.util.List; + @Deprecated public class ServiceConfig extends org.apache.dubbo.config.ServiceConfig { @@ -28,4 +31,97 @@ public class ServiceConfig extends org.apache.dubbo.config.ServiceConfig { public ServiceConfig(Service service) { super(service); } + + public void setProvider(com.alibaba.dubbo.config.ProviderConfig provider) { + super.setProvider(provider); + } + + public void setApplication(com.alibaba.dubbo.config.ApplicationConfig application) { + super.setApplication(application); + } + + public void setModule(com.alibaba.dubbo.config.ModuleConfig module) { + super.setModule(module); + } + + public void setRegistry(com.alibaba.dubbo.config.RegistryConfig registry) { + super.setRegistry(registry); + } + + public void addMethod(com.alibaba.dubbo.config.MethodConfig methodConfig) { + super.addMethod(methodConfig); + } + + public com.alibaba.dubbo.config.MonitorConfig getMonitor() { + org.apache.dubbo.config.MonitorConfig monitorConfig = super.getMonitor(); + if (monitorConfig == null) { + return null; + } + if (monitorConfig instanceof com.alibaba.dubbo.config.MonitorConfig) { + return (com.alibaba.dubbo.config.MonitorConfig) monitorConfig; + } + throw new IllegalArgumentException("Monitor has not been set with type com.alibaba.dubbo.config.MonitorConfig. " + + "Found " + monitorConfig.getClass().getName() + " instead."); + } + + public void setMonitor(com.alibaba.dubbo.config.MonitorConfig monitor) { + super.setMonitor(monitor); + } + + public void setProtocol(com.alibaba.dubbo.config.ProtocolConfig protocol) { + super.setProtocol(protocol); + } + + public void setMock(Boolean mock) { + if (mock == null) { + setMock((String) null); + } else { + setMock(String.valueOf(mock)); + } + } + + public void setProviders(List providers) { + setProtocols(convertProviderToProtocol(providers)); + } + + private static List convertProviderToProtocol(List providers) { + if (providers == null || providers.isEmpty()) { + return null; + } + List protocols = new ArrayList(providers.size()); + for (ProviderConfig provider : providers) { + protocols.add(convertProviderToProtocol(provider)); + } + return protocols; + } + + private static ProtocolConfig convertProviderToProtocol(ProviderConfig provider) { + ProtocolConfig protocol = new ProtocolConfig(); + protocol.setName(provider.getProtocol().getName()); + protocol.setServer(provider.getServer()); + protocol.setClient(provider.getClient()); + protocol.setCodec(provider.getCodec()); + protocol.setHost(provider.getHost()); + protocol.setPort(provider.getPort()); + protocol.setPath(provider.getPath()); + protocol.setPayload(provider.getPayload()); + protocol.setThreads(provider.getThreads()); + protocol.setParameters(provider.getParameters()); + return protocol; + } + + private static ProviderConfig convertProtocolToProvider(ProtocolConfig protocol) { + ProviderConfig provider = new ProviderConfig(); + provider.setProtocol(protocol); + provider.setServer(protocol.getServer()); + provider.setClient(protocol.getClient()); + provider.setCodec(protocol.getCodec()); + provider.setHost(protocol.getHost()); + provider.setPort(protocol.getPort()); + provider.setPath(protocol.getPath()); + provider.setPayload(protocol.getPayload()); + provider.setThreads(protocol.getThreads()); + provider.setParameters(protocol.getParameters()); + return provider; + } } diff --git a/dubbo-compatible/src/main/java/com/alibaba/dubbo/rpc/Exporter.java b/dubbo-compatible/src/main/java/com/alibaba/dubbo/rpc/Exporter.java index c1fadeb9d8..5da68a3b20 100644 --- a/dubbo-compatible/src/main/java/com/alibaba/dubbo/rpc/Exporter.java +++ b/dubbo-compatible/src/main/java/com/alibaba/dubbo/rpc/Exporter.java @@ -23,6 +23,8 @@ public interface Exporter extends org.apache.dubbo.rpc.Exporter { @Override Invoker getInvoker(); + default void unregister() {} + class CompatibleExporter implements Exporter { private org.apache.dubbo.rpc.Exporter delegate; @@ -40,5 +42,10 @@ public interface Exporter extends org.apache.dubbo.rpc.Exporter { public void unexport() { delegate.unexport(); } + + @Override + public void unregister() { + delegate.unregister(); + } } } diff --git a/dubbo-compatible/src/test/java/org/apache/dubbo/config/ModuleConfigTest.java b/dubbo-compatible/src/test/java/org/apache/dubbo/config/ModuleConfigTest.java index 1075f15b9f..45c60bbb20 100644 --- a/dubbo-compatible/src/test/java/org/apache/dubbo/config/ModuleConfigTest.java +++ b/dubbo-compatible/src/test/java/org/apache/dubbo/config/ModuleConfigTest.java @@ -18,6 +18,7 @@ package org.apache.dubbo.config; import com.alibaba.dubbo.config.ModuleConfig; +import com.alibaba.dubbo.config.MonitorConfig; import com.alibaba.dubbo.config.RegistryConfig; import org.hamcrest.Matchers; import org.junit.jupiter.api.Test; diff --git a/dubbo-compatible/src/test/java/org/apache/dubbo/config/SignatureTest.java b/dubbo-compatible/src/test/java/org/apache/dubbo/config/SignatureTest.java new file mode 100644 index 0000000000..ac1d1647dc --- /dev/null +++ b/dubbo-compatible/src/test/java/org/apache/dubbo/config/SignatureTest.java @@ -0,0 +1,67 @@ +/* + * 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.config; + +import org.apache.dubbo.common.utils.IOUtils; +import org.apache.dubbo.common.utils.StringUtils; + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +import java.io.IOException; +import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.Set; +import java.util.stream.Collectors; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.collection.IsCollectionWithSize.hasSize; + +public class SignatureTest { + + @ParameterizedTest + @ValueSource(classes = { + com.alibaba.dubbo.config.ApplicationConfig.class, + com.alibaba.dubbo.config.ArgumentConfig.class, + com.alibaba.dubbo.config.ConsumerConfig.class, + com.alibaba.dubbo.config.MethodConfig.class, + com.alibaba.dubbo.config.ModuleConfig.class, + com.alibaba.dubbo.config.MonitorConfig.class, + com.alibaba.dubbo.config.ProtocolConfig.class, + com.alibaba.dubbo.config.ProviderConfig.class, + com.alibaba.dubbo.config.ReferenceConfig.class, + com.alibaba.dubbo.config.RegistryConfig.class, + com.alibaba.dubbo.config.ServiceConfig.class}) + void test(Class targetClass) throws IOException { + String[] lines = IOUtils.readLines( + this.getClass().getClassLoader().getResourceAsStream("definition/" + targetClass.getName())); + + // only compare setter now. + // getter cannot make it compatible with the old version. + Set setters = Arrays.stream(lines) + .filter(StringUtils::isNotEmpty) + .filter(s -> !s.startsWith("//")) + .filter(s -> s.contains("set")) + .collect(Collectors.toSet()); + + for (Method method : targetClass.getMethods()) { + setters.remove(method.toString().replace(method.getDeclaringClass().getName() + ".", targetClass.getName() + ".")); + } + + assertThat(setters.toString(), setters, hasSize(0)); + } +} diff --git a/dubbo-compatible/src/test/resources/definition/com.alibaba.dubbo.config.ApplicationConfig b/dubbo-compatible/src/test/resources/definition/com.alibaba.dubbo.config.ApplicationConfig new file mode 100644 index 0000000000..3f394402ed --- /dev/null +++ b/dubbo-compatible/src/test/resources/definition/com.alibaba.dubbo.config.ApplicationConfig @@ -0,0 +1,60 @@ +// +// Licensed 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. +// + +public void com.alibaba.dubbo.config.ApplicationConfig.setVersion(java.lang.String) +public java.lang.String com.alibaba.dubbo.config.ApplicationConfig.getOrganization() +public void com.alibaba.dubbo.config.ApplicationConfig.setOrganization(java.lang.String) +public java.lang.String com.alibaba.dubbo.config.ApplicationConfig.getArchitecture() +public void com.alibaba.dubbo.config.ApplicationConfig.setArchitecture(java.lang.String) +public java.lang.String com.alibaba.dubbo.config.ApplicationConfig.getEnvironment() +public void com.alibaba.dubbo.config.ApplicationConfig.setEnvironment(java.lang.String) +public com.alibaba.dubbo.config.RegistryConfig com.alibaba.dubbo.config.ApplicationConfig.getRegistry() +public void com.alibaba.dubbo.config.ApplicationConfig.setRegistry(com.alibaba.dubbo.config.RegistryConfig) +public java.util.List com.alibaba.dubbo.config.ApplicationConfig.getRegistries() +public void com.alibaba.dubbo.config.ApplicationConfig.setRegistries(java.util.List) +public com.alibaba.dubbo.config.MonitorConfig com.alibaba.dubbo.config.ApplicationConfig.getMonitor() +public void com.alibaba.dubbo.config.ApplicationConfig.setMonitor(java.lang.String) +public void com.alibaba.dubbo.config.ApplicationConfig.setMonitor(com.alibaba.dubbo.config.MonitorConfig) +public java.lang.String com.alibaba.dubbo.config.ApplicationConfig.getCompiler() +public void com.alibaba.dubbo.config.ApplicationConfig.setCompiler(java.lang.String) +public void com.alibaba.dubbo.config.ApplicationConfig.setLogger(java.lang.String) +public java.lang.String com.alibaba.dubbo.config.ApplicationConfig.getDumpDirectory() +public void com.alibaba.dubbo.config.ApplicationConfig.setDumpDirectory(java.lang.String) +public java.lang.Boolean com.alibaba.dubbo.config.ApplicationConfig.getQosEnable() +public void com.alibaba.dubbo.config.ApplicationConfig.setQosEnable(java.lang.Boolean) +public java.lang.Integer com.alibaba.dubbo.config.ApplicationConfig.getQosPort() +public void com.alibaba.dubbo.config.ApplicationConfig.setQosPort(java.lang.Integer) +public java.lang.Boolean com.alibaba.dubbo.config.ApplicationConfig.getQosAcceptForeignIp() +public void com.alibaba.dubbo.config.ApplicationConfig.setQosAcceptForeignIp(java.lang.Boolean) +public java.lang.String com.alibaba.dubbo.config.ApplicationConfig.getName() +public java.lang.Boolean com.alibaba.dubbo.config.ApplicationConfig.isDefault() +public void com.alibaba.dubbo.config.ApplicationConfig.setName(java.lang.String) +public java.util.Map com.alibaba.dubbo.config.ApplicationConfig.getParameters() +public void com.alibaba.dubbo.config.ApplicationConfig.setDefault(java.lang.Boolean) +public java.lang.String com.alibaba.dubbo.config.ApplicationConfig.getLogger() +public java.lang.String com.alibaba.dubbo.config.ApplicationConfig.getOwner() +public void com.alibaba.dubbo.config.ApplicationConfig.setOwner(java.lang.String) +public java.lang.String com.alibaba.dubbo.config.ApplicationConfig.getVersion() +public void com.alibaba.dubbo.config.ApplicationConfig.setParameters(java.util.Map) +public void com.alibaba.dubbo.config.ApplicationConfig.setId(java.lang.String) +public java.lang.String com.alibaba.dubbo.config.ApplicationConfig.toString() +public java.lang.String com.alibaba.dubbo.config.ApplicationConfig.getId() +public final void com.alibaba.dubbo.config.ApplicationConfig.wait(long,int) throws java.lang.InterruptedException +public final native void com.alibaba.dubbo.config.ApplicationConfig.wait(long) throws java.lang.InterruptedException +public final void com.alibaba.dubbo.config.ApplicationConfig.wait() throws java.lang.InterruptedException +public boolean com.alibaba.dubbo.config.ApplicationConfig.equals(java.lang.Object) +public native int com.alibaba.dubbo.config.ApplicationConfig.hashCode() +public final native java.lang.Class com.alibaba.dubbo.config.ApplicationConfig.getClass() +public final native void com.alibaba.dubbo.config.ApplicationConfig.notify() +public final native void com.alibaba.dubbo.config.ApplicationConfig.notifyAll() diff --git a/dubbo-compatible/src/test/resources/definition/com.alibaba.dubbo.config.ArgumentConfig b/dubbo-compatible/src/test/resources/definition/com.alibaba.dubbo.config.ArgumentConfig new file mode 100644 index 0000000000..1251574442 --- /dev/null +++ b/dubbo-compatible/src/test/resources/definition/com.alibaba.dubbo.config.ArgumentConfig @@ -0,0 +1,29 @@ +// +// Licensed 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. +// + +public void com.alibaba.dubbo.config.ArgumentConfig.setCallback(java.lang.Boolean) +public java.lang.Boolean com.alibaba.dubbo.config.ArgumentConfig.isCallback() +public void com.alibaba.dubbo.config.ArgumentConfig.setIndex(java.lang.Integer) +public java.lang.String com.alibaba.dubbo.config.ArgumentConfig.getType() +public java.lang.Integer com.alibaba.dubbo.config.ArgumentConfig.getIndex() +public void com.alibaba.dubbo.config.ArgumentConfig.setType(java.lang.String) +public final void com.alibaba.dubbo.config.ArgumentConfig.wait(long,int) throws java.lang.InterruptedException +public final native void com.alibaba.dubbo.config.ArgumentConfig.wait(long) throws java.lang.InterruptedException +public final void com.alibaba.dubbo.config.ArgumentConfig.wait() throws java.lang.InterruptedException +public boolean com.alibaba.dubbo.config.ArgumentConfig.equals(java.lang.Object) +public java.lang.String com.alibaba.dubbo.config.ArgumentConfig.toString() +public native int com.alibaba.dubbo.config.ArgumentConfig.hashCode() +public final native java.lang.Class com.alibaba.dubbo.config.ArgumentConfig.getClass() +public final native void com.alibaba.dubbo.config.ArgumentConfig.notify() +public final native void com.alibaba.dubbo.config.ArgumentConfig.notifyAll() diff --git a/dubbo-compatible/src/test/resources/definition/com.alibaba.dubbo.config.ConsumerConfig b/dubbo-compatible/src/test/resources/definition/com.alibaba.dubbo.config.ConsumerConfig new file mode 100644 index 0000000000..f0cce4aa0a --- /dev/null +++ b/dubbo-compatible/src/test/resources/definition/com.alibaba.dubbo.config.ConsumerConfig @@ -0,0 +1,123 @@ +// +// Licensed 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. +// + +public void com.alibaba.dubbo.config.ConsumerConfig.setTimeout(java.lang.Integer) +public java.lang.String com.alibaba.dubbo.config.ConsumerConfig.getClient() +public void com.alibaba.dubbo.config.ConsumerConfig.setClient(java.lang.String) +public java.lang.String com.alibaba.dubbo.config.ConsumerConfig.getThreadpool() +public void com.alibaba.dubbo.config.ConsumerConfig.setThreadpool(java.lang.String) +public java.lang.Integer com.alibaba.dubbo.config.ConsumerConfig.getCorethreads() +public void com.alibaba.dubbo.config.ConsumerConfig.setCorethreads(java.lang.Integer) +public void com.alibaba.dubbo.config.ConsumerConfig.setThreads(java.lang.Integer) +public java.lang.Integer com.alibaba.dubbo.config.ConsumerConfig.getQueues() +public void com.alibaba.dubbo.config.ConsumerConfig.setQueues(java.lang.Integer) +public java.lang.Boolean com.alibaba.dubbo.config.ConsumerConfig.getDefault() +public java.lang.Boolean com.alibaba.dubbo.config.ConsumerConfig.isDefault() +public java.lang.Integer com.alibaba.dubbo.config.ConsumerConfig.getThreads() +public void com.alibaba.dubbo.config.ConsumerConfig.setDefault(java.lang.Boolean) +public void com.alibaba.dubbo.config.ConsumerConfig.setVersion(java.lang.String) +public void com.alibaba.dubbo.config.ConsumerConfig.setGeneric(java.lang.Boolean) +public void com.alibaba.dubbo.config.ConsumerConfig.setGeneric(java.lang.String) +public java.lang.String com.alibaba.dubbo.config.ConsumerConfig.getGeneric() +public void com.alibaba.dubbo.config.ConsumerConfig.setListener(java.lang.String) +public void com.alibaba.dubbo.config.ConsumerConfig.setOnconnect(java.lang.String) +public void com.alibaba.dubbo.config.ConsumerConfig.setOndisconnect(java.lang.String) +public java.lang.Boolean com.alibaba.dubbo.config.ConsumerConfig.getStubevent() +public java.lang.String com.alibaba.dubbo.config.ConsumerConfig.getReconnect() +public void com.alibaba.dubbo.config.ConsumerConfig.setReconnect(java.lang.String) +public java.lang.Boolean com.alibaba.dubbo.config.ConsumerConfig.getSticky() +public void com.alibaba.dubbo.config.ConsumerConfig.setSticky(java.lang.Boolean) +public java.lang.Boolean com.alibaba.dubbo.config.ConsumerConfig.getLazy() +public void com.alibaba.dubbo.config.ConsumerConfig.setInit(java.lang.Boolean) +public void com.alibaba.dubbo.config.ConsumerConfig.setInjvm(java.lang.Boolean) +public void com.alibaba.dubbo.config.ConsumerConfig.setLazy(java.lang.Boolean) +public java.lang.Boolean com.alibaba.dubbo.config.ConsumerConfig.isInjvm() +public void com.alibaba.dubbo.config.ConsumerConfig.setCheck(java.lang.Boolean) +public java.lang.Boolean com.alibaba.dubbo.config.ConsumerConfig.isCheck() +public void com.alibaba.dubbo.config.ConsumerConfig.setGroup(java.lang.String) +public java.lang.String com.alibaba.dubbo.config.ConsumerConfig.getGroup() +public java.lang.Boolean com.alibaba.dubbo.config.ConsumerConfig.isInit() +public java.lang.Boolean com.alibaba.dubbo.config.ConsumerConfig.isGeneric() +public java.lang.String com.alibaba.dubbo.config.ConsumerConfig.getFilter() +public java.lang.String com.alibaba.dubbo.config.ConsumerConfig.getListener() +public java.lang.String com.alibaba.dubbo.config.ConsumerConfig.getVersion() +public com.alibaba.dubbo.config.RegistryConfig com.alibaba.dubbo.config.ConsumerConfig.getRegistry() +public void com.alibaba.dubbo.config.ConsumerConfig.setRegistry(com.alibaba.dubbo.config.RegistryConfig) +public java.util.List com.alibaba.dubbo.config.ConsumerConfig.getRegistries() +public void com.alibaba.dubbo.config.ConsumerConfig.setRegistries(java.util.List) +public com.alibaba.dubbo.config.MonitorConfig com.alibaba.dubbo.config.ConsumerConfig.getMonitor() +public void com.alibaba.dubbo.config.ConsumerConfig.setMonitor(com.alibaba.dubbo.config.MonitorConfig) +public void com.alibaba.dubbo.config.ConsumerConfig.setMonitor(java.lang.String) +public java.lang.String com.alibaba.dubbo.config.ConsumerConfig.getCluster() +public void com.alibaba.dubbo.config.ConsumerConfig.setCluster(java.lang.String) +public java.lang.Integer com.alibaba.dubbo.config.ConsumerConfig.getConnections() +public void com.alibaba.dubbo.config.ConsumerConfig.setConnections(java.lang.Integer) +public com.alibaba.dubbo.config.ApplicationConfig com.alibaba.dubbo.config.ConsumerConfig.getApplication() +public void com.alibaba.dubbo.config.ConsumerConfig.setApplication(com.alibaba.dubbo.config.ApplicationConfig) +public com.alibaba.dubbo.config.ModuleConfig com.alibaba.dubbo.config.ConsumerConfig.getModule() +public void com.alibaba.dubbo.config.ConsumerConfig.setModule(com.alibaba.dubbo.config.ModuleConfig) +public java.lang.Integer com.alibaba.dubbo.config.ConsumerConfig.getCallbacks() +public void com.alibaba.dubbo.config.ConsumerConfig.setCallbacks(java.lang.Integer) +public java.lang.String com.alibaba.dubbo.config.ConsumerConfig.getOnconnect() +public java.lang.String com.alibaba.dubbo.config.ConsumerConfig.getOndisconnect() +public java.lang.String com.alibaba.dubbo.config.ConsumerConfig.getLocal() +public void com.alibaba.dubbo.config.ConsumerConfig.setLocal(java.lang.String) +public void com.alibaba.dubbo.config.ConsumerConfig.setLocal(java.lang.Boolean) +public void com.alibaba.dubbo.config.ConsumerConfig.setStub(java.lang.Boolean) +public void com.alibaba.dubbo.config.ConsumerConfig.setStub(java.lang.String) +public java.lang.String com.alibaba.dubbo.config.ConsumerConfig.getProxy() +public void com.alibaba.dubbo.config.ConsumerConfig.setProxy(java.lang.String) +public java.lang.String com.alibaba.dubbo.config.ConsumerConfig.getLayer() +public void com.alibaba.dubbo.config.ConsumerConfig.setLayer(java.lang.String) +public void com.alibaba.dubbo.config.ConsumerConfig.setScope(java.lang.String) +public void com.alibaba.dubbo.config.ConsumerConfig.setFilter(java.lang.String) +public java.lang.String com.alibaba.dubbo.config.ConsumerConfig.getOwner() +public java.lang.String com.alibaba.dubbo.config.ConsumerConfig.getScope() +public void com.alibaba.dubbo.config.ConsumerConfig.setOwner(java.lang.String) +public java.lang.String com.alibaba.dubbo.config.ConsumerConfig.getStub() +public java.lang.Integer com.alibaba.dubbo.config.ConsumerConfig.getRetries() +public void com.alibaba.dubbo.config.ConsumerConfig.setRetries(java.lang.Integer) +public java.lang.String com.alibaba.dubbo.config.ConsumerConfig.getLoadbalance() +public void com.alibaba.dubbo.config.ConsumerConfig.setLoadbalance(java.lang.String) +public java.lang.Integer com.alibaba.dubbo.config.ConsumerConfig.getActives() +public void com.alibaba.dubbo.config.ConsumerConfig.setActives(java.lang.Integer) +public java.lang.String com.alibaba.dubbo.config.ConsumerConfig.getMerger() +public void com.alibaba.dubbo.config.ConsumerConfig.setMerger(java.lang.String) +public java.lang.String com.alibaba.dubbo.config.ConsumerConfig.getValidation() +public void com.alibaba.dubbo.config.ConsumerConfig.setValidation(java.lang.String) +public java.lang.Boolean com.alibaba.dubbo.config.ConsumerConfig.isAsync() +public void com.alibaba.dubbo.config.ConsumerConfig.setForks(java.lang.Integer) +public java.lang.Integer com.alibaba.dubbo.config.ConsumerConfig.getForks() +public void com.alibaba.dubbo.config.ConsumerConfig.setAsync(java.lang.Boolean) +public java.lang.Boolean com.alibaba.dubbo.config.ConsumerConfig.getSent() +public void com.alibaba.dubbo.config.ConsumerConfig.setSent(java.lang.Boolean) +public java.lang.String com.alibaba.dubbo.config.ConsumerConfig.getMock() +public void com.alibaba.dubbo.config.ConsumerConfig.setMock(java.lang.String) +public void com.alibaba.dubbo.config.ConsumerConfig.setMock(java.lang.Boolean) +public void com.alibaba.dubbo.config.ConsumerConfig.setCache(java.lang.String) +public java.util.Map com.alibaba.dubbo.config.ConsumerConfig.getParameters() +public java.lang.String com.alibaba.dubbo.config.ConsumerConfig.getCache() +public void com.alibaba.dubbo.config.ConsumerConfig.setParameters(java.util.Map) +public java.lang.Integer com.alibaba.dubbo.config.ConsumerConfig.getTimeout() +public void com.alibaba.dubbo.config.ConsumerConfig.setId(java.lang.String) +public java.lang.String com.alibaba.dubbo.config.ConsumerConfig.toString() +public java.lang.String com.alibaba.dubbo.config.ConsumerConfig.getId() +public final void com.alibaba.dubbo.config.ConsumerConfig.wait(long,int) throws java.lang.InterruptedException +public final native void com.alibaba.dubbo.config.ConsumerConfig.wait(long) throws java.lang.InterruptedException +public final void com.alibaba.dubbo.config.ConsumerConfig.wait() throws java.lang.InterruptedException +public boolean com.alibaba.dubbo.config.ConsumerConfig.equals(java.lang.Object) +public native int com.alibaba.dubbo.config.ConsumerConfig.hashCode() +public final native java.lang.Class com.alibaba.dubbo.config.ConsumerConfig.getClass() +public final native void com.alibaba.dubbo.config.ConsumerConfig.notify() +public final native void com.alibaba.dubbo.config.ConsumerConfig.notifyAll() diff --git a/dubbo-compatible/src/test/resources/definition/com.alibaba.dubbo.config.MethodConfig b/dubbo-compatible/src/test/resources/definition/com.alibaba.dubbo.config.MethodConfig new file mode 100644 index 0000000000..4e0a752b04 --- /dev/null +++ b/dubbo-compatible/src/test/resources/definition/com.alibaba.dubbo.config.MethodConfig @@ -0,0 +1,81 @@ +// +// Licensed 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. +// + +public java.lang.Boolean com.alibaba.dubbo.config.MethodConfig.getSticky() +public void com.alibaba.dubbo.config.MethodConfig.setSticky(java.lang.Boolean) +public static java.util.List com.alibaba.dubbo.config.MethodConfig.constructMethodConfig(com.alibaba.dubbo.config.annotation.Method[]) +public java.lang.Boolean com.alibaba.dubbo.config.MethodConfig.isReliable() +public void com.alibaba.dubbo.config.MethodConfig.setReliable(java.lang.Boolean) +public java.lang.Integer com.alibaba.dubbo.config.MethodConfig.getExecutes() +public void com.alibaba.dubbo.config.MethodConfig.setExecutes(java.lang.Integer) +public java.lang.Boolean com.alibaba.dubbo.config.MethodConfig.getDeprecated() +public void com.alibaba.dubbo.config.MethodConfig.setDeprecated(java.lang.Boolean) +public java.util.List com.alibaba.dubbo.config.MethodConfig.getArguments() +public void com.alibaba.dubbo.config.MethodConfig.setArguments(java.util.List) +public java.lang.Object com.alibaba.dubbo.config.MethodConfig.getOnreturn() +public void com.alibaba.dubbo.config.MethodConfig.setOnreturn(java.lang.Object) +public java.lang.String com.alibaba.dubbo.config.MethodConfig.getOnreturnMethod() +public void com.alibaba.dubbo.config.MethodConfig.setOnreturnMethod(java.lang.String) +public java.lang.Object com.alibaba.dubbo.config.MethodConfig.getOnthrow() +public void com.alibaba.dubbo.config.MethodConfig.setOnthrow(java.lang.Object) +public java.lang.String com.alibaba.dubbo.config.MethodConfig.getOnthrowMethod() +public void com.alibaba.dubbo.config.MethodConfig.setOnthrowMethod(java.lang.String) +public java.lang.Object com.alibaba.dubbo.config.MethodConfig.getOninvoke() +public void com.alibaba.dubbo.config.MethodConfig.setOninvoke(java.lang.Object) +public java.lang.String com.alibaba.dubbo.config.MethodConfig.getOninvokeMethod() +public void com.alibaba.dubbo.config.MethodConfig.setOninvokeMethod(java.lang.String) +public void com.alibaba.dubbo.config.MethodConfig.setReturn(java.lang.Boolean) +public java.lang.Boolean com.alibaba.dubbo.config.MethodConfig.isReturn() +public java.lang.Integer com.alibaba.dubbo.config.MethodConfig.getStat() +public void com.alibaba.dubbo.config.MethodConfig.setStat(java.lang.Integer) +public java.lang.Boolean com.alibaba.dubbo.config.MethodConfig.isRetry() +public void com.alibaba.dubbo.config.MethodConfig.setRetry(java.lang.Boolean) +public java.lang.String com.alibaba.dubbo.config.MethodConfig.getName() +public void com.alibaba.dubbo.config.MethodConfig.setName(java.lang.String) +public void com.alibaba.dubbo.config.MethodConfig.setTimeout(java.lang.Integer) +public java.lang.Integer com.alibaba.dubbo.config.MethodConfig.getRetries() +public void com.alibaba.dubbo.config.MethodConfig.setRetries(java.lang.Integer) +public java.lang.String com.alibaba.dubbo.config.MethodConfig.getLoadbalance() +public void com.alibaba.dubbo.config.MethodConfig.setLoadbalance(java.lang.String) +public java.lang.Integer com.alibaba.dubbo.config.MethodConfig.getActives() +public void com.alibaba.dubbo.config.MethodConfig.setActives(java.lang.Integer) +public java.lang.String com.alibaba.dubbo.config.MethodConfig.getMerger() +public void com.alibaba.dubbo.config.MethodConfig.setMerger(java.lang.String) +public java.lang.String com.alibaba.dubbo.config.MethodConfig.getValidation() +public void com.alibaba.dubbo.config.MethodConfig.setValidation(java.lang.String) +public java.lang.Boolean com.alibaba.dubbo.config.MethodConfig.isAsync() +public void com.alibaba.dubbo.config.MethodConfig.setForks(java.lang.Integer) +public java.lang.Integer com.alibaba.dubbo.config.MethodConfig.getForks() +public void com.alibaba.dubbo.config.MethodConfig.setAsync(java.lang.Boolean) +public java.lang.Boolean com.alibaba.dubbo.config.MethodConfig.getSent() +public void com.alibaba.dubbo.config.MethodConfig.setSent(java.lang.Boolean) +public java.lang.String com.alibaba.dubbo.config.MethodConfig.getMock() +public void com.alibaba.dubbo.config.MethodConfig.setMock(java.lang.String) +public void com.alibaba.dubbo.config.MethodConfig.setMock(java.lang.Boolean) +public void com.alibaba.dubbo.config.MethodConfig.setCache(java.lang.String) +public java.util.Map com.alibaba.dubbo.config.MethodConfig.getParameters() +public java.lang.String com.alibaba.dubbo.config.MethodConfig.getCache() +public void com.alibaba.dubbo.config.MethodConfig.setParameters(java.util.Map) +public java.lang.Integer com.alibaba.dubbo.config.MethodConfig.getTimeout() +public void com.alibaba.dubbo.config.MethodConfig.setId(java.lang.String) +public java.lang.String com.alibaba.dubbo.config.MethodConfig.toString() +public java.lang.String com.alibaba.dubbo.config.MethodConfig.getId() +public final void com.alibaba.dubbo.config.MethodConfig.wait(long,int) throws java.lang.InterruptedException +public final native void com.alibaba.dubbo.config.MethodConfig.wait(long) throws java.lang.InterruptedException +public final void com.alibaba.dubbo.config.MethodConfig.wait() throws java.lang.InterruptedException +public boolean com.alibaba.dubbo.config.MethodConfig.equals(java.lang.Object) +public native int com.alibaba.dubbo.config.MethodConfig.hashCode() +public final native java.lang.Class com.alibaba.dubbo.config.MethodConfig.getClass() +public final native void com.alibaba.dubbo.config.MethodConfig.notify() +public final native void com.alibaba.dubbo.config.MethodConfig.notifyAll() diff --git a/dubbo-compatible/src/test/resources/definition/com.alibaba.dubbo.config.ModuleConfig b/dubbo-compatible/src/test/resources/definition/com.alibaba.dubbo.config.ModuleConfig new file mode 100644 index 0000000000..b1eebe9708 --- /dev/null +++ b/dubbo-compatible/src/test/resources/definition/com.alibaba.dubbo.config.ModuleConfig @@ -0,0 +1,42 @@ +// +// Licensed 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. +// + +public void com.alibaba.dubbo.config.ModuleConfig.setVersion(java.lang.String) +public java.lang.String com.alibaba.dubbo.config.ModuleConfig.getOrganization() +public void com.alibaba.dubbo.config.ModuleConfig.setOrganization(java.lang.String) +public com.alibaba.dubbo.config.RegistryConfig com.alibaba.dubbo.config.ModuleConfig.getRegistry() +public void com.alibaba.dubbo.config.ModuleConfig.setRegistry(com.alibaba.dubbo.config.RegistryConfig) +public java.util.List com.alibaba.dubbo.config.ModuleConfig.getRegistries() +public void com.alibaba.dubbo.config.ModuleConfig.setRegistries(java.util.List) +public com.alibaba.dubbo.config.MonitorConfig com.alibaba.dubbo.config.ModuleConfig.getMonitor() +public void com.alibaba.dubbo.config.ModuleConfig.setMonitor(java.lang.String) +public void com.alibaba.dubbo.config.ModuleConfig.setMonitor(com.alibaba.dubbo.config.MonitorConfig) +public java.lang.String com.alibaba.dubbo.config.ModuleConfig.getName() +public java.lang.Boolean com.alibaba.dubbo.config.ModuleConfig.isDefault() +public void com.alibaba.dubbo.config.ModuleConfig.setName(java.lang.String) +public void com.alibaba.dubbo.config.ModuleConfig.setDefault(java.lang.Boolean) +public java.lang.String com.alibaba.dubbo.config.ModuleConfig.getOwner() +public void com.alibaba.dubbo.config.ModuleConfig.setOwner(java.lang.String) +public java.lang.String com.alibaba.dubbo.config.ModuleConfig.getVersion() +public void com.alibaba.dubbo.config.ModuleConfig.setId(java.lang.String) +public java.lang.String com.alibaba.dubbo.config.ModuleConfig.toString() +public java.lang.String com.alibaba.dubbo.config.ModuleConfig.getId() +public final void com.alibaba.dubbo.config.ModuleConfig.wait(long,int) throws java.lang.InterruptedException +public final native void com.alibaba.dubbo.config.ModuleConfig.wait(long) throws java.lang.InterruptedException +public final void com.alibaba.dubbo.config.ModuleConfig.wait() throws java.lang.InterruptedException +public boolean com.alibaba.dubbo.config.ModuleConfig.equals(java.lang.Object) +public native int com.alibaba.dubbo.config.ModuleConfig.hashCode() +public final native java.lang.Class com.alibaba.dubbo.config.ModuleConfig.getClass() +public final native void com.alibaba.dubbo.config.ModuleConfig.notify() +public final native void com.alibaba.dubbo.config.ModuleConfig.notifyAll() diff --git a/dubbo-compatible/src/test/resources/definition/com.alibaba.dubbo.config.MonitorConfig b/dubbo-compatible/src/test/resources/definition/com.alibaba.dubbo.config.MonitorConfig new file mode 100644 index 0000000000..a5c1b40425 --- /dev/null +++ b/dubbo-compatible/src/test/resources/definition/com.alibaba.dubbo.config.MonitorConfig @@ -0,0 +1,43 @@ +// +// Licensed 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. +// + +public void com.alibaba.dubbo.config.MonitorConfig.setVersion(java.lang.String) +public void com.alibaba.dubbo.config.MonitorConfig.setProtocol(java.lang.String) +public java.lang.String com.alibaba.dubbo.config.MonitorConfig.getUsername() +public void com.alibaba.dubbo.config.MonitorConfig.setUsername(java.lang.String) +public void com.alibaba.dubbo.config.MonitorConfig.setPassword(java.lang.String) +public void com.alibaba.dubbo.config.MonitorConfig.setInterval(java.lang.String) +public java.lang.String com.alibaba.dubbo.config.MonitorConfig.getInterval() +public void com.alibaba.dubbo.config.MonitorConfig.setGroup(java.lang.String) +public java.lang.String com.alibaba.dubbo.config.MonitorConfig.getGroup() +public java.lang.String com.alibaba.dubbo.config.MonitorConfig.getAddress() +public java.lang.Boolean com.alibaba.dubbo.config.MonitorConfig.isDefault() +public java.util.Map com.alibaba.dubbo.config.MonitorConfig.getParameters() +public java.lang.String com.alibaba.dubbo.config.MonitorConfig.getProtocol() +public void com.alibaba.dubbo.config.MonitorConfig.setDefault(java.lang.Boolean) +public java.lang.String com.alibaba.dubbo.config.MonitorConfig.getPassword() +public void com.alibaba.dubbo.config.MonitorConfig.setAddress(java.lang.String) +public java.lang.String com.alibaba.dubbo.config.MonitorConfig.getVersion() +public void com.alibaba.dubbo.config.MonitorConfig.setParameters(java.util.Map) +public void com.alibaba.dubbo.config.MonitorConfig.setId(java.lang.String) +public java.lang.String com.alibaba.dubbo.config.MonitorConfig.toString() +public java.lang.String com.alibaba.dubbo.config.MonitorConfig.getId() +public final void com.alibaba.dubbo.config.MonitorConfig.wait(long,int) throws java.lang.InterruptedException +public final native void com.alibaba.dubbo.config.MonitorConfig.wait(long) throws java.lang.InterruptedException +public final void com.alibaba.dubbo.config.MonitorConfig.wait() throws java.lang.InterruptedException +public boolean com.alibaba.dubbo.config.MonitorConfig.equals(java.lang.Object) +public native int com.alibaba.dubbo.config.MonitorConfig.hashCode() +public final native java.lang.Class com.alibaba.dubbo.config.MonitorConfig.getClass() +public final native void com.alibaba.dubbo.config.MonitorConfig.notify() +public final native void com.alibaba.dubbo.config.MonitorConfig.notifyAll() diff --git a/dubbo-compatible/src/test/resources/definition/com.alibaba.dubbo.config.ProtocolConfig b/dubbo-compatible/src/test/resources/definition/com.alibaba.dubbo.config.ProtocolConfig new file mode 100644 index 0000000000..0f9cd68397 --- /dev/null +++ b/dubbo-compatible/src/test/resources/definition/com.alibaba.dubbo.config.ProtocolConfig @@ -0,0 +1,92 @@ +// +// Licensed 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. +// + +public java.lang.String com.alibaba.dubbo.config.ProtocolConfig.getClient() +public void com.alibaba.dubbo.config.ProtocolConfig.setClient(java.lang.String) +public java.lang.String com.alibaba.dubbo.config.ProtocolConfig.getThreadpool() +public void com.alibaba.dubbo.config.ProtocolConfig.setThreadpool(java.lang.String) +public void com.alibaba.dubbo.config.ProtocolConfig.setThreads(java.lang.Integer) +public java.lang.Integer com.alibaba.dubbo.config.ProtocolConfig.getQueues() +public void com.alibaba.dubbo.config.ProtocolConfig.setQueues(java.lang.Integer) +public java.lang.String com.alibaba.dubbo.config.ProtocolConfig.getContextpath() +public void com.alibaba.dubbo.config.ProtocolConfig.setContextpath(java.lang.String) +public java.lang.Integer com.alibaba.dubbo.config.ProtocolConfig.getIothreads() +public void com.alibaba.dubbo.config.ProtocolConfig.setIothreads(java.lang.Integer) +public java.lang.Integer com.alibaba.dubbo.config.ProtocolConfig.getAccepts() +public void com.alibaba.dubbo.config.ProtocolConfig.setAccepts(java.lang.Integer) +public java.lang.String com.alibaba.dubbo.config.ProtocolConfig.getSerialization() +public void com.alibaba.dubbo.config.ProtocolConfig.setSerialization(java.lang.String) +public java.lang.String com.alibaba.dubbo.config.ProtocolConfig.getCharset() +public void com.alibaba.dubbo.config.ProtocolConfig.setCharset(java.lang.String) +public java.lang.Integer com.alibaba.dubbo.config.ProtocolConfig.getPayload() +public void com.alibaba.dubbo.config.ProtocolConfig.setPayload(java.lang.Integer) +public java.lang.Integer com.alibaba.dubbo.config.ProtocolConfig.getHeartbeat() +public void com.alibaba.dubbo.config.ProtocolConfig.setHeartbeat(java.lang.Integer) +public java.lang.String com.alibaba.dubbo.config.ProtocolConfig.getServer() +public void com.alibaba.dubbo.config.ProtocolConfig.setServer(java.lang.String) +public java.lang.String com.alibaba.dubbo.config.ProtocolConfig.getAccesslog() +public void com.alibaba.dubbo.config.ProtocolConfig.setAccesslog(java.lang.String) +public java.lang.String com.alibaba.dubbo.config.ProtocolConfig.getTelnet() +public void com.alibaba.dubbo.config.ProtocolConfig.setTelnet(java.lang.String) +public java.lang.String com.alibaba.dubbo.config.ProtocolConfig.getPrompt() +public void com.alibaba.dubbo.config.ProtocolConfig.setPrompt(java.lang.String) +public java.lang.String com.alibaba.dubbo.config.ProtocolConfig.getStatus() +public void com.alibaba.dubbo.config.ProtocolConfig.setStatus(java.lang.String) +public java.lang.Boolean com.alibaba.dubbo.config.ProtocolConfig.isRegister() +public void com.alibaba.dubbo.config.ProtocolConfig.setRegister(java.lang.Boolean) +public java.lang.String com.alibaba.dubbo.config.ProtocolConfig.getTransporter() +public void com.alibaba.dubbo.config.ProtocolConfig.setTransporter(java.lang.String) +public java.lang.String com.alibaba.dubbo.config.ProtocolConfig.getExchanger() +public void com.alibaba.dubbo.config.ProtocolConfig.setExchanger(java.lang.String) +public java.lang.String com.alibaba.dubbo.config.ProtocolConfig.getDispather() +public void com.alibaba.dubbo.config.ProtocolConfig.setDispather(java.lang.String) +public void com.alibaba.dubbo.config.ProtocolConfig.setDispatcher(java.lang.String) +public java.lang.String com.alibaba.dubbo.config.ProtocolConfig.getNetworker() +public void com.alibaba.dubbo.config.ProtocolConfig.setNetworker(java.lang.String) +public java.lang.String com.alibaba.dubbo.config.ProtocolConfig.getOptimizer() +public void com.alibaba.dubbo.config.ProtocolConfig.setOptimizer(java.lang.String) +public void com.alibaba.dubbo.config.ProtocolConfig.setExtension(java.lang.String) +public void com.alibaba.dubbo.config.ProtocolConfig.setHost(java.lang.String) +public java.lang.String com.alibaba.dubbo.config.ProtocolConfig.getCodec() +public void com.alibaba.dubbo.config.ProtocolConfig.setCodec(java.lang.String) +public java.lang.String com.alibaba.dubbo.config.ProtocolConfig.getName() +public java.lang.Boolean com.alibaba.dubbo.config.ProtocolConfig.isDefault() +public void com.alibaba.dubbo.config.ProtocolConfig.destroy() +public void com.alibaba.dubbo.config.ProtocolConfig.setName(java.lang.String) +public java.lang.Integer com.alibaba.dubbo.config.ProtocolConfig.getThreads() +public java.util.Map com.alibaba.dubbo.config.ProtocolConfig.getParameters() +public java.lang.String com.alibaba.dubbo.config.ProtocolConfig.getPath() +public java.lang.String com.alibaba.dubbo.config.ProtocolConfig.getHost() +public java.lang.Integer com.alibaba.dubbo.config.ProtocolConfig.getPort() +public void com.alibaba.dubbo.config.ProtocolConfig.setDefault(java.lang.Boolean) +public java.lang.String com.alibaba.dubbo.config.ProtocolConfig.getExtension() +public void com.alibaba.dubbo.config.ProtocolConfig.setPort(java.lang.Integer) +public void com.alibaba.dubbo.config.ProtocolConfig.setKeepAlive(java.lang.Boolean) +public java.lang.Boolean com.alibaba.dubbo.config.ProtocolConfig.getKeepAlive() +public void com.alibaba.dubbo.config.ProtocolConfig.setPath(java.lang.String) +public java.lang.String com.alibaba.dubbo.config.ProtocolConfig.getDispatcher() +public void com.alibaba.dubbo.config.ProtocolConfig.setBuffer(java.lang.Integer) +public java.lang.Integer com.alibaba.dubbo.config.ProtocolConfig.getBuffer() +public void com.alibaba.dubbo.config.ProtocolConfig.setParameters(java.util.Map) +public void com.alibaba.dubbo.config.ProtocolConfig.setId(java.lang.String) +public java.lang.String com.alibaba.dubbo.config.ProtocolConfig.toString() +public java.lang.String com.alibaba.dubbo.config.ProtocolConfig.getId() +public final void com.alibaba.dubbo.config.ProtocolConfig.wait(long,int) throws java.lang.InterruptedException +public final native void com.alibaba.dubbo.config.ProtocolConfig.wait(long) throws java.lang.InterruptedException +public final void com.alibaba.dubbo.config.ProtocolConfig.wait() throws java.lang.InterruptedException +public boolean com.alibaba.dubbo.config.ProtocolConfig.equals(java.lang.Object) +public native int com.alibaba.dubbo.config.ProtocolConfig.hashCode() +public final native java.lang.Class com.alibaba.dubbo.config.ProtocolConfig.getClass() +public final native void com.alibaba.dubbo.config.ProtocolConfig.notify() +public final native void com.alibaba.dubbo.config.ProtocolConfig.notifyAll() diff --git a/dubbo-compatible/src/test/resources/definition/com.alibaba.dubbo.config.ProviderConfig b/dubbo-compatible/src/test/resources/definition/com.alibaba.dubbo.config.ProviderConfig new file mode 100644 index 0000000000..c8479bff05 --- /dev/null +++ b/dubbo-compatible/src/test/resources/definition/com.alibaba.dubbo.config.ProviderConfig @@ -0,0 +1,176 @@ +// +// Licensed 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. +// + +public java.lang.String com.alibaba.dubbo.config.ProviderConfig.getClient() +public void com.alibaba.dubbo.config.ProviderConfig.setClient(java.lang.String) +public java.lang.String com.alibaba.dubbo.config.ProviderConfig.getThreadpool() +public void com.alibaba.dubbo.config.ProviderConfig.setThreadpool(java.lang.String) +public void com.alibaba.dubbo.config.ProviderConfig.setThreads(java.lang.Integer) +public java.lang.Integer com.alibaba.dubbo.config.ProviderConfig.getQueues() +public void com.alibaba.dubbo.config.ProviderConfig.setQueues(java.lang.Integer) +public java.lang.String com.alibaba.dubbo.config.ProviderConfig.getCluster() +public java.lang.Integer com.alibaba.dubbo.config.ProviderConfig.getConnections() +public void com.alibaba.dubbo.config.ProviderConfig.setProtocol(java.lang.String) +public java.lang.Integer com.alibaba.dubbo.config.ProviderConfig.getRetries() +public java.lang.String com.alibaba.dubbo.config.ProviderConfig.getLoadbalance() +public java.lang.Integer com.alibaba.dubbo.config.ProviderConfig.getActives() +public java.lang.String com.alibaba.dubbo.config.ProviderConfig.getContextpath() +public void com.alibaba.dubbo.config.ProviderConfig.setContextpath(java.lang.String) +public java.lang.Integer com.alibaba.dubbo.config.ProviderConfig.getIothreads() +public void com.alibaba.dubbo.config.ProviderConfig.setIothreads(java.lang.Integer) +public java.lang.Integer com.alibaba.dubbo.config.ProviderConfig.getAccepts() +public void com.alibaba.dubbo.config.ProviderConfig.setAccepts(java.lang.Integer) +public java.lang.String com.alibaba.dubbo.config.ProviderConfig.getCharset() +public void com.alibaba.dubbo.config.ProviderConfig.setCharset(java.lang.String) +public java.lang.Integer com.alibaba.dubbo.config.ProviderConfig.getPayload() +public void com.alibaba.dubbo.config.ProviderConfig.setPayload(java.lang.Integer) +public java.lang.String com.alibaba.dubbo.config.ProviderConfig.getServer() +public void com.alibaba.dubbo.config.ProviderConfig.setServer(java.lang.String) +public java.lang.String com.alibaba.dubbo.config.ProviderConfig.getTelnet() +public void com.alibaba.dubbo.config.ProviderConfig.setTelnet(java.lang.String) +public java.lang.String com.alibaba.dubbo.config.ProviderConfig.getPrompt() +public void com.alibaba.dubbo.config.ProviderConfig.setPrompt(java.lang.String) +public java.lang.String com.alibaba.dubbo.config.ProviderConfig.getStatus() +public void com.alibaba.dubbo.config.ProviderConfig.setStatus(java.lang.String) +public java.lang.String com.alibaba.dubbo.config.ProviderConfig.getTransporter() +public void com.alibaba.dubbo.config.ProviderConfig.setTransporter(java.lang.String) +public java.lang.String com.alibaba.dubbo.config.ProviderConfig.getExchanger() +public void com.alibaba.dubbo.config.ProviderConfig.setExchanger(java.lang.String) +public java.lang.String com.alibaba.dubbo.config.ProviderConfig.getDispather() +public void com.alibaba.dubbo.config.ProviderConfig.setDispather(java.lang.String) +public void com.alibaba.dubbo.config.ProviderConfig.setDispatcher(java.lang.String) +public java.lang.String com.alibaba.dubbo.config.ProviderConfig.getNetworker() +public void com.alibaba.dubbo.config.ProviderConfig.setNetworker(java.lang.String) +public java.lang.Boolean com.alibaba.dubbo.config.ProviderConfig.isAsync() +public void com.alibaba.dubbo.config.ProviderConfig.setHost(java.lang.String) +public java.lang.String com.alibaba.dubbo.config.ProviderConfig.getCodec() +public void com.alibaba.dubbo.config.ProviderConfig.setCodec(java.lang.String) +public java.lang.Integer com.alibaba.dubbo.config.ProviderConfig.getWait() +public void com.alibaba.dubbo.config.ProviderConfig.setWait(java.lang.Integer) +public java.lang.Boolean com.alibaba.dubbo.config.ProviderConfig.isDefault() +public java.lang.Integer com.alibaba.dubbo.config.ProviderConfig.getThreads() +public java.lang.String com.alibaba.dubbo.config.ProviderConfig.getPath() +public java.lang.String com.alibaba.dubbo.config.ProviderConfig.getHost() +public java.lang.Integer com.alibaba.dubbo.config.ProviderConfig.getPort() +public void com.alibaba.dubbo.config.ProviderConfig.setDefault(java.lang.Boolean) +public void com.alibaba.dubbo.config.ProviderConfig.setPort(java.lang.Integer) +public void com.alibaba.dubbo.config.ProviderConfig.setPath(java.lang.String) +public java.lang.String com.alibaba.dubbo.config.ProviderConfig.getDispatcher() +public void com.alibaba.dubbo.config.ProviderConfig.setBuffer(java.lang.Integer) +public java.lang.Integer com.alibaba.dubbo.config.ProviderConfig.getBuffer() +public java.lang.Integer com.alibaba.dubbo.config.ProviderConfig.getTimeout() +public void com.alibaba.dubbo.config.ProviderConfig.setVersion(java.lang.String) +public void com.alibaba.dubbo.config.ProviderConfig.setListener(java.lang.String) +public void com.alibaba.dubbo.config.ProviderConfig.setProtocol(com.alibaba.dubbo.config.ProtocolConfig) +public java.lang.Integer com.alibaba.dubbo.config.ProviderConfig.getExecutes() +public void com.alibaba.dubbo.config.ProviderConfig.setExecutes(java.lang.Integer) +public void com.alibaba.dubbo.config.ProviderConfig.setDeprecated(java.lang.Boolean) +public java.lang.String com.alibaba.dubbo.config.ProviderConfig.getSerialization() +public void com.alibaba.dubbo.config.ProviderConfig.setSerialization(java.lang.String) +public java.lang.String com.alibaba.dubbo.config.ProviderConfig.getAccesslog() +public void com.alibaba.dubbo.config.ProviderConfig.setAccesslog(java.lang.String) +public void com.alibaba.dubbo.config.ProviderConfig.setAccesslog(java.lang.Boolean) +public java.lang.Boolean com.alibaba.dubbo.config.ProviderConfig.isRegister() +public void com.alibaba.dubbo.config.ProviderConfig.setRegister(java.lang.Boolean) +public java.lang.Boolean com.alibaba.dubbo.config.ProviderConfig.getExport() +public void com.alibaba.dubbo.config.ProviderConfig.setExport(java.lang.Boolean) +public java.lang.Integer com.alibaba.dubbo.config.ProviderConfig.getWeight() +public void com.alibaba.dubbo.config.ProviderConfig.setWeight(java.lang.Integer) +public java.lang.String com.alibaba.dubbo.config.ProviderConfig.getDocument() +public void com.alibaba.dubbo.config.ProviderConfig.setDocument(java.lang.String) +public java.lang.Boolean com.alibaba.dubbo.config.ProviderConfig.isDeprecated() +public void com.alibaba.dubbo.config.ProviderConfig.setDynamic(java.lang.Boolean) +public java.util.List com.alibaba.dubbo.config.ProviderConfig.getProtocols() +public void com.alibaba.dubbo.config.ProviderConfig.setProtocols(java.util.List) +public java.lang.Integer com.alibaba.dubbo.config.ProviderConfig.getWarmup() +public void com.alibaba.dubbo.config.ProviderConfig.setWarmup(java.lang.Integer) +public void com.alibaba.dubbo.config.ProviderConfig.setGroup(java.lang.String) +public java.lang.String com.alibaba.dubbo.config.ProviderConfig.getGroup() +public void com.alibaba.dubbo.config.ProviderConfig.setDelay(java.lang.Integer) +public java.lang.String com.alibaba.dubbo.config.ProviderConfig.getToken() +public void com.alibaba.dubbo.config.ProviderConfig.setToken(java.lang.String) +public void com.alibaba.dubbo.config.ProviderConfig.setToken(java.lang.Boolean) +public java.lang.String com.alibaba.dubbo.config.ProviderConfig.getTag() +public void com.alibaba.dubbo.config.ProviderConfig.setTag(java.lang.String) +public com.alibaba.dubbo.config.ProtocolConfig com.alibaba.dubbo.config.ProviderConfig.getProtocol() +public java.lang.String com.alibaba.dubbo.config.ProviderConfig.getFilter() +public java.lang.String com.alibaba.dubbo.config.ProviderConfig.getListener() +public java.lang.Boolean com.alibaba.dubbo.config.ProviderConfig.isDynamic() +public java.lang.Integer com.alibaba.dubbo.config.ProviderConfig.getDelay() +public java.lang.String com.alibaba.dubbo.config.ProviderConfig.getVersion() +public com.alibaba.dubbo.config.RegistryConfig com.alibaba.dubbo.config.ProviderConfig.getRegistry() +public void com.alibaba.dubbo.config.ProviderConfig.setRegistry(com.alibaba.dubbo.config.RegistryConfig) +public java.util.List com.alibaba.dubbo.config.ProviderConfig.getRegistries() +public void com.alibaba.dubbo.config.ProviderConfig.setRegistries(java.util.List) +public com.alibaba.dubbo.config.MonitorConfig com.alibaba.dubbo.config.ProviderConfig.getMonitor() +public void com.alibaba.dubbo.config.ProviderConfig.setMonitor(com.alibaba.dubbo.config.MonitorConfig) +public void com.alibaba.dubbo.config.ProviderConfig.setMonitor(java.lang.String) +public void com.alibaba.dubbo.config.ProviderConfig.setOnconnect(java.lang.String) +public void com.alibaba.dubbo.config.ProviderConfig.setOndisconnect(java.lang.String) +public void com.alibaba.dubbo.config.ProviderConfig.setCluster(java.lang.String) +public void com.alibaba.dubbo.config.ProviderConfig.setConnections(java.lang.Integer) +public com.alibaba.dubbo.config.ApplicationConfig com.alibaba.dubbo.config.ProviderConfig.getApplication() +public void com.alibaba.dubbo.config.ProviderConfig.setApplication(com.alibaba.dubbo.config.ApplicationConfig) +public com.alibaba.dubbo.config.ModuleConfig com.alibaba.dubbo.config.ProviderConfig.getModule() +public void com.alibaba.dubbo.config.ProviderConfig.setModule(com.alibaba.dubbo.config.ModuleConfig) +public java.lang.Integer com.alibaba.dubbo.config.ProviderConfig.getCallbacks() +public void com.alibaba.dubbo.config.ProviderConfig.setCallbacks(java.lang.Integer) +public java.lang.String com.alibaba.dubbo.config.ProviderConfig.getOnconnect() +public java.lang.String com.alibaba.dubbo.config.ProviderConfig.getOndisconnect() +public java.lang.String com.alibaba.dubbo.config.ProviderConfig.getLocal() +public void com.alibaba.dubbo.config.ProviderConfig.setLocal(java.lang.String) +public void com.alibaba.dubbo.config.ProviderConfig.setLocal(java.lang.Boolean) +public void com.alibaba.dubbo.config.ProviderConfig.setStub(java.lang.Boolean) +public void com.alibaba.dubbo.config.ProviderConfig.setStub(java.lang.String) +public java.lang.String com.alibaba.dubbo.config.ProviderConfig.getProxy() +public void com.alibaba.dubbo.config.ProviderConfig.setProxy(java.lang.String) +public java.lang.String com.alibaba.dubbo.config.ProviderConfig.getLayer() +public void com.alibaba.dubbo.config.ProviderConfig.setLayer(java.lang.String) +public void com.alibaba.dubbo.config.ProviderConfig.setScope(java.lang.String) +public void com.alibaba.dubbo.config.ProviderConfig.setFilter(java.lang.String) +public java.lang.String com.alibaba.dubbo.config.ProviderConfig.getOwner() +public java.lang.String com.alibaba.dubbo.config.ProviderConfig.getScope() +public void com.alibaba.dubbo.config.ProviderConfig.setOwner(java.lang.String) +public java.lang.String com.alibaba.dubbo.config.ProviderConfig.getStub() +public void com.alibaba.dubbo.config.ProviderConfig.setTimeout(java.lang.Integer) +public void com.alibaba.dubbo.config.ProviderConfig.setRetries(java.lang.Integer) +public void com.alibaba.dubbo.config.ProviderConfig.setLoadbalance(java.lang.String) +public void com.alibaba.dubbo.config.ProviderConfig.setActives(java.lang.Integer) +public java.lang.String com.alibaba.dubbo.config.ProviderConfig.getMerger() +public void com.alibaba.dubbo.config.ProviderConfig.setMerger(java.lang.String) +public java.lang.String com.alibaba.dubbo.config.ProviderConfig.getValidation() +public void com.alibaba.dubbo.config.ProviderConfig.setValidation(java.lang.String) +public void com.alibaba.dubbo.config.ProviderConfig.setForks(java.lang.Integer) +public java.lang.Integer com.alibaba.dubbo.config.ProviderConfig.getForks() +public void com.alibaba.dubbo.config.ProviderConfig.setAsync(java.lang.Boolean) +public java.lang.Boolean com.alibaba.dubbo.config.ProviderConfig.getSent() +public void com.alibaba.dubbo.config.ProviderConfig.setSent(java.lang.Boolean) +public java.lang.String com.alibaba.dubbo.config.ProviderConfig.getMock() +public void com.alibaba.dubbo.config.ProviderConfig.setMock(java.lang.String) +public void com.alibaba.dubbo.config.ProviderConfig.setMock(java.lang.Boolean) +public void com.alibaba.dubbo.config.ProviderConfig.setCache(java.lang.String) +public java.util.Map com.alibaba.dubbo.config.ProviderConfig.getParameters() +public java.lang.String com.alibaba.dubbo.config.ProviderConfig.getCache() +public void com.alibaba.dubbo.config.ProviderConfig.setParameters(java.util.Map) +public void com.alibaba.dubbo.config.ProviderConfig.setId(java.lang.String) +public java.lang.String com.alibaba.dubbo.config.ProviderConfig.toString() +public java.lang.String com.alibaba.dubbo.config.ProviderConfig.getId() +public final void com.alibaba.dubbo.config.ProviderConfig.wait(long,int) throws java.lang.InterruptedException +public final native void com.alibaba.dubbo.config.ProviderConfig.wait(long) throws java.lang.InterruptedException +public final void com.alibaba.dubbo.config.ProviderConfig.wait() throws java.lang.InterruptedException +public boolean com.alibaba.dubbo.config.ProviderConfig.equals(java.lang.Object) +public native int com.alibaba.dubbo.config.ProviderConfig.hashCode() +public final native java.lang.Class com.alibaba.dubbo.config.ProviderConfig.getClass() +public final native void com.alibaba.dubbo.config.ProviderConfig.notify() +public final native void com.alibaba.dubbo.config.ProviderConfig.notifyAll() diff --git a/dubbo-compatible/src/test/resources/definition/com.alibaba.dubbo.config.ReferenceConfig b/dubbo-compatible/src/test/resources/definition/com.alibaba.dubbo.config.ReferenceConfig new file mode 100644 index 0000000000..c5cfff37b5 --- /dev/null +++ b/dubbo-compatible/src/test/resources/definition/com.alibaba.dubbo.config.ReferenceConfig @@ -0,0 +1,130 @@ +// +// Licensed 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. +// + +public java.lang.String com.alibaba.dubbo.config.ReferenceConfig.getClient() +public void com.alibaba.dubbo.config.ReferenceConfig.setClient(java.lang.String) +public void com.alibaba.dubbo.config.ReferenceConfig.setProtocol(java.lang.String) +public java.lang.Class com.alibaba.dubbo.config.ReferenceConfig.getInterfaceClass() +public void com.alibaba.dubbo.config.ReferenceConfig.setInterfaceClass(java.lang.Class) +public java.lang.String com.alibaba.dubbo.config.ReferenceConfig.getInterface() +public void com.alibaba.dubbo.config.ReferenceConfig.setInterface(java.lang.Class) +public void com.alibaba.dubbo.config.ReferenceConfig.setInterface(java.lang.String) +public void com.alibaba.dubbo.config.ReferenceConfig.setMethods(java.util.List) +public com.alibaba.dubbo.config.ConsumerConfig com.alibaba.dubbo.config.ReferenceConfig.getConsumer() +public void com.alibaba.dubbo.config.ReferenceConfig.setConsumer(com.alibaba.dubbo.config.ConsumerConfig) +public java.lang.String com.alibaba.dubbo.config.ReferenceConfig.getUniqueServiceName() +public java.lang.String com.alibaba.dubbo.config.ReferenceConfig.getGroup() +public com.alibaba.dubbo.common.URL com.alibaba.dubbo.config.ReferenceConfig.toUrl() +public java.util.List com.alibaba.dubbo.config.ReferenceConfig.toUrls() +public java.lang.String com.alibaba.dubbo.config.ReferenceConfig.getUrl() +public void com.alibaba.dubbo.config.ReferenceConfig.setUrl(java.lang.String) +public synchronized java.lang.Object com.alibaba.dubbo.config.ReferenceConfig.get() +public java.util.List com.alibaba.dubbo.config.ReferenceConfig.getMethods() +public synchronized void com.alibaba.dubbo.config.ReferenceConfig.destroy() +public java.lang.String com.alibaba.dubbo.config.ReferenceConfig.getProtocol() +public java.lang.String com.alibaba.dubbo.config.ReferenceConfig.getVersion() +public void com.alibaba.dubbo.config.ReferenceConfig.setVersion(java.lang.String) +public void com.alibaba.dubbo.config.ReferenceConfig.setGeneric(java.lang.Boolean) +public void com.alibaba.dubbo.config.ReferenceConfig.setGeneric(java.lang.String) +public java.lang.String com.alibaba.dubbo.config.ReferenceConfig.getGeneric() +public void com.alibaba.dubbo.config.ReferenceConfig.setListener(java.lang.String) +public void com.alibaba.dubbo.config.ReferenceConfig.setOnconnect(java.lang.String) +public void com.alibaba.dubbo.config.ReferenceConfig.setOndisconnect(java.lang.String) +public java.lang.Boolean com.alibaba.dubbo.config.ReferenceConfig.getStubevent() +public java.lang.String com.alibaba.dubbo.config.ReferenceConfig.getReconnect() +public void com.alibaba.dubbo.config.ReferenceConfig.setReconnect(java.lang.String) +public java.lang.Boolean com.alibaba.dubbo.config.ReferenceConfig.getSticky() +public void com.alibaba.dubbo.config.ReferenceConfig.setSticky(java.lang.Boolean) +public java.lang.Boolean com.alibaba.dubbo.config.ReferenceConfig.getLazy() +public void com.alibaba.dubbo.config.ReferenceConfig.setInit(java.lang.Boolean) +public void com.alibaba.dubbo.config.ReferenceConfig.setInjvm(java.lang.Boolean) +public void com.alibaba.dubbo.config.ReferenceConfig.setLazy(java.lang.Boolean) +public java.lang.Boolean com.alibaba.dubbo.config.ReferenceConfig.isInjvm() +public void com.alibaba.dubbo.config.ReferenceConfig.setCheck(java.lang.Boolean) +public java.lang.Boolean com.alibaba.dubbo.config.ReferenceConfig.isCheck() +public void com.alibaba.dubbo.config.ReferenceConfig.setGroup(java.lang.String) +public java.lang.Boolean com.alibaba.dubbo.config.ReferenceConfig.isInit() +public java.lang.Boolean com.alibaba.dubbo.config.ReferenceConfig.isGeneric() +public java.lang.String com.alibaba.dubbo.config.ReferenceConfig.getFilter() +public java.lang.String com.alibaba.dubbo.config.ReferenceConfig.getListener() +public com.alibaba.dubbo.config.RegistryConfig com.alibaba.dubbo.config.ReferenceConfig.getRegistry() +public void com.alibaba.dubbo.config.ReferenceConfig.setRegistry(com.alibaba.dubbo.config.RegistryConfig) +public java.util.List com.alibaba.dubbo.config.ReferenceConfig.getRegistries() +public void com.alibaba.dubbo.config.ReferenceConfig.setRegistries(java.util.List) +public com.alibaba.dubbo.config.MonitorConfig com.alibaba.dubbo.config.ReferenceConfig.getMonitor() +public void com.alibaba.dubbo.config.ReferenceConfig.setMonitor(com.alibaba.dubbo.config.MonitorConfig) +public void com.alibaba.dubbo.config.ReferenceConfig.setMonitor(java.lang.String) +public java.lang.String com.alibaba.dubbo.config.ReferenceConfig.getCluster() +public void com.alibaba.dubbo.config.ReferenceConfig.setCluster(java.lang.String) +public java.lang.Integer com.alibaba.dubbo.config.ReferenceConfig.getConnections() +public void com.alibaba.dubbo.config.ReferenceConfig.setConnections(java.lang.Integer) +public com.alibaba.dubbo.config.ApplicationConfig com.alibaba.dubbo.config.ReferenceConfig.getApplication() +public void com.alibaba.dubbo.config.ReferenceConfig.setApplication(com.alibaba.dubbo.config.ApplicationConfig) +public com.alibaba.dubbo.config.ModuleConfig com.alibaba.dubbo.config.ReferenceConfig.getModule() +public void com.alibaba.dubbo.config.ReferenceConfig.setModule(com.alibaba.dubbo.config.ModuleConfig) +public java.lang.Integer com.alibaba.dubbo.config.ReferenceConfig.getCallbacks() +public void com.alibaba.dubbo.config.ReferenceConfig.setCallbacks(java.lang.Integer) +public java.lang.String com.alibaba.dubbo.config.ReferenceConfig.getOnconnect() +public java.lang.String com.alibaba.dubbo.config.ReferenceConfig.getOndisconnect() +public java.lang.String com.alibaba.dubbo.config.ReferenceConfig.getLocal() +public void com.alibaba.dubbo.config.ReferenceConfig.setLocal(java.lang.String) +public void com.alibaba.dubbo.config.ReferenceConfig.setLocal(java.lang.Boolean) +public void com.alibaba.dubbo.config.ReferenceConfig.setStub(java.lang.Boolean) +public void com.alibaba.dubbo.config.ReferenceConfig.setStub(java.lang.String) +public java.lang.String com.alibaba.dubbo.config.ReferenceConfig.getProxy() +public void com.alibaba.dubbo.config.ReferenceConfig.setProxy(java.lang.String) +public java.lang.String com.alibaba.dubbo.config.ReferenceConfig.getLayer() +public void com.alibaba.dubbo.config.ReferenceConfig.setLayer(java.lang.String) +public void com.alibaba.dubbo.config.ReferenceConfig.setScope(java.lang.String) +public void com.alibaba.dubbo.config.ReferenceConfig.setFilter(java.lang.String) +public java.lang.String com.alibaba.dubbo.config.ReferenceConfig.getOwner() +public java.lang.String com.alibaba.dubbo.config.ReferenceConfig.getScope() +public void com.alibaba.dubbo.config.ReferenceConfig.setOwner(java.lang.String) +public java.lang.String com.alibaba.dubbo.config.ReferenceConfig.getStub() +public void com.alibaba.dubbo.config.ReferenceConfig.setTimeout(java.lang.Integer) +public java.lang.Integer com.alibaba.dubbo.config.ReferenceConfig.getRetries() +public void com.alibaba.dubbo.config.ReferenceConfig.setRetries(java.lang.Integer) +public java.lang.String com.alibaba.dubbo.config.ReferenceConfig.getLoadbalance() +public void com.alibaba.dubbo.config.ReferenceConfig.setLoadbalance(java.lang.String) +public java.lang.Integer com.alibaba.dubbo.config.ReferenceConfig.getActives() +public void com.alibaba.dubbo.config.ReferenceConfig.setActives(java.lang.Integer) +public java.lang.String com.alibaba.dubbo.config.ReferenceConfig.getMerger() +public void com.alibaba.dubbo.config.ReferenceConfig.setMerger(java.lang.String) +public java.lang.String com.alibaba.dubbo.config.ReferenceConfig.getValidation() +public void com.alibaba.dubbo.config.ReferenceConfig.setValidation(java.lang.String) +public java.lang.Boolean com.alibaba.dubbo.config.ReferenceConfig.isAsync() +public void com.alibaba.dubbo.config.ReferenceConfig.setForks(java.lang.Integer) +public java.lang.Integer com.alibaba.dubbo.config.ReferenceConfig.getForks() +public void com.alibaba.dubbo.config.ReferenceConfig.setAsync(java.lang.Boolean) +public java.lang.Boolean com.alibaba.dubbo.config.ReferenceConfig.getSent() +public void com.alibaba.dubbo.config.ReferenceConfig.setSent(java.lang.Boolean) +public java.lang.String com.alibaba.dubbo.config.ReferenceConfig.getMock() +public void com.alibaba.dubbo.config.ReferenceConfig.setMock(java.lang.String) +public void com.alibaba.dubbo.config.ReferenceConfig.setMock(java.lang.Boolean) +public void com.alibaba.dubbo.config.ReferenceConfig.setCache(java.lang.String) +public java.util.Map com.alibaba.dubbo.config.ReferenceConfig.getParameters() +public java.lang.String com.alibaba.dubbo.config.ReferenceConfig.getCache() +public void com.alibaba.dubbo.config.ReferenceConfig.setParameters(java.util.Map) +public java.lang.Integer com.alibaba.dubbo.config.ReferenceConfig.getTimeout() +public void com.alibaba.dubbo.config.ReferenceConfig.setId(java.lang.String) +public java.lang.String com.alibaba.dubbo.config.ReferenceConfig.toString() +public java.lang.String com.alibaba.dubbo.config.ReferenceConfig.getId() +public final void com.alibaba.dubbo.config.ReferenceConfig.wait(long,int) throws java.lang.InterruptedException +public final native void com.alibaba.dubbo.config.ReferenceConfig.wait(long) throws java.lang.InterruptedException +public final void com.alibaba.dubbo.config.ReferenceConfig.wait() throws java.lang.InterruptedException +public boolean com.alibaba.dubbo.config.ReferenceConfig.equals(java.lang.Object) +public native int com.alibaba.dubbo.config.ReferenceConfig.hashCode() +public final native java.lang.Class com.alibaba.dubbo.config.ReferenceConfig.getClass() +public final native void com.alibaba.dubbo.config.ReferenceConfig.notify() +public final native void com.alibaba.dubbo.config.ReferenceConfig.notifyAll() diff --git a/dubbo-compatible/src/test/resources/definition/com.alibaba.dubbo.config.RegistryConfig b/dubbo-compatible/src/test/resources/definition/com.alibaba.dubbo.config.RegistryConfig new file mode 100644 index 0000000000..532718e375 --- /dev/null +++ b/dubbo-compatible/src/test/resources/definition/com.alibaba.dubbo.config.RegistryConfig @@ -0,0 +1,69 @@ +// +// Licensed 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. +// + +public void com.alibaba.dubbo.config.RegistryConfig.setVersion(java.lang.String) +public void com.alibaba.dubbo.config.RegistryConfig.setTimeout(java.lang.Integer) +public java.lang.String com.alibaba.dubbo.config.RegistryConfig.getClient() +public void com.alibaba.dubbo.config.RegistryConfig.setClient(java.lang.String) +public java.lang.String com.alibaba.dubbo.config.RegistryConfig.getCluster() +public void com.alibaba.dubbo.config.RegistryConfig.setCluster(java.lang.String) +public void com.alibaba.dubbo.config.RegistryConfig.setProtocol(java.lang.String) +public java.lang.String com.alibaba.dubbo.config.RegistryConfig.getUsername() +public void com.alibaba.dubbo.config.RegistryConfig.setUsername(java.lang.String) +public void com.alibaba.dubbo.config.RegistryConfig.setPassword(java.lang.String) +public java.lang.String com.alibaba.dubbo.config.RegistryConfig.getServer() +public void com.alibaba.dubbo.config.RegistryConfig.setServer(java.lang.String) +public java.lang.Boolean com.alibaba.dubbo.config.RegistryConfig.isRegister() +public void com.alibaba.dubbo.config.RegistryConfig.setRegister(java.lang.Boolean) +public java.lang.String com.alibaba.dubbo.config.RegistryConfig.getTransporter() +public void com.alibaba.dubbo.config.RegistryConfig.setTransporter(java.lang.String) +public void com.alibaba.dubbo.config.RegistryConfig.setDynamic(java.lang.Boolean) +public java.lang.String com.alibaba.dubbo.config.RegistryConfig.getTransport() +public void com.alibaba.dubbo.config.RegistryConfig.setTransport(java.lang.String) +public java.lang.Integer com.alibaba.dubbo.config.RegistryConfig.getSession() +public void com.alibaba.dubbo.config.RegistryConfig.setSession(java.lang.Integer) +public java.lang.Boolean com.alibaba.dubbo.config.RegistryConfig.isSubscribe() +public void com.alibaba.dubbo.config.RegistryConfig.setSubscribe(java.lang.Boolean) +public void com.alibaba.dubbo.config.RegistryConfig.setCheck(java.lang.Boolean) +public java.lang.Boolean com.alibaba.dubbo.config.RegistryConfig.isCheck() +public void com.alibaba.dubbo.config.RegistryConfig.setGroup(java.lang.String) +public java.lang.String com.alibaba.dubbo.config.RegistryConfig.getGroup() +public java.lang.Integer com.alibaba.dubbo.config.RegistryConfig.getWait() +public void com.alibaba.dubbo.config.RegistryConfig.setWait(java.lang.Integer) +public void com.alibaba.dubbo.config.RegistryConfig.setFile(java.lang.String) +public java.lang.String com.alibaba.dubbo.config.RegistryConfig.getAddress() +public java.lang.Boolean com.alibaba.dubbo.config.RegistryConfig.isDefault() +public java.util.Map com.alibaba.dubbo.config.RegistryConfig.getParameters() +public java.lang.String com.alibaba.dubbo.config.RegistryConfig.getProtocol() +public java.lang.String com.alibaba.dubbo.config.RegistryConfig.getFile() +public java.lang.Integer com.alibaba.dubbo.config.RegistryConfig.getPort() +public void com.alibaba.dubbo.config.RegistryConfig.setDefault(java.lang.Boolean) +public java.lang.String com.alibaba.dubbo.config.RegistryConfig.getPassword() +public void com.alibaba.dubbo.config.RegistryConfig.setAddress(java.lang.String) +public void com.alibaba.dubbo.config.RegistryConfig.setPort(java.lang.Integer) +public java.lang.Boolean com.alibaba.dubbo.config.RegistryConfig.isDynamic() +public java.lang.String com.alibaba.dubbo.config.RegistryConfig.getVersion() +public void com.alibaba.dubbo.config.RegistryConfig.setParameters(java.util.Map) +public java.lang.Integer com.alibaba.dubbo.config.RegistryConfig.getTimeout() +public void com.alibaba.dubbo.config.RegistryConfig.setId(java.lang.String) +public java.lang.String com.alibaba.dubbo.config.RegistryConfig.toString() +public java.lang.String com.alibaba.dubbo.config.RegistryConfig.getId() +public final void com.alibaba.dubbo.config.RegistryConfig.wait(long,int) throws java.lang.InterruptedException +public final native void com.alibaba.dubbo.config.RegistryConfig.wait(long) throws java.lang.InterruptedException +public final void com.alibaba.dubbo.config.RegistryConfig.wait() throws java.lang.InterruptedException +public boolean com.alibaba.dubbo.config.RegistryConfig.equals(java.lang.Object) +public native int com.alibaba.dubbo.config.RegistryConfig.hashCode() +public final native java.lang.Class com.alibaba.dubbo.config.RegistryConfig.getClass() +public final native void com.alibaba.dubbo.config.RegistryConfig.notify() +public final native void com.alibaba.dubbo.config.RegistryConfig.notifyAll() diff --git a/dubbo-compatible/src/test/resources/definition/com.alibaba.dubbo.config.ServiceConfig b/dubbo-compatible/src/test/resources/definition/com.alibaba.dubbo.config.ServiceConfig new file mode 100644 index 0000000000..6d1e874c4d --- /dev/null +++ b/dubbo-compatible/src/test/resources/definition/com.alibaba.dubbo.config.ServiceConfig @@ -0,0 +1,150 @@ +// +// Licensed 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. +// + +public void com.alibaba.dubbo.config.ServiceConfig.setGeneric(java.lang.String) +public java.lang.String com.alibaba.dubbo.config.ServiceConfig.getGeneric() +public boolean com.alibaba.dubbo.config.ServiceConfig.isExported() +public boolean com.alibaba.dubbo.config.ServiceConfig.isUnexported() +public void com.alibaba.dubbo.config.ServiceConfig.setProvider(com.alibaba.dubbo.config.ProviderConfig) +public java.util.List com.alibaba.dubbo.config.ServiceConfig.getExportedUrls() +public void com.alibaba.dubbo.config.ServiceConfig.setProviders(java.util.List) +public java.lang.Class com.alibaba.dubbo.config.ServiceConfig.getInterfaceClass() +public void com.alibaba.dubbo.config.ServiceConfig.setInterfaceClass(java.lang.Class) +public java.lang.String com.alibaba.dubbo.config.ServiceConfig.getInterface() +public void com.alibaba.dubbo.config.ServiceConfig.setInterface(java.lang.String) +public void com.alibaba.dubbo.config.ServiceConfig.setInterface(java.lang.Class) +public void com.alibaba.dubbo.config.ServiceConfig.setMethods(java.util.List) +public java.lang.String com.alibaba.dubbo.config.ServiceConfig.getUniqueServiceName() +public java.lang.String com.alibaba.dubbo.config.ServiceConfig.getGroup() +public void com.alibaba.dubbo.config.ServiceConfig.setMock(java.lang.Boolean) +public void com.alibaba.dubbo.config.ServiceConfig.setMock(java.lang.String) +public com.alibaba.dubbo.common.URL com.alibaba.dubbo.config.ServiceConfig.toUrl() +public java.util.List com.alibaba.dubbo.config.ServiceConfig.toUrls() +public synchronized void com.alibaba.dubbo.config.ServiceConfig.unexport() +public java.util.List com.alibaba.dubbo.config.ServiceConfig.getMethods() +public java.lang.String com.alibaba.dubbo.config.ServiceConfig.getPath() +public java.lang.Object com.alibaba.dubbo.config.ServiceConfig.getRef() +public synchronized void com.alibaba.dubbo.config.ServiceConfig.export() +public java.util.List com.alibaba.dubbo.config.ServiceConfig.getProviders() +public com.alibaba.dubbo.config.ProviderConfig com.alibaba.dubbo.config.ServiceConfig.getProvider() +public java.lang.String com.alibaba.dubbo.config.ServiceConfig.getVersion() +public void com.alibaba.dubbo.config.ServiceConfig.setPath(java.lang.String) +public void com.alibaba.dubbo.config.ServiceConfig.setRef(java.lang.Object) +public void com.alibaba.dubbo.config.ServiceConfig.setVersion(java.lang.String) +public void com.alibaba.dubbo.config.ServiceConfig.setListener(java.lang.String) +public void com.alibaba.dubbo.config.ServiceConfig.setProtocol(com.alibaba.dubbo.config.ProtocolConfig) +public java.lang.Integer com.alibaba.dubbo.config.ServiceConfig.getExecutes() +public void com.alibaba.dubbo.config.ServiceConfig.setExecutes(java.lang.Integer) +public void com.alibaba.dubbo.config.ServiceConfig.setDeprecated(java.lang.Boolean) +public java.lang.String com.alibaba.dubbo.config.ServiceConfig.getSerialization() +public void com.alibaba.dubbo.config.ServiceConfig.setSerialization(java.lang.String) +public java.lang.String com.alibaba.dubbo.config.ServiceConfig.getAccesslog() +public void com.alibaba.dubbo.config.ServiceConfig.setAccesslog(java.lang.String) +public void com.alibaba.dubbo.config.ServiceConfig.setAccesslog(java.lang.Boolean) +public java.lang.Boolean com.alibaba.dubbo.config.ServiceConfig.isRegister() +public void com.alibaba.dubbo.config.ServiceConfig.setRegister(java.lang.Boolean) +public java.lang.Boolean com.alibaba.dubbo.config.ServiceConfig.getExport() +public void com.alibaba.dubbo.config.ServiceConfig.setExport(java.lang.Boolean) +public java.lang.Integer com.alibaba.dubbo.config.ServiceConfig.getWeight() +public void com.alibaba.dubbo.config.ServiceConfig.setWeight(java.lang.Integer) +public java.lang.String com.alibaba.dubbo.config.ServiceConfig.getDocument() +public void com.alibaba.dubbo.config.ServiceConfig.setDocument(java.lang.String) +public java.lang.Boolean com.alibaba.dubbo.config.ServiceConfig.isDeprecated() +public void com.alibaba.dubbo.config.ServiceConfig.setDynamic(java.lang.Boolean) +public java.util.List com.alibaba.dubbo.config.ServiceConfig.getProtocols() +public void com.alibaba.dubbo.config.ServiceConfig.setProtocols(java.util.List) +public java.lang.Integer com.alibaba.dubbo.config.ServiceConfig.getWarmup() +public void com.alibaba.dubbo.config.ServiceConfig.setWarmup(java.lang.Integer) +public void com.alibaba.dubbo.config.ServiceConfig.setGroup(java.lang.String) +public void com.alibaba.dubbo.config.ServiceConfig.setDelay(java.lang.Integer) +public java.lang.String com.alibaba.dubbo.config.ServiceConfig.getToken() +public void com.alibaba.dubbo.config.ServiceConfig.setToken(java.lang.String) +public void com.alibaba.dubbo.config.ServiceConfig.setToken(java.lang.Boolean) +public java.lang.String com.alibaba.dubbo.config.ServiceConfig.getTag() +public void com.alibaba.dubbo.config.ServiceConfig.setTag(java.lang.String) +public com.alibaba.dubbo.config.ProtocolConfig com.alibaba.dubbo.config.ServiceConfig.getProtocol() +public java.lang.String com.alibaba.dubbo.config.ServiceConfig.getFilter() +public java.lang.String com.alibaba.dubbo.config.ServiceConfig.getListener() +public java.lang.Boolean com.alibaba.dubbo.config.ServiceConfig.isDynamic() +public java.lang.Integer com.alibaba.dubbo.config.ServiceConfig.getDelay() +public com.alibaba.dubbo.config.RegistryConfig com.alibaba.dubbo.config.ServiceConfig.getRegistry() +public void com.alibaba.dubbo.config.ServiceConfig.setRegistry(com.alibaba.dubbo.config.RegistryConfig) +public java.util.List com.alibaba.dubbo.config.ServiceConfig.getRegistries() +public void com.alibaba.dubbo.config.ServiceConfig.setRegistries(java.util.List) +public com.alibaba.dubbo.config.MonitorConfig com.alibaba.dubbo.config.ServiceConfig.getMonitor() +public void com.alibaba.dubbo.config.ServiceConfig.setMonitor(com.alibaba.dubbo.config.MonitorConfig) +public void com.alibaba.dubbo.config.ServiceConfig.setMonitor(java.lang.String) +public void com.alibaba.dubbo.config.ServiceConfig.setOnconnect(java.lang.String) +public void com.alibaba.dubbo.config.ServiceConfig.setOndisconnect(java.lang.String) +public java.lang.String com.alibaba.dubbo.config.ServiceConfig.getCluster() +public void com.alibaba.dubbo.config.ServiceConfig.setCluster(java.lang.String) +public java.lang.Integer com.alibaba.dubbo.config.ServiceConfig.getConnections() +public void com.alibaba.dubbo.config.ServiceConfig.setConnections(java.lang.Integer) +public com.alibaba.dubbo.config.ApplicationConfig com.alibaba.dubbo.config.ServiceConfig.getApplication() +public void com.alibaba.dubbo.config.ServiceConfig.setApplication(com.alibaba.dubbo.config.ApplicationConfig) +public com.alibaba.dubbo.config.ModuleConfig com.alibaba.dubbo.config.ServiceConfig.getModule() +public void com.alibaba.dubbo.config.ServiceConfig.setModule(com.alibaba.dubbo.config.ModuleConfig) +public java.lang.Integer com.alibaba.dubbo.config.ServiceConfig.getCallbacks() +public void com.alibaba.dubbo.config.ServiceConfig.setCallbacks(java.lang.Integer) +public java.lang.String com.alibaba.dubbo.config.ServiceConfig.getOnconnect() +public java.lang.String com.alibaba.dubbo.config.ServiceConfig.getOndisconnect() +public java.lang.String com.alibaba.dubbo.config.ServiceConfig.getLocal() +public void com.alibaba.dubbo.config.ServiceConfig.setLocal(java.lang.String) +public void com.alibaba.dubbo.config.ServiceConfig.setLocal(java.lang.Boolean) +public void com.alibaba.dubbo.config.ServiceConfig.setStub(java.lang.Boolean) +public void com.alibaba.dubbo.config.ServiceConfig.setStub(java.lang.String) +public java.lang.String com.alibaba.dubbo.config.ServiceConfig.getProxy() +public void com.alibaba.dubbo.config.ServiceConfig.setProxy(java.lang.String) +public java.lang.String com.alibaba.dubbo.config.ServiceConfig.getLayer() +public void com.alibaba.dubbo.config.ServiceConfig.setLayer(java.lang.String) +public void com.alibaba.dubbo.config.ServiceConfig.setScope(java.lang.String) +public void com.alibaba.dubbo.config.ServiceConfig.setFilter(java.lang.String) +public java.lang.String com.alibaba.dubbo.config.ServiceConfig.getOwner() +public java.lang.String com.alibaba.dubbo.config.ServiceConfig.getScope() +public void com.alibaba.dubbo.config.ServiceConfig.setOwner(java.lang.String) +public java.lang.String com.alibaba.dubbo.config.ServiceConfig.getStub() +public void com.alibaba.dubbo.config.ServiceConfig.setTimeout(java.lang.Integer) +public java.lang.Integer com.alibaba.dubbo.config.ServiceConfig.getRetries() +public void com.alibaba.dubbo.config.ServiceConfig.setRetries(java.lang.Integer) +public java.lang.String com.alibaba.dubbo.config.ServiceConfig.getLoadbalance() +public void com.alibaba.dubbo.config.ServiceConfig.setLoadbalance(java.lang.String) +public java.lang.Integer com.alibaba.dubbo.config.ServiceConfig.getActives() +public void com.alibaba.dubbo.config.ServiceConfig.setActives(java.lang.Integer) +public java.lang.String com.alibaba.dubbo.config.ServiceConfig.getMerger() +public void com.alibaba.dubbo.config.ServiceConfig.setMerger(java.lang.String) +public java.lang.String com.alibaba.dubbo.config.ServiceConfig.getValidation() +public void com.alibaba.dubbo.config.ServiceConfig.setValidation(java.lang.String) +public java.lang.Boolean com.alibaba.dubbo.config.ServiceConfig.isAsync() +public void com.alibaba.dubbo.config.ServiceConfig.setForks(java.lang.Integer) +public java.lang.Integer com.alibaba.dubbo.config.ServiceConfig.getForks() +public void com.alibaba.dubbo.config.ServiceConfig.setAsync(java.lang.Boolean) +public java.lang.Boolean com.alibaba.dubbo.config.ServiceConfig.getSent() +public void com.alibaba.dubbo.config.ServiceConfig.setSent(java.lang.Boolean) +public java.lang.String com.alibaba.dubbo.config.ServiceConfig.getMock() +public void com.alibaba.dubbo.config.ServiceConfig.setCache(java.lang.String) +public java.util.Map com.alibaba.dubbo.config.ServiceConfig.getParameters() +public java.lang.String com.alibaba.dubbo.config.ServiceConfig.getCache() +public void com.alibaba.dubbo.config.ServiceConfig.setParameters(java.util.Map) +public java.lang.Integer com.alibaba.dubbo.config.ServiceConfig.getTimeout() +public void com.alibaba.dubbo.config.ServiceConfig.setId(java.lang.String) +public java.lang.String com.alibaba.dubbo.config.ServiceConfig.toString() +public java.lang.String com.alibaba.dubbo.config.ServiceConfig.getId() +public final void com.alibaba.dubbo.config.ServiceConfig.wait(long,int) throws java.lang.InterruptedException +public final native void com.alibaba.dubbo.config.ServiceConfig.wait(long) throws java.lang.InterruptedException +public final void com.alibaba.dubbo.config.ServiceConfig.wait() throws java.lang.InterruptedException +public boolean com.alibaba.dubbo.config.ServiceConfig.equals(java.lang.Object) +public native int com.alibaba.dubbo.config.ServiceConfig.hashCode() +public final native java.lang.Class com.alibaba.dubbo.config.ServiceConfig.getClass() +public final native void com.alibaba.dubbo.config.ServiceConfig.notify() +public final native void com.alibaba.dubbo.config.ServiceConfig.notifyAll() diff --git a/dubbo-config/dubbo-config-api/pom.xml b/dubbo-config/dubbo-config-api/pom.xml index 110b043ba1..23a642faf0 100644 --- a/dubbo-config/dubbo-config-api/pom.xml +++ b/dubbo-config/dubbo-config-api/pom.xml @@ -66,6 +66,12 @@ ${project.parent.version} + + org.apache.dubbo + dubbo-metrics-config-center + ${project.parent.version} + + org.apache.dubbo dubbo-monitor-api diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/DubboShutdownHook.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/DubboShutdownHook.java index e32a3f4fd3..3172525e72 100644 --- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/DubboShutdownHook.java +++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/DubboShutdownHook.java @@ -22,9 +22,11 @@ import org.apache.dubbo.common.constants.LoggerCodeConstants; import org.apache.dubbo.common.logger.ErrorTypeAwareLogger; import org.apache.dubbo.common.logger.LoggerFactory; import org.apache.dubbo.common.utils.Assert; +import org.apache.dubbo.rpc.GracefulShutdown; import org.apache.dubbo.rpc.model.ApplicationModel; import org.apache.dubbo.rpc.model.ModuleModel; +import java.util.List; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; @@ -80,6 +82,12 @@ public class DubboShutdownHook extends Thread { } private void doDestroy() { + // send readonly for shutdown hook + List gracefulShutdowns = GracefulShutdown.getGracefulShutdowns(applicationModel.getFrameworkModel()); + for (GracefulShutdown gracefulShutdown : gracefulShutdowns) { + gracefulShutdown.readonly(); + } + boolean hasModuleBindSpring = false; // check if any modules are bound to Spring for (ModuleModel module: applicationModel.getModuleModels()) { @@ -92,11 +100,11 @@ public class DubboShutdownHook extends Thread { int timeout = ConfigurationUtils.getServerShutdownTimeout(applicationModel); if (timeout > 0) { long start = System.currentTimeMillis(); - /** - * To avoid shutdown conflicts between Dubbo and Spring, - * wait for the modules bound to Spring to be handled by Spring util timeout. + /* + To avoid shutdown conflicts between Dubbo and Spring, + wait for the modules bound to Spring to be handled by Spring until timeout. */ - logger.info("Waiting for modules managed by Spring to be shut down."); + logger.info("Waiting for modules managed by Spring to be shutdown."); while (!applicationModel.isDestroyed() && hasModuleBindSpring && (System.currentTimeMillis() - start) < timeout) { try { 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 61784867c3..291296240b 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 @@ -19,6 +19,7 @@ package org.apache.dubbo.config; import org.apache.dubbo.common.URL; import org.apache.dubbo.common.URLBuilder; import org.apache.dubbo.common.Version; +import org.apache.dubbo.common.config.ConfigurationUtils; import org.apache.dubbo.common.constants.CommonConstants; import org.apache.dubbo.common.extension.ExtensionLoader; import org.apache.dubbo.common.logger.ErrorTypeAwareLogger; @@ -86,6 +87,7 @@ import static org.apache.dubbo.common.constants.LoggerCodeConstants.CONFIG_NO_ME import static org.apache.dubbo.common.constants.LoggerCodeConstants.CONFIG_SERVER_DISCONNECTED; import static org.apache.dubbo.common.constants.LoggerCodeConstants.CONFIG_UNEXPORT_ERROR; import static org.apache.dubbo.common.constants.LoggerCodeConstants.CONFIG_USE_RANDOM_PORT; +import static org.apache.dubbo.common.constants.LoggerCodeConstants.INTERNAL_ERROR; import static org.apache.dubbo.common.constants.RegistryConstants.DYNAMIC_KEY; import static org.apache.dubbo.common.constants.RegistryConstants.SERVICE_REGISTRY_PROTOCOL; import static org.apache.dubbo.common.utils.NetUtils.getAvailablePort; @@ -194,6 +196,14 @@ public class ServiceConfig extends ServiceConfigBase { return; } if (!exporters.isEmpty()) { + for (Exporter exporter : exporters) { + try { + exporter.unregister(); + } catch (Throwable t) { + logger.warn(CONFIG_UNEXPORT_ERROR, "", "", "Unexpected error occurred when unexport " + exporter, t); + } + } + waitForIdle(); for (Exporter exporter : exporters) { try { exporter.unexport(); @@ -209,6 +219,51 @@ public class ServiceConfig extends ServiceConfigBase { repository.unregisterProvider(providerModel); } + private void waitForIdle() { + int timeout = ConfigurationUtils.getServerShutdownTimeout(getScopeModel()); + + long idleTime = System.currentTimeMillis() - providerModel.getLastInvokeTime(); + + // 1. if service has idle for 10s(shutdown time), un-export directly + if (idleTime > timeout) { + return; + } + + // 2. if service has idle for more than 6.7s(2/3 of shutdown time), wait for the rest time, then un-export directly + int tick = timeout / 3; + if (timeout - idleTime < tick) { + logger.info("Service " + getUniqueServiceName() + " has idle for " + idleTime + " ms, wait for " + (timeout - idleTime) + " ms to un-export"); + try { + Thread.sleep(timeout - idleTime); + } catch (InterruptedException e) { + logger.warn(INTERNAL_ERROR, "unknown error in registry module", "", e.getMessage(), e); + Thread.currentThread().interrupt(); + } + return; + } + + // 3. Wait for 3.33s(1/3 of shutdown time), if service has idle for 3.33s(1/3 of shutdown time), un-export directly, + // otherwise wait for the rest time until idle for 3.33s(1/3 of shutdown time). The max wait time is 10s(shutdown time). + idleTime = 0; + long startTime = System.currentTimeMillis(); + while (idleTime < tick) { + // service idle time. + idleTime = System.currentTimeMillis() - Math.max(providerModel.getLastInvokeTime(), startTime); + if (idleTime >= tick || System.currentTimeMillis() - startTime > timeout) { + return; + } + // idle rest time or timeout rest time + long waitTime = Math.min(tick - idleTime, timeout + startTime - System.currentTimeMillis()); + logger.info("Service " + getUniqueServiceName() + " has idle for " + idleTime + " ms, wait for " + waitTime + " ms to un-export"); + try { + Thread.sleep(waitTime); + } catch (InterruptedException e) { + logger.warn(INTERNAL_ERROR, "unknown error in registry module", "", e.getMessage(), e); + Thread.currentThread().interrupt(); + } + } + } + /** * for early init serviceMetadata */ diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/deploy/DefaultApplicationDeployer.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/deploy/DefaultApplicationDeployer.java index bd30eb9b56..faf8123717 100644 --- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/deploy/DefaultApplicationDeployer.java +++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/deploy/DefaultApplicationDeployer.java @@ -20,6 +20,7 @@ import org.apache.dubbo.common.URL; import org.apache.dubbo.common.config.ConfigurationUtils; import org.apache.dubbo.common.config.Environment; import org.apache.dubbo.common.config.ReferenceCache; +import org.apache.dubbo.common.config.configcenter.ConfigChangeType; import org.apache.dubbo.common.config.configcenter.DynamicConfiguration; import org.apache.dubbo.common.config.configcenter.DynamicConfigurationFactory; import org.apache.dubbo.common.config.configcenter.wrapper.CompositeDynamicConfiguration; @@ -50,17 +51,21 @@ import org.apache.dubbo.config.utils.CompositeReferenceCache; import org.apache.dubbo.config.utils.ConfigValidationUtils; import org.apache.dubbo.metadata.report.MetadataReportFactory; import org.apache.dubbo.metadata.report.MetadataReportInstance; -import org.apache.dubbo.metrics.collector.ConfigCenterMetricsCollector; import org.apache.dubbo.metrics.collector.DefaultMetricsCollector; +import org.apache.dubbo.metrics.config.event.ConfigCenterEvent; import org.apache.dubbo.metrics.event.MetricsEventBus; import org.apache.dubbo.metrics.registry.event.RegistryEvent; import org.apache.dubbo.metrics.report.MetricsReporter; import org.apache.dubbo.metrics.report.MetricsReporterFactory; import org.apache.dubbo.metrics.service.MetricsServiceExporter; +import org.apache.dubbo.registry.Registry; +import org.apache.dubbo.registry.RegistryFactory; import org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils; import org.apache.dubbo.registry.support.RegistryManager; import org.apache.dubbo.rpc.model.ApplicationModel; import org.apache.dubbo.rpc.model.ModuleModel; +import org.apache.dubbo.rpc.model.ModuleServiceRepository; +import org.apache.dubbo.rpc.model.ProviderModel; import org.apache.dubbo.rpc.model.ScopeModel; import org.apache.dubbo.rpc.model.ScopeModelUtil; @@ -799,8 +804,6 @@ public class DefaultApplicationDeployer extends AbstractDeployer exportedServices = serviceRepository.getExportedServices(); + for (ProviderModel exportedService : exportedServices) { + List statedUrls = exportedService.getStatedUrl(); + for (ProviderModel.RegisterStatedURL statedURL : statedUrls) { + if (statedURL.isRegistered()) { + doOffline(statedURL); + } + } + } + } + } catch (Throwable t) { + logger.error(LoggerCodeConstants.INTERNAL_ERROR, "", "", "Exceptions occurred when unregister services.", t); + } + } + + private void doOffline(ProviderModel.RegisterStatedURL statedURL) { + RegistryFactory registryFactory = + statedURL.getRegistryUrl().getOrDefaultApplicationModel().getExtensionLoader(RegistryFactory.class).getAdaptiveExtension(); + Registry registry = registryFactory.getRegistry(statedURL.getRegistryUrl()); + registry.unregister(statedURL.getProviderUrl()); + statedURL.setRegistered(false); + } + @Override public void postDestroy() { synchronized (destroyLock) { @@ -1153,6 +1185,7 @@ public class DefaultApplicationDeployer extends AbstractDeployer impleme return; } onModuleStopping(); + + offline(); + } + + private void offline() { + try { + ModuleServiceRepository serviceRepository = moduleModel.getServiceRepository(); + List exportedServices = serviceRepository.getExportedServices(); + for (ProviderModel exportedService : exportedServices) { + List statedUrls = exportedService.getStatedUrl(); + for (ProviderModel.RegisterStatedURL statedURL : statedUrls) { + if (statedURL.isRegistered()) { + doOffline(statedURL); + } + } + } + } catch (Throwable t) { + logger.error(LoggerCodeConstants.INTERNAL_ERROR, "", "", "Exceptions occurred when unregister services.", t); + } + } + + private void doOffline(ProviderModel.RegisterStatedURL statedURL) { + RegistryFactory registryFactory = + statedURL.getRegistryUrl().getOrDefaultApplicationModel().getExtensionLoader(RegistryFactory.class).getAdaptiveExtension(); + Registry registry = registryFactory.getRegistry(statedURL.getRegistryUrl()); + registry.unregister(statedURL.getProviderUrl()); + statedURL.setRegistered(false); } @Override @@ -436,7 +466,7 @@ public class DefaultModuleDeployer extends AbstractDeployer impleme exportFuture = CompletableFuture.allOf(asyncExportingFutures.toArray(new CompletableFuture[0])); exportFuture.get(); } catch (Throwable e) { - logger.warn(CONFIG_FAILED_EXPORT_SERVICE, "","",getIdentifier() + " export services occurred an exception: " + e.toString()); + logger.warn(CONFIG_FAILED_EXPORT_SERVICE, "", "", getIdentifier() + " export services occurred an exception: " + e.toString()); } finally { logger.info(getIdentifier() + " export services finished."); asyncExportingFutures.clear(); diff --git a/dubbo-config/dubbo-config-spring/pom.xml b/dubbo-config/dubbo-config-spring/pom.xml index 42247d25a5..25252f67b3 100644 --- a/dubbo-config/dubbo-config-spring/pom.xml +++ b/dubbo-config/dubbo-config-spring/pom.xml @@ -27,7 +27,7 @@ The spring config module of dubbo project false - 2.7.10 + 2.7.11 diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/reference/ReferenceBeanSupport.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/reference/ReferenceBeanSupport.java index a1ff985c13..dcc740e82e 100644 --- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/reference/ReferenceBeanSupport.java +++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/reference/ReferenceBeanSupport.java @@ -52,7 +52,7 @@ import static org.apache.dubbo.common.utils.StringUtils.join; public class ReferenceBeanSupport { - private static List IGNORED_ATTRS = Arrays.asList(ReferenceAttributes.ID, ReferenceAttributes.GROUP, + private static final List IGNORED_ATTRS = Arrays.asList(ReferenceAttributes.ID, ReferenceAttributes.GROUP, ReferenceAttributes.VERSION, ReferenceAttributes.INTERFACE, ReferenceAttributes.INTERFACE_NAME, ReferenceAttributes.INTERFACE_CLASS); @@ -66,7 +66,7 @@ public class ReferenceBeanSupport { if (interfaceName == null) { Object interfaceClassValue = attributes.get(ReferenceAttributes.INTERFACE_CLASS); if (interfaceClassValue instanceof Class) { - interfaceName = ((Class) interfaceClassValue).getName(); + interfaceName = ((Class) interfaceClassValue).getName(); } else if (interfaceClassValue instanceof String) { if (interfaceClassValue.equals("void")) { attributes.remove(ReferenceAttributes.INTERFACE_CLASS); diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/schema/DubboBeanDefinitionParser.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/schema/DubboBeanDefinitionParser.java index 8f63565b21..9f0c8c7d90 100644 --- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/schema/DubboBeanDefinitionParser.java +++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/schema/DubboBeanDefinitionParser.java @@ -175,7 +175,10 @@ public class DubboBeanDefinitionParser implements BeanDefinitionParser { if ("registry".equals(property) && RegistryConfig.NO_AVAILABLE.equalsIgnoreCase(value)) { RegistryConfig registryConfig = new RegistryConfig(); registryConfig.setAddress(RegistryConfig.NO_AVAILABLE); - beanDefinition.getPropertyValues().addPropertyValue(beanProperty, registryConfig); + // see AbstractInterfaceConfig#registries, It will be invoker setRegistries method when BeanDefinition is registered, + beanDefinition.getPropertyValues().addPropertyValue("registries", registryConfig); + // If registry is N/A, don't init it until the reference is invoked + beanDefinition.setLazyInit(true); } else if ("provider".equals(property) || "registry".equals(property) || ("protocol".equals(property) && AbstractServiceConfig.class.isAssignableFrom(beanClass))) { /** * For 'provider' 'protocol' 'registry', keep literal value (should be id/name) and set the value to 'registryIds' 'providerIds' protocolIds' diff --git a/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/dubbo.xsd b/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/dubbo.xsd index ca5a6ec455..141b5d5169 100644 --- a/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/dubbo.xsd +++ b/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/dubbo.xsd @@ -547,6 +547,12 @@ + + + + + + @@ -1210,6 +1216,7 @@ + @@ -1238,6 +1245,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -2187,4 +2221,18 @@ means that these fields would end up as key-value pairs in e.g. MDC. ]]> + + + + + + + + + + + + + + diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/ControllerServiceConfigTest.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/ControllerServiceConfigTest.java new file mode 100644 index 0000000000..6f059143a8 --- /dev/null +++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/ControllerServiceConfigTest.java @@ -0,0 +1,42 @@ +/* + * 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.config.spring; + +import org.apache.dubbo.config.ApplicationConfig; +import org.apache.dubbo.config.ProtocolConfig; +import org.apache.dubbo.config.ServiceConfig; +import org.apache.dubbo.config.spring.api.SpringControllerService; +import org.junit.jupiter.api.Test; + +public class ControllerServiceConfigTest { + + @Test + void testServiceConfig() { + + ServiceConfig serviceServiceConfig = new ServiceConfig<>(); + ApplicationConfig applicationConfig = new ApplicationConfig(); + applicationConfig.setName("dubbo"); + serviceServiceConfig.setApplication(applicationConfig); + serviceServiceConfig.setProtocol(new ProtocolConfig("rest",8080)); + serviceServiceConfig.setRef(new SpringControllerService()); + serviceServiceConfig.setInterface(SpringControllerService.class.getName()); + serviceServiceConfig.export(); + serviceServiceConfig.unexport(); + + + } +} diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/api/SpringControllerService.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/api/SpringControllerService.java new file mode 100644 index 0000000000..da2866f85f --- /dev/null +++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/api/SpringControllerService.java @@ -0,0 +1,29 @@ +/* + * 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.config.spring.api; + +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; + +@RequestMapping("/controller") +public class SpringControllerService { + + @GetMapping("/sayHello") + public String sayHello(String say) { + return say; + } +} diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/reference/registryNA/consumer/DubboXmlConsumerTest.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/reference/registryNA/consumer/DubboXmlConsumerTest.java new file mode 100644 index 0000000000..af17e997cc --- /dev/null +++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/reference/registryNA/consumer/DubboXmlConsumerTest.java @@ -0,0 +1,36 @@ +/* + * 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.config.spring.reference.registryNA.consumer; + +import org.apache.dubbo.config.spring.api.HelloService; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.springframework.context.support.ClassPathXmlApplicationContext; + +class DubboXmlConsumerTest { + + + @Test + void testConsumer() { + ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:/org/apache/dubbo/config/spring/reference/registryNA/consumer/dubbo-registryNA-consumer.xml"); + context.start(); + HelloService helloService = context.getBean("helloService", HelloService.class); + IllegalStateException exception = Assertions.assertThrows(IllegalStateException.class, () -> helloService.sayHello("dubbo")); + Assertions.assertTrue(exception.getMessage().contains("No such any registry to reference org.apache.dubbo.config.spring.api.HelloService")); + } + +} diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/reference/registryNA/consumer/dubbo-consumer.xml b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/reference/registryNA/consumer/dubbo-consumer.xml new file mode 100644 index 0000000000..ca6485632a --- /dev/null +++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/reference/registryNA/consumer/dubbo-consumer.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/reference/registryNA/consumer/dubbo-registryNA-consumer.xml b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/reference/registryNA/consumer/dubbo-registryNA-consumer.xml new file mode 100644 index 0000000000..0bfc310ba4 --- /dev/null +++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/reference/registryNA/consumer/dubbo-registryNA-consumer.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/reference/registryNA/provider/DubboXmlProviderTest.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/reference/registryNA/provider/DubboXmlProviderTest.java new file mode 100644 index 0000000000..b45a649901 --- /dev/null +++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/reference/registryNA/provider/DubboXmlProviderTest.java @@ -0,0 +1,51 @@ +/* + * 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.config.spring.reference.registryNA.provider; + +import org.apache.dubbo.config.spring.api.HelloService; +import org.apache.dubbo.rpc.RpcException; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.springframework.context.support.ClassPathXmlApplicationContext; + +/** + * @author KamTo Hung + */ +public class DubboXmlProviderTest { + + @Test + void testProvider() { + ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:/org/apache/dubbo/config/spring/reference/registryNA/provider/dubbo-provider.xml"); + context.start(); + Object bean = context.getBean("helloService"); + Assertions.assertNotNull(bean); + } + + @Test + void testProvider2() { + ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:/org/apache/dubbo/config/spring/reference/registryNA/provider/dubbo-provider.xml"); + context.start(); + Assertions.assertNotNull(context.getBean("helloService")); + ClassPathXmlApplicationContext context2 = new ClassPathXmlApplicationContext("classpath:/org/apache/dubbo/config/spring/reference/registryNA/consumer/dubbo-consumer.xml"); + context2.start(); + HelloService helloService = context2.getBean("helloService", HelloService.class); + Assertions.assertNotNull(helloService); + RpcException exception = Assertions.assertThrows(RpcException.class, () -> helloService.sayHello("dubbo")); + Assertions.assertTrue(exception.getMessage().contains("Failed to invoke the method sayHello in the service org.apache.dubbo.config.spring.api.HelloService. No provider available for the service org.apache.dubbo.config.spring.api.HelloService")); + } + +} diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/reference/registryNA/provider/dubbo-provider.xml b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/reference/registryNA/provider/dubbo-provider.xml new file mode 100644 index 0000000000..09a71c3aca --- /dev/null +++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/reference/registryNA/provider/dubbo-provider.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/dubbo-configcenter/dubbo-configcenter-apollo/pom.xml b/dubbo-configcenter/dubbo-configcenter-apollo/pom.xml index bb56439b4c..fb39e096c2 100644 --- a/dubbo-configcenter/dubbo-configcenter-apollo/pom.xml +++ b/dubbo-configcenter/dubbo-configcenter-apollo/pom.xml @@ -63,5 +63,10 @@ ${apollo_mock_server_version} test + + org.apache.dubbo + dubbo-metrics-config-center + ${project.parent.version} + diff --git a/dubbo-configcenter/dubbo-configcenter-apollo/src/main/java/org/apache/dubbo/configcenter/support/apollo/ApolloDynamicConfiguration.java b/dubbo-configcenter/dubbo-configcenter-apollo/src/main/java/org/apache/dubbo/configcenter/support/apollo/ApolloDynamicConfiguration.java index 1b33e85781..75b6973f1f 100644 --- a/dubbo-configcenter/dubbo-configcenter-apollo/src/main/java/org/apache/dubbo/configcenter/support/apollo/ApolloDynamicConfiguration.java +++ b/dubbo-configcenter/dubbo-configcenter-apollo/src/main/java/org/apache/dubbo/configcenter/support/apollo/ApolloDynamicConfiguration.java @@ -16,15 +16,6 @@ */ package org.apache.dubbo.configcenter.support.apollo; -import org.apache.dubbo.common.URL; -import org.apache.dubbo.common.config.configcenter.ConfigChangeType; -import org.apache.dubbo.common.config.configcenter.ConfigChangedEvent; -import org.apache.dubbo.common.config.configcenter.ConfigurationListener; -import org.apache.dubbo.common.config.configcenter.DynamicConfiguration; -import org.apache.dubbo.common.logger.ErrorTypeAwareLogger; -import org.apache.dubbo.common.logger.LoggerFactory; -import org.apache.dubbo.common.utils.StringUtils; - import com.ctrip.framework.apollo.Config; import com.ctrip.framework.apollo.ConfigChangeListener; import com.ctrip.framework.apollo.ConfigFile; @@ -33,7 +24,16 @@ import com.ctrip.framework.apollo.core.enums.ConfigFileFormat; import com.ctrip.framework.apollo.enums.ConfigSourceType; import com.ctrip.framework.apollo.enums.PropertyChangeType; import com.ctrip.framework.apollo.model.ConfigChange; -import org.apache.dubbo.metrics.collector.ConfigCenterMetricsCollector; +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.config.configcenter.ConfigChangeType; +import org.apache.dubbo.common.config.configcenter.ConfigChangedEvent; +import org.apache.dubbo.common.config.configcenter.ConfigurationListener; +import org.apache.dubbo.common.config.configcenter.DynamicConfiguration; +import org.apache.dubbo.common.logger.ErrorTypeAwareLogger; +import org.apache.dubbo.common.logger.LoggerFactory; +import org.apache.dubbo.common.utils.StringUtils; +import org.apache.dubbo.metrics.config.event.ConfigCenterEvent; +import org.apache.dubbo.metrics.event.MetricsEventBus; import org.apache.dubbo.rpc.model.ApplicationModel; import java.util.Arrays; @@ -52,6 +52,7 @@ import static org.apache.dubbo.common.constants.CommonConstants.CONFIG_NAMESPACE import static org.apache.dubbo.common.constants.LoggerCodeConstants.CONFIG_FAILED_CLOSE_CONNECT_APOLLO; import static org.apache.dubbo.common.constants.LoggerCodeConstants.CONFIG_FAILED_CONNECT_REGISTRY; import static org.apache.dubbo.common.constants.LoggerCodeConstants.CONFIG_NOT_EFFECT_EMPTY_RULE_APOLLO; +import static org.apache.dubbo.metrics.MetricsConstants.SELF_INCREMENT_SIZE; /** * Apollo implementation, https://github.com/ctripcorp/apollo @@ -250,9 +251,8 @@ public class ApolloDynamicConfiguration implements DynamicConfiguration { ConfigChangedEvent event = new ConfigChangedEvent(key, change.getNamespace(), change.getNewValue(), getChangeType(change)); listeners.forEach(listener -> listener.process(event)); - ConfigCenterMetricsCollector collector = - applicationModel.getBeanFactory().getBean(ConfigCenterMetricsCollector.class); - collector.increaseUpdated("apollo", applicationModel.getApplicationName(), event); + MetricsEventBus.publish(ConfigCenterEvent.toChangeEvent(applicationModel, event.getKey(), event.getGroup(), + ConfigCenterEvent.APOLLO_PROTOCOL, ConfigChangeType.ADDED.name(), SELF_INCREMENT_SIZE)); } } diff --git a/dubbo-configcenter/dubbo-configcenter-nacos/pom.xml b/dubbo-configcenter/dubbo-configcenter-nacos/pom.xml index a6bc25f483..730c695b31 100644 --- a/dubbo-configcenter/dubbo-configcenter-nacos/pom.xml +++ b/dubbo-configcenter/dubbo-configcenter-nacos/pom.xml @@ -56,5 +56,10 @@ dubbo-metrics-prometheus ${project.parent.version} + + org.apache.dubbo + dubbo-metrics-config-center + ${project.parent.version} + diff --git a/dubbo-configcenter/dubbo-configcenter-nacos/src/main/java/org/apache/dubbo/configcenter/support/nacos/NacosDynamicConfiguration.java b/dubbo-configcenter/dubbo-configcenter-nacos/src/main/java/org/apache/dubbo/configcenter/support/nacos/NacosDynamicConfiguration.java index 9a8e42b2bb..7a851e45f0 100644 --- a/dubbo-configcenter/dubbo-configcenter-nacos/src/main/java/org/apache/dubbo/configcenter/support/nacos/NacosDynamicConfiguration.java +++ b/dubbo-configcenter/dubbo-configcenter-nacos/src/main/java/org/apache/dubbo/configcenter/support/nacos/NacosDynamicConfiguration.java @@ -17,14 +17,11 @@ package org.apache.dubbo.configcenter.support.nacos; -import java.util.Map; -import java.util.Properties; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; -import java.util.concurrent.CopyOnWriteArraySet; -import java.util.concurrent.Executor; - +import com.alibaba.nacos.api.NacosFactory; +import com.alibaba.nacos.api.PropertyKeyConst; +import com.alibaba.nacos.api.config.ConfigService; +import com.alibaba.nacos.api.config.listener.AbstractSharedListener; +import com.alibaba.nacos.api.exception.NacosException; import org.apache.dubbo.common.URL; import org.apache.dubbo.common.config.configcenter.ConfigChangeType; import org.apache.dubbo.common.config.configcenter.ConfigChangedEvent; @@ -37,15 +34,18 @@ import org.apache.dubbo.common.logger.LoggerFactory; import org.apache.dubbo.common.utils.ConcurrentHashMapUtils; import org.apache.dubbo.common.utils.MD5Utils; import org.apache.dubbo.common.utils.StringUtils; - -import com.alibaba.nacos.api.NacosFactory; -import com.alibaba.nacos.api.PropertyKeyConst; -import com.alibaba.nacos.api.config.ConfigService; -import com.alibaba.nacos.api.config.listener.AbstractSharedListener; -import com.alibaba.nacos.api.exception.NacosException; -import org.apache.dubbo.metrics.collector.ConfigCenterMetricsCollector; +import org.apache.dubbo.metrics.config.event.ConfigCenterEvent; +import org.apache.dubbo.metrics.event.MetricsEventBus; import org.apache.dubbo.rpc.model.ApplicationModel; +import java.util.Map; +import java.util.Properties; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.CopyOnWriteArraySet; +import java.util.concurrent.Executor; + import static com.alibaba.nacos.api.PropertyKeyConst.PASSWORD; import static com.alibaba.nacos.api.PropertyKeyConst.SERVER_ADDR; import static com.alibaba.nacos.api.PropertyKeyConst.USERNAME; @@ -55,6 +55,7 @@ import static org.apache.dubbo.common.constants.LoggerCodeConstants.INTERNAL_INT import static org.apache.dubbo.common.constants.RemotingConstants.BACKUP_KEY; import static org.apache.dubbo.common.utils.StringConstantFieldValuePredicate.of; import static org.apache.dubbo.common.utils.StringUtils.HYPHEN_CHAR; +import static org.apache.dubbo.metrics.MetricsConstants.SELF_INCREMENT_SIZE; /** * The nacos implementation of {@link DynamicConfiguration} @@ -345,9 +346,8 @@ public class NacosDynamicConfiguration implements DynamicConfiguration { } listeners.forEach(listener -> listener.process(event)); - ConfigCenterMetricsCollector collector = - applicationModel.getBeanFactory().getOrRegisterBean(ConfigCenterMetricsCollector.class); - collector.increaseUpdated("nacos", applicationModel.getApplicationName(), event); + MetricsEventBus.publish(ConfigCenterEvent.toChangeEvent(applicationModel, event.getKey(), event.getGroup(), + ConfigCenterEvent.NACOS_PROTOCOL, ConfigChangeType.ADDED.name(), SELF_INCREMENT_SIZE)); } void addListener(ConfigurationListener configurationListener) { diff --git a/dubbo-configcenter/dubbo-configcenter-zookeeper/pom.xml b/dubbo-configcenter/dubbo-configcenter-zookeeper/pom.xml index 825fbbb289..c4fbdb3ac6 100644 --- a/dubbo-configcenter/dubbo-configcenter-zookeeper/pom.xml +++ b/dubbo-configcenter/dubbo-configcenter-zookeeper/pom.xml @@ -75,6 +75,11 @@ dubbo-metrics-prometheus ${project.parent.version} + + org.apache.dubbo + dubbo-metrics-config-center + ${project.parent.version} + diff --git a/dubbo-configcenter/dubbo-configcenter-zookeeper/src/main/java/org/apache/dubbo/configcenter/support/zookeeper/ZookeeperDataListener.java b/dubbo-configcenter/dubbo-configcenter-zookeeper/src/main/java/org/apache/dubbo/configcenter/support/zookeeper/ZookeeperDataListener.java index a21babe2a2..df22f5de0f 100644 --- a/dubbo-configcenter/dubbo-configcenter-zookeeper/src/main/java/org/apache/dubbo/configcenter/support/zookeeper/ZookeeperDataListener.java +++ b/dubbo-configcenter/dubbo-configcenter-zookeeper/src/main/java/org/apache/dubbo/configcenter/support/zookeeper/ZookeeperDataListener.java @@ -20,7 +20,8 @@ import org.apache.dubbo.common.config.configcenter.ConfigChangeType; import org.apache.dubbo.common.config.configcenter.ConfigChangedEvent; import org.apache.dubbo.common.config.configcenter.ConfigurationListener; import org.apache.dubbo.common.utils.CollectionUtils; -import org.apache.dubbo.metrics.collector.ConfigCenterMetricsCollector; +import org.apache.dubbo.metrics.config.event.ConfigCenterEvent; +import org.apache.dubbo.metrics.event.MetricsEventBus; import org.apache.dubbo.remoting.zookeeper.DataListener; import org.apache.dubbo.remoting.zookeeper.EventType; import org.apache.dubbo.rpc.model.ApplicationModel; @@ -28,6 +29,8 @@ import org.apache.dubbo.rpc.model.ApplicationModel; import java.util.Set; import java.util.concurrent.CopyOnWriteArraySet; +import static org.apache.dubbo.metrics.MetricsConstants.SELF_INCREMENT_SIZE; + /** * one path has multi configurationListeners */ @@ -77,9 +80,8 @@ public class ZookeeperDataListener implements DataListener { listeners.forEach(listener -> listener.process(configChangeEvent)); } - ConfigCenterMetricsCollector collector = - applicationModel.getBeanFactory().getBean(ConfigCenterMetricsCollector.class); - collector.increaseUpdated("zookeeper", applicationModel.getApplicationName(), configChangeEvent); + MetricsEventBus.publish(ConfigCenterEvent.toChangeEvent(applicationModel, configChangeEvent.getKey(), configChangeEvent.getGroup(), + ConfigCenterEvent.ZK_PROTOCOL, ConfigChangeType.ADDED.name(), SELF_INCREMENT_SIZE)); } } diff --git a/dubbo-demo/dubbo-demo-annotation/pom.xml b/dubbo-demo/dubbo-demo-annotation/pom.xml index b84ceb28f7..fcdf966e93 100644 --- a/dubbo-demo/dubbo-demo-annotation/pom.xml +++ b/dubbo-demo/dubbo-demo-annotation/pom.xml @@ -30,7 +30,7 @@ true - 2.7.10 + 2.7.11 diff --git a/dubbo-demo/dubbo-demo-api/pom.xml b/dubbo-demo/dubbo-demo-api/pom.xml index c68afe43a4..05db3e38db 100644 --- a/dubbo-demo/dubbo-demo-api/pom.xml +++ b/dubbo-demo/dubbo-demo-api/pom.xml @@ -36,7 +36,7 @@ true - 2.7.10 + 2.7.11 dubbo-demo-api diff --git a/dubbo-demo/dubbo-demo-interface/pom.xml b/dubbo-demo/dubbo-demo-interface/pom.xml index 7cc0c57707..c906f1d1d2 100644 --- a/dubbo-demo/dubbo-demo-interface/pom.xml +++ b/dubbo-demo/dubbo-demo-interface/pom.xml @@ -36,18 +36,17 @@ dubbo-rpc-rest - - - org.springframework - spring-web - test - - org.springframework spring-context test + + + org.springframework + spring-web + + diff --git a/dubbo-demo/dubbo-demo-interface/src/main/java/org/apache/dubbo/demo/rest/api/CurlService.java b/dubbo-demo/dubbo-demo-interface/src/main/java/org/apache/dubbo/demo/rest/api/CurlService.java new file mode 100644 index 0000000000..09a202ab58 --- /dev/null +++ b/dubbo-demo/dubbo-demo-interface/src/main/java/org/apache/dubbo/demo/rest/api/CurlService.java @@ -0,0 +1,34 @@ +/* + * 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.demo.rest.api; + + + +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.Path; + +@Path("/curl") +public interface CurlService { + // curl -X GET http://localhost:8888/services/curl + // http://localhost:8888/services/curl + @GET + @Consumes({javax.ws.rs.core.MediaType.TEXT_PLAIN}) + String curl(); + +} + diff --git a/dubbo-demo/dubbo-demo-interface/src/main/java/org/apache/dubbo/demo/rest/api/DubboServiceAnnotationService.java b/dubbo-demo/dubbo-demo-interface/src/main/java/org/apache/dubbo/demo/rest/api/DubboServiceAnnotationService.java new file mode 100644 index 0000000000..0ef70bf293 --- /dev/null +++ b/dubbo-demo/dubbo-demo-interface/src/main/java/org/apache/dubbo/demo/rest/api/DubboServiceAnnotationService.java @@ -0,0 +1,32 @@ +/* + * 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.demo.rest.api; + + + +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.Path; + +@Path("/annotation") +public interface DubboServiceAnnotationService { + @GET + @Consumes({javax.ws.rs.core.MediaType.TEXT_PLAIN}) + String annotation(); + +} + diff --git a/dubbo-demo/dubbo-demo-interface/src/main/java/org/apache/dubbo/demo/rest/api/ExceptionMapperService.java b/dubbo-demo/dubbo-demo-interface/src/main/java/org/apache/dubbo/demo/rest/api/ExceptionMapperService.java new file mode 100644 index 0000000000..313159be0a --- /dev/null +++ b/dubbo-demo/dubbo-demo-interface/src/main/java/org/apache/dubbo/demo/rest/api/ExceptionMapperService.java @@ -0,0 +1,31 @@ +/* + * 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.demo.rest.api; + + + +import javax.ws.rs.POST; +import javax.ws.rs.Path; + +@Path("/exception/mapper") +public interface ExceptionMapperService { + + @POST + @Path("/exception") + String exception(String message); + +} diff --git a/dubbo-demo/dubbo-demo-interface/src/main/java/org/apache/dubbo/demo/rest/api/HttpMethodService.java b/dubbo-demo/dubbo-demo-interface/src/main/java/org/apache/dubbo/demo/rest/api/HttpMethodService.java new file mode 100644 index 0000000000..ebbc1b10f3 --- /dev/null +++ b/dubbo-demo/dubbo-demo-interface/src/main/java/org/apache/dubbo/demo/rest/api/HttpMethodService.java @@ -0,0 +1,71 @@ +/* + * 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.demo.rest.api; + + +import io.swagger.jaxrs.PATCH; + +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.HEAD; +import javax.ws.rs.OPTIONS; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.QueryParam; + +@Path("/demoService") +public interface HttpMethodService { + + @POST + @Path("/sayPost") + @Consumes({javax.ws.rs.core.MediaType.TEXT_PLAIN}) + String sayHelloPost(String hello); + + @DELETE + @Path("/sayDelete") + @Consumes({javax.ws.rs.core.MediaType.TEXT_PLAIN}) + String sayHelloDelete(@QueryParam("name") String hello); + + @HEAD + @Path("/sayHead") + @Consumes({javax.ws.rs.core.MediaType.TEXT_PLAIN}) + String sayHelloHead(@QueryParam("name") String hello); + + @GET + @Path("/sayGet") + @Consumes({javax.ws.rs.core.MediaType.TEXT_PLAIN}) + String sayHelloGet(@QueryParam("name") String hello); + + @PUT + @Path("/sayPut") + @Consumes({javax.ws.rs.core.MediaType.TEXT_PLAIN}) + String sayHelloPut(@QueryParam("name") String hello); + + @PATCH + @Path("/sayPatch") + @Consumes({javax.ws.rs.core.MediaType.TEXT_PLAIN}) + String sayHelloPatch(@QueryParam("name") String hello); + + @OPTIONS + @Path("/sayOptions") + @Consumes({javax.ws.rs.core.MediaType.TEXT_PLAIN}) + String sayHelloOptions(@QueryParam("name") String hello); + +} + diff --git a/dubbo-demo/dubbo-demo-interface/src/main/java/org/apache/dubbo/demo/rest/api/HttpRequestAndResponseRPCContextService.java b/dubbo-demo/dubbo-demo-interface/src/main/java/org/apache/dubbo/demo/rest/api/HttpRequestAndResponseRPCContextService.java new file mode 100644 index 0000000000..e1df730e20 --- /dev/null +++ b/dubbo-demo/dubbo-demo-interface/src/main/java/org/apache/dubbo/demo/rest/api/HttpRequestAndResponseRPCContextService.java @@ -0,0 +1,47 @@ +/* + * 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.demo.rest.api; + + +import javax.ws.rs.Consumes; +import javax.ws.rs.HeaderParam; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.QueryParam; +import java.util.List; + +@Path("/demoService") +public interface HttpRequestAndResponseRPCContextService { + + @POST + @Path("/httpRequestParam") + @Consumes({javax.ws.rs.core.MediaType.TEXT_PLAIN}) + String httpRequestParam(@QueryParam("name") String hello); + + @POST + @Path("/httpRequestHeader") + @Consumes({javax.ws.rs.core.MediaType.TEXT_PLAIN}) + String httpRequestHeader(@HeaderParam("header") String hello); + + @POST + @Path("/httpResponseHeader") + @Consumes({javax.ws.rs.core.MediaType.TEXT_PLAIN}) + List httpResponseHeader(@HeaderParam("response") String hello); + + +} + diff --git a/dubbo-demo/dubbo-demo-interface/src/main/java/org/apache/dubbo/demo/rest/api/JaxRsRestDemoService.java b/dubbo-demo/dubbo-demo-interface/src/main/java/org/apache/dubbo/demo/rest/api/JaxRsRestDemoService.java new file mode 100644 index 0000000000..198304a5b6 --- /dev/null +++ b/dubbo-demo/dubbo-demo-interface/src/main/java/org/apache/dubbo/demo/rest/api/JaxRsRestDemoService.java @@ -0,0 +1,120 @@ +/* + * 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.demo.rest.api; + + +import po.User; + +import javax.ws.rs.Consumes; +import javax.ws.rs.FormParam; +import javax.ws.rs.GET; +import javax.ws.rs.HeaderParam; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.MultivaluedMap; +import java.util.List; +import java.util.Map; + +/** + * + * @Consumers & @Produces can be not used ,we will make sure the content-type of request by arg type + * but the Request method is forbidden disappear + * parameters which annotation are not present , it is from the body (jaxrs anntation is diffrent from spring web from param(only request param can ignore anntation)) + * + * Every method only one param from body + * + * the path annotation must present in class & method + */ + +@Path("/jaxrs/demo/service") +public interface JaxRsRestDemoService { + @GET + @Path("/hello") + Integer hello(@QueryParam("a") Integer a, @QueryParam("b") Integer b); + + @GET + @Path("/error") + String error(); + + @POST + @Path("/say") + String sayHello(String name); + + + + + + @POST + @Path("/testFormBody") + Long testFormBody(@FormParam("number") Long number); + + @POST + @Path("/testJavaBeanBody") + @Consumes({MediaType.APPLICATION_JSON}) + User testJavaBeanBody(User user); + + + + @GET + @Path("/primitive") + int primitiveInt(@QueryParam("a") int a, @QueryParam("b") int b); + + @GET + @Path("/primitiveLong") + long primitiveLong(@QueryParam("a") long a, @QueryParam("b") Long b); + + @GET + @Path("/primitiveByte") + long primitiveByte(@QueryParam("a") byte a, @QueryParam("b") Long b); + + @POST + @Path("/primitiveShort") + long primitiveShort(@QueryParam("a") short a, @QueryParam("b") Long b, int c); + + @GET + @Path("testMapParam") + @Produces({MediaType.TEXT_PLAIN}) + @Consumes({MediaType.TEXT_PLAIN}) + String testMapParam(@QueryParam("test") Map params); + + @GET + @Path("testMapHeader") + @Produces({MediaType.TEXT_PLAIN}) + @Consumes({MediaType.TEXT_PLAIN}) + String testMapHeader(@HeaderParam("test") Map headers); + + @POST + @Path("testMapForm") + @Produces({MediaType.APPLICATION_JSON}) + @Consumes({MediaType.APPLICATION_FORM_URLENCODED}) + List testMapForm(MultivaluedMap params); + + @POST + @Path("/header") + @Consumes({MediaType.TEXT_PLAIN}) + String header(@HeaderParam("header") String header); + + @POST + @Path("/headerInt") + @Consumes({MediaType.TEXT_PLAIN}) + int headerInt(@HeaderParam("header") int header); + + +} diff --git a/dubbo-demo/dubbo-demo-interface/src/main/java/org/apache/dubbo/demo/rest/api/SpringRestDemoService.java b/dubbo-demo/dubbo-demo-interface/src/main/java/org/apache/dubbo/demo/rest/api/SpringRestDemoService.java new file mode 100644 index 0000000000..d5da64403e --- /dev/null +++ b/dubbo-demo/dubbo-demo-interface/src/main/java/org/apache/dubbo/demo/rest/api/SpringRestDemoService.java @@ -0,0 +1,79 @@ +/* + * 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.demo.rest.api; + + +import org.springframework.http.MediaType; +import org.springframework.util.MultiValueMap; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import po.User; + +import java.util.List; +import java.util.Map; + +@RequestMapping("/spring/demo/service") +public interface SpringRestDemoService { + + @RequestMapping(method = RequestMethod.GET, value = "/hello") + Integer hello(@RequestParam("a") Integer a, @RequestParam("b") Integer b); + + @RequestMapping(method = RequestMethod.GET, value = "/error") + String error(); + + @RequestMapping(method = RequestMethod.POST, value = "/say") + String sayHello(@RequestBody String name); + + @RequestMapping(method = RequestMethod.POST, value = "/testFormBody", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE) + Long testFormBody(@RequestBody Long number); + + @RequestMapping(method = RequestMethod.POST, value = "/testJavaBeanBody", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE) + User testJavaBeanBody(@RequestBody User user); + + + @RequestMapping(method = RequestMethod.GET, value = "/primitive") + int primitiveInt(@RequestParam("a") int a, @RequestParam("b") int b); + + @RequestMapping(method = RequestMethod.GET, value = "/primitiveLong") + long primitiveLong(@RequestParam("a") long a, @RequestParam("b") Long b); + + @RequestMapping(method = RequestMethod.GET, value = "/primitiveByte") + long primitiveByte(@RequestParam("a") byte a, @RequestParam("b") Long b); + + + @RequestMapping(method = RequestMethod.POST, value = "/primitiveShort") + long primitiveShort(@RequestParam("a") short a, @RequestParam("b") Long b, @RequestBody int c); + + + @RequestMapping(method = RequestMethod.GET, value = "/testMapParam") + String testMapParam(@RequestParam Map params); + + @RequestMapping(method = RequestMethod.GET, value = "/testMapHeader") + String testMapHeader(@RequestHeader Map headers); + + @RequestMapping(method = RequestMethod.POST, value = "/testMapForm", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE) + List testMapForm(MultiValueMap params); + + + @RequestMapping(method = RequestMethod.GET, value = "/headerInt") + int headerInt(@RequestHeader("header") int header); + + +} diff --git a/dubbo-demo/dubbo-demo-interface/src/main/java/po/User.java b/dubbo-demo/dubbo-demo-interface/src/main/java/po/User.java new file mode 100644 index 0000000000..2c58d9d3f2 --- /dev/null +++ b/dubbo-demo/dubbo-demo-interface/src/main/java/po/User.java @@ -0,0 +1,78 @@ +/* + * 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 po; + +import java.io.Serializable; +import java.util.Objects; + + +public class User implements Serializable { + + + private Long id; + + private String name; + + public User() { + } + + public User(Long id, String name) { + this.id = id; + this.name = name; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public static User getInstance() { + return new User(1l, "dubbo-rest"); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + User user = (User) o; + return Objects.equals(id, user.id) && Objects.equals(name, user.name); + } + + @Override + public int hashCode() { + return Objects.hash(id, name); + } + + @Override + public String toString() { + return "User (" + + "id=" + id + + ", name='" + name + '\'' + + ')'; + } +} diff --git a/dubbo-demo/dubbo-demo-native/dubbo-demo-native-consumer/pom.xml b/dubbo-demo/dubbo-demo-native/dubbo-demo-native-consumer/pom.xml index 9d8c06ba24..72fa5fe3b4 100644 --- a/dubbo-demo/dubbo-demo-native/dubbo-demo-native-consumer/pom.xml +++ b/dubbo-demo/dubbo-demo-native/dubbo-demo-native-consumer/pom.xml @@ -133,7 +133,7 @@ org.graalvm.buildtools native-maven-plugin - 0.9.20 + 0.9.21 ${project.build.outputDirectory} diff --git a/dubbo-demo/dubbo-demo-native/dubbo-demo-native-provider/pom.xml b/dubbo-demo/dubbo-demo-native/dubbo-demo-native-provider/pom.xml index 0e03083dbf..6430631523 100644 --- a/dubbo-demo/dubbo-demo-native/dubbo-demo-native-provider/pom.xml +++ b/dubbo-demo/dubbo-demo-native/dubbo-demo-native-provider/pom.xml @@ -130,7 +130,7 @@ org.graalvm.buildtools native-maven-plugin - 0.9.20 + 0.9.21 ${project.build.outputDirectory} diff --git a/dubbo-demo/dubbo-demo-spring-boot/dubbo-demo-spring-boot-consumer/pom.xml b/dubbo-demo/dubbo-demo-spring-boot/dubbo-demo-spring-boot-consumer/pom.xml index 36a26644aa..89b23d6ade 100644 --- a/dubbo-demo/dubbo-demo-spring-boot/dubbo-demo-spring-boot-consumer/pom.xml +++ b/dubbo-demo/dubbo-demo-spring-boot/dubbo-demo-spring-boot-consumer/pom.xml @@ -31,7 +31,7 @@ 8 8 1.7.33 - 2.7.10 + 2.7.11 true @@ -125,7 +125,7 @@ org.apache.dubbo - dubbo-spring-boot-observability-starter + dubbo-spring-boot-tracing-otel-zipkin-starter diff --git a/dubbo-demo/dubbo-demo-spring-boot/dubbo-demo-spring-boot-provider/pom.xml b/dubbo-demo/dubbo-demo-spring-boot/dubbo-demo-spring-boot-provider/pom.xml index 6df0e80c2a..083a27bcd5 100644 --- a/dubbo-demo/dubbo-demo-spring-boot/dubbo-demo-spring-boot-provider/pom.xml +++ b/dubbo-demo/dubbo-demo-spring-boot/dubbo-demo-spring-boot-provider/pom.xml @@ -31,7 +31,7 @@ 8 8 1.7.33 - 2.7.10 + 2.7.11 true @@ -120,7 +120,7 @@ org.apache.dubbo - dubbo-spring-boot-observability-starter + dubbo-spring-boot-tracing-otel-zipkin-starter diff --git a/dubbo-demo/dubbo-demo-spring-boot/pom.xml b/dubbo-demo/dubbo-demo-spring-boot/pom.xml index 69e1e07ed6..610ff36643 100644 --- a/dubbo-demo/dubbo-demo-spring-boot/pom.xml +++ b/dubbo-demo/dubbo-demo-spring-boot/pom.xml @@ -36,8 +36,8 @@ 8 8 true - 2.7.10 - 2.7.10 + 2.7.11 + 2.7.11 1.10.6 diff --git a/dubbo-demo/dubbo-demo-triple/pom.xml b/dubbo-demo/dubbo-demo-triple/pom.xml index e336afc1a4..760e7db95d 100644 --- a/dubbo-demo/dubbo-demo-triple/pom.xml +++ b/dubbo-demo/dubbo-demo-triple/pom.xml @@ -34,7 +34,6 @@ true 1.8 1.8 - 3.22.2 3.11.0 @@ -115,7 +114,6 @@ com.google.protobuf protobuf-java - ${protobuf-java.version} @@ -124,7 +122,7 @@ kr.motd.maven os-maven-plugin - 1.7.1 + ${maven_os_plugin_version} initialize @@ -137,9 +135,9 @@ org.xolstice.maven.plugins protobuf-maven-plugin - 0.6.1 + ${maven_protobuf_plugin_version} - com.google.protobuf:protoc:${protobuf-java.version}:exe:${os.detected.classifier} + com.google.protobuf:protoc:${protobuf-java_version}:exe:${os.detected.classifier} triple-java build/generated/source/proto/main/java diff --git a/dubbo-demo/dubbo-demo-xml/dubbo-demo-jaxrs-rest-consumer/pom.xml b/dubbo-demo/dubbo-demo-xml/dubbo-demo-jaxrs-rest-consumer/pom.xml new file mode 100644 index 0000000000..78fc871305 --- /dev/null +++ b/dubbo-demo/dubbo-demo-xml/dubbo-demo-jaxrs-rest-consumer/pom.xml @@ -0,0 +1,153 @@ + + + + 4.0.0 + + org.apache.dubbo + dubbo-demo-xml + ${revision} + ../pom.xml + + + dubbo-demo-jaxrs-rest-consumer + + jar + Dubbo JAXRS Rest Consumer Demo + ${project.artifactId} + + + true + 1.7.33 + + + + org.springframework + spring-context + + + org.springframework + spring-web + + + + org.apache.dubbo + dubbo-registry-multicast + + + org.apache.dubbo + dubbo-registry-zookeeper + + + org.apache.dubbo + dubbo-registry-nacos + + + com.alibaba.nacos + nacos-client + + + org.apache.dubbo + dubbo-configcenter-zookeeper + + + org.apache.dubbo + dubbo-configcenter-nacos + + + org.apache.dubbo + dubbo-metadata-report-zookeeper + + + org.apache.dubbo + dubbo-metadata-report-nacos + + + org.apache.dubbo + dubbo-rpc-dubbo + + + org.apache.dubbo + dubbo-rpc-rest + + + org.apache.dubbo + dubbo-config-spring + + + org.apache.dubbo + dubbo-remoting-netty4 + + + org.apache.dubbo + dubbo-serialization-hessian2 + + + org.apache.dubbo + dubbo-serialization-fastjson2 + + + org.apache.dubbo + dubbo-serialization-jdk + + + org.slf4j + slf4j-api + + + org.slf4j + slf4j-log4j12 + ${slf4j-log4j12.version} + + + log4j + log4j + + + + org.springframework + spring-test + test + + + + org.apache.dubbo + dubbo-demo-interface + ${project.version} + + + + + + + javax.annotation + + [1.11,) + + + + javax.annotation + javax.annotation-api + 1.3.2 + + + + + + diff --git a/dubbo-demo/dubbo-demo-xml/dubbo-demo-jaxrs-rest-consumer/src/main/java/org/apache/dubbo/demo/rest/api/RestConsumer.java b/dubbo-demo/dubbo-demo-xml/dubbo-demo-jaxrs-rest-consumer/src/main/java/org/apache/dubbo/demo/rest/api/RestConsumer.java new file mode 100644 index 0000000000..1977f19efa --- /dev/null +++ b/dubbo-demo/dubbo-demo-xml/dubbo-demo-jaxrs-rest-consumer/src/main/java/org/apache/dubbo/demo/rest/api/RestConsumer.java @@ -0,0 +1,114 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.dubbo.demo.rest.api; + +import org.apache.dubbo.demo.rest.api.annotation.DubboServiceAnnotationServiceConsumer; +import org.jboss.resteasy.specimpl.MultivaluedMapImpl; +import org.springframework.context.support.ClassPathXmlApplicationContext; +import po.User; + +import java.util.Arrays; + +public class RestConsumer { + + public static void main(String[] args) { + consumerService(); + } + + public static void consumerService() { + ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"spring/rest-consumer.xml"}); + context.start(); + System.out.println("rest consumer start"); + testExceptionMapperService(context); + testHttpMethodService(context); + httpRPCContextTest(context); + jaxRsRestDemoServiceTest(context); + annotationTest(context); + System.out.println("rest consumer test success"); + } + + private static void annotationTest(ClassPathXmlApplicationContext context) { + DubboServiceAnnotationServiceConsumer bean = context.getBean(DubboServiceAnnotationServiceConsumer.class); + bean.invokeAnnotationService(); + } + + private static void jaxRsRestDemoServiceTest(ClassPathXmlApplicationContext context) { + JaxRsRestDemoService jaxRsRestDemoService = context.getBean("jaxRsRestDemoService", JaxRsRestDemoService.class); + String hello = jaxRsRestDemoService.sayHello("hello"); + assertEquals("Hello, hello", hello); + Integer result = jaxRsRestDemoService.primitiveInt(1, 2); + Long resultLong = jaxRsRestDemoService.primitiveLong(1, 2l); + long resultByte = jaxRsRestDemoService.primitiveByte((byte) 1, 2l); + long resultShort = jaxRsRestDemoService.primitiveShort((short) 1, 2l, 1); + + assertEquals(result, 3); + assertEquals(resultShort, 3l); + assertEquals(resultLong, 3l); + assertEquals(resultByte, 3l); + + assertEquals(Long.valueOf(1l), jaxRsRestDemoService.testFormBody(1l)); + + MultivaluedMapImpl forms = new MultivaluedMapImpl<>(); + forms.put("form", Arrays.asList("F1")); + + assertEquals(Arrays.asList("F1"), jaxRsRestDemoService.testMapForm(forms)); + assertEquals(User.getInstance(), jaxRsRestDemoService.testJavaBeanBody(User.getInstance())); + } + + + private static void testExceptionMapperService(ClassPathXmlApplicationContext context) { + String returnStr = "exception"; + String paramStr = "exception"; + ExceptionMapperService exceptionMapperService = context.getBean("exceptionMapperService", ExceptionMapperService.class); + assertEquals(returnStr, exceptionMapperService.exception(paramStr)); + } + + private static void httpRPCContextTest(ClassPathXmlApplicationContext context) { + + HttpRequestAndResponseRPCContextService requestAndResponseRPCContextService = context.getBean("httpRequestAndResponseRPCContextService", HttpRequestAndResponseRPCContextService.class); + String returnStr = "hello"; + String paramStr = "hello"; + assertEquals(returnStr, requestAndResponseRPCContextService.httpRequestHeader(paramStr)); + assertEquals(returnStr, requestAndResponseRPCContextService.httpRequestParam(paramStr)); + assertEquals(returnStr, requestAndResponseRPCContextService.httpResponseHeader(paramStr).get(0)); + } + + + private static void testHttpMethodService(ClassPathXmlApplicationContext context) { + HttpMethodService httpMethodService = context.getBean("httpMethodService", HttpMethodService.class); + String returnStr = "hello"; + String paramStr = "hello"; +// assertEquals(null, httpMethodService.sayHelloHead(paramStr)); + assertEquals(returnStr, httpMethodService.sayHelloGet(paramStr)); + assertEquals(returnStr, httpMethodService.sayHelloDelete(paramStr)); + assertEquals(returnStr, httpMethodService.sayHelloPut(paramStr)); + assertEquals(returnStr, httpMethodService.sayHelloOptions(paramStr)); +// Assert.assertEquals(returnStr, httpMethodService.sayHelloPatch(paramStr)); + assertEquals(returnStr, httpMethodService.sayHelloPost(paramStr)); + } + + private static void assertEquals(Object returnStr, Object exception) { + boolean equal = returnStr != null && returnStr.equals(exception); + + if (equal) { + return; + } else { + throw new RuntimeException(); + } + } + +} diff --git a/dubbo-demo/dubbo-demo-xml/dubbo-demo-jaxrs-rest-consumer/src/main/java/org/apache/dubbo/demo/rest/api/annotation/DubboServiceAnnotationServiceConsumer.java b/dubbo-demo/dubbo-demo-xml/dubbo-demo-jaxrs-rest-consumer/src/main/java/org/apache/dubbo/demo/rest/api/annotation/DubboServiceAnnotationServiceConsumer.java new file mode 100644 index 0000000000..bda5281231 --- /dev/null +++ b/dubbo-demo/dubbo-demo-xml/dubbo-demo-jaxrs-rest-consumer/src/main/java/org/apache/dubbo/demo/rest/api/annotation/DubboServiceAnnotationServiceConsumer.java @@ -0,0 +1,33 @@ +/* + * 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.demo.rest.api.annotation; + +import org.apache.dubbo.config.annotation.DubboReference; +import org.apache.dubbo.demo.rest.api.DubboServiceAnnotationService; +import org.springframework.stereotype.Component; + +@Component +public class DubboServiceAnnotationServiceConsumer { + + @DubboReference(interfaceClass = DubboServiceAnnotationService.class) + DubboServiceAnnotationService dubboServiceAnnotationService; + + public void invokeAnnotationService() { + String annotation = dubboServiceAnnotationService.annotation(); + System.out.println(annotation); + } +} diff --git a/dubbo-demo/dubbo-demo-xml/dubbo-demo-jaxrs-rest-consumer/src/main/java/org/apache/dubbo/demo/rest/api/config/DubboConfig.java b/dubbo-demo/dubbo-demo-xml/dubbo-demo-jaxrs-rest-consumer/src/main/java/org/apache/dubbo/demo/rest/api/config/DubboConfig.java new file mode 100644 index 0000000000..a5d0edfacf --- /dev/null +++ b/dubbo-demo/dubbo-demo-xml/dubbo-demo-jaxrs-rest-consumer/src/main/java/org/apache/dubbo/demo/rest/api/config/DubboConfig.java @@ -0,0 +1,23 @@ +/* + * 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.demo.rest.api.config; + +import org.apache.dubbo.config.spring.context.annotation.DubboComponentScan; + +@DubboComponentScan("org.apache.dubbo.demo.rest") +public class DubboConfig { +} diff --git a/dubbo-demo/dubbo-demo-xml/dubbo-demo-jaxrs-rest-consumer/src/main/resources/spring/rest-consumer.xml b/dubbo-demo/dubbo-demo-xml/dubbo-demo-jaxrs-rest-consumer/src/main/resources/spring/rest-consumer.xml new file mode 100644 index 0000000000..ea6a63b04f --- /dev/null +++ b/dubbo-demo/dubbo-demo-xml/dubbo-demo-jaxrs-rest-consumer/src/main/resources/spring/rest-consumer.xml @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dubbo-demo/dubbo-demo-xml/dubbo-demo-jaxrs-rest-provider/pom.xml b/dubbo-demo/dubbo-demo-xml/dubbo-demo-jaxrs-rest-provider/pom.xml new file mode 100644 index 0000000000..9989d45b7a --- /dev/null +++ b/dubbo-demo/dubbo-demo-xml/dubbo-demo-jaxrs-rest-provider/pom.xml @@ -0,0 +1,153 @@ + + + + 4.0.0 + + org.apache.dubbo + dubbo-demo-xml + ${revision} + ../pom.xml + + + dubbo-demo-jaxrs-rest-provider + + jar + Dubbo JAXRS Rest Provider Demo + ${project.artifactId} + + + true + 1.7.33 + + + + org.springframework + spring-context + + + org.springframework + spring-web + + + + org.apache.dubbo + dubbo-registry-multicast + + + org.apache.dubbo + dubbo-registry-zookeeper + + + org.apache.dubbo + dubbo-registry-nacos + + + com.alibaba.nacos + nacos-client + + + org.apache.dubbo + dubbo-configcenter-zookeeper + + + org.apache.dubbo + dubbo-configcenter-nacos + + + org.apache.dubbo + dubbo-metadata-report-zookeeper + + + org.apache.dubbo + dubbo-metadata-report-nacos + + + org.apache.dubbo + dubbo-rpc-dubbo + + + org.apache.dubbo + dubbo-rpc-rest + + + org.apache.dubbo + dubbo-config-spring + + + org.apache.dubbo + dubbo-remoting-netty4 + + + org.apache.dubbo + dubbo-serialization-hessian2 + + + org.apache.dubbo + dubbo-serialization-fastjson2 + + + org.apache.dubbo + dubbo-serialization-jdk + + + org.slf4j + slf4j-api + + + org.slf4j + slf4j-log4j12 + ${slf4j-log4j12.version} + + + log4j + log4j + + + + org.springframework + spring-test + test + + + + org.apache.dubbo + dubbo-demo-interface + ${project.version} + + + + + + + javax.annotation + + [1.11,) + + + + javax.annotation + javax.annotation-api + 1.3.2 + + + + + + diff --git a/dubbo-demo/dubbo-demo-xml/dubbo-demo-jaxrs-rest-provider/src/main/java/org/apache/dubbo/demo/rest/api/RestProvider.java b/dubbo-demo/dubbo-demo-xml/dubbo-demo-jaxrs-rest-provider/src/main/java/org/apache/dubbo/demo/rest/api/RestProvider.java new file mode 100644 index 0000000000..ebc2ccfe73 --- /dev/null +++ b/dubbo-demo/dubbo-demo-xml/dubbo-demo-jaxrs-rest-provider/src/main/java/org/apache/dubbo/demo/rest/api/RestProvider.java @@ -0,0 +1,43 @@ +/* + * 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.demo.rest.api; + +import org.springframework.context.support.ClassPathXmlApplicationContext; + + +public class RestProvider { + + public static void main(String[] args) throws Exception { + ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"spring/rest-provider.xml"}); + + context.refresh(); + +// SpringControllerService springControllerService = context.getBean(SpringControllerService.class); +// ServiceConfig serviceConfig = new ServiceConfig<>(); +// serviceConfig.setInterface(SpringControllerService.class); +// serviceConfig.setProtocol(new ProtocolConfig("rest", 8888)); +// serviceConfig.setRef(springControllerService); +// serviceConfig.export(); + + + System.out.println("dubbo service started"); + + System.in.read(); + } + + +} diff --git a/dubbo-demo/dubbo-demo-xml/dubbo-demo-jaxrs-rest-provider/src/main/java/org/apache/dubbo/demo/rest/api/config/DubboConfig.java b/dubbo-demo/dubbo-demo-xml/dubbo-demo-jaxrs-rest-provider/src/main/java/org/apache/dubbo/demo/rest/api/config/DubboConfig.java new file mode 100644 index 0000000000..a5d0edfacf --- /dev/null +++ b/dubbo-demo/dubbo-demo-xml/dubbo-demo-jaxrs-rest-provider/src/main/java/org/apache/dubbo/demo/rest/api/config/DubboConfig.java @@ -0,0 +1,23 @@ +/* + * 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.demo.rest.api.config; + +import org.apache.dubbo.config.spring.context.annotation.DubboComponentScan; + +@DubboComponentScan("org.apache.dubbo.demo.rest") +public class DubboConfig { +} diff --git a/dubbo-demo/dubbo-demo-xml/dubbo-demo-jaxrs-rest-provider/src/main/java/org/apache/dubbo/demo/rest/api/extension/ExceptionMapperForTest.java b/dubbo-demo/dubbo-demo-xml/dubbo-demo-jaxrs-rest-provider/src/main/java/org/apache/dubbo/demo/rest/api/extension/ExceptionMapperForTest.java new file mode 100644 index 0000000000..49099a606a --- /dev/null +++ b/dubbo-demo/dubbo-demo-xml/dubbo-demo-jaxrs-rest-provider/src/main/java/org/apache/dubbo/demo/rest/api/extension/ExceptionMapperForTest.java @@ -0,0 +1,29 @@ +/* + * 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.demo.rest.api.extension; + + +import org.apache.dubbo.rpc.protocol.rest.exception.mapper.ExceptionHandler; + +public class ExceptionMapperForTest implements ExceptionHandler { + + + @Override + public Object result(RuntimeException exception) { + return exception.getMessage(); + } +} diff --git a/dubbo-demo/dubbo-demo-xml/dubbo-demo-jaxrs-rest-provider/src/main/java/org/apache/dubbo/demo/rest/api/impl/CurlServiceImpl.java b/dubbo-demo/dubbo-demo-xml/dubbo-demo-jaxrs-rest-provider/src/main/java/org/apache/dubbo/demo/rest/api/impl/CurlServiceImpl.java new file mode 100644 index 0000000000..64dacac29f --- /dev/null +++ b/dubbo-demo/dubbo-demo-xml/dubbo-demo-jaxrs-rest-provider/src/main/java/org/apache/dubbo/demo/rest/api/impl/CurlServiceImpl.java @@ -0,0 +1,31 @@ +/* + * 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.demo.rest.api.impl; + +import org.apache.dubbo.config.annotation.DubboService; +import org.apache.dubbo.demo.rest.api.CurlService; + +@DubboService( interfaceClass = CurlService.class,protocol = "rest") +public class CurlServiceImpl implements CurlService { + + + + @Override + public String curl() { + return "hello,dubbo rest curl request"; + } +} diff --git a/dubbo-demo/dubbo-demo-xml/dubbo-demo-jaxrs-rest-provider/src/main/java/org/apache/dubbo/demo/rest/api/impl/DubboServiceAnnotationServiceImpl.java b/dubbo-demo/dubbo-demo-xml/dubbo-demo-jaxrs-rest-provider/src/main/java/org/apache/dubbo/demo/rest/api/impl/DubboServiceAnnotationServiceImpl.java new file mode 100644 index 0000000000..823af088f7 --- /dev/null +++ b/dubbo-demo/dubbo-demo-xml/dubbo-demo-jaxrs-rest-provider/src/main/java/org/apache/dubbo/demo/rest/api/impl/DubboServiceAnnotationServiceImpl.java @@ -0,0 +1,28 @@ +/* + * 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.demo.rest.api.impl; + +import org.apache.dubbo.config.annotation.DubboService; +import org.apache.dubbo.demo.rest.api.DubboServiceAnnotationService; + +@DubboService(protocol = "rest") +public class DubboServiceAnnotationServiceImpl implements DubboServiceAnnotationService { + @Override + public String annotation() { + return "Dubbo Service Annotation service demo!"; + } +} diff --git a/dubbo-demo/dubbo-demo-xml/dubbo-demo-jaxrs-rest-provider/src/main/java/org/apache/dubbo/demo/rest/api/impl/ExceptionMapperServiceImpl.java b/dubbo-demo/dubbo-demo-xml/dubbo-demo-jaxrs-rest-provider/src/main/java/org/apache/dubbo/demo/rest/api/impl/ExceptionMapperServiceImpl.java new file mode 100644 index 0000000000..26a69ff7fb --- /dev/null +++ b/dubbo-demo/dubbo-demo-xml/dubbo-demo-jaxrs-rest-provider/src/main/java/org/apache/dubbo/demo/rest/api/impl/ExceptionMapperServiceImpl.java @@ -0,0 +1,32 @@ +/* + * 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.demo.rest.api.impl; + + +import org.apache.dubbo.demo.rest.api.ExceptionMapperService; +import org.springframework.stereotype.Service; + +@Service("exceptionMapperService") +public class ExceptionMapperServiceImpl implements ExceptionMapperService { + + @Override + public String exception(String message) { + + throw new RuntimeException(message); + } + +} diff --git a/dubbo-demo/dubbo-demo-xml/dubbo-demo-jaxrs-rest-provider/src/main/java/org/apache/dubbo/demo/rest/api/impl/HttpMethodServiceImpl.java b/dubbo-demo/dubbo-demo-xml/dubbo-demo-jaxrs-rest-provider/src/main/java/org/apache/dubbo/demo/rest/api/impl/HttpMethodServiceImpl.java new file mode 100644 index 0000000000..cc1e832ca1 --- /dev/null +++ b/dubbo-demo/dubbo-demo-xml/dubbo-demo-jaxrs-rest-provider/src/main/java/org/apache/dubbo/demo/rest/api/impl/HttpMethodServiceImpl.java @@ -0,0 +1,60 @@ +/* + * 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.demo.rest.api.impl; + +import org.apache.dubbo.demo.rest.api.HttpMethodService; +import org.springframework.stereotype.Service; + +@Service("httpMethodService") +public class HttpMethodServiceImpl implements HttpMethodService { + + @Override + public String sayHelloPost(String hello) { + return hello; + } + + @Override + public String sayHelloDelete(String hello) { + return hello; + } + + @Override + public String sayHelloHead(String hello) { + return hello; + } + + @Override + public String sayHelloGet(String hello) { + return hello; + } + + @Override + public String sayHelloPut(String hello) { + return hello; + } + + @Override + public String sayHelloPatch(String hello) { + return hello; + } + + @Override + public String sayHelloOptions(String hello) { + return hello; + } +} + diff --git a/dubbo-demo/dubbo-demo-xml/dubbo-demo-jaxrs-rest-provider/src/main/java/org/apache/dubbo/demo/rest/api/impl/HttpRequestAndResponseRPCContextServiceImpl.java b/dubbo-demo/dubbo-demo-xml/dubbo-demo-jaxrs-rest-provider/src/main/java/org/apache/dubbo/demo/rest/api/impl/HttpRequestAndResponseRPCContextServiceImpl.java new file mode 100644 index 0000000000..0aa6d69e6e --- /dev/null +++ b/dubbo-demo/dubbo-demo-xml/dubbo-demo-jaxrs-rest-provider/src/main/java/org/apache/dubbo/demo/rest/api/impl/HttpRequestAndResponseRPCContextServiceImpl.java @@ -0,0 +1,53 @@ +/* + * 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.demo.rest.api.impl; + +import org.apache.dubbo.rpc.RpcContext; +import org.apache.dubbo.rpc.protocol.rest.netty.NettyHttpResponse; +import org.apache.dubbo.rpc.protocol.rest.request.RequestFacade; +import org.apache.dubbo.demo.rest.api.HttpRequestAndResponseRPCContextService; +import org.springframework.stereotype.Service; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +@Service("httpRequestAndResponseRPCContextService") +public class HttpRequestAndResponseRPCContextServiceImpl implements HttpRequestAndResponseRPCContextService { + @Override + public String httpRequestParam(String hello) { + Object request = RpcContext.getServerAttachment().getRequest(); + return ((RequestFacade) request).getParameter("name"); + } + + @Override + public String httpRequestHeader(String hello) { + Object request = RpcContext.getServerAttachment().getRequest(); + return ((RequestFacade) request).getHeader("header"); + } + + @Override + public List httpResponseHeader(String hello) { + Object response = RpcContext.getServerAttachment().getResponse(); + Map> outputHeaders = ((NettyHttpResponse) response).getOutputHeaders(); + String responseKey = "response"; + outputHeaders.put(responseKey, Arrays.asList(hello)); + + + return outputHeaders.get(responseKey); + } +} diff --git a/dubbo-demo/dubbo-demo-xml/dubbo-demo-jaxrs-rest-provider/src/main/java/org/apache/dubbo/demo/rest/api/impl/JaxRsRestDemoServiceImpl.java b/dubbo-demo/dubbo-demo-xml/dubbo-demo-jaxrs-rest-provider/src/main/java/org/apache/dubbo/demo/rest/api/impl/JaxRsRestDemoServiceImpl.java new file mode 100644 index 0000000000..ad177d0940 --- /dev/null +++ b/dubbo-demo/dubbo-demo-xml/dubbo-demo-jaxrs-rest-provider/src/main/java/org/apache/dubbo/demo/rest/api/impl/JaxRsRestDemoServiceImpl.java @@ -0,0 +1,105 @@ +/* + * 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.demo.rest.api.impl; + + +import org.apache.dubbo.demo.rest.api.JaxRsRestDemoService; +import org.springframework.stereotype.Service; +import po.User; + +import javax.ws.rs.core.MultivaluedMap; +import java.util.List; +import java.util.Map; +@Service("jaxRsRestDemoService") +public class JaxRsRestDemoServiceImpl implements JaxRsRestDemoService { + + @Override + public String sayHello(String name) { + return "Hello, " + name; + } + + @Override + public Long testFormBody(Long number) { + return number; + } + + @Override + public User testJavaBeanBody(User user) { + return user; + } + + + @Override + public int primitiveInt(int a, int b) { + return a + b; + } + + @Override + public long primitiveLong(long a, Long b) { + return a + b; + } + + @Override + public long primitiveByte(byte a, Long b) { + return a + b; + } + + @Override + public long primitiveShort(short a, Long b, int c) { + return a + b; + } + + + + @Override + public String testMapParam(Map params) { + return params.get("param"); + } + + @Override + public String testMapHeader(Map headers) { + return headers.get("header"); + } + + @Override + public List testMapForm(MultivaluedMap params) { + return params.get("form"); + } + + @Override + public String header(String header) { + return header; + } + + @Override + public int headerInt(int header) { + return header; + } + + + @Override + public Integer hello(Integer a, Integer b) { + return a + b; + } + + + @Override + public String error() { + throw new RuntimeException("test error"); + } + +} diff --git a/dubbo-demo/dubbo-demo-xml/dubbo-demo-jaxrs-rest-provider/src/main/resources/spring/rest-provider.xml b/dubbo-demo/dubbo-demo-xml/dubbo-demo-jaxrs-rest-provider/src/main/resources/spring/rest-provider.xml new file mode 100644 index 0000000000..f0471d1dc7 --- /dev/null +++ b/dubbo-demo/dubbo-demo-xml/dubbo-demo-jaxrs-rest-provider/src/main/resources/spring/rest-provider.xml @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dubbo-demo/dubbo-demo-xml/dubbo-demo-spring-mvc-rest-consumer/pom.xml b/dubbo-demo/dubbo-demo-xml/dubbo-demo-spring-mvc-rest-consumer/pom.xml new file mode 100644 index 0000000000..63c51491c7 --- /dev/null +++ b/dubbo-demo/dubbo-demo-xml/dubbo-demo-spring-mvc-rest-consumer/pom.xml @@ -0,0 +1,154 @@ + + + + + dubbo-demo-xml + org.apache.dubbo + ${revision} + ../pom.xml + + 4.0.0 + + dubbo-demo-spring-mvc-rest-consumer + + jar + Dubbo Spring MVC Rest Consumer Demo + ${project.artifactId} + + + true + 1.7.33 + + + + org.springframework + spring-context + + + org.springframework + spring-web + + + + org.apache.dubbo + dubbo-registry-multicast + + + org.apache.dubbo + dubbo-registry-zookeeper + + + org.apache.dubbo + dubbo-registry-nacos + + + com.alibaba.nacos + nacos-client + + + org.apache.dubbo + dubbo-configcenter-zookeeper + + + org.apache.dubbo + dubbo-configcenter-nacos + + + org.apache.dubbo + dubbo-metadata-report-zookeeper + + + org.apache.dubbo + dubbo-metadata-report-nacos + + + org.apache.dubbo + dubbo-rpc-dubbo + + + org.apache.dubbo + dubbo-rpc-rest + + + org.apache.dubbo + dubbo-config-spring + + + org.apache.dubbo + dubbo-remoting-netty4 + + + org.apache.dubbo + dubbo-serialization-hessian2 + + + org.apache.dubbo + dubbo-serialization-fastjson2 + + + org.apache.dubbo + dubbo-serialization-jdk + + + org.slf4j + slf4j-api + + + org.slf4j + slf4j-log4j12 + ${slf4j-log4j12.version} + + + log4j + log4j + + + + org.springframework + spring-test + test + + + + org.apache.dubbo + dubbo-demo-interface + ${project.version} + + + + + + + javax.annotation + + [1.11,) + + + + javax.annotation + javax.annotation-api + 1.3.2 + + + + + + + diff --git a/dubbo-demo/dubbo-demo-xml/dubbo-demo-spring-mvc-rest-consumer/src/main/java/org/apache/dubbo/demo/rest/api/SpringMvcRestConsumer.java b/dubbo-demo/dubbo-demo-xml/dubbo-demo-spring-mvc-rest-consumer/src/main/java/org/apache/dubbo/demo/rest/api/SpringMvcRestConsumer.java new file mode 100644 index 0000000000..43e1dc5854 --- /dev/null +++ b/dubbo-demo/dubbo-demo-xml/dubbo-demo-spring-mvc-rest-consumer/src/main/java/org/apache/dubbo/demo/rest/api/SpringMvcRestConsumer.java @@ -0,0 +1,74 @@ +/* + * 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.demo.rest.api; + +import org.springframework.context.support.ClassPathXmlApplicationContext; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import po.User; + +import java.util.Arrays; + +public class SpringMvcRestConsumer { + + public static void main(String[] args) { + consumerService(); + } + + public static void consumerService() { + ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"spring/rest-consumer.xml"}); + context.start(); + System.out.println("spring mvc rest consumer start"); + springMvcRestDemoServiceTest(context); + System.out.println("spring mvc rest consumer test success"); + } + + private static void springMvcRestDemoServiceTest(ClassPathXmlApplicationContext context) { + SpringRestDemoService springRestDemoService = context.getBean("springRestDemoService", SpringRestDemoService.class); + String hello = springRestDemoService.sayHello("hello"); + assertEquals("Hello, hello", hello); + Integer result = springRestDemoService.primitiveInt(1, 2); + Long resultLong = springRestDemoService.primitiveLong(1, 2l); + long resultByte = springRestDemoService.primitiveByte((byte) 1, 2l); + long resultShort = springRestDemoService.primitiveShort((short) 1, 2l, 1); + + assertEquals(result, 3); + assertEquals(resultShort, 3l); + assertEquals(resultLong, 3l); + assertEquals(resultByte, 3l); + + assertEquals(Long.valueOf(1l), springRestDemoService.testFormBody(1l)); + + MultiValueMap forms = new LinkedMultiValueMap<>(); + forms.put("form", Arrays.asList("F1")); + + assertEquals(Arrays.asList("F1"), springRestDemoService.testMapForm(forms)); + assertEquals(User.getInstance(), springRestDemoService.testJavaBeanBody(User.getInstance())); + } + + + private static void assertEquals(Object returnStr, Object exception) { + boolean equal = returnStr != null && returnStr.equals(exception); + + if (equal) { + return; + } else { + throw new RuntimeException(); + } + } + +} diff --git a/dubbo-demo/dubbo-demo-xml/dubbo-demo-spring-mvc-rest-consumer/src/main/java/org/apache/dubbo/demo/rest/api/config/DubboConfig.java b/dubbo-demo/dubbo-demo-xml/dubbo-demo-spring-mvc-rest-consumer/src/main/java/org/apache/dubbo/demo/rest/api/config/DubboConfig.java new file mode 100644 index 0000000000..9710c76921 --- /dev/null +++ b/dubbo-demo/dubbo-demo-xml/dubbo-demo-spring-mvc-rest-consumer/src/main/java/org/apache/dubbo/demo/rest/api/config/DubboConfig.java @@ -0,0 +1,25 @@ +/* + * 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.demo.rest.api.config; + +import org.apache.dubbo.config.spring.context.annotation.DubboComponentScan; + +@DubboComponentScan("org.apache.dubbo.demo.rest") +public class DubboConfig { + + +} diff --git a/dubbo-demo/dubbo-demo-xml/dubbo-demo-spring-mvc-rest-consumer/src/main/java/org/apache/dubbo/demo/rest/api/consumer/SpringRestDemoServiceConsumer.java b/dubbo-demo/dubbo-demo-xml/dubbo-demo-spring-mvc-rest-consumer/src/main/java/org/apache/dubbo/demo/rest/api/consumer/SpringRestDemoServiceConsumer.java new file mode 100644 index 0000000000..180947cd2d --- /dev/null +++ b/dubbo-demo/dubbo-demo-xml/dubbo-demo-spring-mvc-rest-consumer/src/main/java/org/apache/dubbo/demo/rest/api/consumer/SpringRestDemoServiceConsumer.java @@ -0,0 +1,29 @@ +/* + * 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.demo.rest.api.consumer; + +import org.apache.dubbo.config.annotation.DubboReference; +import org.apache.dubbo.demo.rest.api.SpringRestDemoService; +import org.springframework.stereotype.Component; + +@Component +public class SpringRestDemoServiceConsumer { + @DubboReference(interfaceClass = SpringRestDemoService.class ) + SpringRestDemoService springRestDemoService; + + +} diff --git a/dubbo-demo/dubbo-demo-xml/dubbo-demo-spring-mvc-rest-consumer/src/main/resources/spring/rest-consumer.xml b/dubbo-demo/dubbo-demo-xml/dubbo-demo-spring-mvc-rest-consumer/src/main/resources/spring/rest-consumer.xml new file mode 100644 index 0000000000..b028879160 --- /dev/null +++ b/dubbo-demo/dubbo-demo-xml/dubbo-demo-spring-mvc-rest-consumer/src/main/resources/spring/rest-consumer.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + diff --git a/dubbo-demo/dubbo-demo-xml/dubbo-demo-spring-mvc-rest-provider/pom.xml b/dubbo-demo/dubbo-demo-xml/dubbo-demo-spring-mvc-rest-provider/pom.xml new file mode 100644 index 0000000000..8c042046e2 --- /dev/null +++ b/dubbo-demo/dubbo-demo-xml/dubbo-demo-spring-mvc-rest-provider/pom.xml @@ -0,0 +1,153 @@ + + + + + dubbo-demo-xml + org.apache.dubbo + ${revision} + ../pom.xml + + 4.0.0 + + dubbo-demo-spring-mvc-rest-provider + + jar + Dubbo Spring MVC Rest Provider Demo + ${project.artifactId} + + + true + 1.7.33 + + + + org.springframework + spring-context + + + org.springframework + spring-web + + + + org.apache.dubbo + dubbo-registry-multicast + + + org.apache.dubbo + dubbo-registry-zookeeper + + + org.apache.dubbo + dubbo-registry-nacos + + + com.alibaba.nacos + nacos-client + + + org.apache.dubbo + dubbo-configcenter-zookeeper + + + org.apache.dubbo + dubbo-configcenter-nacos + + + org.apache.dubbo + dubbo-metadata-report-zookeeper + + + org.apache.dubbo + dubbo-metadata-report-nacos + + + org.apache.dubbo + dubbo-rpc-dubbo + + + org.apache.dubbo + dubbo-rpc-rest + + + org.apache.dubbo + dubbo-config-spring + + + org.apache.dubbo + dubbo-remoting-netty4 + + + org.apache.dubbo + dubbo-serialization-hessian2 + + + org.apache.dubbo + dubbo-serialization-fastjson2 + + + org.apache.dubbo + dubbo-serialization-jdk + + + org.slf4j + slf4j-api + + + org.slf4j + slf4j-log4j12 + ${slf4j-log4j12.version} + + + log4j + log4j + + + + org.springframework + spring-test + test + + + + org.apache.dubbo + dubbo-demo-interface + ${project.version} + + + + + + + javax.annotation + + [1.11,) + + + + javax.annotation + javax.annotation-api + 1.3.2 + + + + + + diff --git a/dubbo-demo/dubbo-demo-xml/dubbo-demo-spring-mvc-rest-provider/src/main/java/org/apache/dubbo/demo/rest/api/SpringMvcRestProvider.java b/dubbo-demo/dubbo-demo-xml/dubbo-demo-spring-mvc-rest-provider/src/main/java/org/apache/dubbo/demo/rest/api/SpringMvcRestProvider.java new file mode 100644 index 0000000000..70b2fe9a41 --- /dev/null +++ b/dubbo-demo/dubbo-demo-xml/dubbo-demo-spring-mvc-rest-provider/src/main/java/org/apache/dubbo/demo/rest/api/SpringMvcRestProvider.java @@ -0,0 +1,36 @@ +/* + * 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.demo.rest.api; + +import org.springframework.context.support.ClassPathXmlApplicationContext; + + +public class SpringMvcRestProvider { + + public static void main(String[] args) throws Exception { + ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"spring/rest-provider.xml"}); + + context.refresh(); + + + System.out.println("spring mvc rest provider started"); + + System.in.read(); + } + + +} diff --git a/dubbo-demo/dubbo-demo-xml/dubbo-demo-spring-mvc-rest-provider/src/main/java/org/apache/dubbo/demo/rest/api/config/DubboConfig.java b/dubbo-demo/dubbo-demo-xml/dubbo-demo-spring-mvc-rest-provider/src/main/java/org/apache/dubbo/demo/rest/api/config/DubboConfig.java new file mode 100644 index 0000000000..a5d0edfacf --- /dev/null +++ b/dubbo-demo/dubbo-demo-xml/dubbo-demo-spring-mvc-rest-provider/src/main/java/org/apache/dubbo/demo/rest/api/config/DubboConfig.java @@ -0,0 +1,23 @@ +/* + * 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.demo.rest.api.config; + +import org.apache.dubbo.config.spring.context.annotation.DubboComponentScan; + +@DubboComponentScan("org.apache.dubbo.demo.rest") +public class DubboConfig { +} diff --git a/dubbo-demo/dubbo-demo-xml/dubbo-demo-spring-mvc-rest-provider/src/main/java/org/apache/dubbo/demo/rest/api/impl/SpringRestDemoServiceImpl.java b/dubbo-demo/dubbo-demo-xml/dubbo-demo-spring-mvc-rest-provider/src/main/java/org/apache/dubbo/demo/rest/api/impl/SpringRestDemoServiceImpl.java new file mode 100644 index 0000000000..2798e89aa3 --- /dev/null +++ b/dubbo-demo/dubbo-demo-xml/dubbo-demo-spring-mvc-rest-provider/src/main/java/org/apache/dubbo/demo/rest/api/impl/SpringRestDemoServiceImpl.java @@ -0,0 +1,101 @@ +/* + * 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.demo.rest.api.impl; + + +import org.apache.dubbo.config.annotation.DubboService; +import org.apache.dubbo.demo.rest.api.SpringRestDemoService; +import org.springframework.util.MultiValueMap; +import po.User; + +import java.util.List; +import java.util.Map; + +@DubboService(interfaceClass = SpringRestDemoService.class ,protocol = "rest") +public class SpringRestDemoServiceImpl implements SpringRestDemoService { + + @Override + public String sayHello(String name) { + return "Hello, " + name; + } + + @Override + public Long testFormBody(Long number) { + return number; + } + + @Override + public User testJavaBeanBody(User user) { + return user; + } + + + @Override + public int primitiveInt(int a, int b) { + return a + b; + } + + @Override + public long primitiveLong(long a, Long b) { + return a + b; + } + + @Override + public long primitiveByte(byte a, Long b) { + return a + b; + } + + @Override + public long primitiveShort(short a, Long b, int c) { + return a + b; + } + + + @Override + public String testMapParam(Map params) { + return params.get("param"); + } + + @Override + public String testMapHeader(Map headers) { + return headers.get("header"); + } + + @Override + public List testMapForm(MultiValueMap params) { + return params.get("form"); + } + + + @Override + public int headerInt(int header) { + return header; + } + + + @Override + public Integer hello(Integer a, Integer b) { + return a + b; + } + + + @Override + public String error() { + throw new RuntimeException("test error"); + } + +} diff --git a/dubbo-demo/dubbo-demo-xml/dubbo-demo-spring-mvc-rest-provider/src/main/resources/spring/rest-provider.xml b/dubbo-demo/dubbo-demo-xml/dubbo-demo-spring-mvc-rest-provider/src/main/resources/spring/rest-provider.xml new file mode 100644 index 0000000000..8c6be976f7 --- /dev/null +++ b/dubbo-demo/dubbo-demo-xml/dubbo-demo-spring-mvc-rest-provider/src/main/resources/spring/rest-provider.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + diff --git a/dubbo-demo/dubbo-demo-xml/pom.xml b/dubbo-demo/dubbo-demo-xml/pom.xml index 6e4c678b2e..0514421d5b 100644 --- a/dubbo-demo/dubbo-demo-xml/pom.xml +++ b/dubbo-demo/dubbo-demo-xml/pom.xml @@ -32,12 +32,16 @@ true - 2.7.10 + 2.7.11 dubbo-demo-xml-provider dubbo-demo-xml-consumer + dubbo-demo-jaxrs-rest-consumer + dubbo-demo-jaxrs-rest-provider + dubbo-demo-spring-mvc-rest-consumer + dubbo-demo-spring-mvc-rest-provider diff --git a/dubbo-dependencies-bom/pom.xml b/dubbo-dependencies-bom/pom.xml index b94c9a83ff..ea8ce5fb20 100644 --- a/dubbo-dependencies-bom/pom.xml +++ b/dubbo-dependencies-bom/pom.xml @@ -92,21 +92,21 @@ 5.3.25 - 5.8.2 + 5.8.3 3.29.2-GA 1.14.4 3.2.10.Final - 4.1.91.Final + 4.1.92.Final 2.2.1 2.4.4 4.5.14 4.4.16 1.2.83 - 2.0.27 + 2.0.29 3.4.14 4.3.0 2.12.0 - 3.9.0 + 3.10.0 1.4.5 2.2.1 1.5.3 @@ -114,7 +114,7 @@ 3.5.5 0.18.1 4.0.66 - 3.22.2 + 3.22.3 1.3.2 3.1.0 9.4.51.v20230217 @@ -135,11 +135,12 @@ 0.1.35 1.10.6 - 1.0.3 + 1.0.4 3.3 0.16.0 1.0.4 - 3.5.4 + 3.5.5 + 2.2.21 3.14.9 2.1.1 @@ -147,8 +148,8 @@ 1.9.13 8.5.87 0.7.5 - 2.1.2 - 1.54.0 + 2.2.2 + 1.54.1 0.8.1 1.2.2 @@ -183,7 +184,7 @@ 2.0.6 5.4.3 2.10.1 - 2.14.2 + 2.15.0 1.6 6.1.26 2.0 @@ -898,6 +899,11 @@ reactor-core ${reactor.version} + + io.reactivex.rxjava2 + rxjava + ${rxjava.version} + diff --git a/dubbo-distribution/dubbo-all/pom.xml b/dubbo-distribution/dubbo-all/pom.xml index f5464ae99c..94df39e1b6 100644 --- a/dubbo-distribution/dubbo-all/pom.xml +++ b/dubbo-distribution/dubbo-all/pom.xml @@ -211,6 +211,13 @@ compile true + + org.apache.dubbo + dubbo-metrics-config-center + ${project.version} + compile + true + @@ -521,6 +528,7 @@ org.apache.dubbo:dubbo-metrics-default org.apache.dubbo:dubbo-metrics-registry org.apache.dubbo:dubbo-metrics-metadata + org.apache.dubbo:dubbo-metrics-config-center org.apache.dubbo:dubbo-metrics-prometheus org.apache.dubbo:dubbo-monitor-api org.apache.dubbo:dubbo-monitor-default @@ -1315,6 +1323,12 @@ + + + META-INF/dubbo/internal/org.apache.dubbo.rpc.model.PackableMethodFactory + + @@ -1342,7 +1356,6 @@ META-INF/dubbo/internal/org.apache.dubbo.common.json.JsonUtil - diff --git a/dubbo-distribution/dubbo-bom/pom.xml b/dubbo-distribution/dubbo-bom/pom.xml index 73fc53cbe2..6f834cf078 100644 --- a/dubbo-distribution/dubbo-bom/pom.xml +++ b/dubbo-distribution/dubbo-bom/pom.xml @@ -256,6 +256,11 @@ dubbo-metrics-metadata ${project.version} + + org.apache.dubbo + dubbo-metrics-config-center + ${project.version} + @@ -503,6 +508,26 @@ pom ${project.version} + + org.apache.dubbo + dubbo-spring-boot-observability-starters + ${project.version} + + + org.apache.dubbo + dubbo-spring-boot-observability-autoconfigure + ${project.version} + + + org.apache.dubbo + dubbo-spring-boot-tracing-otel-zipkin-starter + ${project.version} + + + org.apache.dubbo + dubbo-spring-boot-tracing-brave-zipkin-starter + ${project.version} + org.apache.dubbo dubbo-spring-boot-observability-starter diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/AbstractServiceRestMetadataResolver.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/AbstractServiceRestMetadataResolver.java index 206fd1fad7..615911e93c 100644 --- a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/AbstractServiceRestMetadataResolver.java +++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/AbstractServiceRestMetadataResolver.java @@ -72,15 +72,17 @@ public abstract class AbstractServiceRestMetadataResolver implements ServiceRest @Override public final boolean supports(Class serviceType, boolean consumer) { - // for consumer - if (consumer) { - // it is possible serviceType is impl - return supports0(serviceType); + + if (serviceType == null) { + return false; } + // for consumer + // it is possible serviceType is impl // for provider // for xml config bean && isServiceAnnotationPresent(serviceType) - return isImplementedInterface(serviceType) && supports0(serviceType); + // isImplementedInterface(serviceType) SpringController + return supports0(serviceType); } protected final boolean isImplementedInterface(Class serviceType) { @@ -172,9 +174,15 @@ public abstract class AbstractServiceRestMetadataResolver implements ServiceRest // exclude the public methods declared in java.lang.Object.class List declaredServiceMethods = new ArrayList<>(getAllMethods(serviceInterfaceClass, excludedDeclaredClass(Object.class))); + // controller class + if (serviceType.equals(serviceInterfaceClass)) { + putServiceMethodToMap(serviceMethodsMap, declaredServiceMethods); + return unmodifiableMap(serviceMethodsMap); + } + // for interface , such as consumer interface if (serviceType.isInterface()) { - putInterfaceMethodToMap(serviceMethodsMap, declaredServiceMethods); + putServiceMethodToMap(serviceMethodsMap, declaredServiceMethods); return unmodifiableMap(serviceMethodsMap); } @@ -198,7 +206,7 @@ public abstract class AbstractServiceRestMetadataResolver implements ServiceRest return unmodifiableMap(serviceMethodsMap); } - private void putInterfaceMethodToMap(Map serviceMethodsMap, List declaredServiceMethods) { + private void putServiceMethodToMap(Map serviceMethodsMap, List declaredServiceMethods) { declaredServiceMethods.stream().forEach(method -> { // filter static private default diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/PathMatcher.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/PathMatcher.java index 12d0644ac8..f4d57b1c30 100644 --- a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/PathMatcher.java +++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/PathMatcher.java @@ -31,6 +31,9 @@ public class PathMatcher { private String[] pathSplits; private boolean hasPathVariable; private String contextPath; + private String httpMethod; + // for provider http method compare + private boolean needCompareMethod = true; public PathMatcher(String path) { @@ -45,6 +48,10 @@ public class PathMatcher { this.port = (port == null || port == -1 || port == 0) ? null : port; } + public PathMatcher(String path, String version, String group, Integer port, String httpMethod) { + this(path, version, group, port); + setHttpMethod(httpMethod); + } private void dealPathVariable(String path) { this.pathSplits = path.split(SEPARATOR); @@ -88,8 +95,8 @@ public class PathMatcher { } - public static PathMatcher getInvokeCreatePathMatcher(String path, String version, String group, Integer port) { - return new PathMatcher(path, version, group, port); + public static PathMatcher getInvokeCreatePathMatcher(String path, String version, String group, Integer port, String method) { + return new PathMatcher(path, version, group, port, method).noNeedHttpMethodCompare(); } public boolean hasPathVariable() { @@ -100,6 +107,20 @@ public class PathMatcher { return port; } + public String getHttpMethod() { + return httpMethod; + } + + public PathMatcher setHttpMethod(String httpMethod) { + this.httpMethod = httpMethod; + return this; + } + + private PathMatcher noNeedHttpMethodCompare() { + this.needCompareMethod = false; + return this; + } + @Override public boolean equals(Object o) { if (this == o) return true; @@ -107,6 +128,7 @@ public class PathMatcher { PathMatcher that = (PathMatcher) o; return pathEqual(that) && Objects.equals(version, that.version) + && (this.needCompareMethod ? Objects.equals(httpMethod, that.httpMethod) : true) && Objects.equals(group, that.group) && Objects.equals(port, that.port); } @@ -200,6 +222,7 @@ public class PathMatcher { ", port=" + port + ", hasPathVariable=" + hasPathVariable + ", contextPath='" + contextPath + '\'' + + ", httpMethod='" + httpMethod + '\'' + '}'; } } diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/RequestMetadata.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/RequestMetadata.java index 66ff17f5ad..e7f825d26a 100644 --- a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/RequestMetadata.java +++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/RequestMetadata.java @@ -206,6 +206,10 @@ public class RequestMetadata implements Serializable { setPath(contextPathFromUrl + path); } + public boolean methodAllowed(String method) { + return method != null && method.equals(this.method); + } + @Override public boolean equals(Object o) { if (this == o) { diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/ServiceRestMetadata.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/ServiceRestMetadata.java index 55970c7fe7..14f8bdcbb9 100644 --- a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/ServiceRestMetadata.java +++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/ServiceRestMetadata.java @@ -110,7 +110,7 @@ public class ServiceRestMetadata implements Serializable { public void addRestMethodMetadata(RestMethodMetadata restMethodMetadata) { PathMatcher pathMather = new PathMatcher(restMethodMetadata.getRequest().getPath(), - this.getVersion(), this.getGroup(), this.getPort()); + this.getVersion(), this.getGroup(), this.getPort(),restMethodMetadata.getRequest().getMethod()); addPathToServiceMap(pathMather, restMethodMetadata); addMethodToServiceMap(restMethodMetadata); getMeta().add(restMethodMetadata); diff --git a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/event/MethodEvent.java b/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/rest/api/JaxrsUsingService.java similarity index 53% rename from dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/event/MethodEvent.java rename to dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/rest/api/JaxrsUsingService.java index 3686c03197..7490c75341 100644 --- a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/event/MethodEvent.java +++ b/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/rest/api/JaxrsUsingService.java @@ -14,34 +14,35 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -package org.apache.dubbo.metrics.event; - -import org.apache.dubbo.metrics.model.MethodMetric; -import org.apache.dubbo.rpc.model.ApplicationModel; - -public class MethodEvent extends MetricsEvent { - private String type; - private final MethodMetric methodMetric; - - public MethodEvent(ApplicationModel applicationModel, MethodMetric methodMetric, String type) { - super(applicationModel); - this.type = type; - this.methodMetric = methodMetric; - setAvailable(true); - } - - public MethodMetric getMethodMetric() { - return methodMetric; - } - - public String getType() { - return type; - } - - public void setType(String type) { - this.type = type; - } +package org.apache.dubbo.metadata.rest.api; +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +@Path("usingService") +@Consumes({MediaType.APPLICATION_JSON}) +@Produces({MediaType.APPLICATION_JSON}) +public interface JaxrsUsingService { + + @GET + Response getUsers(); + + @POST + Response createUser(Object user); + + @GET + @Path("{uid}") + Response getUserByUid(@PathParam("uid") String uid); + + @DELETE + @Path("{uid}") + Response deleteUserByUid(@PathParam("uid") String uid); } diff --git a/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/rest/api/SpringControllerService.java b/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/rest/api/SpringControllerService.java new file mode 100644 index 0000000000..dfea020905 --- /dev/null +++ b/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/rest/api/SpringControllerService.java @@ -0,0 +1,71 @@ +/* + * 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.metadata.rest.api; + +import org.apache.dubbo.metadata.rest.User; +import org.springframework.http.MediaType; +import org.springframework.util.MultiValueMap; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class SpringControllerService { + @RequestMapping(value = "/param", method = RequestMethod.GET, consumes = MediaType.TEXT_PLAIN_VALUE, produces = MediaType.TEXT_PLAIN_VALUE) + public String param(@RequestParam String param) { + return param; + } + + @RequestMapping(value = "/header", method = RequestMethod.GET, consumes = MediaType.TEXT_PLAIN_VALUE, produces = MediaType.TEXT_PLAIN_VALUE) + public String header(@RequestHeader String header) { + return header; + } + + @RequestMapping(value = "/body", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) + public User body(@RequestBody User user) { + return user; + } + + @RequestMapping(value = "/multiValue", method = RequestMethod.POST, consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE, produces = MediaType.APPLICATION_FORM_URLENCODED_VALUE) + public MultiValueMap multiValue(@RequestBody MultiValueMap map) { + return map; + } + + @RequestMapping(value = "/pathVariable/{a}", method = RequestMethod.POST, consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE, produces = MediaType.APPLICATION_FORM_URLENCODED_VALUE) + public String pathVariable(@PathVariable String a) { + return a; + } + + @RequestMapping(value = "/noAnnoParam", method = RequestMethod.POST, consumes = MediaType.TEXT_PLAIN_VALUE, produces = MediaType.TEXT_PLAIN_VALUE) + public String noAnnoParam(String a) { + return a; + } + + @RequestMapping(value = "/noAnnoNumber", method = RequestMethod.POST, consumes = MediaType.ALL_VALUE, produces = MediaType.ALL_VALUE) + public int noAnnoNumber(Integer b) { + return b; + } + + @RequestMapping(value = "/noAnnoPrimitive", method = RequestMethod.POST, consumes = MediaType.ALL_VALUE, produces = MediaType.ALL_VALUE) + public int noAnnoPrimitive(int c) { + return c; + } +} diff --git a/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/rest/jaxrs/JaxrsRestDoubleCheckTest.java b/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/rest/jaxrs/JaxrsRestDoubleCheckTest.java index 97ce07d5ec..3e8f129f20 100644 --- a/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/rest/jaxrs/JaxrsRestDoubleCheckTest.java +++ b/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/rest/jaxrs/JaxrsRestDoubleCheckTest.java @@ -16,13 +16,18 @@ */ package org.apache.dubbo.metadata.rest.jaxrs; +import org.apache.dubbo.metadata.rest.PathMatcher; +import org.apache.dubbo.metadata.rest.RestMethodMetadata; import org.apache.dubbo.metadata.rest.ServiceRestMetadata; import org.apache.dubbo.metadata.rest.api.JaxrsRestDoubleCheckContainsPathVariableService; import org.apache.dubbo.metadata.rest.api.JaxrsRestDoubleCheckService; +import org.apache.dubbo.metadata.rest.api.JaxrsUsingService; import org.apache.dubbo.rpc.model.ApplicationModel; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; +import java.util.Map; + public class JaxrsRestDoubleCheckTest { private JAXRSServiceRestMetadataResolver instance = new JAXRSServiceRestMetadataResolver(ApplicationModel.defaultModel()); @@ -45,4 +50,27 @@ public class JaxrsRestDoubleCheckTest { } + @Test + void testSameHttpMethodException() { + + Assertions.assertDoesNotThrow(() -> { + ServiceRestMetadata resolve = new ServiceRestMetadata(); + resolve.setServiceInterface(JaxrsUsingService.class.getName()); + instance.resolve(JaxrsUsingService.class, resolve); + }); + + ServiceRestMetadata resolve = new ServiceRestMetadata(); + resolve.setServiceInterface(JaxrsUsingService.class.getName()); + instance.resolve(JaxrsUsingService.class, resolve); + + Map pathContainPathVariableToServiceMap = resolve.getPathContainPathVariableToServiceMap(); + + + RestMethodMetadata restMethodMetadata = pathContainPathVariableToServiceMap.get(PathMatcher.getInvokeCreatePathMatcher("/usingService/aaa", null, null, null, "TEST")); + + Assertions.assertNotNull(restMethodMetadata); + + + } + } diff --git a/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/rest/springmvc/SpringMvcServiceRestMetadataResolverTest.java b/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/rest/springmvc/SpringMvcServiceRestMetadataResolverTest.java index 40f123a952..a79c6e5061 100644 --- a/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/rest/springmvc/SpringMvcServiceRestMetadataResolverTest.java +++ b/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/rest/springmvc/SpringMvcServiceRestMetadataResolverTest.java @@ -25,6 +25,7 @@ import org.apache.dubbo.metadata.rest.RestMethodMetadata; import org.apache.dubbo.metadata.rest.RestService; import org.apache.dubbo.metadata.rest.ServiceRestMetadata; import org.apache.dubbo.metadata.rest.StandardRestService; +import org.apache.dubbo.metadata.rest.api.SpringControllerService; import org.apache.dubbo.metadata.rest.api.SpringRestService; import org.apache.dubbo.metadata.rest.api.SpringRestServiceImpl; import org.apache.dubbo.rpc.model.ApplicationModel; @@ -86,6 +87,7 @@ class SpringMvcServiceRestMetadataResolverTest { void testResolves() { testResolve(SpringRestService.class); testResolve(SpringRestServiceImpl.class); + testResolve(SpringControllerService.class); } void testResolve(Class service) { diff --git a/dubbo-metadata/dubbo-metadata-report-redis/pom.xml b/dubbo-metadata/dubbo-metadata-report-redis/pom.xml index 91fd5690ef..708178b432 100644 --- a/dubbo-metadata/dubbo-metadata-report-redis/pom.xml +++ b/dubbo-metadata/dubbo-metadata-report-redis/pom.xml @@ -24,7 +24,7 @@ dubbo-metadata-report-redis - 3.9.0 + 3.10.0 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 a4c7516321..3c3871c0d7 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 @@ -19,6 +19,11 @@ package org.apache.dubbo.metrics; public interface MetricsConstants { + String INVOCATION = "metric_filter_invocation"; + String INVOCATION_METRICS_COUNTER = "metric_filter_invocation_counter"; + + String INVOCATION_SIDE = "metric_filter_side"; + String ATTACHMENT_KEY_SERVICE = "serviceKey"; String ATTACHMENT_KEY_SIZE = "size"; String ATTACHMENT_KEY_LAST_NUM_MAP = "lastNumMap"; 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 f9eb9ac5c6..03f9478052 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 @@ -20,15 +20,18 @@ package org.apache.dubbo.metrics.collector; 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.MetricsCategory; import org.apache.dubbo.metrics.model.key.MetricsKey; -import org.apache.dubbo.metrics.model.sample.GaugeMetricSample; +import org.apache.dubbo.metrics.model.key.MetricsKeyWrapper; +import org.apache.dubbo.metrics.model.sample.MetricSample; +import org.apache.dubbo.rpc.Invocation; import java.util.List; import static org.apache.dubbo.metrics.MetricsConstants.SELF_INCREMENT_SIZE; -public abstract class CombMetricsCollector implements ApplicationMetricsCollector, ServiceMetricsCollector { +public abstract class CombMetricsCollector extends AbstractMetricsListener implements ApplicationMetricsCollector, ServiceMetricsCollector, MethodMetricsCollector { private final BaseStatComposite stats; private MetricsEventMulticaster eventMulticaster; @@ -43,7 +46,7 @@ public abstract class CombMetricsCollector implement } @Override - public void setNum(MetricsKey metricsKey, String applicationName, String serviceKey, int num) { + public void setNum(MetricsKeyWrapper metricsKey, String applicationName, String serviceKey, int num) { this.stats.setServiceKey(metricsKey, applicationName, serviceKey, num); } @@ -52,8 +55,8 @@ public abstract class CombMetricsCollector implement this.stats.incrementApp(metricsKey, applicationName, SELF_INCREMENT_SIZE); } - public void increment(String applicationName, String serviceKey, MetricsKey metricsKey, int size) { - this.stats.incrementServiceKey(metricsKey, applicationName, serviceKey, size); + public void increment(String applicationName, String serviceKey, MetricsKeyWrapper metricsKeyWrapper, int size) { + this.stats.incrementServiceKey(metricsKeyWrapper, applicationName, serviceKey, size); } @Override @@ -65,11 +68,24 @@ public abstract class CombMetricsCollector implement stats.calcServiceKeyRt(applicationName, serviceKey, registryOpType, responseTime); } - @SuppressWarnings({"rawtypes"}) - protected List export(MetricsCategory category) { + @Override + public void increment(String applicationName, Invocation invocation, MetricsKeyWrapper wrapper, int size) { + this.stats.incrementMethodKey(wrapper, applicationName, invocation, size); + } + + @Override + public void addRt(String applicationName, Invocation invocation, String registryOpType, Long responseTime) { + stats.calcMethodKeyRt(applicationName, invocation, registryOpType, responseTime); + } + + protected List export(MetricsCategory category) { return stats.export(category); } + public MetricsEventMulticaster getEventMulticaster() { + return eventMulticaster; + } + @Override public void onEvent(TimeCounterEvent event) { eventMulticaster.publishEvent(event); diff --git a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/event/RTEvent.java b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/collector/MethodMetricsCollector.java similarity index 58% rename from dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/event/RTEvent.java rename to dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/collector/MethodMetricsCollector.java index 18256ffda4..25732f3416 100644 --- a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/event/RTEvent.java +++ b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/collector/MethodMetricsCollector.java @@ -15,33 +15,19 @@ * limitations under the License. */ -package org.apache.dubbo.metrics.event; +package org.apache.dubbo.metrics.collector; -import org.apache.dubbo.rpc.model.ApplicationModel; +import org.apache.dubbo.metrics.event.TimeCounterEvent; +import org.apache.dubbo.metrics.model.key.MetricsKeyWrapper; +import org.apache.dubbo.rpc.Invocation; /** - * RtEvent. + * Method-level metrics collection for rpc invocation scenarios */ -public class RTEvent extends MetricsEvent { - private Long rt; - private final Object metric; +public interface MethodMetricsCollector extends MetricsCollector { - public RTEvent(ApplicationModel applicationModel, Object metric, Long rt) { - super(applicationModel); - this.rt = rt; - this.metric = metric; - setAvailable(true); - } + void increment(String applicationName, Invocation invocation, MetricsKeyWrapper wrapper, int size); - public Long getRt() { - return rt; - } - - public void setRt(Long rt) { - this.rt = rt; - } - - public Object getMetric() { - return metric; - } + void addRt(String applicationName, 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 b4876716bf..af0aabc635 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 @@ -18,19 +18,17 @@ package org.apache.dubbo.metrics.collector; import org.apache.dubbo.metrics.event.TimeCounterEvent; -import org.apache.dubbo.metrics.model.key.MetricsKey; +import org.apache.dubbo.metrics.model.key.MetricsKeyWrapper; /** - * Application-level collector. + * Service-level collector. * registration center, configuration center and other scenarios - * - * @Params metrics type */ public interface ServiceMetricsCollector extends MetricsCollector { - void increment(String applicationName, String serviceKey, MetricsKey metricsKey, int size); + void increment(String applicationName, String serviceKey, MetricsKeyWrapper wrapper, int size); - void setNum(MetricsKey metricsKey, String applicationName, String serviceKey, int num); + void setNum(MetricsKeyWrapper metricsKey, String applicationName, String serviceKey, int num); void addRt(String applicationName, String serviceKey, String registryOpType, Long responseTime); } diff --git a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/data/ApplicationStatComposite.java b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/data/ApplicationStatComposite.java index 087334bc09..72b23eb234 100644 --- a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/data/ApplicationStatComposite.java +++ b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/data/ApplicationStatComposite.java @@ -22,6 +22,7 @@ import org.apache.dubbo.metrics.model.MetricsCategory; import org.apache.dubbo.metrics.model.MetricsSupport; import org.apache.dubbo.metrics.model.key.MetricsKey; import org.apache.dubbo.metrics.model.sample.GaugeMetricSample; +import org.apache.dubbo.metrics.model.sample.MetricSample; import org.apache.dubbo.metrics.report.MetricsExport; import java.util.ArrayList; @@ -48,17 +49,9 @@ public class ApplicationStatComposite implements MetricsExport { applicationNumStats.get(metricsKey).computeIfAbsent(applicationName, k -> new AtomicLong(0L)).getAndAdd(size); } - public void setApplicationKey(MetricsKey metricsKey, String applicationName, int num) { - if (!applicationNumStats.containsKey(metricsKey)) { - return; - } - applicationNumStats.get(metricsKey).computeIfAbsent(applicationName, k -> new AtomicLong(0L)).set(num); - } - - @SuppressWarnings({"rawtypes"}) - public List export(MetricsCategory category) { - List list = new ArrayList<>(); + public List export(MetricsCategory category) { + List list = new ArrayList<>(); for (MetricsKey type : applicationNumStats.keySet()) { Map stringAtomicLongMap = applicationNumStats.get(type); for (String applicationName : stringAtomicLongMap.keySet()) { 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 0805c9e090..7f99f5e85c 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 @@ -20,9 +20,10 @@ package org.apache.dubbo.metrics.data; import org.apache.dubbo.metrics.collector.MetricsCollector; import org.apache.dubbo.metrics.model.MetricsCategory; import org.apache.dubbo.metrics.model.key.MetricsKey; -import org.apache.dubbo.metrics.model.sample.GaugeMetricSample; - +import org.apache.dubbo.metrics.model.key.MetricsKeyWrapper; +import org.apache.dubbo.metrics.model.sample.MetricSample; import org.apache.dubbo.metrics.report.MetricsExport; +import org.apache.dubbo.rpc.Invocation; import java.util.ArrayList; import java.util.List; @@ -37,14 +38,31 @@ public abstract class BaseStatComposite implements MetricsExport { private final ApplicationStatComposite applicationStatComposite = new ApplicationStatComposite(); private final ServiceStatComposite serviceStatComposite = new ServiceStatComposite(); + + private final MethodStatComposite methodStatComposite = new MethodStatComposite(); private final RtStatComposite rtStatComposite = new RtStatComposite(); public BaseStatComposite() { - init(applicationStatComposite, serviceStatComposite, rtStatComposite); + init(applicationStatComposite); + init(serviceStatComposite); + init(methodStatComposite); + init(rtStatComposite); } - protected abstract void init(ApplicationStatComposite applicationStatComposite, ServiceStatComposite serviceStatComposite, RtStatComposite rtStatComposite); + + protected void init(ApplicationStatComposite applicationStatComposite) { + } + + protected void init(ServiceStatComposite serviceStatComposite) { + + } + + protected void init(MethodStatComposite methodStatComposite) { + } + + protected void init(RtStatComposite rtStatComposite) { + } public void calcApplicationRt(String applicationName, String registryOpType, Long responseTime) { rtStatComposite.calcApplicationRt(applicationName, registryOpType, responseTime); @@ -54,29 +72,33 @@ public abstract class BaseStatComposite implements MetricsExport { rtStatComposite.calcServiceKeyRt(applicationName, serviceKey, registryOpType, responseTime); } - public void setServiceKey(MetricsKey metricsKey, String applicationName, String serviceKey, int num) { - serviceStatComposite.setServiceKey(metricsKey, applicationName, serviceKey, num); + public void calcMethodKeyRt(String applicationName, Invocation invocation, String registryOpType, Long responseTime) { + rtStatComposite.calcMethodKeyRt(applicationName, invocation, registryOpType, responseTime); } - public void setApplicationKey(MetricsKey metricsKey, String applicationName, int num) { - applicationStatComposite.setApplicationKey(metricsKey, applicationName, num); + public void setServiceKey(MetricsKeyWrapper metricsKey, String applicationName, String serviceKey, int num) { + serviceStatComposite.setServiceKey(metricsKey, applicationName, serviceKey, num); } public void incrementApp(MetricsKey metricsKey, String applicationName, int size) { applicationStatComposite.incrementSize(metricsKey, applicationName, size); } - public void incrementServiceKey(MetricsKey metricsKey, String applicationName, String attServiceKey, int size) { - serviceStatComposite.incrementServiceKey(metricsKey, applicationName, attServiceKey, size); + public void incrementServiceKey(MetricsKeyWrapper metricsKeyWrapper, String applicationName, String attServiceKey, int size) { + serviceStatComposite.incrementServiceKey(metricsKeyWrapper, applicationName, attServiceKey, size); + } + + public void incrementMethodKey(MetricsKeyWrapper metricsKeyWrapper, String applicationName, Invocation invocation, int size) { + methodStatComposite.incrementMethodKey(metricsKeyWrapper, applicationName, invocation, size); } @Override - @SuppressWarnings({"rawtypes"}) - public List export(MetricsCategory category) { - List list = new ArrayList<>(); + public List export(MetricsCategory category) { + List list = new ArrayList<>(); list.addAll(applicationStatComposite.export(category)); list.addAll(rtStatComposite.export(category)); list.addAll(serviceStatComposite.export(category)); + list.addAll(methodStatComposite.export(category)); return list; } 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 new file mode 100644 index 0000000000..ad099221bb --- /dev/null +++ b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/data/MethodStatComposite.java @@ -0,0 +1,71 @@ +/* + * 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.data; + +import org.apache.dubbo.common.utils.CollectionUtils; +import org.apache.dubbo.metrics.model.MethodMetric; +import org.apache.dubbo.metrics.model.MetricsCategory; +import org.apache.dubbo.metrics.model.key.MetricsKeyWrapper; +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.MetricsExport; +import org.apache.dubbo.rpc.Invocation; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicLong; + +public class MethodStatComposite implements MetricsExport { + + private final Map> methodNumStats = new ConcurrentHashMap<>(); + + public void initWrapper(List metricsKeyWrappers) { + if (CollectionUtils.isEmpty(metricsKeyWrappers)) { + return; + } + metricsKeyWrappers.forEach(appKey -> methodNumStats.put(appKey, new ConcurrentHashMap<>())); + } + + public void incrementMethodKey(MetricsKeyWrapper wrapper, String applicationName, Invocation invocation, int size) { + if (!methodNumStats.containsKey(wrapper)) { + return; + } + methodNumStats.get(wrapper).computeIfAbsent(new MethodMetric(applicationName, invocation), k -> new AtomicLong(0L)).getAndAdd(size); + } + + public List export(MetricsCategory category) { + List list = new ArrayList<>(); + for (MetricsKeyWrapper wrapper : methodNumStats.keySet()) { + Map stringAtomicLongMap = methodNumStats.get(wrapper); + for (MethodMetric methodMetric : stringAtomicLongMap.keySet()) { + if (methodMetric.getSampleType() == MetricSample.Type.GAUGE) { + list.add(new CounterMetricSample<>(wrapper, + methodMetric.getTags(), category, stringAtomicLongMap.get(methodMetric))); + } else { + list.add(new GaugeMetricSample<>(wrapper, methodMetric.getTags(), category, stringAtomicLongMap, value -> value.get(methodMetric).get())); + } + + } + } + return list; + } + +} 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 bf1bd09179..27ba8fe97a 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 @@ -24,9 +24,11 @@ import org.apache.dubbo.metrics.model.container.AtomicLongContainer; import org.apache.dubbo.metrics.model.container.LongAccumulatorContainer; import org.apache.dubbo.metrics.model.container.LongContainer; import org.apache.dubbo.metrics.model.key.MetricsKey; -import org.apache.dubbo.metrics.model.key.MetricsPlaceType; +import org.apache.dubbo.metrics.model.key.MetricsPlaceValue; import org.apache.dubbo.metrics.model.sample.GaugeMetricSample; +import org.apache.dubbo.metrics.model.sample.MetricSample; import org.apache.dubbo.metrics.report.MetricsExport; +import org.apache.dubbo.rpc.Invocation; import java.util.ArrayList; import java.util.Arrays; @@ -36,18 +38,19 @@ import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.LongAccumulator; import java.util.stream.Collectors; +@SuppressWarnings({"rawtypes", "unchecked"}) public class RtStatComposite implements MetricsExport { private final List> rtStats = new ArrayList<>(); - public void init(MetricsPlaceType... placeValues) { + public void init(MetricsPlaceValue... placeValues) { if (placeValues == null) { return; } Arrays.stream(placeValues).forEach(metricsPlaceType -> rtStats.addAll(initStats(metricsPlaceType))); } - private List> initStats(MetricsPlaceType placeValue) { + private List> initStats(MetricsPlaceValue placeValue) { List> singleRtStats = new ArrayList<>(); singleRtStats.add(new AtomicLongContainer(new MetricsKeyWrapper(MetricsKey.METRIC_RT_LAST, placeValue))); singleRtStats.add(new LongAccumulatorContainer(new MetricsKeyWrapper(MetricsKey.METRIC_RT_MIN, placeValue), new LongAccumulator(Long::min, Long.MAX_VALUE))); @@ -65,7 +68,6 @@ public class RtStatComposite implements MetricsExport { return singleRtStats; } - @SuppressWarnings({"rawtypes", "unchecked"}) public void calcApplicationRt(String applicationName, String registryOpType, Long responseTime) { for (LongContainer container : rtStats.stream().filter(longContainer -> longContainer.specifyType(registryOpType)).collect(Collectors.toList())) { Number current = (Number) ConcurrentHashMapUtils.computeIfAbsent(container, applicationName, container.getInitFunc()); @@ -73,7 +75,6 @@ public class RtStatComposite implements MetricsExport { } } - @SuppressWarnings({"rawtypes", "unchecked"}) public void calcServiceKeyRt(String applicationName, 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, applicationName + "_" + serviceKey, container.getInitFunc()); @@ -81,9 +82,15 @@ public class RtStatComposite implements MetricsExport { } } - @SuppressWarnings({"rawtypes"}) - public List export(MetricsCategory category) { - List list = new ArrayList<>(); + public void calcMethodKeyRt(String applicationName, 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, applicationName + "_" + invocation.getServiceName() + "_" + invocation.getMethodName(), container.getInitFunc()); + container.getConsumerFunc().accept(responseTime, current); + } + } + + public List export(MetricsCategory category) { + List list = new ArrayList<>(); for (LongContainer rtContainer : rtStats) { MetricsKeyWrapper metricsKeyWrapper = rtContainer.getMetricsKeyWrapper(); for (Map.Entry entry : rtContainer.entrySet()) { diff --git a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/data/ServiceStatComposite.java b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/data/ServiceStatComposite.java index 7b46751392..f1bfc32b1c 100644 --- a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/data/ServiceStatComposite.java +++ b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/data/ServiceStatComposite.java @@ -20,8 +20,9 @@ package org.apache.dubbo.metrics.data; import org.apache.dubbo.common.utils.CollectionUtils; import org.apache.dubbo.metrics.model.MetricsCategory; import org.apache.dubbo.metrics.model.ServiceKeyMetric; -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 org.apache.dubbo.metrics.model.sample.MetricSample; import org.apache.dubbo.metrics.report.MetricsExport; import java.util.ArrayList; @@ -32,36 +33,35 @@ import java.util.concurrent.atomic.AtomicLong; public class ServiceStatComposite implements MetricsExport { - private final Map> serviceNumStats = new ConcurrentHashMap<>(); + private final Map> serviceWrapperNumStats = new ConcurrentHashMap<>(); - public void init(List serviceKeys) { - if (CollectionUtils.isEmpty(serviceKeys)) { + public void initWrapper(List metricsKeyWrappers) { + if (CollectionUtils.isEmpty(metricsKeyWrappers)) { return; } - serviceKeys.forEach(appKey -> serviceNumStats.put(appKey, new ConcurrentHashMap<>())); + metricsKeyWrappers.forEach(appKey -> serviceWrapperNumStats.put(appKey, new ConcurrentHashMap<>())); } - public void incrementServiceKey(MetricsKey metricsKey, String applicationName, String serviceKey, int size) { - if (!serviceNumStats.containsKey(metricsKey)) { + public void incrementServiceKey(MetricsKeyWrapper wrapper, String applicationName, String serviceKey, int size) { + if (!serviceWrapperNumStats.containsKey(wrapper)) { return; } - serviceNumStats.get(metricsKey).computeIfAbsent(new ServiceKeyMetric(applicationName, serviceKey), k -> new AtomicLong(0L)).getAndAdd(size); + serviceWrapperNumStats.get(wrapper).computeIfAbsent(new ServiceKeyMetric(applicationName, serviceKey), k -> new AtomicLong(0L)).getAndAdd(size); } - public void setServiceKey(MetricsKey type, String applicationName, String serviceKey, int num) { - if (!serviceNumStats.containsKey(type)) { + public void setServiceKey(MetricsKeyWrapper wrapper, String applicationName, String serviceKey, int num) { + if (!serviceWrapperNumStats.containsKey(wrapper)) { return; } - serviceNumStats.get(type).computeIfAbsent(new ServiceKeyMetric(applicationName, serviceKey), k -> new AtomicLong(0L)).set(num); + serviceWrapperNumStats.get(wrapper).computeIfAbsent(new ServiceKeyMetric(applicationName, serviceKey), k -> new AtomicLong(0L)).set(num); } - @SuppressWarnings({"rawtypes"}) - public List export(MetricsCategory category) { - List list = new ArrayList<>(); - for (MetricsKey type : serviceNumStats.keySet()) { - Map stringAtomicLongMap = serviceNumStats.get(type); + public List export(MetricsCategory category) { + List list = new ArrayList<>(); + for (MetricsKeyWrapper wrapper : serviceWrapperNumStats.keySet()) { + Map stringAtomicLongMap = serviceWrapperNumStats.get(wrapper); for (ServiceKeyMetric serviceKeyMetric : stringAtomicLongMap.keySet()) { - list.add(new GaugeMetricSample<>(type, serviceKeyMetric.getTags(), category, stringAtomicLongMap, value -> value.get(serviceKeyMetric).get())); + list.add(new GaugeMetricSample<>(wrapper, serviceKeyMetric.getTags(), category, stringAtomicLongMap, value -> value.get(serviceKeyMetric).get())); } } return list; diff --git a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/event/EmptyEvent.java b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/event/EmptyEvent.java index 7cc8e3e1a2..70c9764dd3 100644 --- a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/event/EmptyEvent.java +++ b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/event/EmptyEvent.java @@ -27,7 +27,7 @@ public class EmptyEvent extends MetricsEvent { private static final EmptyEvent empty = new EmptyEvent(null); private EmptyEvent(ApplicationModel source) { - super(source); + super(source, null); } public static EmptyEvent instance() { 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 26396c8acd..baa5d812fd 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 @@ -35,11 +35,12 @@ public abstract class MetricsEvent { */ protected transient ApplicationModel source; private boolean available = true; - protected TypeWrapper typeWrapper; + private final TypeWrapper typeWrapper; private final Map attachment = new HashMap<>(8); - public MetricsEvent(ApplicationModel source) { + public MetricsEvent(ApplicationModel source, TypeWrapper typeWrapper) { + this.typeWrapper = typeWrapper; if (source == null) { this.source = ApplicationModel.defaultModel(); // Appears only in unit tests @@ -51,8 +52,8 @@ public abstract class MetricsEvent { @SuppressWarnings("unchecked") public T getAttachmentValue(String key) { - if (!attachment.containsKey(key)) { - throw new MetricsNeverHappenException("Attachment key [" + key + "] not found"); + if (key == null) { + throw new MetricsNeverHappenException("Attachment key is null"); } return (T) attachment.get(key); } @@ -82,6 +83,10 @@ public abstract class MetricsEvent { return getSource().getApplicationName(); } + public TypeWrapper getTypeWrapper() { + return typeWrapper; + } + public boolean isAssignableFrom(Object type) { return typeWrapper.isAssignableFrom(type); } @@ -103,6 +108,7 @@ public abstract class MetricsEvent { NETWORK_EXCEPTION("NETWORK_EXCEPTION_%s"), SERVICE_UNAVAILABLE("SERVICE_UNAVAILABLE_%s"), CODEC_EXCEPTION("CODEC_EXCEPTION_%s"), + NO_INVOKER_AVAILABLE("NO_INVOKER_AVAILABLE_%s"), ; private final String name; 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 193f7feb37..8a4121baa6 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 @@ -73,48 +73,77 @@ public class MetricsEventBus { * @return Biz result */ public static T post(MetricsEvent event, Supplier targetSupplier, Function trFunction) { - if (event.getSource() == null) { - return targetSupplier.get(); - } - ApplicationModel applicationModel = event.getSource(); - if (applicationModel.isDestroyed()) { - return targetSupplier.get(); - } - ScopeBeanFactory beanFactory = applicationModel.getBeanFactory(); - if (beanFactory.isDestroyed()) { - return targetSupplier.get(); - } - MetricsDispatcher dispatcher = beanFactory.getBean(MetricsDispatcher.class); - if (dispatcher == null) { - return targetSupplier.get(); - } - dispatcher.publishEvent(event); - if (!(event instanceof TimeCounterEvent)) { - return targetSupplier.get(); - } - TimeCounterEvent timeCounterEvent = (TimeCounterEvent) event; T result; + before(event); if (trFunction == null) { try { result = targetSupplier.get(); } catch (Throwable e) { - dispatcher.publishErrorEvent(timeCounterEvent); + error(event); throw e; } - event.customAfterPost(result); - dispatcher.publishFinishEvent(timeCounterEvent); + after(event, result); } else { // Custom failure status result = targetSupplier.get(); if (trFunction.apply(result)) { - event.customAfterPost(result); - dispatcher.publishFinishEvent(timeCounterEvent); + after(event, result); } else { - dispatcher.publishErrorEvent(timeCounterEvent); + error(event); } } 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) { + MetricsDispatcher dispatcher = validate(event); + if (dispatcher == null) return; + dispatcher.publishEvent(event); + if (eventSaveRunner != null) { + eventSaveRunner.run(); + } + } + + public static void after(MetricsEvent event, Object result) { + MetricsDispatcher dispatcher = validate(event); + if (dispatcher == null) return; + event.customAfterPost(result); + dispatcher.publishFinishEvent((TimeCounterEvent) event); + } + + public static void error(MetricsEvent event) { + MetricsDispatcher dispatcher = validate(event); + if (dispatcher == null) return; + dispatcher.publishErrorEvent((TimeCounterEvent) event); + } + + 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); + if (dispatcher == null) { + return null; + } + if (!(event instanceof TimeCounterEvent)) { + return null; + } + return dispatcher; + } } 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 b4a0db1322..c8f91df47e 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 @@ -18,6 +18,7 @@ package org.apache.dubbo.metrics.event; import org.apache.dubbo.metrics.model.TimePair; +import org.apache.dubbo.metrics.model.key.TypeWrapper; import org.apache.dubbo.rpc.model.ApplicationModel; /** @@ -27,8 +28,8 @@ public abstract class TimeCounterEvent extends MetricsEvent { private final TimePair timePair; - public TimeCounterEvent(ApplicationModel source) { - super(source); + public TimeCounterEvent(ApplicationModel source, TypeWrapper typeWrapper) { + super(source, typeWrapper); this.timePair = TimePair.start(); } diff --git a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/listener/AbstractMetricsKeyListener.java b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/listener/AbstractMetricsKeyListener.java new file mode 100644 index 0000000000..04c18f5263 --- /dev/null +++ b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/listener/AbstractMetricsKeyListener.java @@ -0,0 +1,83 @@ +/* + * 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.listener; + +import org.apache.dubbo.metrics.event.MetricsEvent; +import org.apache.dubbo.metrics.event.MetricsEventBus; +import org.apache.dubbo.metrics.event.TimeCounterEvent; +import org.apache.dubbo.metrics.model.key.MetricsKey; + +import java.util.function.Consumer; + +/** + * According to the event template of {@link MetricsEventBus}, + * build a consistent static method for general and custom monitoring consume methods + */ +public abstract class AbstractMetricsKeyListener extends AbstractMetricsListener implements MetricsLifeListener { + + private final MetricsKey metricsKey; + + public AbstractMetricsKeyListener(MetricsKey metricsKey) { + this.metricsKey = metricsKey; + } + + /** + * The MetricsKey type determines whether events are supported + */ + @Override + public boolean isSupport(MetricsEvent event) { + return super.isSupport(event) && event.isAssignableFrom(metricsKey); + } + + @Override + public void onEvent(TimeCounterEvent event) { + + } + + public static AbstractMetricsKeyListener onEvent(MetricsKey metricsKey, Consumer postFunc) { + + return new AbstractMetricsKeyListener(metricsKey) { + @Override + public void onEvent(TimeCounterEvent event) { + postFunc.accept(event); + } + }; + } + + public static AbstractMetricsKeyListener onFinish(MetricsKey metricsKey, Consumer finishFunc) { + + return new AbstractMetricsKeyListener(metricsKey) { + @Override + public void onEventFinish(TimeCounterEvent event) { + finishFunc.accept(event); + } + }; + } + + public static AbstractMetricsKeyListener onError(MetricsKey metricsKey, Consumer errorFunc) { + + return new AbstractMetricsKeyListener(metricsKey) { + @Override + public void onEventError(TimeCounterEvent event) { + errorFunc.accept(event); + } + }; + } + + +} 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 c588a33ade..5c0247ad6a 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 @@ -17,54 +17,21 @@ package org.apache.dubbo.metrics.listener; +import org.apache.dubbo.common.utils.ReflectionUtils; import org.apache.dubbo.metrics.event.MetricsEvent; -import org.apache.dubbo.metrics.event.TimeCounterEvent; -import org.apache.dubbo.metrics.model.key.MetricsKey; -import java.util.function.Consumer; +import java.util.List; -public abstract class AbstractMetricsListener implements MetricsLifeListener { +public abstract class AbstractMetricsListener implements MetricsListener { - private final MetricsKey metricsKey; - - public AbstractMetricsListener(MetricsKey metricsKey) { - this.metricsKey = metricsKey; + /** + * Whether to support the general determination of event points depends on the event type + */ + public boolean isSupport(MetricsEvent event) { + List> eventTypes = ReflectionUtils.getClassGenerics(getClass(), AbstractMetricsListener.class); + return event.isAvailable() && eventTypes.stream().allMatch(clazz -> clazz.isInstance(event)); } @Override - public boolean isSupport(MetricsEvent event) { - return event.isAvailable() && event.isAssignableFrom(metricsKey); - } - - public static AbstractMetricsListener onEvent(MetricsKey metricsKey, Consumer postFunc) { - - return new AbstractMetricsListener(metricsKey) { - @Override - public void onEvent(TimeCounterEvent event) { - postFunc.accept(event); - } - }; - } - - public static AbstractMetricsListener onFinish(MetricsKey metricsKey, Consumer finishFunc) { - - return new AbstractMetricsListener(metricsKey) { - @Override - public void onEventFinish(TimeCounterEvent event) { - finishFunc.accept(event); - } - }; - } - - public static AbstractMetricsListener onError(MetricsKey metricsKey, Consumer errorFunc) { - - return new AbstractMetricsListener(metricsKey) { - @Override - public void onEventError(TimeCounterEvent event) { - errorFunc.accept(event); - } - }; - } - - + public abstract void onEvent(E event); } 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 d5b6d77ec0..956b518c26 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 @@ -18,24 +18,23 @@ package org.apache.dubbo.metrics.listener; import org.apache.dubbo.metrics.collector.CombMetricsCollector; -import org.apache.dubbo.metrics.event.TimeCounterEvent; import org.apache.dubbo.metrics.model.key.MetricsKey; -import org.apache.dubbo.metrics.model.key.MetricsPlaceType; +import org.apache.dubbo.metrics.model.key.MetricsPlaceValue; -public class MetricsApplicationListener extends AbstractMetricsListener { +public class MetricsApplicationListener extends AbstractMetricsKeyListener { public MetricsApplicationListener(MetricsKey metricsKey) { super(metricsKey); } - public static AbstractMetricsListener onPostEventBuild(MetricsKey metricsKey, CombMetricsCollector collector) { - return AbstractMetricsListener.onEvent(metricsKey, + public static AbstractMetricsKeyListener onPostEventBuild(MetricsKey metricsKey, CombMetricsCollector collector) { + return AbstractMetricsKeyListener.onEvent(metricsKey, event -> collector.increment(event.appName(), metricsKey) ); } - public static AbstractMetricsListener onFinishEventBuild(MetricsKey metricsKey, MetricsPlaceType placeType, CombMetricsCollector collector) { - return AbstractMetricsListener.onFinish(metricsKey, + public static AbstractMetricsKeyListener onFinishEventBuild(MetricsKey metricsKey, MetricsPlaceValue placeType, CombMetricsCollector collector) { + return AbstractMetricsKeyListener.onFinish(metricsKey, event -> { collector.increment(event.appName(), metricsKey); collector.addRt(event.appName(), placeType.getType(), event.getTimePair().calc()); @@ -43,8 +42,8 @@ public class MetricsApplicationListener extends AbstractMetricsListener { ); } - public static AbstractMetricsListener onErrorEventBuild(MetricsKey metricsKey, MetricsPlaceType placeType, CombMetricsCollector collector) { - return AbstractMetricsListener.onError(metricsKey, + public static AbstractMetricsKeyListener onErrorEventBuild(MetricsKey metricsKey, MetricsPlaceValue placeType, CombMetricsCollector collector) { + return AbstractMetricsKeyListener.onError(metricsKey, event -> { collector.increment(event.appName(), metricsKey); collector.addRt(event.appName(), placeType.getType(), event.getTimePair().calc()); diff --git a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/listener/MetricsListener.java b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/listener/MetricsListener.java index 8f0926796e..4e355802db 100644 --- a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/listener/MetricsListener.java +++ b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/listener/MetricsListener.java @@ -19,21 +19,21 @@ package org.apache.dubbo.metrics.listener; import org.apache.dubbo.metrics.event.MetricsEvent; + /** * Metrics Listener. */ public interface MetricsListener { - default boolean isSupport(MetricsEvent event) { - return event.isAvailable(); - } + + boolean isSupport(MetricsEvent event); /** * notify event. * * @param event BaseMetricsEvent */ - default void onEvent(E event) { - } + void onEvent(E event); + } diff --git a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/listener/MetricsServiceListener.java b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/listener/MetricsServiceListener.java index 07a76ab19b..18989d78b4 100644 --- a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/listener/MetricsServiceListener.java +++ b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/listener/MetricsServiceListener.java @@ -19,38 +19,32 @@ package org.apache.dubbo.metrics.listener; import org.apache.dubbo.metrics.collector.ServiceMetricsCollector; import org.apache.dubbo.metrics.event.TimeCounterEvent; +import org.apache.dubbo.metrics.model.MetricsSupport; import org.apache.dubbo.metrics.model.key.MetricsKey; -import org.apache.dubbo.metrics.model.key.MetricsPlaceType; +import org.apache.dubbo.metrics.model.key.MetricsPlaceValue; -import static org.apache.dubbo.metrics.MetricsConstants.ATTACHMENT_KEY_SERVICE; -import static org.apache.dubbo.metrics.MetricsConstants.SELF_INCREMENT_SIZE; - -public class MetricsServiceListener extends AbstractMetricsListener { +public class MetricsServiceListener extends AbstractMetricsKeyListener { public MetricsServiceListener(MetricsKey metricsKey) { super(metricsKey); } - public static AbstractMetricsListener onPostEventBuild(MetricsKey metricsKey, ServiceMetricsCollector collector) { - return AbstractMetricsListener.onEvent(metricsKey, - event -> collector.increment(event.appName(), event.getAttachmentValue(ATTACHMENT_KEY_SERVICE), metricsKey, SELF_INCREMENT_SIZE) + public static AbstractMetricsKeyListener onPostEventBuild(MetricsKey metricsKey, MetricsPlaceValue placeType, ServiceMetricsCollector collector) { + return AbstractMetricsKeyListener.onEvent(metricsKey, + event -> MetricsSupport.increment(metricsKey, placeType, collector, event) ); } - public static AbstractMetricsListener onFinishEventBuild(MetricsKey metricsKey, MetricsPlaceType placeType, ServiceMetricsCollector collector) { - return AbstractMetricsListener.onFinish(metricsKey, - event -> incrAndAddRt(metricsKey, placeType, collector, event) + public static AbstractMetricsKeyListener onFinishEventBuild(MetricsKey metricsKey, MetricsPlaceValue placeType, ServiceMetricsCollector collector) { + return AbstractMetricsKeyListener.onFinish(metricsKey, + event -> MetricsSupport.incrAndAddRt(metricsKey, placeType, collector, event) ); } - public static AbstractMetricsListener onErrorEventBuild(MetricsKey metricsKey, MetricsPlaceType placeType, ServiceMetricsCollector collector) { - return AbstractMetricsListener.onError(metricsKey, - event -> incrAndAddRt(metricsKey, placeType, collector, event) + public static AbstractMetricsKeyListener onErrorEventBuild(MetricsKey metricsKey, MetricsPlaceValue placeType, ServiceMetricsCollector collector) { + return AbstractMetricsKeyListener.onError(metricsKey, + event -> MetricsSupport.incrAndAddRt(metricsKey, placeType, collector, event) ); } - private static void incrAndAddRt(MetricsKey metricsKey, MetricsPlaceType placeType, ServiceMetricsCollector collector, TimeCounterEvent event) { - collector.increment(event.appName(), event.getAttachmentValue(ATTACHMENT_KEY_SERVICE), metricsKey, SELF_INCREMENT_SIZE); - collector.addRt(event.appName(), event.getAttachmentValue(ATTACHMENT_KEY_SERVICE), placeType.getType(), event.getTimePair().calc()); - } } 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 35b7a6bf71..3ab9a91110 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,6 +17,7 @@ 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.Invoker; import org.apache.dubbo.rpc.RpcInvocation; @@ -38,6 +39,7 @@ import static org.apache.dubbo.common.constants.MetricsConstants.TAG_METHOD_KEY; import static org.apache.dubbo.common.constants.MetricsConstants.TAG_VERSION_KEY; 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.INVOCATION_METRICS_COUNTER; import static org.apache.dubbo.rpc.support.RpcUtils.isGenericCall; /** @@ -51,13 +53,21 @@ public class MethodMetric implements Metric { private String group; private String version; - public MethodMetric() {} + private MetricSample.Type sampleType; + + public MethodMetric() { + } public MethodMetric(String applicationName, Invocation invocation) { this.applicationName = applicationName; + this.sampleType = (MetricSample.Type) invocation.get(INVOCATION_METRICS_COUNTER); init(invocation); } + public MetricSample.Type getSampleType() { + return sampleType; + } + public String getInterfaceName() { return interfaceName; } @@ -106,9 +116,9 @@ public class MethodMetric implements Metric { String serviceUniqueName = invocation.getTargetServiceUniqueName(); String methodName = invocation.getMethodName(); if (invocation instanceof RpcInvocation - && isGenericCall(((RpcInvocation) invocation).getParameterTypesDesc(), methodName) - && invocation.getArguments() != null - && invocation.getArguments().length == 3) { + && isGenericCall(((RpcInvocation) invocation).getParameterTypesDesc(), methodName) + && invocation.getArguments() != null + && invocation.getArguments().length == 3) { methodName = ((String) invocation.getArguments()[0]).trim(); } String group = null; @@ -150,13 +160,13 @@ public class MethodMetric implements Metric { @Override public String toString() { return "MethodMetric{" + - "applicationName='" + applicationName + '\'' + - ", side='" + side + '\'' + - ", interfaceName='" + interfaceName + '\'' + - ", methodName='" + methodName + '\'' + - ", group='" + group + '\'' + - ", version='" + version + '\'' + - '}'; + "applicationName='" + applicationName + '\'' + + ", side='" + side + '\'' + + ", interfaceName='" + interfaceName + '\'' + + ", methodName='" + methodName + '\'' + + ", group='" + group + '\'' + + ", version='" + version + '\'' + + '}'; } @Override 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 18b40fc265..2029e6501d 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 @@ -18,19 +18,36 @@ package org.apache.dubbo.metrics.model; import org.apache.dubbo.common.Version; +import org.apache.dubbo.metrics.collector.MethodMetricsCollector; +import org.apache.dubbo.metrics.collector.ServiceMetricsCollector; +import org.apache.dubbo.metrics.event.MetricsEvent; +import org.apache.dubbo.metrics.event.TimeCounterEvent; import org.apache.dubbo.metrics.exception.MetricsNeverHappenException; import org.apache.dubbo.metrics.model.key.MetricsKey; +import org.apache.dubbo.metrics.model.key.MetricsKeyWrapper; +import org.apache.dubbo.metrics.model.key.MetricsPlaceValue; +import org.apache.dubbo.rpc.Invocation; +import org.apache.dubbo.rpc.Invoker; +import org.apache.dubbo.rpc.RpcException; import java.util.HashMap; import java.util.Map; +import java.util.Optional; +import static org.apache.dubbo.common.constants.CommonConstants.GROUP_CHAR_SEPARATOR; +import static org.apache.dubbo.common.constants.CommonConstants.PATH_SEPARATOR; +import static org.apache.dubbo.common.constants.CommonConstants.PROVIDER_SIDE; import static org.apache.dubbo.common.constants.MetricsConstants.TAG_APPLICATION_NAME; import static org.apache.dubbo.common.constants.MetricsConstants.TAG_APPLICATION_VERSION_KEY; import static org.apache.dubbo.common.constants.MetricsConstants.TAG_HOSTNAME; import static org.apache.dubbo.common.constants.MetricsConstants.TAG_INTERFACE_KEY; import static org.apache.dubbo.common.constants.MetricsConstants.TAG_IP; +import static org.apache.dubbo.common.constants.MetricsConstants.TAG_METHOD_KEY; 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.SELF_INCREMENT_SIZE; public class MetricsSupport { @@ -56,4 +73,120 @@ public class MetricsSupport { tags.put(TAG_INTERFACE_KEY, keys[1]); return tags; } + + public static Map methodTags(String names) { + String[] keys = names.split("_"); + if (keys.length != 3) { + throw new MetricsNeverHappenException("Error names: " + names); + } + Map tags = applicationTags(keys[0]); + tags.put(TAG_INTERFACE_KEY, keys[1]); + tags.put(TAG_METHOD_KEY, keys[2]); + return tags; + } + + public static MetricsKey getMetricsKey(RpcException e) { + MetricsKey targetKey; + targetKey = MetricsKey.METRIC_REQUESTS_FAILED; + if (e.isTimeout()) { + targetKey = MetricsKey.METRIC_REQUESTS_TIMEOUT; + } + if (e.isLimitExceed()) { + targetKey = MetricsKey.METRIC_REQUESTS_LIMIT; + } + if (e.isBiz()) { + targetKey = MetricsKey.METRIC_REQUEST_BUSINESS_FAILED; + } + if (e.isSerialization()) { + targetKey = MetricsKey.METRIC_REQUESTS_CODEC_FAILED; + } + if (e.isNetwork()) { + targetKey = MetricsKey.METRIC_REQUESTS_NETWORK_FAILED; + } + return targetKey; + } + + public static MetricsKey getAggMetricsKey(RpcException e) { + MetricsKey targetKey; + targetKey = MetricsKey.METRIC_REQUESTS_FAILED_AGG; + if (e.isTimeout()) { + targetKey = MetricsKey.METRIC_REQUESTS_TIMEOUT_AGG; + } + if (e.isLimitExceed()) { + targetKey = MetricsKey.METRIC_REQUESTS_LIMIT_AGG; + } + if (e.isBiz()) { + targetKey = MetricsKey.METRIC_REQUEST_BUSINESS_FAILED_AGG; + } + if (e.isSerialization()) { + targetKey = MetricsKey.METRIC_REQUESTS_CODEC_FAILED_AGG; + } + if (e.isNetwork()) { + targetKey = MetricsKey.METRIC_REQUESTS_NETWORK_FAILED_AGG; + } + return targetKey; + } + + public static String getSide(Invocation invocation) { + Optional> invoker = Optional.ofNullable(invocation.getInvoker()); + return invoker.isPresent() ? invoker.get().getUrl().getSide() : PROVIDER_SIDE; + } + + + 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]; + } else { + interfaceAndVersion = arr[0]; + } + String[] ivArr = interfaceAndVersion.split(GROUP_CHAR_SEPARATOR); + return ivArr[0]; + } + + /** + * Incr service num + */ + public static void increment(MetricsKey metricsKey, MetricsPlaceValue placeType, ServiceMetricsCollector collector, MetricsEvent event) { + collector.increment(event.appName(), event.getAttachmentValue(ATTACHMENT_KEY_SERVICE), new MetricsKeyWrapper(metricsKey, placeType), SELF_INCREMENT_SIZE); + } + + /** + * Dec service num + */ + public static void dec(MetricsKey metricsKey, MetricsPlaceValue placeType, ServiceMetricsCollector collector, MetricsEvent event) { + collector.increment(event.appName(), event.getAttachmentValue(ATTACHMENT_KEY_SERVICE), new MetricsKeyWrapper(metricsKey, placeType), -SELF_INCREMENT_SIZE); + } + + /** + * Incr service num&&rt + */ + public static void incrAndAddRt(MetricsKey metricsKey, MetricsPlaceValue placeType, ServiceMetricsCollector collector, TimeCounterEvent event) { + collector.increment(event.appName(), event.getAttachmentValue(ATTACHMENT_KEY_SERVICE), new MetricsKeyWrapper(metricsKey, placeType), SELF_INCREMENT_SIZE); + collector.addRt(event.appName(), 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.appName(), event.getAttachmentValue(INVOCATION), 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.appName(), event.getAttachmentValue(INVOCATION), 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.appName(), event.getAttachmentValue(INVOCATION), new MetricsKeyWrapper(metricsKey, placeType), SELF_INCREMENT_SIZE); + collector.addRt(event.appName(), event.getAttachmentValue(INVOCATION), placeType.getType(), event.getTimePair().calc()); + } } diff --git a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/model/key/CategoryOverall.java b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/model/key/CategoryOverall.java index 007a904b72..c13973d17a 100644 --- a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/model/key/CategoryOverall.java +++ b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/model/key/CategoryOverall.java @@ -19,13 +19,20 @@ package org.apache.dubbo.metrics.model.key; import io.micrometer.common.lang.Nullable; +/** + * The overall event set, including the event processing functions in three stages + */ public class CategoryOverall { private final MetricsCat post; private MetricsCat finish; private MetricsCat error; - public CategoryOverall(MetricsPlaceType placeType, MetricsCat post, @Nullable MetricsCat finish, @Nullable MetricsCat error) { + /** + * @param placeType When placeType is null, it means that placeType is obtained dynamically + * @param post Statistics of the number of events, as long as it occurs, it will take effect, so it cannot be null + */ + public CategoryOverall(@Nullable MetricsPlaceValue placeType, MetricsCat post, @Nullable MetricsCat finish, @Nullable MetricsCat error) { this.post = post.setPlaceType(placeType); if (finish != null) { this.finish = finish.setPlaceType(placeType); diff --git a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/model/key/MetricsCat.java b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/model/key/MetricsCat.java index a6301bbd85..88b19cd2f8 100644 --- a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/model/key/MetricsCat.java +++ b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/model/key/MetricsCat.java @@ -18,31 +18,34 @@ package org.apache.dubbo.metrics.model.key; import org.apache.dubbo.metrics.collector.CombMetricsCollector; -import org.apache.dubbo.metrics.event.TimeCounterEvent; -import org.apache.dubbo.metrics.listener.AbstractMetricsListener; +import org.apache.dubbo.metrics.listener.AbstractMetricsKeyListener; import java.util.function.BiFunction; import java.util.function.Function; public class MetricsCat { - private MetricsPlaceType placeType; - private final Function, AbstractMetricsListener> eventFunc; + private MetricsPlaceValue placeType; + private final Function eventFunc; - public MetricsCat(MetricsKey metricsKey, BiFunction, AbstractMetricsListener> biFunc) { + public MetricsCat(MetricsKey metricsKey, BiFunction biFunc) { this.eventFunc = collector -> biFunc.apply(metricsKey, collector); } - public MetricsCat(MetricsKey metricsKey, TpFunction, AbstractMetricsListener> tpFunc) { + /** + * @param metricsKey The key that the current category listens to,not necessarily the export key(export key may be dynamic) + * @param tpFunc Build the func that outputs the MetricsListener by listen metricsKey + */ + public MetricsCat(MetricsKey metricsKey, TpFunction tpFunc) { this.eventFunc = collector -> tpFunc.apply(metricsKey, placeType, collector); } - public MetricsCat setPlaceType(MetricsPlaceType placeType) { + public MetricsCat setPlaceType(MetricsPlaceValue placeType) { this.placeType = placeType; return this; } - public Function, AbstractMetricsListener> getEventFunc() { + public Function getEventFunc() { return eventFunc; } diff --git a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/model/key/MetricsKey.java b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/model/key/MetricsKey.java index 0d993bb4cd..b6158be79a 100644 --- a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/model/key/MetricsKey.java +++ b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/model/key/MetricsKey.java @@ -39,12 +39,12 @@ public enum MetricsKey { METRIC_REQUESTS_TOTAL_AGG("dubbo.%s.requests.total.aggregate", "Aggregated Total Requests"), METRIC_REQUESTS_SUCCEED_AGG("dubbo.%s.requests.succeed.aggregate", "Aggregated Succeed Requests"), METRIC_REQUESTS_FAILED_AGG("dubbo.%s.requests.failed.aggregate", "Aggregated Failed Requests"), - METRIC_REQUESTS_BUSINESS_FAILED_AGG("dubbo.%s.requests.business.failed.aggregate", "Aggregated Business Failed Requests"), + METRIC_REQUEST_BUSINESS_FAILED_AGG("dubbo.%s.requests.business.failed.aggregate", "Aggregated Business Failed Requests"), METRIC_REQUESTS_TIMEOUT_AGG("dubbo.%s.requests.timeout.failed.aggregate", "Aggregated timeout Failed Requests"), METRIC_REQUESTS_LIMIT_AGG("dubbo.%s.requests.limit.aggregate", "Aggregated limit Requests"), METRIC_REQUESTS_TOTAL_FAILED_AGG("dubbo.%s.requests.failed.total.aggregate", "Aggregated failed total Requests"), - METRIC_REQUESTS_TOTAL_NETWORK_FAILED_AGG("dubbo.%s.requests.failed.network.total.aggregate", "Aggregated failed network total Requests"), - METRIC_REQUESTS_TOTAL_CODEC_FAILED_AGG("dubbo.%s.requests.failed.codec.total.aggregate", "Aggregated failed codec total Requests"), + METRIC_REQUESTS_NETWORK_FAILED_AGG("dubbo.%s.requests.failed.network.total.aggregate", "Aggregated failed network total Requests"), + METRIC_REQUESTS_CODEC_FAILED_AGG("dubbo.%s.requests.failed.codec.total.aggregate", "Aggregated failed codec total Requests"), METRIC_REQUESTS_TOTAL_SERVICE_UNAVAILABLE_FAILED_AGG("dubbo.%s.requests.failed.service.unavailable.total.aggregate", "Aggregated failed codec total Requests"), METRIC_QPS("dubbo.%s.qps.total", "Query Per Seconds"), @@ -118,6 +118,7 @@ public enum MetricsKey { METADATA_GIT_COMMITID_METRIC("git.commit.id", "Git Commit Id Metrics"), // consumer metrics key + INVOKER_NO_AVAILABLE_COUNT("dubbo.consumer.invoker.no.available.count", "Request Throw No Invoker Available Exception Count"), ; private String name; diff --git a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/model/key/MetricsKeyWrapper.java b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/model/key/MetricsKeyWrapper.java index c3862f5f38..e213be48cb 100644 --- a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/model/key/MetricsKeyWrapper.java +++ b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/model/key/MetricsKeyWrapper.java @@ -17,9 +17,11 @@ package org.apache.dubbo.metrics.model.key; +import io.micrometer.common.lang.Nullable; import org.apache.dubbo.metrics.model.MetricsSupport; import java.util.Map; +import java.util.Objects; /** * Let {@link MetricsKey MetricsKey} output dynamic, custom string content @@ -31,15 +33,21 @@ public class MetricsKeyWrapper { */ private final MetricsKey metricsKey; + /** + * The value corresponding to the MetricsKey placeholder (if exist) + */ + private final MetricsPlaceValue placeType; - private final MetricsPlaceType placeType; - - public MetricsKeyWrapper(MetricsKey metricsKey, MetricsPlaceType placeType) { + /** + * When the MetricsPlaceType is null, it is equivalent to a single MetricsKey. + * Use the decorator mode to share a container with MetricsKey + */ + public MetricsKeyWrapper(MetricsKey metricsKey, @Nullable MetricsPlaceValue placeType) { this.metricsKey = metricsKey; this.placeType = placeType; } - public MetricsPlaceType getPlaceType() { + public MetricsPlaceValue getPlaceType() { return placeType; } @@ -55,11 +63,14 @@ public class MetricsKeyWrapper { return metricsKey == getMetricsKey() && registryOpType.equals(getType()); } - public boolean isServiceLevel() { - return getPlaceType().getMetricsLevel().equals(MetricsLevel.SERVICE); + public MetricsLevel getLevel() { + return getPlaceType().getMetricsLevel(); } public String targetKey() { + if (placeType == null) { + return metricsKey.getName(); + } try { return String.format(metricsKey.getName(), getType()); } catch (Exception ignore) { @@ -68,6 +79,9 @@ public class MetricsKeyWrapper { } public String targetDesc() { + if (placeType == null) { + return metricsKey.getDescription(); + } try { return String.format(metricsKey.getDescription(), getType()); } catch (Exception ignore) { @@ -76,6 +90,37 @@ public class MetricsKeyWrapper { } public Map tagName(String key) { - return isServiceLevel() ? MetricsSupport.serviceTags(key) : MetricsSupport.applicationTags(key); + MetricsLevel level = getLevel(); + switch (level) { + case APP: + return MetricsSupport.applicationTags(key); + case SERVICE: + return MetricsSupport.serviceTags(key); + case METHOD: + return MetricsSupport.methodTags(key); + } + return MetricsSupport.applicationTags(key); + } + + public static MetricsKeyWrapper wrapper(MetricsKey metricsKey) { + return new MetricsKeyWrapper(metricsKey, null); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + MetricsKeyWrapper wrapper = (MetricsKeyWrapper) o; + + if (metricsKey != wrapper.metricsKey) return false; + return Objects.equals(placeType, wrapper.placeType); + } + + @Override + public int hashCode() { + int result = metricsKey != null ? metricsKey.hashCode() : 0; + result = 31 * result + (placeType != null ? placeType.hashCode() : 0); + return result; } } diff --git a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/model/key/MetricsLevel.java b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/model/key/MetricsLevel.java index aa86ad4946..783de99948 100644 --- a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/model/key/MetricsLevel.java +++ b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/model/key/MetricsLevel.java @@ -18,5 +18,5 @@ package org.apache.dubbo.metrics.model.key; public enum MetricsLevel { - APP,SERVICE + APP, SERVICE, METHOD, CONFIG } diff --git a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/model/key/MetricsPlaceValue.java b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/model/key/MetricsPlaceValue.java new file mode 100644 index 0000000000..30542f73bb --- /dev/null +++ b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/model/key/MetricsPlaceValue.java @@ -0,0 +1,62 @@ +/* + * 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.model.key; + +/** + * The value corresponding to the placeholder in {@link MetricsKey} + */ +public class MetricsPlaceValue { + + private final String type; + private final MetricsLevel metricsLevel; + + private MetricsPlaceValue(String type, MetricsLevel metricsLevel) { + this.type = type; + this.metricsLevel = metricsLevel; + } + + public static MetricsPlaceValue of(String type, MetricsLevel metricsLevel) { + return new MetricsPlaceValue(type, metricsLevel); + } + + public String getType() { + return type; + } + + public MetricsLevel getMetricsLevel() { + return metricsLevel; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + MetricsPlaceValue that = (MetricsPlaceValue) o; + + if (!type.equals(that.type)) return false; + return metricsLevel == that.metricsLevel; + } + + @Override + public int hashCode() { + int result = type.hashCode(); + result = 31 * result + metricsLevel.hashCode(); + return result; + } +} diff --git a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/model/key/TypeWrapper.java b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/model/key/TypeWrapper.java index 812db8f8e6..76c37a5899 100644 --- a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/model/key/TypeWrapper.java +++ b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/model/key/TypeWrapper.java @@ -25,6 +25,10 @@ public class TypeWrapper { private final MetricsKey finishType; private final MetricsKey errorType; + public TypeWrapper(MetricsLevel level, MetricsKey postType) { + this(level, postType, null, null); + } + public TypeWrapper(MetricsLevel level, MetricsKey postType, MetricsKey finishType, MetricsKey errorType) { this.level = level; this.postType = postType; @@ -36,12 +40,9 @@ public class TypeWrapper { return level; } - public MetricsKey getErrorType() { - return errorType; - } - public boolean isAssignableFrom(Object type) { Assert.notNull(type, "Type can not be null"); return type.equals(postType) || type.equals(finishType) || type.equals(errorType); } + } diff --git a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/model/sample/CounterMetricSample.java b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/model/sample/CounterMetricSample.java index 46ce0d50f9..860f1f63b7 100644 --- a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/model/sample/CounterMetricSample.java +++ b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/model/sample/CounterMetricSample.java @@ -17,23 +17,22 @@ package org.apache.dubbo.metrics.model.sample; import org.apache.dubbo.metrics.model.MetricsCategory; +import org.apache.dubbo.metrics.model.key.MetricsKeyWrapper; import java.util.Map; -public class CounterMetricSample extends MetricSample { +public class CounterMetricSample extends MetricSample { private final T value; public CounterMetricSample(String name, String description, Map tags, - MetricsCategory category, T value ) { + MetricsCategory category, T value) { super(name, description, tags, Type.COUNTER, category); this.value = value; } - public CounterMetricSample(String name, String description, Map tags, MetricsCategory category, - String baseUnit, T value) { - super(name, description, tags, Type.COUNTER, category, baseUnit); - this.value = value; + public CounterMetricSample(MetricsKeyWrapper metricsKeyWrapper, Map tags, MetricsCategory category, T value) { + this(metricsKeyWrapper.targetKey(), metricsKeyWrapper.targetDesc(), tags, category, value); } public T getValue() { diff --git a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/model/sample/GaugeMetricSample.java b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/model/sample/GaugeMetricSample.java index b795207070..5a3401d282 100644 --- a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/model/sample/GaugeMetricSample.java +++ b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/model/sample/GaugeMetricSample.java @@ -19,6 +19,7 @@ package org.apache.dubbo.metrics.model.sample; import org.apache.dubbo.metrics.model.MetricsCategory; import org.apache.dubbo.metrics.model.key.MetricsKey; +import org.apache.dubbo.metrics.model.key.MetricsKeyWrapper; import java.util.Map; import java.util.Objects; @@ -37,6 +38,10 @@ public class GaugeMetricSample extends MetricSample { this(metricsKey.getName(), metricsKey.getDescription(), tags, category, null, value, apply); } + public GaugeMetricSample(MetricsKeyWrapper metricsKeyWrapper, Map tags, MetricsCategory category, T value, ToDoubleFunction apply) { + this(metricsKeyWrapper.targetKey(), metricsKeyWrapper.targetDesc(), tags, category, null, value, apply); + } + public GaugeMetricSample(String name, String description, Map tags, MetricsCategory category, T value, ToDoubleFunction apply) { this(name, description, tags, category, null, value, apply); } diff --git a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/report/MetricsExport.java b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/report/MetricsExport.java index 82db29a1cc..d2b7c9eca5 100644 --- a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/report/MetricsExport.java +++ b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/report/MetricsExport.java @@ -18,7 +18,7 @@ package org.apache.dubbo.metrics.report; import org.apache.dubbo.metrics.model.MetricsCategory; -import org.apache.dubbo.metrics.model.sample.GaugeMetricSample; +import org.apache.dubbo.metrics.model.sample.MetricSample; import java.util.List; @@ -31,6 +31,6 @@ public interface MetricsExport { /** * export all. */ - List export(MetricsCategory category); + List export(MetricsCategory category); } 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 16ad2edf05..c18627b584 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 @@ -19,8 +19,8 @@ package org.apache.dubbo.metrics.event; import org.apache.dubbo.config.ApplicationConfig; 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.metrics.listener.MetricsListener; import org.apache.dubbo.rpc.model.ApplicationModel; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; @@ -39,7 +39,7 @@ public class SimpleMetricsEventMulticasterTest { public void setup() { eventMulticaster = new SimpleMetricsEventMulticaster(); objects = new Object[]{obj}; - eventMulticaster.addListener(new MetricsListener() { + eventMulticaster.addListener(new AbstractMetricsListener() { @Override public void onEvent(MetricsEvent event) { objects[0] = new Object(); @@ -52,7 +52,7 @@ public class SimpleMetricsEventMulticasterTest { ConfigManager configManager = new ConfigManager(applicationModel); configManager.setApplication(applicationConfig); applicationModel.setConfigManager(configManager); - requestEvent = new TimeCounterEvent(applicationModel) { + requestEvent = new TimeCounterEvent(applicationModel,null) { }; } @@ -77,6 +77,11 @@ public class SimpleMetricsEventMulticasterTest { //do onEventFinish with MetricsLifeListener eventMulticaster.addListener((new MetricsLifeListener() { + @Override + public boolean isSupport(MetricsEvent event) { + return event instanceof TimeCounterEvent; + } + @Override public void onEvent(TimeCounterEvent event) { diff --git a/dubbo-metrics/dubbo-metrics-api/src/test/java/org/apache/dubbo/metrics/observation/DefaultDubboClientObservationConventionTest.java b/dubbo-metrics/dubbo-metrics-api/src/test/java/org/apache/dubbo/metrics/observation/DefaultDubboClientObservationConventionTest.java new file mode 100644 index 0000000000..8b91e2531d --- /dev/null +++ b/dubbo-metrics/dubbo-metrics-api/src/test/java/org/apache/dubbo/metrics/observation/DefaultDubboClientObservationConventionTest.java @@ -0,0 +1,71 @@ +/* + * 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.observation; + +import io.micrometer.common.KeyValues; +import org.apache.dubbo.metrics.observation.utils.ObservationConventionUtils; +import org.apache.dubbo.rpc.Invoker; +import org.apache.dubbo.rpc.RpcInvocation; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + + +public class DefaultDubboClientObservationConventionTest { + + static DubboClientObservationConvention dubboClientObservationConvention = DefaultDubboClientObservationConvention.getInstance(); + + @Test + void testGetName() { + Assertions.assertEquals("rpc.client.duration", dubboClientObservationConvention.getName()); + } + + @Test + void testGetLowCardinalityKeyValues() throws NoSuchFieldException, IllegalAccessException { + RpcInvocation invocation = new RpcInvocation(); + invocation.setMethodName("testMethod"); + invocation.setAttachment("interface", "com.example.TestService"); + invocation.setTargetServiceUniqueName("targetServiceName1"); + + Invoker invoker = ObservationConventionUtils.getMockInvokerWithUrl(); + invocation.setInvoker(invoker); + + DubboClientContext context = new DubboClientContext(invoker, invocation); + + KeyValues keyValues = dubboClientObservationConvention.getLowCardinalityKeyValues(context); + + Assertions.assertEquals("testMethod", ObservationConventionUtils.getValueForKey(keyValues, "rpc.method")); + Assertions.assertEquals("targetServiceName1", ObservationConventionUtils.getValueForKey(keyValues, "rpc.service")); + Assertions.assertEquals("apache_dubbo", ObservationConventionUtils.getValueForKey(keyValues, "rpc.system")); + } + + @Test + void testGetContextualName() { + RpcInvocation invocation = new RpcInvocation(); + Invoker invoker = ObservationConventionUtils.getMockInvokerWithUrl(); + invocation.setMethodName("testMethod"); + invocation.setServiceName("com.example.TestService"); + + DubboClientContext context = new DubboClientContext(invoker, invocation); + + DefaultDubboClientObservationConvention convention = new DefaultDubboClientObservationConvention(); + + String contextualName = convention.getContextualName(context); + Assertions.assertEquals("com.example.TestService/testMethod", contextualName); + } + + +} diff --git a/dubbo-metrics/dubbo-metrics-api/src/test/java/org/apache/dubbo/metrics/observation/DefaultDubboServerObservationConventionTest.java b/dubbo-metrics/dubbo-metrics-api/src/test/java/org/apache/dubbo/metrics/observation/DefaultDubboServerObservationConventionTest.java new file mode 100644 index 0000000000..faa49457e7 --- /dev/null +++ b/dubbo-metrics/dubbo-metrics-api/src/test/java/org/apache/dubbo/metrics/observation/DefaultDubboServerObservationConventionTest.java @@ -0,0 +1,69 @@ +/* + * 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.observation; + +import io.micrometer.common.KeyValues; +import org.apache.dubbo.metrics.observation.utils.ObservationConventionUtils; +import org.apache.dubbo.rpc.Invoker; +import org.apache.dubbo.rpc.RpcInvocation; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +@SuppressWarnings("deprecation") +public class DefaultDubboServerObservationConventionTest { + + static DubboServerObservationConvention dubboServerObservationConvention = DefaultDubboServerObservationConvention.getInstance(); + + @Test + void testGetName() { + Assertions.assertEquals("rpc.server.duration", dubboServerObservationConvention.getName()); + } + + @Test + void testGetLowCardinalityKeyValues() throws NoSuchFieldException, IllegalAccessException { + RpcInvocation invocation = new RpcInvocation(); + invocation.setMethodName("testMethod"); + invocation.setAttachment("interface", "com.example.TestService"); + invocation.setTargetServiceUniqueName("targetServiceName1"); + + Invoker invoker = ObservationConventionUtils.getMockInvokerWithUrl(); + invocation.setInvoker(invoker); + + DubboServerContext context = new DubboServerContext(invoker, invocation); + + KeyValues keyValues = dubboServerObservationConvention.getLowCardinalityKeyValues(context); + + Assertions.assertEquals("testMethod", ObservationConventionUtils.getValueForKey(keyValues, "rpc.method")); + Assertions.assertEquals("targetServiceName1", ObservationConventionUtils.getValueForKey(keyValues, "rpc.service")); + Assertions.assertEquals("apache_dubbo", ObservationConventionUtils.getValueForKey(keyValues, "rpc.system")); + } + + @Test + void testGetContextualName() { + RpcInvocation invocation = new RpcInvocation(); + Invoker invoker = ObservationConventionUtils.getMockInvokerWithUrl(); + invocation.setMethodName("testMethod"); + invocation.setServiceName("com.example.TestService"); + + DubboClientContext context = new DubboClientContext(invoker, invocation); + + DefaultDubboClientObservationConvention convention = new DefaultDubboClientObservationConvention(); + + String contextualName = convention.getContextualName(context); + Assertions.assertEquals("com.example.TestService/testMethod", contextualName); + } +} diff --git a/dubbo-metrics/dubbo-metrics-api/src/test/java/org/apache/dubbo/metrics/observation/utils/ObservationConventionUtils.java b/dubbo-metrics/dubbo-metrics-api/src/test/java/org/apache/dubbo/metrics/observation/utils/ObservationConventionUtils.java new file mode 100644 index 0000000000..4bf2abfa1e --- /dev/null +++ b/dubbo-metrics/dubbo-metrics-api/src/test/java/org/apache/dubbo/metrics/observation/utils/ObservationConventionUtils.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.observation.utils; + +import io.micrometer.common.KeyValue; +import io.micrometer.common.KeyValues; +import org.apache.dubbo.common.URL; +import org.apache.dubbo.rpc.Invoker; +import org.mockito.Mockito; + +import java.lang.reflect.Field; + +public class ObservationConventionUtils { + + + public static Invoker getMockInvokerWithUrl(){ + URL url = URL.valueOf("dubbo://127.0.0.1:12345/com.example.TestService?anyhost=true&application=test&category=providers&dubbo=2.0.2&generic=false&interface=com.example.TestService&methods=testMethod&pid=26716&side=provider×tamp=1633863896653"); + Invoker invoker = Mockito.mock(Invoker.class); + Mockito.when(invoker.getUrl()).thenReturn(url); + return invoker; + } + + public static String getValueForKey(KeyValues keyValues, Object key) throws NoSuchFieldException, IllegalAccessException { + Field f = KeyValues.class.getDeclaredField("keyValues"); + f.setAccessible(true); + KeyValue[] kv = (KeyValue[]) f.get(keyValues); + for (KeyValue keyValue : kv) { + if (keyValue.getKey().equals(key)) { + return keyValue.getValue(); + } + } + return null; + } +} diff --git a/dubbo-metrics/dubbo-metrics-config-center/pom.xml b/dubbo-metrics/dubbo-metrics-config-center/pom.xml new file mode 100644 index 0000000000..aa65f3aef0 --- /dev/null +++ b/dubbo-metrics/dubbo-metrics-config-center/pom.xml @@ -0,0 +1,34 @@ + + + 4.0.0 + + org.apache.dubbo + dubbo-metrics + ${revision} + ../pom.xml + + dubbo-metrics-config-center + ${project.artifactId} + + + + org.apache.dubbo + dubbo-metrics-api + ${project.parent.version} + + + diff --git a/dubbo-metrics/dubbo-metrics-config-center/src/main/java/org/apache/dubbo/metrics/config/ConfigCenterMetricsConstants.java b/dubbo-metrics/dubbo-metrics-config-center/src/main/java/org/apache/dubbo/metrics/config/ConfigCenterMetricsConstants.java new file mode 100644 index 0000000000..8a7d22c762 --- /dev/null +++ b/dubbo-metrics/dubbo-metrics-config-center/src/main/java/org/apache/dubbo/metrics/config/ConfigCenterMetricsConstants.java @@ -0,0 +1,26 @@ +/* + * 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.config; + +public interface ConfigCenterMetricsConstants { + + String ATTACHMENT_KEY_CONFIG_FILE = "configFileKey"; + String ATTACHMENT_KEY_CONFIG_GROUP = "configGroup"; + String ATTACHMENT_KEY_CONFIG_PROTOCOL = "configProtocol"; + String ATTACHMENT_KEY_CHANGE_TYPE = "configChangeType"; + +} diff --git a/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/collector/ConfigCenterMetricsCollector.java b/dubbo-metrics/dubbo-metrics-config-center/src/main/java/org/apache/dubbo/metrics/config/collector/ConfigCenterMetricsCollector.java similarity index 61% rename from dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/collector/ConfigCenterMetricsCollector.java rename to dubbo-metrics/dubbo-metrics-config-center/src/main/java/org/apache/dubbo/metrics/config/collector/ConfigCenterMetricsCollector.java index 5fa34e4d42..d0dd1a7d7a 100644 --- a/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/collector/ConfigCenterMetricsCollector.java +++ b/dubbo-metrics/dubbo-metrics-config-center/src/main/java/org/apache/dubbo/metrics/config/collector/ConfigCenterMetricsCollector.java @@ -15,10 +15,14 @@ * limitations under the License. */ -package org.apache.dubbo.metrics.collector; +package org.apache.dubbo.metrics.config.collector; -import org.apache.dubbo.common.config.configcenter.ConfigChangeType; -import org.apache.dubbo.common.config.configcenter.ConfigChangedEvent; +import org.apache.dubbo.common.extension.Activate; +import org.apache.dubbo.config.context.ConfigManager; +import org.apache.dubbo.metrics.collector.CombMetricsCollector; +import org.apache.dubbo.metrics.collector.MetricsCollector; +import org.apache.dubbo.metrics.config.event.ConfigCenterEvent; +import org.apache.dubbo.metrics.config.event.ConfigCenterSubDispatcher; import org.apache.dubbo.metrics.model.ConfigCenterMetric; import org.apache.dubbo.metrics.model.key.MetricsKey; import org.apache.dubbo.metrics.model.sample.GaugeMetricSample; @@ -28,25 +32,28 @@ import org.apache.dubbo.rpc.model.ApplicationModel; import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicLong; -import static org.apache.dubbo.common.constants.CommonConstants.DUBBO_METRICS_CONFIGCENTER_ENABLE; import static org.apache.dubbo.metrics.model.MetricsCategory.CONFIGCENTER; -public class ConfigCenterMetricsCollector implements MetricsCollector { - private boolean collectEnabled = true; +/** + * Config center implementation of {@link MetricsCollector} + */ +@Activate +public class ConfigCenterMetricsCollector extends CombMetricsCollector { + + private Boolean collectEnabled = null; private final ApplicationModel applicationModel; private final Map updatedMetrics = new ConcurrentHashMap<>(); public ConfigCenterMetricsCollector(ApplicationModel applicationModel) { + super(null); this.applicationModel = applicationModel; - // default is true, disable when config false - if ("false".equals(System.getProperty(DUBBO_METRICS_CONFIGCENTER_ENABLE))) { - collectEnabled = false; - } + super.setEventMulticaster(new ConfigCenterSubDispatcher(this)); } public void setCollectEnabled(Boolean collectEnabled) { @@ -57,29 +64,21 @@ public class ConfigCenterMetricsCollector implements MetricsCollector { @Override public boolean isCollectEnabled() { - return collectEnabled; + if (collectEnabled == null) { + ConfigManager configManager = applicationModel.getApplicationConfigManager(); + configManager.getMetrics().ifPresent(metricsConfig -> setCollectEnabled(metricsConfig.getEnableMetadata())); + } + return Optional.ofNullable(collectEnabled).orElse(true); } - public void increase4Initialized(String key, String group, String protocol, String applicationName, int count) { + public void increase(String key, String group, String protocol, String changeTypeName, int size) { if (!isCollectEnabled()) { return; } - if (count <= 0) { - return; - } - ConfigCenterMetric metric = new ConfigCenterMetric(applicationName, key, group, protocol, ConfigChangeType.ADDED.name()); - AtomicLong aLong = updatedMetrics.computeIfAbsent(metric, k -> new AtomicLong(0L)); - aLong.addAndGet(count); + ConfigCenterMetric metric = new ConfigCenterMetric(applicationModel.getApplicationName(), key, group, protocol, changeTypeName); + updatedMetrics.computeIfAbsent(metric, k -> new AtomicLong(0L)).addAndGet(size); } - public void increaseUpdated(String protocol, String applicationName, ConfigChangedEvent event) { - if (!isCollectEnabled()) { - return; - } - ConfigCenterMetric metric = new ConfigCenterMetric(applicationName, event.getKey(), event.getGroup(), protocol, event.getChangeType().name()); - AtomicLong count = updatedMetrics.computeIfAbsent(metric, k -> new AtomicLong(0L)); - count.incrementAndGet(); - } @Override public List collect() { @@ -88,12 +87,9 @@ public class ConfigCenterMetricsCollector implements MetricsCollector { if (!isCollectEnabled()) { return list; } - collect(list); + updatedMetrics.forEach((k, v) -> list.add(new GaugeMetricSample<>(MetricsKey.CONFIGCENTER_METRIC_TOTAL, k.getTags(), CONFIGCENTER, v, AtomicLong::get))); return list; } - private void collect(List list) { - updatedMetrics.forEach((k, v) -> list.add(new GaugeMetricSample<>(MetricsKey.CONFIGCENTER_METRIC_TOTAL, k.getTags(), CONFIGCENTER, v, AtomicLong::get))); - } } 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 new file mode 100644 index 0000000000..3c1577a700 --- /dev/null +++ b/dubbo-metrics/dubbo-metrics-config-center/src/main/java/org/apache/dubbo/metrics/config/event/ConfigCenterEvent.java @@ -0,0 +1,69 @@ +/* + * 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.config.event; + +import org.apache.dubbo.common.beans.factory.ScopeBeanFactory; +import org.apache.dubbo.metrics.config.collector.ConfigCenterMetricsCollector; +import org.apache.dubbo.metrics.event.TimeCounterEvent; +import org.apache.dubbo.metrics.model.key.MetricsLevel; +import org.apache.dubbo.metrics.model.key.TypeWrapper; +import org.apache.dubbo.rpc.model.ApplicationModel; + +import static org.apache.dubbo.metrics.MetricsConstants.ATTACHMENT_KEY_SIZE; +import static org.apache.dubbo.metrics.config.ConfigCenterMetricsConstants.ATTACHMENT_KEY_CHANGE_TYPE; +import static org.apache.dubbo.metrics.config.ConfigCenterMetricsConstants.ATTACHMENT_KEY_CONFIG_FILE; +import static org.apache.dubbo.metrics.config.ConfigCenterMetricsConstants.ATTACHMENT_KEY_CONFIG_GROUP; +import static org.apache.dubbo.metrics.config.ConfigCenterMetricsConstants.ATTACHMENT_KEY_CONFIG_PROTOCOL; +import static org.apache.dubbo.metrics.model.key.MetricsKey.CONFIGCENTER_METRIC_TOTAL; + +/** + * Registry related events + * Triggered in three types of configuration centers (apollo, zk, nacos) + */ +public class ConfigCenterEvent extends TimeCounterEvent { + + + public static final String NACOS_PROTOCOL = "nacos"; + public static final String APOLLO_PROTOCOL = "apollo"; + public static final String ZK_PROTOCOL = "zookeeper"; + + + public ConfigCenterEvent(ApplicationModel applicationModel, TypeWrapper typeWrapper) { + super(applicationModel,typeWrapper); + ScopeBeanFactory beanFactory = applicationModel.getBeanFactory(); + ConfigCenterMetricsCollector collector; + if (!beanFactory.isDestroyed()) { + collector = beanFactory.getBean(ConfigCenterMetricsCollector.class); + super.setAvailable(collector != null && collector.isCollectEnabled()); + } + } + + + public static ConfigCenterEvent toChangeEvent(ApplicationModel applicationModel, String key, String group, String protocol, String changeType, int count) { + ConfigCenterEvent configCenterEvent = new ConfigCenterEvent(applicationModel, new TypeWrapper(MetricsLevel.CONFIG, CONFIGCENTER_METRIC_TOTAL)); + configCenterEvent.putAttachment(ATTACHMENT_KEY_CONFIG_FILE, key); + configCenterEvent.putAttachment(ATTACHMENT_KEY_CONFIG_GROUP, group); + configCenterEvent.putAttachment(ATTACHMENT_KEY_CONFIG_PROTOCOL, protocol); + configCenterEvent.putAttachment(ATTACHMENT_KEY_CHANGE_TYPE, changeType); + configCenterEvent.putAttachment(ATTACHMENT_KEY_SIZE, count); + return configCenterEvent; + + } + + +} diff --git a/dubbo-metrics/dubbo-metrics-config-center/src/main/java/org/apache/dubbo/metrics/config/event/ConfigCenterSubDispatcher.java b/dubbo-metrics/dubbo-metrics-config-center/src/main/java/org/apache/dubbo/metrics/config/event/ConfigCenterSubDispatcher.java new file mode 100644 index 0000000000..1604cb3b62 --- /dev/null +++ b/dubbo-metrics/dubbo-metrics-config-center/src/main/java/org/apache/dubbo/metrics/config/event/ConfigCenterSubDispatcher.java @@ -0,0 +1,58 @@ +/* + * 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.config.event; + +import org.apache.dubbo.metrics.config.collector.ConfigCenterMetricsCollector; +import org.apache.dubbo.metrics.event.MetricsEvent; +import org.apache.dubbo.metrics.event.SimpleMetricsEventMulticaster; +import org.apache.dubbo.metrics.event.TimeCounterEvent; +import org.apache.dubbo.metrics.listener.AbstractMetricsKeyListener; +import org.apache.dubbo.metrics.model.key.MetricsKey; + +import static org.apache.dubbo.metrics.MetricsConstants.ATTACHMENT_KEY_SIZE; +import static org.apache.dubbo.metrics.config.ConfigCenterMetricsConstants.ATTACHMENT_KEY_CHANGE_TYPE; +import static org.apache.dubbo.metrics.config.ConfigCenterMetricsConstants.ATTACHMENT_KEY_CONFIG_FILE; +import static org.apache.dubbo.metrics.config.ConfigCenterMetricsConstants.ATTACHMENT_KEY_CONFIG_GROUP; +import static org.apache.dubbo.metrics.config.ConfigCenterMetricsConstants.ATTACHMENT_KEY_CONFIG_PROTOCOL; + + +public final class ConfigCenterSubDispatcher extends SimpleMetricsEventMulticaster { + + public ConfigCenterSubDispatcher(ConfigCenterMetricsCollector collector) { + + super.addListener(new AbstractMetricsKeyListener(MetricsKey.CONFIGCENTER_METRIC_TOTAL) { + @Override + public boolean isSupport(MetricsEvent event) { + return event instanceof ConfigCenterEvent; + } + + @Override + public void onEvent(TimeCounterEvent event) { + collector.increase( + event.getAttachmentValue(ATTACHMENT_KEY_CONFIG_FILE), + event.getAttachmentValue(ATTACHMENT_KEY_CONFIG_GROUP), + event.getAttachmentValue(ATTACHMENT_KEY_CONFIG_PROTOCOL), + event.getAttachmentValue(ATTACHMENT_KEY_CHANGE_TYPE), + event.getAttachmentValue(ATTACHMENT_KEY_SIZE) + ); + } + }); + + } + + +} diff --git a/dubbo-metrics/dubbo-metrics-config-center/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.metrics.collector.MetricsCollector b/dubbo-metrics/dubbo-metrics-config-center/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.metrics.collector.MetricsCollector new file mode 100644 index 0000000000..fcf8df6889 --- /dev/null +++ b/dubbo-metrics/dubbo-metrics-config-center/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.metrics.collector.MetricsCollector @@ -0,0 +1 @@ +config-collector=org.apache.dubbo.metrics.config.collector.ConfigCenterMetricsCollector diff --git a/dubbo-metrics/dubbo-metrics-default/src/test/java/org/apache/dubbo/metrics/collector/ConfigCenterMetricsCollectorTest.java b/dubbo-metrics/dubbo-metrics-config-center/src/test/java/org/apache/dubbo/metrics/collector/ConfigCenterMetricsCollectorTest.java similarity index 82% rename from dubbo-metrics/dubbo-metrics-default/src/test/java/org/apache/dubbo/metrics/collector/ConfigCenterMetricsCollectorTest.java rename to dubbo-metrics/dubbo-metrics-config-center/src/test/java/org/apache/dubbo/metrics/collector/ConfigCenterMetricsCollectorTest.java index e234279339..f20c047871 100644 --- a/dubbo-metrics/dubbo-metrics-default/src/test/java/org/apache/dubbo/metrics/collector/ConfigCenterMetricsCollectorTest.java +++ b/dubbo-metrics/dubbo-metrics-config-center/src/test/java/org/apache/dubbo/metrics/collector/ConfigCenterMetricsCollectorTest.java @@ -20,7 +20,7 @@ package org.apache.dubbo.metrics.collector; import org.apache.dubbo.common.config.configcenter.ConfigChangeType; import org.apache.dubbo.common.config.configcenter.ConfigChangedEvent; import org.apache.dubbo.config.ApplicationConfig; -import org.apache.dubbo.metrics.model.ConfigCenterMetric; +import org.apache.dubbo.metrics.config.collector.ConfigCenterMetricsCollector; import org.apache.dubbo.metrics.model.sample.GaugeMetricSample; import org.apache.dubbo.metrics.model.sample.MetricSample; import org.apache.dubbo.rpc.model.ApplicationModel; @@ -32,14 +32,9 @@ import org.junit.jupiter.api.Test; import java.util.List; import java.util.Map; -import java.util.function.Supplier; import static org.apache.dubbo.common.constants.MetricsConstants.TAG_APPLICATION_NAME; -import static org.apache.dubbo.common.constants.MetricsConstants.TAG_GROUP_KEY; -import static org.apache.dubbo.common.constants.MetricsConstants.TAG_INTERFACE_KEY; -import static org.apache.dubbo.common.constants.MetricsConstants.TAG_METHOD_KEY; -import static org.apache.dubbo.common.constants.MetricsConstants.TAG_VERSION_KEY; -import static org.junit.jupiter.api.Assertions.*; +import static org.apache.dubbo.metrics.MetricsConstants.SELF_INCREMENT_SIZE; class ConfigCenterMetricsCollectorTest { @@ -66,8 +61,8 @@ class ConfigCenterMetricsCollectorTest { ConfigCenterMetricsCollector collector = new ConfigCenterMetricsCollector(applicationModel); collector.setCollectEnabled(true); String applicationName = applicationModel.getApplicationName(); - collector.increase4Initialized("key", "group", "nacos", applicationName, 1); - collector.increase4Initialized("key", "group", "nacos", applicationName, 1); + collector.increase("key", "group", "nacos", ConfigChangeType.ADDED.name(), 1); + collector.increase("key", "group", "nacos", ConfigChangeType.ADDED.name(), 1); List samples = collector.collect(); for (MetricSample sample : samples) { @@ -87,9 +82,12 @@ class ConfigCenterMetricsCollectorTest { String applicationName = applicationModel.getApplicationName(); ConfigChangedEvent event = new ConfigChangedEvent("key", "group", null, ConfigChangeType.ADDED); - - collector.increaseUpdated("nacos", applicationName, event); - collector.increaseUpdated("nacos", applicationName, event); + + collector.increase(event.getKey(), event.getGroup(), + "apollo", ConfigChangeType.ADDED.name(), SELF_INCREMENT_SIZE); + + collector.increase(event.getKey(), event.getGroup(), + "apollo", ConfigChangeType.ADDED.name(), SELF_INCREMENT_SIZE); List samples = collector.collect(); for (MetricSample sample : samples) { diff --git a/dubbo-metrics/dubbo-metrics-default/pom.xml b/dubbo-metrics/dubbo-metrics-default/pom.xml index 27e5ccfe82..f9130bf7e1 100644 --- a/dubbo-metrics/dubbo-metrics-default/pom.xml +++ b/dubbo-metrics/dubbo-metrics-default/pom.xml @@ -53,6 +53,5 @@ micrometer-tracing-integration-test test - diff --git a/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/DefaultConstants.java b/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/DefaultConstants.java new file mode 100644 index 0000000000..c4e6f9485c --- /dev/null +++ b/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/DefaultConstants.java @@ -0,0 +1,70 @@ +/* + * 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; + +import org.apache.dubbo.common.constants.CommonConstants; +import org.apache.dubbo.metrics.model.key.MetricsKeyWrapper; +import org.apache.dubbo.metrics.model.key.MetricsLevel; +import org.apache.dubbo.metrics.model.key.MetricsPlaceValue; + +import java.util.Arrays; +import java.util.List; + +import static org.apache.dubbo.metrics.model.key.MetricsKey.METRIC_REQUESTS; +import static org.apache.dubbo.metrics.model.key.MetricsKey.METRIC_REQUESTS_CODEC_FAILED; +import static org.apache.dubbo.metrics.model.key.MetricsKey.METRIC_REQUESTS_FAILED; +import static org.apache.dubbo.metrics.model.key.MetricsKey.METRIC_REQUESTS_LIMIT; +import static org.apache.dubbo.metrics.model.key.MetricsKey.METRIC_REQUESTS_NETWORK_FAILED; +import static org.apache.dubbo.metrics.model.key.MetricsKey.METRIC_REQUESTS_PROCESSING; +import static org.apache.dubbo.metrics.model.key.MetricsKey.METRIC_REQUESTS_SERVICE_UNAVAILABLE_FAILED; +import static org.apache.dubbo.metrics.model.key.MetricsKey.METRIC_REQUESTS_SUCCEED; +import static org.apache.dubbo.metrics.model.key.MetricsKey.METRIC_REQUESTS_TIMEOUT; +import static org.apache.dubbo.metrics.model.key.MetricsKey.METRIC_REQUESTS_TOTAL_FAILED; +import static org.apache.dubbo.metrics.model.key.MetricsKey.METRIC_REQUEST_BUSINESS_FAILED; + +public interface DefaultConstants { + + String METRIC_FILTER_EVENT = "metric_filter_event"; + + String METRIC_THROWABLE = "metric_filter_throwable"; + + List METHOD_LEVEL_KEYS = Arrays.asList( + new MetricsKeyWrapper(METRIC_REQUESTS, MetricsPlaceValue.of(CommonConstants.PROVIDER, MetricsLevel.METHOD)), + new MetricsKeyWrapper(METRIC_REQUESTS, MetricsPlaceValue.of(CommonConstants.CONSUMER, MetricsLevel.METHOD)), + new MetricsKeyWrapper(METRIC_REQUESTS_PROCESSING, MetricsPlaceValue.of(CommonConstants.PROVIDER, MetricsLevel.METHOD)), + new MetricsKeyWrapper(METRIC_REQUESTS_PROCESSING, MetricsPlaceValue.of(CommonConstants.CONSUMER, MetricsLevel.METHOD)), + new MetricsKeyWrapper(METRIC_REQUESTS_SUCCEED, MetricsPlaceValue.of(CommonConstants.PROVIDER, MetricsLevel.METHOD)), + new MetricsKeyWrapper(METRIC_REQUESTS_SUCCEED, MetricsPlaceValue.of(CommonConstants.CONSUMER, MetricsLevel.METHOD)), + new MetricsKeyWrapper(METRIC_REQUEST_BUSINESS_FAILED, MetricsPlaceValue.of(CommonConstants.PROVIDER, MetricsLevel.METHOD)), + new MetricsKeyWrapper(METRIC_REQUEST_BUSINESS_FAILED, MetricsPlaceValue.of(CommonConstants.CONSUMER, MetricsLevel.METHOD)), + new MetricsKeyWrapper(METRIC_REQUESTS_TIMEOUT, MetricsPlaceValue.of(CommonConstants.PROVIDER, MetricsLevel.METHOD)), + new MetricsKeyWrapper(METRIC_REQUESTS_TIMEOUT, MetricsPlaceValue.of(CommonConstants.CONSUMER, MetricsLevel.METHOD)), + new MetricsKeyWrapper(METRIC_REQUESTS_LIMIT, MetricsPlaceValue.of(CommonConstants.PROVIDER, MetricsLevel.METHOD)), + new MetricsKeyWrapper(METRIC_REQUESTS_LIMIT, MetricsPlaceValue.of(CommonConstants.CONSUMER, MetricsLevel.METHOD)), + new MetricsKeyWrapper(METRIC_REQUESTS_FAILED, MetricsPlaceValue.of(CommonConstants.PROVIDER, MetricsLevel.METHOD)), + new MetricsKeyWrapper(METRIC_REQUESTS_FAILED, MetricsPlaceValue.of(CommonConstants.CONSUMER, MetricsLevel.METHOD)), + new MetricsKeyWrapper(METRIC_REQUESTS_TOTAL_FAILED, MetricsPlaceValue.of(CommonConstants.PROVIDER, MetricsLevel.METHOD)), + new MetricsKeyWrapper(METRIC_REQUESTS_TOTAL_FAILED, MetricsPlaceValue.of(CommonConstants.CONSUMER, MetricsLevel.METHOD)), + new MetricsKeyWrapper(METRIC_REQUESTS_NETWORK_FAILED, MetricsPlaceValue.of(CommonConstants.PROVIDER, MetricsLevel.METHOD)), + new MetricsKeyWrapper(METRIC_REQUESTS_NETWORK_FAILED, MetricsPlaceValue.of(CommonConstants.CONSUMER, MetricsLevel.METHOD)), + new MetricsKeyWrapper(METRIC_REQUESTS_SERVICE_UNAVAILABLE_FAILED, MetricsPlaceValue.of(CommonConstants.PROVIDER, MetricsLevel.METHOD)), + new MetricsKeyWrapper(METRIC_REQUESTS_SERVICE_UNAVAILABLE_FAILED, MetricsPlaceValue.of(CommonConstants.CONSUMER, MetricsLevel.METHOD)), + new MetricsKeyWrapper(METRIC_REQUESTS_CODEC_FAILED, MetricsPlaceValue.of(CommonConstants.PROVIDER, MetricsLevel.METHOD)), + new MetricsKeyWrapper(METRIC_REQUESTS_CODEC_FAILED, MetricsPlaceValue.of(CommonConstants.CONSUMER, MetricsLevel.METHOD)) + ); +} diff --git a/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/MetricsScopeModelInitializer.java b/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/MetricsScopeModelInitializer.java index 15b2806cc6..660fcc835d 100644 --- a/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/MetricsScopeModelInitializer.java +++ b/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/MetricsScopeModelInitializer.java @@ -18,7 +18,6 @@ package org.apache.dubbo.metrics; import org.apache.dubbo.common.beans.factory.ScopeBeanFactory; -import org.apache.dubbo.metrics.collector.DefaultMetricsCollector; import org.apache.dubbo.metrics.event.MetricsDispatcher; import org.apache.dubbo.rpc.model.ApplicationModel; import org.apache.dubbo.rpc.model.FrameworkModel; @@ -35,7 +34,6 @@ public class MetricsScopeModelInitializer implements ScopeModelInitializer { @Override public void initializeApplicationModel(ApplicationModel applicationModel) { ScopeBeanFactory beanFactory = applicationModel.getBeanFactory(); - beanFactory.registerBean(DefaultMetricsCollector.class); beanFactory.registerBean(MetricsDispatcher.class); } diff --git a/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/collector/AggregateMetricsCollector.java b/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/collector/AggregateMetricsCollector.java index 286fa1dcd0..4dc18f896e 100644 --- a/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/collector/AggregateMetricsCollector.java +++ b/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/collector/AggregateMetricsCollector.java @@ -21,26 +21,32 @@ import org.apache.dubbo.common.utils.ConcurrentHashMapUtils; import org.apache.dubbo.config.MetricsConfig; import org.apache.dubbo.config.context.ConfigManager; import org.apache.dubbo.config.nested.AggregationConfig; +import org.apache.dubbo.metrics.MetricsConstants; import org.apache.dubbo.metrics.aggregate.TimeWindowCounter; import org.apache.dubbo.metrics.aggregate.TimeWindowQuantile; -import org.apache.dubbo.metrics.event.MethodEvent; import org.apache.dubbo.metrics.event.MetricsEvent; -import org.apache.dubbo.metrics.event.RTEvent; -import org.apache.dubbo.metrics.listener.MetricsListener; +import org.apache.dubbo.metrics.event.RequestEvent; 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.MetricsKeyWrapper; +import org.apache.dubbo.metrics.model.key.MetricsLevel; +import org.apache.dubbo.metrics.model.key.MetricsPlaceValue; import org.apache.dubbo.metrics.model.sample.GaugeMetricSample; import org.apache.dubbo.metrics.model.sample.MetricSample; +import org.apache.dubbo.rpc.RpcException; import org.apache.dubbo.rpc.model.ApplicationModel; import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import static org.apache.dubbo.common.constants.CommonConstants.CONSUMER_SIDE; import static org.apache.dubbo.common.constants.CommonConstants.PROVIDER_SIDE; +import static org.apache.dubbo.metrics.DefaultConstants.METRIC_THROWABLE; import static org.apache.dubbo.metrics.model.MetricsCategory.QPS; import static org.apache.dubbo.metrics.model.MetricsCategory.REQUESTS; import static org.apache.dubbo.metrics.model.MetricsCategory.RT; @@ -49,68 +55,101 @@ import static org.apache.dubbo.metrics.model.MetricsCategory.RT; * Aggregation metrics collector implementation of {@link MetricsCollector}. * This collector only enabled when metrics aggregation config is enabled. */ -public class AggregateMetricsCollector implements MetricsCollector, MetricsListener { +public class AggregateMetricsCollector implements MetricsCollector { private int bucketNum; private int timeWindowSeconds; - private final Map> methodTypeCounter = new ConcurrentHashMap<>(); + private final Map> methodTypeCounter = new ConcurrentHashMap<>(); private final ConcurrentMap rt = new ConcurrentHashMap<>(); private final ConcurrentHashMap qps = new ConcurrentHashMap<>(); private final ApplicationModel applicationModel; private static final Integer DEFAULT_COMPRESSION = 100; private static final Integer DEFAULT_BUCKET_NUM = 10; private static final Integer DEFAULT_TIME_WINDOW_SECONDS = 120; + private Boolean collectEnabled = null; public AggregateMetricsCollector(ApplicationModel applicationModel) { - this.registryEventTypeHandler(); - this.applicationModel = applicationModel; ConfigManager configManager = applicationModel.getApplicationConfigManager(); - MetricsConfig config = configManager.getMetrics().orElse(null); - if (config != null && config.getAggregation() != null && (config.getAggregation().getEnabled() == null || Boolean.TRUE.equals(config.getAggregation().getEnabled()))) { + if (isCollectEnabled()) { // only registered when aggregation is enabled. - registerListener(); - - AggregationConfig aggregation = config.getAggregation(); - this.bucketNum = aggregation.getBucketNum() == null ? DEFAULT_BUCKET_NUM : aggregation.getBucketNum(); - this.timeWindowSeconds = aggregation.getTimeWindowSeconds() == null ? DEFAULT_TIME_WINDOW_SECONDS : aggregation.getTimeWindowSeconds(); + Optional optional = configManager.getMetrics(); + if (optional.isPresent()) { + registerListener(); + AggregationConfig aggregation = optional.get().getAggregation(); + this.bucketNum = aggregation.getBucketNum() == null ? DEFAULT_BUCKET_NUM : aggregation.getBucketNum(); + this.timeWindowSeconds = aggregation.getTimeWindowSeconds() == null ? DEFAULT_TIME_WINDOW_SECONDS : aggregation.getTimeWindowSeconds(); + } } } + public void setCollectEnabled(Boolean collectEnabled) { + if (collectEnabled != null) { + this.collectEnabled = collectEnabled; + } + } + + + @Override + public boolean isCollectEnabled() { + if (collectEnabled == null) { + ConfigManager configManager = applicationModel.getApplicationConfigManager(); + configManager.getMetrics().ifPresent(metricsConfig -> setCollectEnabled(metricsConfig.getAggregation().getEnabled())); + } + return Optional.ofNullable(collectEnabled).orElse(true); + } + @Override - public void onEvent(MetricsEvent event) { - if (event instanceof RTEvent) { - onRTEvent((RTEvent) event); - } else if (event instanceof MethodEvent) { - onRequestEvent((MethodEvent) event); - } + public boolean isSupport(MetricsEvent event) { + return event instanceof RequestEvent; } - private void onRTEvent(RTEvent event) { - MethodMetric metric = (MethodMetric) event.getMetric(); - Long responseTime = event.getRt(); + @Override + public void onEvent(RequestEvent event) { + MethodMetric metric = calcWindowCounter(event, MetricsKey.METRIC_REQUESTS); + TimeWindowCounter qpsCounter = ConcurrentHashMapUtils.computeIfAbsent(qps, metric, methodMetric -> new TimeWindowCounter(bucketNum, timeWindowSeconds)); + qpsCounter.increment(); + } + + @Override + public void onEventFinish(RequestEvent event) { + MetricsKey targetKey = MetricsKey.METRIC_REQUESTS_SUCCEED; + Object throwableObj = event.getAttachmentValue(METRIC_THROWABLE); + if (throwableObj != null) { + targetKey = MetricsSupport.getAggMetricsKey((RpcException) throwableObj); + } + calcWindowCounter(event, targetKey); + onRTEvent(event); + } + + @Override + public void onEventError(RequestEvent event) { + MetricsKey targetKey = MetricsKey.METRIC_REQUESTS_FAILED; + Object throwableObj = event.getAttachmentValue(METRIC_THROWABLE); + if (throwableObj != null) { + targetKey = MetricsSupport.getAggMetricsKey((RpcException) throwableObj); + } + calcWindowCounter(event, targetKey); + onRTEvent(event); + } + + private void onRTEvent(RequestEvent event) { + MethodMetric metric = new MethodMetric(applicationModel.getApplicationName(), event.getAttachmentValue(MetricsConstants.INVOCATION)); + long responseTime = event.getTimePair().calc(); TimeWindowQuantile quantile = ConcurrentHashMapUtils.computeIfAbsent(rt, metric, k -> new TimeWindowQuantile(DEFAULT_COMPRESSION, bucketNum, timeWindowSeconds)); quantile.add(responseTime); } - private void onRequestEvent(MethodEvent event) { - MethodMetric metric = event.getMethodMetric(); + private MethodMetric calcWindowCounter(RequestEvent event, MetricsKey targetKey) { + MetricsPlaceValue placeType = MetricsPlaceValue.of(event.getAttachmentValue(MetricsConstants.INVOCATION_SIDE), MetricsLevel.SERVICE); + MetricsKeyWrapper metricsKeyWrapper = new MetricsKeyWrapper(targetKey, placeType); + MethodMetric metric = new MethodMetric(applicationModel.getApplicationName(), event.getAttachmentValue(MetricsConstants.INVOCATION)); - String type = event.getType(); + ConcurrentMap counter = methodTypeCounter.computeIfAbsent(metricsKeyWrapper, k -> new ConcurrentHashMap<>()); - ConcurrentMap counter = methodTypeCounter.get(type); - - if (counter == null) { - return; - } TimeWindowCounter windowCounter = ConcurrentHashMapUtils.computeIfAbsent(counter, metric, methodMetric -> new TimeWindowCounter(bucketNum, timeWindowSeconds)); - - if (MetricsEvent.Type.TOTAL.getNameByType(PROVIDER_SIDE).equals(type) - || MetricsEvent.Type.TOTAL.getNameByType(CONSUMER_SIDE).equals(type)) { - TimeWindowCounter qpsCounter = ConcurrentHashMapUtils.computeIfAbsent(qps, metric, methodMetric -> new TimeWindowCounter(bucketNum, timeWindowSeconds)); - qpsCounter.increment(); - } windowCounter.increment(); + return metric; } @Override @@ -129,20 +168,21 @@ public class AggregateMetricsCollector implements MetricsCollector, MetricsListe } private void collectBySide(List list, String side) { - collectMethod(list, MetricsEvent.Type.TOTAL.getNameByType(side), MetricsKey.METRIC_REQUESTS_TOTAL_AGG); - collectMethod(list, MetricsEvent.Type.SUCCEED.getNameByType(side), MetricsKey.METRIC_REQUESTS_SUCCEED_AGG); - collectMethod(list, MetricsEvent.Type.UNKNOWN_FAILED.getNameByType(side), MetricsKey.METRIC_REQUESTS_FAILED_AGG); - collectMethod(list, MetricsEvent.Type.BUSINESS_FAILED.getNameByType(side), MetricsKey.METRIC_REQUESTS_BUSINESS_FAILED_AGG); - collectMethod(list, MetricsEvent.Type.REQUEST_TIMEOUT.getNameByType(side), MetricsKey.METRIC_REQUESTS_TIMEOUT_AGG); - collectMethod(list, MetricsEvent.Type.REQUEST_LIMIT.getNameByType(side), MetricsKey.METRIC_REQUESTS_LIMIT_AGG); - collectMethod(list, MetricsEvent.Type.TOTAL_FAILED.getNameByType(side), MetricsKey.METRIC_REQUESTS_TOTAL_FAILED_AGG); - collectMethod(list, MetricsEvent.Type.NETWORK_EXCEPTION.getNameByType(side), MetricsKey.METRIC_REQUESTS_TOTAL_NETWORK_FAILED_AGG); - collectMethod(list, MetricsEvent.Type.CODEC_EXCEPTION.getNameByType(side), MetricsKey.METRIC_REQUESTS_TOTAL_CODEC_FAILED_AGG); - collectMethod(list, MetricsEvent.Type.SERVICE_UNAVAILABLE.getNameByType(side), MetricsKey.METRIC_REQUESTS_TOTAL_SERVICE_UNAVAILABLE_FAILED_AGG); + collectMethod(list, side, MetricsKey.METRIC_REQUESTS_TOTAL_AGG); + collectMethod(list, side, MetricsKey.METRIC_REQUESTS_SUCCEED_AGG); + collectMethod(list, side, MetricsKey.METRIC_REQUESTS_FAILED_AGG); + collectMethod(list, side, MetricsKey.METRIC_REQUEST_BUSINESS_FAILED_AGG); + collectMethod(list, side, MetricsKey.METRIC_REQUESTS_TIMEOUT_AGG); + collectMethod(list, side, MetricsKey.METRIC_REQUESTS_LIMIT_AGG); + collectMethod(list, side, MetricsKey.METRIC_REQUESTS_TOTAL_FAILED_AGG); + collectMethod(list, side, MetricsKey.METRIC_REQUESTS_NETWORK_FAILED_AGG); + collectMethod(list, side, MetricsKey.METRIC_REQUESTS_CODEC_FAILED_AGG); + collectMethod(list, side, MetricsKey.METRIC_REQUESTS_TOTAL_SERVICE_UNAVAILABLE_FAILED_AGG); } - private void collectMethod(List list, String eventType, MetricsKey metricsKey) { - ConcurrentHashMap windowCounter = methodTypeCounter.get(eventType); + private void collectMethod(List list, String side, MetricsKey metricsKey) { + MetricsKeyWrapper metricsKeyWrapper = new MetricsKeyWrapper(metricsKey, MetricsPlaceValue.of(side, MetricsLevel.SERVICE)); + ConcurrentHashMap windowCounter = methodTypeCounter.get(metricsKeyWrapper); if (windowCounter != null) { windowCounter.forEach((k, v) -> list.add(new GaugeMetricSample<>(metricsKey.getNameByType(k.getSide()), metricsKey.getDescription(), k.getTags(), REQUESTS, v, TimeWindowCounter::get))); @@ -163,26 +203,8 @@ public class AggregateMetricsCollector implements MetricsCollector, MetricsListe }); } - private void registryEventTypeHandler() { - registryBySide(PROVIDER_SIDE); - registryBySide(CONSUMER_SIDE); - } - - private void registryBySide(String side) { - methodTypeCounter.put(MetricsEvent.Type.TOTAL.getNameByType(side), new ConcurrentHashMap<>()); - methodTypeCounter.put(MetricsEvent.Type.SUCCEED.getNameByType(side), new ConcurrentHashMap<>()); - methodTypeCounter.put(MetricsEvent.Type.UNKNOWN_FAILED.getNameByType(side), new ConcurrentHashMap<>()); - methodTypeCounter.put(MetricsEvent.Type.BUSINESS_FAILED.getNameByType(side), new ConcurrentHashMap<>()); - methodTypeCounter.put(MetricsEvent.Type.REQUEST_TIMEOUT.getNameByType(side), new ConcurrentHashMap<>()); - methodTypeCounter.put(MetricsEvent.Type.REQUEST_LIMIT.getNameByType(side), new ConcurrentHashMap<>()); - methodTypeCounter.put(MetricsEvent.Type.TOTAL_FAILED.getNameByType(side), new ConcurrentHashMap<>()); - methodTypeCounter.put(MetricsEvent.Type.SERVICE_UNAVAILABLE.getNameByType(side), new ConcurrentHashMap<>()); - methodTypeCounter.put(MetricsEvent.Type.NETWORK_EXCEPTION.getNameByType(side), new ConcurrentHashMap<>()); - methodTypeCounter.put(MetricsEvent.Type.CODEC_EXCEPTION.getNameByType(side), new ConcurrentHashMap<>()); - } - private void registerListener() { - applicationModel.getBeanFactory().getBean(DefaultMetricsCollector.class).addListener(this); + applicationModel.getBeanFactory().getBean(DefaultMetricsCollector.class).getEventMulticaster().addListener(this); } } diff --git a/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/collector/DefaultMetricsCollector.java b/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/collector/DefaultMetricsCollector.java index 953cc075e6..937893310c 100644 --- a/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/collector/DefaultMetricsCollector.java +++ b/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/collector/DefaultMetricsCollector.java @@ -16,48 +16,71 @@ */ package org.apache.dubbo.metrics.collector; -import org.apache.dubbo.metrics.collector.sample.MethodMetricsSampler; + +import org.apache.dubbo.common.constants.CommonConstants; +import org.apache.dubbo.common.extension.Activate; +import org.apache.dubbo.metrics.DefaultConstants; import org.apache.dubbo.metrics.collector.sample.MetricsCountSampleConfigurer; import org.apache.dubbo.metrics.collector.sample.MetricsSampler; import org.apache.dubbo.metrics.collector.sample.SimpleMetricsCountSampler; import org.apache.dubbo.metrics.collector.sample.ThreadPoolMetricsSampler; +import org.apache.dubbo.metrics.data.BaseStatComposite; +import org.apache.dubbo.metrics.data.MethodStatComposite; +import org.apache.dubbo.metrics.data.RtStatComposite; +import org.apache.dubbo.metrics.event.DefaultSubDispatcher; import org.apache.dubbo.metrics.event.MetricsEvent; -import org.apache.dubbo.metrics.event.SimpleMetricsEventMulticaster; -import org.apache.dubbo.metrics.listener.MetricsListener; +import org.apache.dubbo.metrics.event.RequestBeforeEvent; +import org.apache.dubbo.metrics.event.RequestEvent; import org.apache.dubbo.metrics.model.ApplicationMetric; +import org.apache.dubbo.metrics.model.MetricsCategory; +import org.apache.dubbo.metrics.model.key.MetricsLevel; +import org.apache.dubbo.metrics.model.key.MetricsPlaceValue; import org.apache.dubbo.metrics.model.sample.CounterMetricSample; import org.apache.dubbo.metrics.model.sample.MetricSample; import org.apache.dubbo.rpc.model.ApplicationModel; + import java.util.ArrayList; import java.util.List; + import static org.apache.dubbo.metrics.model.MetricsCategory.APPLICATION; import static org.apache.dubbo.metrics.model.key.MetricsKey.APPLICATION_METRIC_INFO; /** * Default implementation of {@link MetricsCollector} */ -public class DefaultMetricsCollector implements MetricsCollector { +@Activate +public class DefaultMetricsCollector extends CombMetricsCollector { private boolean collectEnabled = false; - private volatile boolean threadpoolCollectEnabled=false; - private final SimpleMetricsEventMulticaster eventMulticaster; - private final MethodMetricsSampler methodSampler = new MethodMetricsSampler(this); + private volatile boolean threadpoolCollectEnabled = false; private final ThreadPoolMetricsSampler threadPoolSampler = new ThreadPoolMetricsSampler(this); private String applicationName; private ApplicationModel applicationModel; private final List samplers = new ArrayList<>(); public DefaultMetricsCollector() { - this.eventMulticaster = new SimpleMetricsEventMulticaster(); - samplers.add(methodSampler); + super(new BaseStatComposite() { + @Override + protected void init(MethodStatComposite methodStatComposite) { + methodStatComposite.initWrapper(DefaultConstants.METHOD_LEVEL_KEYS); + } + + @Override + protected void init(RtStatComposite rtStatComposite) { + rtStatComposite.init(MetricsPlaceValue.of(CommonConstants.PROVIDER, MetricsLevel.METHOD), + MetricsPlaceValue.of(CommonConstants.CONSUMER, MetricsLevel.METHOD)); + } + }); + super.setEventMulticaster(new DefaultSubDispatcher(this)); samplers.add(applicationSampler); samplers.add(threadPoolSampler); } - public void addSampler(MetricsSampler sampler){ + public void addSampler(MetricsSampler sampler) { samplers.add(sampler); } + public void setApplicationName(String applicationName) { this.applicationName = applicationName; } @@ -70,10 +93,6 @@ public class DefaultMetricsCollector implements MetricsCollector { return this.applicationModel; } - public SimpleMetricsEventMulticaster getEventMulticaster() { - return this.eventMulticaster; - } - public void setCollectEnabled(Boolean collectEnabled) { this.collectEnabled = collectEnabled; } @@ -90,14 +109,6 @@ public class DefaultMetricsCollector implements MetricsCollector { this.threadpoolCollectEnabled = threadpoolCollectEnabled; } - public MethodMetricsSampler getMethodSampler() { - return this.methodSampler; - } - - public ThreadPoolMetricsSampler getThreadPoolSampler() { - return this.threadPoolSampler; - } - public void collectApplication(ApplicationModel applicationModel) { this.setApplicationName(applicationModel.getApplicationName()); this.applicationModel = applicationModel; @@ -111,15 +122,21 @@ public class DefaultMetricsCollector implements MetricsCollector { @Override public List collect() { List list = new ArrayList<>(); + if (!isCollectEnabled()) { + return list; + } + for (MetricsSampler sampler : samplers) { List sample = sampler.sample(); list.addAll(sample); } + list.addAll(super.export(MetricsCategory.REQUESTS)); return list; } - public void addListener(MetricsListener listener) { - this.eventMulticaster.addListener(listener); + @Override + public boolean isSupport(MetricsEvent event) { + return event instanceof RequestEvent || event instanceof RequestBeforeEvent; } public SimpleMetricsCountSampler applicationSampler = new SimpleMetricsCountSampler() { @@ -127,17 +144,17 @@ public class DefaultMetricsCollector implements MetricsCollector { public List sample() { List samples = new ArrayList<>(); this.getCount(MetricsEvent.Type.APPLICATION_INFO).filter(e -> !e.isEmpty()) - .ifPresent(map -> map.forEach((k, v) -> - samples.add(new CounterMetricSample<>(APPLICATION_METRIC_INFO.getName(), - APPLICATION_METRIC_INFO.getDescription(), - k.getTags(), APPLICATION, v))) - ); + .ifPresent(map -> map.forEach((k, v) -> + samples.add(new CounterMetricSample<>(APPLICATION_METRIC_INFO.getName(), + APPLICATION_METRIC_INFO.getDescription(), + k.getTags(), APPLICATION, v))) + ); return samples; } @Override protected void countConfigure( - MetricsCountSampleConfigurer sampleConfigure) { + MetricsCountSampleConfigurer sampleConfigure) { sampleConfigure.configureMetrics(configure -> new ApplicationMetric(sampleConfigure.getSource())); } }; diff --git a/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/collector/HistogramMetricsCollector.java b/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/collector/HistogramMetricsCollector.java index 28792e8b60..9979707364 100644 --- a/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/collector/HistogramMetricsCollector.java +++ b/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/collector/HistogramMetricsCollector.java @@ -22,22 +22,25 @@ import org.apache.dubbo.common.utils.ConcurrentHashMapUtils; import org.apache.dubbo.config.MetricsConfig; import org.apache.dubbo.config.context.ConfigManager; import org.apache.dubbo.config.nested.HistogramConfig; +import org.apache.dubbo.metrics.MetricsConstants; import org.apache.dubbo.metrics.MetricsGlobalRegistry; -import org.apache.dubbo.metrics.event.MetricsEvent; -import org.apache.dubbo.metrics.event.RTEvent; -import org.apache.dubbo.metrics.listener.MetricsListener; +import org.apache.dubbo.metrics.event.RequestEvent; +import org.apache.dubbo.metrics.listener.AbstractMetricsListener; import org.apache.dubbo.metrics.model.MethodMetric; import org.apache.dubbo.metrics.model.key.MetricsKey; +import org.apache.dubbo.metrics.model.sample.MetricSample; import org.apache.dubbo.metrics.register.HistogramMetricRegister; import org.apache.dubbo.metrics.sample.HistogramMetricSample; import org.apache.dubbo.rpc.model.ApplicationModel; +import java.util.ArrayList; +import java.util.List; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.TimeUnit; import static org.apache.dubbo.metrics.model.MetricsCategory.RT; -public class HistogramMetricsCollector implements MetricsListener { +public class HistogramMetricsCollector extends AbstractMetricsListener implements MetricsCollector { private final ConcurrentHashMap rt = new ConcurrentHashMap<>(); private HistogramMetricRegister metricRegister; @@ -63,20 +66,28 @@ public class HistogramMetricsCollector implements MetricsListener { } private void registerListener() { - applicationModel.getBeanFactory().getBean(DefaultMetricsCollector.class).addListener(this); + applicationModel.getBeanFactory().getBean(DefaultMetricsCollector.class).getEventMulticaster().addListener(this); } @Override - public void onEvent(MetricsEvent event) { - if (event instanceof RTEvent) { - onRTEvent((RTEvent) event); - } + public void onEvent(RequestEvent event) { + } - private void onRTEvent(RTEvent event) { + @Override + public void onEventFinish(RequestEvent event) { + onRTEvent(event); + } + + @Override + public void onEventError(RequestEvent event) { + onRTEvent(event); + } + + private void onRTEvent(RequestEvent event) { if (metricRegister != null) { - MethodMetric metric = (MethodMetric) event.getMetric(); - Long responseTime = event.getRt(); + MethodMetric metric = new MethodMetric(applicationModel.getApplicationName(), event.getAttachmentValue(MetricsConstants.INVOCATION)); + long responseTime = event.getTimePair().calc(); HistogramMetricSample sample = new HistogramMetricSample(MetricsKey.METRIC_RT_HISTOGRAM.getNameByType(metric.getSide()), MetricsKey.METRIC_RT_HISTOGRAM.getDescription(), metric.getTags(), RT); @@ -85,4 +96,9 @@ public class HistogramMetricsCollector implements MetricsListener { timer.record(responseTime, TimeUnit.MILLISECONDS); } } + + @Override + public List collect() { + return new ArrayList<>(); + } } diff --git a/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/collector/sample/MethodMetricsSampler.java b/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/collector/sample/MethodMetricsSampler.java deleted file mode 100644 index 29a14e1ed5..0000000000 --- a/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/collector/sample/MethodMetricsSampler.java +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.dubbo.metrics.collector.sample; - -import org.apache.dubbo.metrics.collector.DefaultMetricsCollector; -import org.apache.dubbo.metrics.event.MethodEvent; -import org.apache.dubbo.metrics.event.MetricsEvent; -import org.apache.dubbo.metrics.event.RTEvent; -import org.apache.dubbo.metrics.model.MethodMetric; -import org.apache.dubbo.metrics.model.Metric; -import org.apache.dubbo.metrics.model.MetricsCategory; -import org.apache.dubbo.metrics.model.key.MetricsKey; -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.rpc.Invocation; - -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.atomic.AtomicLong; -import java.util.function.ToDoubleFunction; - -import static org.apache.dubbo.common.constants.CommonConstants.CONSUMER_SIDE; -import static org.apache.dubbo.common.constants.CommonConstants.PROVIDER_SIDE; - -public class MethodMetricsSampler extends SimpleMetricsCountSampler { - - private final DefaultMetricsCollector collector; - - public MethodMetricsSampler(DefaultMetricsCollector collector) { - this.collector = collector; - } - - @Override - protected void countConfigure( - MetricsCountSampleConfigurer sampleConfigure) { - sampleConfigure.configureMetrics(configure -> new MethodMetric(collector.getApplicationName(), configure.getSource())); - sampleConfigure.configureEventHandler(configure -> collector.getEventMulticaster().publishEvent(new MethodEvent(collector.getApplicationModel(), configure.getMetric(), - configure.getMetricName()))); - } - - @Override - public void rtConfigure( - MetricsCountSampleConfigurer sampleConfigure) { - sampleConfigure.configureMetrics(configure -> new MethodMetric(collector.getApplicationName(), configure.getSource())); - sampleConfigure.configureEventHandler(configure -> collector.getEventMulticaster().publishEvent(new RTEvent(collector.getApplicationModel(), configure.getMetric(), configure.getRt()))); - } - - @Override - public List sample() { - List metricSamples = new ArrayList<>(); - - collect(metricSamples); - metricSamples.addAll( - this.collectRT(new MetricSampleFactory>() { - @Override - public GaugeMetricSample newInstance(MetricsKey key, MethodMetric metric, T value, ToDoubleFunction apply) { - return createGaugeMetricSample(key, metric, MetricsCategory.RT, value, apply); - } - })); - - return metricSamples; - } - - private void collect(List list) { - collectBySide(list, PROVIDER_SIDE); - collectBySide(list, CONSUMER_SIDE); - } - - private void collectBySide(List list, String side) { - count(list, MetricsEvent.Type.TOTAL.getNameByType(side), MetricSample.Type.COUNTER, MetricsKey.METRIC_REQUESTS); - count(list, MetricsEvent.Type.SUCCEED.getNameByType(side), MetricSample.Type.COUNTER, MetricsKey.METRIC_REQUESTS_SUCCEED); - count(list, MetricsEvent.Type.UNKNOWN_FAILED.getNameByType(side), MetricSample.Type.COUNTER, MetricsKey.METRIC_REQUESTS_FAILED); - count(list, MetricsEvent.Type.PROCESSING.getNameByType(side), MetricSample.Type.GAUGE, MetricsKey.METRIC_REQUESTS_PROCESSING); - count(list, MetricsEvent.Type.BUSINESS_FAILED.getNameByType(side), MetricSample.Type.COUNTER, MetricsKey.METRIC_REQUEST_BUSINESS_FAILED); - count(list, MetricsEvent.Type.REQUEST_TIMEOUT.getNameByType(side), MetricSample.Type.COUNTER, MetricsKey.METRIC_REQUESTS_TIMEOUT); - count(list, MetricsEvent.Type.REQUEST_LIMIT.getNameByType(side), MetricSample.Type.COUNTER, MetricsKey.METRIC_REQUESTS_LIMIT); - count(list, MetricsEvent.Type.TOTAL_FAILED.getNameByType(side), MetricSample.Type.COUNTER, MetricsKey.METRIC_REQUESTS_TOTAL_FAILED); - count(list, MetricsEvent.Type.NETWORK_EXCEPTION.getNameByType(side), MetricSample.Type.COUNTER, MetricsKey.METRIC_REQUESTS_NETWORK_FAILED); - count(list, MetricsEvent.Type.SERVICE_UNAVAILABLE.getNameByType(side), MetricSample.Type.COUNTER, MetricsKey.METRIC_REQUESTS_SERVICE_UNAVAILABLE_FAILED); - count(list, MetricsEvent.Type.CODEC_EXCEPTION.getNameByType(side), MetricSample.Type.COUNTER, MetricsKey.METRIC_REQUESTS_CODEC_FAILED); - } - - - private GaugeMetricSample createGaugeMetricSample(MetricsKey metricsKey, - MethodMetric methodMetric, - MetricsCategory metricsCategory, - T value, - ToDoubleFunction apply) { - return new GaugeMetricSample<>( - metricsKey.getNameByType(methodMetric.getSide()), - metricsKey.getDescription(), - methodMetric.getTags(), - metricsCategory, - value, - apply); - } - - private void count(List list, String eventType, MetricSample.Type type, MetricsKey metricsKey) { - getCount(eventType).filter(e -> !e.isEmpty()) - .ifPresent(map -> map.forEach((k, v) -> { - if(type == MetricSample.Type.COUNTER){ - list.add(createCounterMetricSample(metricsKey, k, MetricsCategory.REQUESTS, v)); - }else if(type == MetricSample.Type.GAUGE){ - list.add(createGaugeMetricSample(metricsKey, k, MetricsCategory.REQUESTS, v, AtomicLong::get)); - } - } - )); - } - - private MetricSample createCounterMetricSample(MetricsKey metricsKey, MethodMetric methodMetric, MetricsCategory metricsCategory, AtomicLong value) { - return new CounterMetricSample<>(metricsKey.getNameByType(methodMetric.getSide()), - metricsKey.getDescription(), - methodMetric.getTags(), metricsCategory, value); - - - } -} diff --git a/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/collector/sample/MetricsCountSampleConfigurer.java b/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/collector/sample/MetricsCountSampleConfigurer.java index 439b04eabf..d66ba6021e 100644 --- a/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/collector/sample/MetricsCountSampleConfigurer.java +++ b/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/collector/sample/MetricsCountSampleConfigurer.java @@ -52,20 +52,10 @@ public class MetricsCountSampleConfigurer { return this; } - public MetricsCountSampleConfigurer configureEventHandler( - Consumer> fireEventHandler){ - this.fireEventHandler = fireEventHandler; - return this; - } - public S getSource() { return source; } - public K getMetricName() { - return metricName; - } - public M getMetric() { return metric; } diff --git a/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/collector/sample/MetricsCountSampler.java b/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/collector/sample/MetricsCountSampler.java index 8bcd5a976b..0b561f54c0 100644 --- a/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/collector/sample/MetricsCountSampler.java +++ b/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/collector/sample/MetricsCountSampler.java @@ -18,36 +18,17 @@ package org.apache.dubbo.metrics.collector.sample; import org.apache.dubbo.metrics.model.Metric; -import org.apache.dubbo.metrics.model.key.MetricsKey; -import org.apache.dubbo.metrics.model.sample.MetricSample; -import java.util.List; import java.util.Optional; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.atomic.AtomicLong; -import java.util.function.ToDoubleFunction; public interface MetricsCountSampler extends MetricsSampler { void inc(S source, K metricName); - void dec(S source, K metricName); - void incOnEvent(S source, K metricName); - void decOnEvent(S source, K metricName); - - void addRT(S source, Long rt); - - void addRT(S source, K metricName, Long rt); - Optional> getCount(K metricName); - List collectRT(MetricSampleFactory factory); - - List collectRT(MetricSampleFactory factory, K metricName); - - interface MetricSampleFactory { - R newInstance(MetricsKey key, M metric, T value, ToDoubleFunction apply); - } } diff --git a/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/collector/sample/SimpleMetricsCountSampler.java b/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/collector/sample/SimpleMetricsCountSampler.java index 167fbb383b..7f01dcd222 100644 --- a/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/collector/sample/SimpleMetricsCountSampler.java +++ b/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/collector/sample/SimpleMetricsCountSampler.java @@ -18,20 +18,13 @@ package org.apache.dubbo.metrics.collector.sample; import org.apache.dubbo.common.utils.Assert; -import org.apache.dubbo.common.utils.ConcurrentHashMapUtils; import org.apache.dubbo.metrics.model.Metric; -import org.apache.dubbo.metrics.model.key.MetricsKey; -import org.apache.dubbo.metrics.model.sample.MetricSample; -import java.util.ArrayList; -import java.util.List; import java.util.Map; import java.util.Optional; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.atomic.AtomicLong; -import java.util.concurrent.atomic.AtomicLongArray; -import java.util.concurrent.atomic.LongAccumulator; import java.util.function.Function; /** @@ -45,14 +38,6 @@ public abstract class SimpleMetricsCountSampler private final ConcurrentMap EMPTY_COUNT = new ConcurrentHashMap<>(); private final Map> metricCounter = new ConcurrentHashMap<>(); - // lastRT, totalRT, rtCount, avgRT share a container, can utilize the system cache line - private final ConcurrentMap rtSample = new ConcurrentHashMap<>(); - private final ConcurrentMap minRT = new ConcurrentHashMap<>(); - private final ConcurrentMap maxRT = new ConcurrentHashMap<>(); - - private final ConcurrentMap> rtGroupSample = new ConcurrentHashMap<>(); - private final ConcurrentMap> groupMinRT = new ConcurrentHashMap<>(); - private final ConcurrentMap> groupMaxRT = new ConcurrentHashMap<>(); @Override public void inc(S source, K metricName) { @@ -62,14 +47,6 @@ public abstract class SimpleMetricsCountSampler }); } - @Override - public void dec(S source, K metricName) { - doExecute(source, metricName, counter -> { - counter.decrementAndGet(); - return false; - }); - } - @Override public void incOnEvent(S source, K metricName) { doExecute(source, metricName, counter -> { @@ -78,91 +55,6 @@ public abstract class SimpleMetricsCountSampler }); } - @Override - public void decOnEvent(S source, K metricName) { - doExecute(source, metricName, counter -> { - counter.decrementAndGet(); - return true; - }); - } - - @Override - public void addRT(S source, Long rt) { - MetricsCountSampleConfigurer sampleConfigure = new MetricsCountSampleConfigurer<>(); - sampleConfigure.setSource(source); - - this.rtConfigure(sampleConfigure); - - M metric = sampleConfigure.getMetric(); - - AtomicLongArray rtCalculator = ConcurrentHashMapUtils.computeIfAbsent(this.rtSample, metric, k -> new AtomicLongArray(4)); - - // set lastRT - rtCalculator.set(0, rt); - - // add to totalRT - rtCalculator.addAndGet(1, rt); - - // add to rtCount - rtCalculator.incrementAndGet(2); - - // calc avgRT. In order to reduce the amount of calculation, calculated when collect - //rtArray.set(3, Math.floorDiv(rtArray.get(1), rtArray.get(2))); - - LongAccumulator min = ConcurrentHashMapUtils.computeIfAbsent(minRT, metric, k -> new LongAccumulator(Long::min, Long.MAX_VALUE)); - min.accumulate(rt); - - LongAccumulator max = ConcurrentHashMapUtils.computeIfAbsent(maxRT, metric, k -> new LongAccumulator(Long::max, Long.MIN_VALUE)); - max.accumulate(rt); - - sampleConfigure.setRt(rt); - - sampleConfigure.getFireEventHandler().accept(sampleConfigure); - } - - @Override - public void addRT(S source, K metricName, Long rt) { - MetricsCountSampleConfigurer sampleConfigure = new MetricsCountSampleConfigurer<>(); - sampleConfigure.setSource(source); - sampleConfigure.setMetricsName(metricName); - - this.rtConfigure(sampleConfigure); - - M metric = sampleConfigure.getMetric(); - - ConcurrentMap nameToCalculator = rtGroupSample.get(metricName); - - if (nameToCalculator == null) { - ConcurrentHashMap calculator = new ConcurrentHashMap<>(); - calculator.put(metric, new AtomicLongArray(4)); - - rtGroupSample.put(metricName, calculator); - - nameToCalculator = rtGroupSample.get(metricName); - } - AtomicLongArray calculator = nameToCalculator.get(metric); - - // set lastRT - calculator.set(0, rt); - - // add to totalRT - calculator.addAndGet(1, rt); - - // add to rtCount - calculator.incrementAndGet(2); - - ConcurrentMap minRT = ConcurrentHashMapUtils.computeIfAbsent(groupMinRT, metricName, k -> new ConcurrentHashMap<>()); - LongAccumulator min = ConcurrentHashMapUtils.computeIfAbsent(minRT, metric, k -> new LongAccumulator(Long::min, Long.MAX_VALUE)); - min.accumulate(rt); - - ConcurrentMap maxRT = ConcurrentHashMapUtils.computeIfAbsent(groupMaxRT, metricName, k -> new ConcurrentHashMap<>()); - LongAccumulator max = ConcurrentHashMapUtils.computeIfAbsent(maxRT, metric, k -> new LongAccumulator(Long::max, Long.MIN_VALUE)); - max.accumulate(rt); - sampleConfigure.setRt(rt); - - sampleConfigure.getFireEventHandler().accept(sampleConfigure); - } - @Override public Optional> getCount(K metricName) { return Optional.ofNullable(metricCounter.get(metricName) == null ? @@ -170,42 +62,6 @@ public abstract class SimpleMetricsCountSampler metricCounter.get(metricName)); } - @Override - public List collectRT(MetricSampleFactory factory) { - return collect(factory, rtSample, this.minRT, this.maxRT); - } - - @Override - public List collectRT(MetricSampleFactory factory, K metricName) { - return collect(factory, rtGroupSample.get(metricName), groupMinRT.get(metricName), groupMaxRT.get(metricName)); - } - - private List collect(MetricSampleFactory factory, - ConcurrentMap rtSample, - ConcurrentMap min, - ConcurrentMap max) { - final List result = new ArrayList<>(); - rtSample.forEach((k, v) -> { - // lastRT - result.add(factory.newInstance(MetricsKey.METRIC_RT_LAST, k, v, value -> value.get(0))); - // totalRT - result.add(factory.newInstance(MetricsKey.METRIC_RT_SUM, k, v, value -> value.get(1))); - // avgRT - result.add(factory.newInstance(MetricsKey.METRIC_RT_AVG, k, v, value -> Math.floorDiv(value.get(1), value.get(2)))); - }); - - min.forEach((k, v) -> - result.add(factory.newInstance(MetricsKey.METRIC_RT_MIN, k, v, LongAccumulator::get))); - - max.forEach((k, v) -> - result.add(factory.newInstance(MetricsKey.METRIC_RT_MAX, k, v, LongAccumulator::get))); - - return result; - } - - protected void rtConfigure(MetricsCountSampleConfigurer configure) { - } - protected abstract void countConfigure(MetricsCountSampleConfigurer sampleConfigure); private void doExecute(S source, K metricsName, Function counter) { 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 new file mode 100644 index 0000000000..8ec3f46573 --- /dev/null +++ b/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/event/DefaultSubDispatcher.java @@ -0,0 +1,113 @@ +/* + * 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.event; + +import org.apache.dubbo.common.constants.CommonConstants; +import org.apache.dubbo.metrics.MetricsConstants; +import org.apache.dubbo.metrics.collector.DefaultMetricsCollector; +import org.apache.dubbo.metrics.collector.MethodMetricsCollector; +import org.apache.dubbo.metrics.listener.AbstractMetricsKeyListener; +import org.apache.dubbo.metrics.listener.MetricsListener; +import org.apache.dubbo.metrics.model.MetricsSupport; +import org.apache.dubbo.metrics.model.key.CategoryOverall; +import org.apache.dubbo.metrics.model.key.MetricsCat; +import org.apache.dubbo.metrics.model.key.MetricsKey; +import org.apache.dubbo.metrics.model.key.MetricsLevel; +import org.apache.dubbo.metrics.model.key.MetricsPlaceValue; +import org.apache.dubbo.metrics.model.sample.MetricSample; +import org.apache.dubbo.rpc.Invocation; +import org.apache.dubbo.rpc.RpcException; + +import static org.apache.dubbo.metrics.DefaultConstants.METRIC_THROWABLE; +import static org.apache.dubbo.metrics.MetricsConstants.INVOCATION; +import static org.apache.dubbo.metrics.MetricsConstants.INVOCATION_METRICS_COUNTER; +import static org.apache.dubbo.metrics.model.key.MetricsKey.METRIC_REQUESTS_SERVICE_UNAVAILABLE_FAILED; + +@SuppressWarnings({"unchecked", "rawtypes"}) +public final class DefaultSubDispatcher extends SimpleMetricsEventMulticaster { + + public DefaultSubDispatcher(DefaultMetricsCollector collector) { + + CategoryOverall categoryOverall = initMethodRequest(); + super.addListener(categoryOverall.getPost().getEventFunc().apply(collector)); + super.addListener(categoryOverall.getFinish().getEventFunc().apply(collector)); + super.addListener(categoryOverall.getError().getEventFunc().apply(collector)); + + super.addListener(new MetricsListener() { + + @Override + public boolean isSupport(MetricsEvent event) { + return event instanceof RequestBeforeEvent; + } + + @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); + } + }); + } + + + private CategoryOverall initMethodRequest() { + + return new CategoryOverall(null, + new MetricsCat(MetricsKey.METRIC_REQUESTS, (key, placeType, collector) -> AbstractMetricsKeyListener.onEvent(key, + event -> + { + MetricsPlaceValue dynamicPlaceType = MetricsPlaceValue.of(event.getAttachmentValue(MetricsConstants.INVOCATION_SIDE), MetricsLevel.METHOD); + MetricsSupport.increment(key, dynamicPlaceType, (MethodMetricsCollector) collector, event); + + // METRIC_REQUESTS_PROCESSING use GAUGE + Invocation invocation = event.getAttachmentValue(INVOCATION); + invocation.put(INVOCATION_METRICS_COUNTER, MetricSample.Type.GAUGE); + MetricsSupport.increment(MetricsKey.METRIC_REQUESTS_PROCESSING, dynamicPlaceType, (MethodMetricsCollector) collector, event); + })), + new MetricsCat(MetricsKey.METRIC_REQUESTS_SUCCEED, (key, placeType, collector) -> AbstractMetricsKeyListener.onFinish(key, + event -> + { + MetricsPlaceValue dynamicPlaceType = MetricsPlaceValue.of(event.getAttachmentValue(MetricsConstants.INVOCATION_SIDE), MetricsLevel.METHOD); + MetricsSupport.dec(MetricsKey.METRIC_REQUESTS_PROCESSING, dynamicPlaceType, (MethodMetricsCollector) collector, event); + + Object throwableObj = event.getAttachmentValue(METRIC_THROWABLE); + MetricsKey targetKey; + if (throwableObj == null) { + targetKey = key; + } else { + targetKey = MetricsSupport.getMetricsKey((RpcException) throwableObj); + } + MetricsSupport.incrAndAddRt(targetKey, dynamicPlaceType, (MethodMetricsCollector) collector, event); + })), + new MetricsCat(MetricsKey.METRIC_REQUEST_BUSINESS_FAILED, (key, placeType, collector) -> AbstractMetricsKeyListener.onError(key, + event -> + { + Throwable throwable = event.getAttachmentValue(METRIC_THROWABLE); + MetricsKey targetKey = MetricsKey.METRIC_REQUESTS_FAILED_AGG; + if (throwable instanceof RpcException) { + targetKey = MetricsSupport.getMetricsKey((RpcException) throwable); + } + // Dynamic metricsKey && dynamicPlaceType + MetricsPlaceValue dynamicPlaceType = MetricsPlaceValue.of(event.getAttachmentValue(MetricsConstants.INVOCATION_SIDE), MetricsLevel.METHOD); + MetricsSupport.increment(MetricsKey.METRIC_REQUESTS_TOTAL_FAILED, dynamicPlaceType, (MethodMetricsCollector) collector, event); + MetricsSupport.dec(MetricsKey.METRIC_REQUESTS_PROCESSING, dynamicPlaceType, (MethodMetricsCollector) collector, event); + MetricsSupport.incrAndAddRt(targetKey, 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 new file mode 100644 index 0000000000..cad2de5e5a --- /dev/null +++ b/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/event/RequestBeforeEvent.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.event; + +import org.apache.dubbo.metrics.MetricsConstants; +import org.apache.dubbo.metrics.model.MetricsSupport; +import org.apache.dubbo.metrics.model.key.MetricsKey; +import org.apache.dubbo.metrics.model.key.MetricsLevel; +import org.apache.dubbo.metrics.model.key.TypeWrapper; +import org.apache.dubbo.rpc.Invocation; +import org.apache.dubbo.rpc.model.ApplicationModel; + +import static org.apache.dubbo.metrics.MetricsConstants.ATTACHMENT_KEY_SERVICE; + +/** + * Acts on MetricsClusterFilter to monitor exceptions that occur before request execution + */ +public class RequestBeforeEvent extends TimeCounterEvent { + + public RequestBeforeEvent(ApplicationModel source, TypeWrapper typeWrapper) { + super(source, typeWrapper); + + } + + public static RequestBeforeEvent toEvent(ApplicationModel applicationModel, Invocation invocation) { + RequestBeforeEvent event = new RequestBeforeEvent(applicationModel, new TypeWrapper(MetricsLevel.METHOD, MetricsKey.METRIC_REQUESTS)); + event.putAttachment(ATTACHMENT_KEY_SERVICE, MetricsSupport.getInterfaceName(invocation)); + event.putAttachment(MetricsConstants.INVOCATION_SIDE, MetricsSupport.getSide(invocation)); + event.putAttachment(MetricsConstants.INVOCATION, 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 new file mode 100644 index 0000000000..13eafa48a1 --- /dev/null +++ b/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/event/RequestEvent.java @@ -0,0 +1,71 @@ +/* + * 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.event; + +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.MetricsSupport; +import org.apache.dubbo.metrics.model.key.MetricsLevel; +import org.apache.dubbo.metrics.model.key.TypeWrapper; +import org.apache.dubbo.rpc.Invocation; +import org.apache.dubbo.rpc.Result; +import org.apache.dubbo.rpc.model.ApplicationModel; + +import static org.apache.dubbo.metrics.DefaultConstants.METRIC_THROWABLE; +import static org.apache.dubbo.metrics.MetricsConstants.ATTACHMENT_KEY_SERVICE; +import static org.apache.dubbo.metrics.model.key.MetricsKey.METRIC_REQUESTS; +import static org.apache.dubbo.metrics.model.key.MetricsKey.METRIC_REQUESTS_SUCCEED; +import static org.apache.dubbo.metrics.model.key.MetricsKey.METRIC_REQUEST_BUSINESS_FAILED; + +/** + * 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()); + } + } + + 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()); + } + }; + requestEvent.putAttachment(MetricsConstants.INVOCATION, invocation); + requestEvent.putAttachment(ATTACHMENT_KEY_SERVICE, MetricsSupport.getInterfaceName(invocation)); + requestEvent.putAttachment(MetricsConstants.INVOCATION_SIDE, MetricsSupport.getSide(invocation)); + return requestEvent; + } + + +} diff --git a/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/filter/MethodMetricsInterceptor.java b/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/filter/MethodMetricsInterceptor.java deleted file mode 100644 index 7c61eda55f..0000000000 --- a/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/filter/MethodMetricsInterceptor.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.dubbo.metrics.filter; - -import org.apache.dubbo.metrics.collector.sample.MethodMetricsSampler; -import org.apache.dubbo.metrics.event.MetricsEvent; -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 java.util.Optional; - -import static org.apache.dubbo.common.constants.CommonConstants.PROVIDER_SIDE; -import static org.apache.dubbo.common.constants.MetricsConstants.METRIC_FILTER_START_TIME; - -public class MethodMetricsInterceptor { - - private final MethodMetricsSampler sampler; - - public MethodMetricsInterceptor(MethodMetricsSampler sampler) { - this.sampler = sampler; - } - - public void beforeMethod(Invocation invocation) { - String side = getSide(invocation); - sampler.incOnEvent(invocation, MetricsEvent.Type.TOTAL.getNameByType(side)); - sampler.incOnEvent(invocation, MetricsEvent.Type.PROCESSING.getNameByType(side)); - invocation.put(METRIC_FILTER_START_TIME, System.currentTimeMillis()); - } - - private String getSide(Invocation invocation) { - Optional> invoker = Optional.ofNullable(invocation.getInvoker()); - String side = invoker.isPresent() ? invoker.get().getUrl().getSide() : PROVIDER_SIDE; - return side; - } - - public void afterMethod(Invocation invocation, Result result) { - if (result.hasException()) { - handleMethodException(invocation, result.getException()); - } else { - sampler.incOnEvent(invocation, MetricsEvent.Type.SUCCEED.getNameByType(getSide(invocation))); - onCompleted(invocation); - } - } - - public void handleMethodException(Invocation invocation, Throwable throwable) { - if (throwable == null) { - return; - } - String side = getSide(invocation); - - MetricsEvent.Type eventType = MetricsEvent.Type.UNKNOWN_FAILED; - if (throwable instanceof RpcException) { - RpcException e = (RpcException) throwable; - - if (e.isTimeout()) { - eventType = MetricsEvent.Type.REQUEST_TIMEOUT; - } - if (e.isLimitExceed()) { - eventType = MetricsEvent.Type.REQUEST_LIMIT; - } - if (e.isBiz()) { - eventType = MetricsEvent.Type.BUSINESS_FAILED; - } - if (e.isSerialization()) { - eventType = MetricsEvent.Type.CODEC_EXCEPTION; - } - if (e.isNetwork()) { - eventType = MetricsEvent.Type.NETWORK_EXCEPTION; - } - } - sampler.incOnEvent(invocation, eventType.getNameByType(side)); - onCompleted(invocation); - sampler.incOnEvent(invocation, MetricsEvent.Type.TOTAL_FAILED.getNameByType(side)); - } - - private void rtTime(Invocation invocation) { - Long endTime = System.currentTimeMillis(); - Long beginTime = (Long) invocation.get(METRIC_FILTER_START_TIME); - Long rt = endTime - beginTime; - sampler.addRT(invocation, rt); - } - - private void onCompleted(Invocation invocation) { - rtTime(invocation); - sampler.dec(invocation, MetricsEvent.Type.PROCESSING.getNameByType(getSide(invocation))); - } -} 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 c981f62831..4b5cd74502 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 @@ -17,7 +17,10 @@ package org.apache.dubbo.metrics.filter; import org.apache.dubbo.common.extension.Activate; -import org.apache.dubbo.metrics.collector.DefaultMetricsCollector; +import org.apache.dubbo.common.logger.ErrorTypeAwareLogger; +import org.apache.dubbo.common.logger.LoggerFactory; +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.rpc.Invocation; @@ -29,47 +32,58 @@ import org.apache.dubbo.rpc.model.ScopeModelAware; import static org.apache.dubbo.common.constants.CommonConstants.CONSUMER; import static org.apache.dubbo.common.constants.CommonConstants.PROVIDER; +import static org.apache.dubbo.common.constants.LoggerCodeConstants.INTERNAL_ERROR; +import static org.apache.dubbo.metrics.DefaultConstants.METRIC_FILTER_EVENT; +import static org.apache.dubbo.metrics.DefaultConstants.METRIC_THROWABLE; -@Activate(group = {CONSUMER, PROVIDER}, order = -1) +@Activate(group = {CONSUMER, PROVIDER}, order = Integer.MIN_VALUE + 100) public class MetricsFilter implements Filter, BaseFilter.Listener, ScopeModelAware { - private DefaultMetricsCollector collector = null; - private MethodMetricsInterceptor metricsInterceptor; + private ApplicationModel applicationModel; + private final static ErrorTypeAwareLogger LOGGER = LoggerFactory.getErrorTypeAwareLogger(MetricsFilter.class); @Override public void setApplicationModel(ApplicationModel applicationModel) { - collector = applicationModel.getBeanFactory().getBean(DefaultMetricsCollector.class); - - if (collector != null) { - metricsInterceptor = new MethodMetricsInterceptor(collector.getMethodSampler()); - } + this.applicationModel = applicationModel; } @Override public Result invoke(Invoker invoker, Invocation invocation) throws RpcException { - if (collector == null || !collector.isCollectEnabled()) { - return invoker.invoke(invocation); + try { + RequestEvent requestEvent = RequestEvent.toRequestEvent(applicationModel, invocation); + MetricsEventBus.before(requestEvent, () -> invocation.put(METRIC_FILTER_EVENT, requestEvent)); + } catch (Throwable t) { + LOGGER.warn(INTERNAL_ERROR, "", "", "Error occurred when invoke.", t); } - - metricsInterceptor.beforeMethod(invocation); - return invoker.invoke(invocation); } @Override public void onResponse(Result result, Invoker invoker, Invocation invocation) { - if (collector == null || !collector.isCollectEnabled()) { - return; + Object eventObj = invocation.get(METRIC_FILTER_EVENT); + if (eventObj != null) { + try { + MetricsEventBus.after((RequestEvent) eventObj, result); + } catch (Throwable t) { + LOGGER.warn(INTERNAL_ERROR, "", "", "Error occurred when onResponse.", t); + } } - metricsInterceptor.afterMethod(invocation, result); } @Override public void onError(Throwable t, Invoker invoker, Invocation invocation) { - if (collector == null || !collector.isCollectEnabled()) { - return; + Object eventObj = invocation.get(METRIC_FILTER_EVENT); + if (eventObj != null) { + try { + RequestEvent requestEvent = (RequestEvent) eventObj; + requestEvent.putAttachment(METRIC_THROWABLE, t); + MetricsEventBus.error(requestEvent); + } catch (Throwable throwable) { + LOGGER.warn(INTERNAL_ERROR, "", "", "Error occurred when onResponse.", throwable); + } } - metricsInterceptor.handleMethodException(invocation, t); } + + } diff --git a/dubbo-metrics/dubbo-metrics-default/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.metrics.collector.MetricsCollector b/dubbo-metrics/dubbo-metrics-default/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.metrics.collector.MetricsCollector index 488b68d50f..e806704e86 100644 --- a/dubbo-metrics/dubbo-metrics-default/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.metrics.collector.MetricsCollector +++ b/dubbo-metrics/dubbo-metrics-default/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.metrics.collector.MetricsCollector @@ -1,3 +1,3 @@ -default=org.apache.dubbo.metrics.collector.DefaultMetricsCollector +default-collector=org.apache.dubbo.metrics.collector.DefaultMetricsCollector aggregateMetricsCollector=org.apache.dubbo.metrics.collector.AggregateMetricsCollector configCenterMetricsCollector=org.apache.dubbo.metrics.collector.ConfigCenterMetricsCollector diff --git a/dubbo-metrics/dubbo-metrics-default/src/test/java/org/apache/dubbo/metrics/DefaultMetricsServiceTest.java b/dubbo-metrics/dubbo-metrics-default/src/test/java/org/apache/dubbo/metrics/DefaultMetricsServiceTest.java new file mode 100644 index 0000000000..5bb8c014b7 --- /dev/null +++ b/dubbo-metrics/dubbo-metrics-default/src/test/java/org/apache/dubbo/metrics/DefaultMetricsServiceTest.java @@ -0,0 +1,84 @@ +/* + * 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; + +import org.apache.dubbo.common.beans.factory.ScopeBeanFactory; +import org.apache.dubbo.metrics.collector.MetricsCollector; +import org.apache.dubbo.metrics.model.MetricsCategory; +import org.apache.dubbo.metrics.model.sample.GaugeMetricSample; +import org.apache.dubbo.metrics.model.sample.MetricSample; +import org.apache.dubbo.metrics.service.DefaultMetricsService; +import org.apache.dubbo.metrics.service.MetricsEntity; +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; +import org.mockito.Mockito; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import static org.mockito.Mockito.when; + +@SuppressWarnings("rawtypes") +public class DefaultMetricsServiceTest { + + private MetricsCollector metricsCollector; + + private DefaultMetricsService defaultMetricsService; + + + @BeforeEach + public void setUp() { + ApplicationModel applicationModel = Mockito.mock(ApplicationModel.class); + ScopeBeanFactory beanFactory = Mockito.mock(ScopeBeanFactory.class); + metricsCollector = Mockito.mock(MetricsCollector.class); + + when(applicationModel.getBeanFactory()).thenReturn(beanFactory); + when(beanFactory.getBeansOfType(MetricsCollector.class)).thenReturn(Collections.singletonList(metricsCollector)); + + defaultMetricsService = new DefaultMetricsService(applicationModel); + } + + @Test + public void testGetMetricsByCategories() { + MetricSample sample = new GaugeMetricSample<>( + "testMetric", + "testDescription", + null, + MetricsCategory.REQUESTS, + 42, + value -> 42.0 + ); + when(metricsCollector.collect()).thenReturn(Collections.singletonList(sample)); + List categories = Collections.singletonList(MetricsCategory.REQUESTS); + + Map> result = defaultMetricsService.getMetricsByCategories(categories); + + Assertions.assertNotNull(result); + Assertions.assertEquals(1, result.size()); + List entities = result.get(MetricsCategory.REQUESTS); + Assertions.assertNotNull(entities); + Assertions.assertEquals(1, entities.size()); + + MetricsEntity entity = entities.get(0); + Assertions.assertEquals("testMetric", entity.getName()); + Assertions.assertEquals(42.0, entity.getValue()); + Assertions.assertEquals(MetricsCategory.REQUESTS, entity.getCategory()); + } +} 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 f2275125b1..ff6e7a7582 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 @@ -18,57 +18,94 @@ package org.apache.dubbo.metrics.collector; import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.beans.factory.ScopeBeanFactory; import org.apache.dubbo.common.constants.CommonConstants; +import org.apache.dubbo.common.utils.ReflectionUtils; import org.apache.dubbo.config.ApplicationConfig; import org.apache.dubbo.config.MetricsConfig; +import org.apache.dubbo.config.context.ConfigManager; import org.apache.dubbo.config.nested.AggregationConfig; +import org.apache.dubbo.metrics.MetricsConstants; import org.apache.dubbo.metrics.TestMetricsInvoker; -import org.apache.dubbo.metrics.collector.sample.MethodMetricsSampler; -import org.apache.dubbo.metrics.event.MetricsEvent; +import org.apache.dubbo.metrics.aggregate.TimeWindowCounter; +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.metrics.event.RequestEvent; +import org.apache.dubbo.metrics.filter.MetricsFilter; +import org.apache.dubbo.metrics.model.MethodMetric; +import org.apache.dubbo.metrics.model.MetricsSupport; +import org.apache.dubbo.metrics.model.TimePair; import org.apache.dubbo.metrics.model.key.MetricsKey; +import org.apache.dubbo.metrics.model.key.MetricsLevel; +import org.apache.dubbo.metrics.model.key.TypeWrapper; import org.apache.dubbo.metrics.model.sample.GaugeMetricSample; import org.apache.dubbo.metrics.model.sample.MetricSample; +import org.apache.dubbo.rpc.AppResponse; +import org.apache.dubbo.rpc.AsyncRpcResult; +import org.apache.dubbo.rpc.Result; 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; import org.junit.jupiter.api.Test; +import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.Map; +import java.util.Optional; +import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; -import static org.apache.dubbo.common.constants.CommonConstants.*; +import static org.apache.dubbo.common.constants.CommonConstants.GROUP_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.VERSION_KEY; import static org.apache.dubbo.common.constants.MetricsConstants.TAG_GROUP_KEY; import static org.apache.dubbo.common.constants.MetricsConstants.TAG_INTERFACE_KEY; import static org.apache.dubbo.common.constants.MetricsConstants.TAG_METHOD_KEY; import static org.apache.dubbo.common.constants.MetricsConstants.TAG_VERSION_KEY; +import static org.apache.dubbo.metrics.MetricsConstants.ATTACHMENT_KEY_SERVICE; +import static org.apache.dubbo.metrics.model.MetricsCategory.QPS; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; class AggregateMetricsCollectorTest { private ApplicationModel applicationModel; private DefaultMetricsCollector defaultCollector; - private String interfaceName; private String methodName; private String group; private String version; private RpcInvocation invocation; private String side; + private MetricsDispatcher metricsDispatcher; + private AggregateMetricsCollector collector; + private MetricsFilter metricsFilter; + + public static MethodMetric getTestMethodMetric() { + + MethodMetric methodMetric = new MethodMetric(); + methodMetric.setApplicationName("TestApp"); + methodMetric.setInterfaceName("TestInterface"); + methodMetric.setMethodName("TestMethod"); + methodMetric.setGroup("TestGroup"); + methodMetric.setVersion("1.0.0"); + methodMetric.setSide("PROVIDER"); + + return methodMetric; + } @BeforeEach public void setup() { + applicationModel = ApplicationModel.defaultModel(); ApplicationConfig config = new ApplicationConfig(); config.setName("MockMetrics"); - - applicationModel = ApplicationModel.defaultModel(); applicationModel.getApplicationConfigManager().setApplication(config); - defaultCollector = new DefaultMetricsCollector(); - defaultCollector.setCollectEnabled(true); MetricsConfig metricsConfig = new MetricsConfig(); AggregationConfig aggregationConfig = new AggregationConfig(); aggregationConfig.setEnabled(true); @@ -76,7 +113,16 @@ class AggregateMetricsCollectorTest { aggregationConfig.setTimeWindowSeconds(120); metricsConfig.setAggregation(aggregationConfig); applicationModel.getApplicationConfigManager().setMetrics(metricsConfig); + metricsDispatcher = applicationModel.getBeanFactory().getOrRegisterBean(MetricsDispatcher.class); defaultCollector = applicationModel.getBeanFactory().getBean(DefaultMetricsCollector.class); + collector = applicationModel.getBeanFactory().getOrRegisterBean(AggregateMetricsCollector.class); + collector.setCollectEnabled(true); + + defaultCollector = new DefaultMetricsCollector(); + defaultCollector.setCollectEnabled(true); + + metricsFilter = new MetricsFilter(); + metricsFilter.setApplicationModel(applicationModel); interfaceName = "org.apache.dubbo.MockInterface"; methodName = "mockMethod"; @@ -88,10 +134,20 @@ class AggregateMetricsCollectorTest { invocation.setAttachment(VERSION_KEY, version); side = CommonConstants.CONSUMER; invocation.setInvoker(new TestMetricsInvoker(side)); + invocation.setTargetServiceUniqueName(group + "/" + interfaceName + ":" + version); RpcContext.getServiceContext().setUrl(URL.valueOf("test://test:11/test?accesslog=true&group=dubbo&version=1.1&side=" + side)); } + @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)); + Assertions.assertTrue(metricsCollector.isSupport(event)); + Assertions.assertFalse(metricsCollector.isSupport(beforeEvent)); + } + @AfterEach public void teardown() { applicationModel.destroy(); @@ -100,18 +156,20 @@ class AggregateMetricsCollectorTest { @Test void testRequestsMetrics() { String applicationName = applicationModel.getApplicationName(); - AggregateMetricsCollector collector = new AggregateMetricsCollector(applicationModel); defaultCollector.setApplicationName(applicationName); - MethodMetricsSampler methodMetricsCountSampler = defaultCollector.getMethodSampler(); - methodMetricsCountSampler.incOnEvent(invocation, MetricsEvent.Type.TOTAL.getNameByType(side)); - methodMetricsCountSampler.incOnEvent(invocation, MetricsEvent.Type.SUCCEED.getNameByType(side)); - methodMetricsCountSampler.incOnEvent(invocation, MetricsEvent.Type.UNKNOWN_FAILED.getNameByType(side)); - methodMetricsCountSampler.incOnEvent(invocation, MetricsEvent.Type.BUSINESS_FAILED.getNameByType(side)); - methodMetricsCountSampler.incOnEvent(invocation, MetricsEvent.Type.NETWORK_EXCEPTION.getNameByType(side)); - methodMetricsCountSampler.incOnEvent(invocation, MetricsEvent.Type.SERVICE_UNAVAILABLE.getNameByType(side)); - methodMetricsCountSampler.incOnEvent(invocation, MetricsEvent.Type.CODEC_EXCEPTION.getNameByType(side)); + metricsFilter.invoke(new TestMetricsInvoker(side), invocation); + try { + Thread.sleep(50); + } catch (InterruptedException e) { + e.printStackTrace(); + } + AppResponse mockRpcResult = new AppResponse(); + mockRpcResult.setException(new RpcException(RpcException.NETWORK_EXCEPTION)); + Result result = AsyncRpcResult.newDefaultAsyncResult(mockRpcResult, invocation); + metricsFilter.onResponse(result, new TestMetricsInvoker(side), invocation); + List samples = collector.collect(); @@ -129,42 +187,144 @@ class AggregateMetricsCollectorTest { @SuppressWarnings("rawtypes") Map sampleMap = samples.stream().collect(Collectors.toMap(MetricSample::getName, k -> ((GaugeMetricSample) k).applyAsLong())); - Assertions.assertEquals(sampleMap.get(MetricsKey.METRIC_REQUESTS_TOTAL_AGG.getNameByType(side)), 1L); - Assertions.assertEquals(sampleMap.get(MetricsKey.METRIC_REQUESTS_SUCCEED_AGG.getNameByType(side)), 1L); - Assertions.assertEquals(sampleMap.get(MetricsKey.METRIC_REQUESTS_FAILED_AGG.getNameByType(side)), 1L); - Assertions.assertEquals(sampleMap.get(MetricsKey.METRIC_REQUESTS_BUSINESS_FAILED_AGG.getNameByType(side)), 1L); - - Assertions.assertEquals(sampleMap.get(MetricsKey.METRIC_REQUESTS_TOTAL_NETWORK_FAILED_AGG.getNameByType(side)), 1L); - Assertions.assertEquals(sampleMap.get(MetricsKey.METRIC_REQUESTS_TOTAL_CODEC_FAILED_AGG.getNameByType(side)), 1L); - Assertions.assertEquals(sampleMap.get(MetricsKey.METRIC_REQUESTS_TOTAL_SERVICE_UNAVAILABLE_FAILED_AGG.getNameByType(side)), 1L); - + Assertions.assertEquals(sampleMap.get(MetricsKey.METRIC_REQUESTS_NETWORK_FAILED_AGG.getNameByType(side)), 1L); Assertions.assertTrue(sampleMap.containsKey(MetricsKey.METRIC_QPS.getNameByType(side))); } @Test - void testRTMetrics() { + public void testQPS() { + ApplicationModel applicationModel = mock(ApplicationModel.class); + ConfigManager configManager = mock(ConfigManager.class); + MetricsConfig metricsConfig = mock(MetricsConfig.class); + ScopeBeanFactory beanFactory = mock(ScopeBeanFactory.class); + AggregationConfig aggregationConfig = mock(AggregationConfig.class); + + when(applicationModel.getApplicationConfigManager()).thenReturn(configManager); + when(applicationModel.getBeanFactory()).thenReturn(beanFactory); + when(beanFactory.getBean(DefaultMetricsCollector.class)).thenReturn(new DefaultMetricsCollector()); + when(configManager.getMetrics()).thenReturn(Optional.of(metricsConfig)); + when(metricsConfig.getAggregation()).thenReturn(aggregationConfig); + when(aggregationConfig.getEnabled()).thenReturn(Boolean.TRUE); + AggregateMetricsCollector collector = new AggregateMetricsCollector(applicationModel); - defaultCollector.setApplicationName(applicationModel.getApplicationName()); + MethodMetric methodMetric = getTestMethodMetric(); - MethodMetricsSampler methodMetricsCountSampler = defaultCollector.getMethodSampler(); + TimeWindowCounter qpsCounter = new TimeWindowCounter(10, 120); - methodMetricsCountSampler.addRT(invocation, 10L); - - List samples = collector.collect(); - for (MetricSample sample : samples) { - Map tags = sample.getTags(); - - Assertions.assertEquals(tags.get(TAG_INTERFACE_KEY), interfaceName); - Assertions.assertEquals(tags.get(TAG_METHOD_KEY), methodName); - Assertions.assertEquals(tags.get(TAG_GROUP_KEY), group); - Assertions.assertEquals(tags.get(TAG_VERSION_KEY), version); + for (int i = 0; i < 10000; i++) { + qpsCounter.increment(); } - @SuppressWarnings("rawtypes") - Map sampleMap = samples.stream().collect(Collectors.toMap(MetricSample::getName, k -> ((GaugeMetricSample) k).applyAsLong())); + @SuppressWarnings("unchecked") + ConcurrentHashMap qps = (ConcurrentHashMap) ReflectionUtils.getField(collector, "qps"); + qps.put(methodMetric, qpsCounter); - Assertions.assertTrue(sampleMap.containsKey(MetricsKey.METRIC_RT_P99.getNameByType(side))); - Assertions.assertTrue(sampleMap.containsKey(MetricsKey.METRIC_RT_P95.getNameByType(side))); + List collectedQPS = new ArrayList<>(); + ReflectionUtils.invoke(collector, "collectQPS", collectedQPS); + + Assertions.assertFalse(collectedQPS.isEmpty()); + Assertions.assertEquals(1, collectedQPS.size()); + + MetricSample sample = collectedQPS.get(0); + Assertions.assertEquals(MetricsKey.METRIC_QPS.getNameByType("PROVIDER"), sample.getName()); + Assertions.assertEquals(MetricsKey.METRIC_QPS.getDescription(), sample.getDescription()); + + Assertions.assertEquals(QPS, sample.getCategory()); + Assertions.assertEquals(10000, ((TimeWindowCounter) ((GaugeMetricSample) sample).getValue()).get()); + } + + @Test + void testP95AndP99() throws InterruptedException { + + metricsDispatcher.addListener(collector); + ConfigManager configManager = applicationModel.getApplicationConfigManager(); + MetricsConfig config = configManager.getMetrics().orElse(null); + AggregationConfig aggregationConfig = new AggregationConfig(); + aggregationConfig.setEnabled(true); + config.setAggregation(aggregationConfig); + + List requestTimes = new ArrayList<>(10000); + + for (int i = 0; i < 300; i++) { + requestTimes.add(Double.valueOf(1000 * Math.random()).longValue()); + } + + Collections.sort(requestTimes); + double p95Index = 0.95 * (requestTimes.size() - 1); + double p99Index = 0.99 * (requestTimes.size() - 1); + + double manualP95 = requestTimes.get((int) Math.round(p95Index)); + double manualP99 = requestTimes.get((int) Math.round(p99Index)); + + for (Long requestTime : requestTimes) { + RequestEvent requestEvent = RequestEvent.toRequestEvent(applicationModel, invocation); + TestRequestEvent testRequestEvent = new TestRequestEvent(requestEvent.getSource(), requestEvent.getTypeWrapper()); + testRequestEvent.putAttachment(MetricsConstants.INVOCATION, invocation); + testRequestEvent.putAttachment(ATTACHMENT_KEY_SERVICE, MetricsSupport.getInterfaceName(invocation)); + testRequestEvent.putAttachment(MetricsConstants.INVOCATION_SIDE, MetricsSupport.getSide(invocation)); + testRequestEvent.setRt(requestTime); + MetricsEventBus.post(testRequestEvent, () -> null); + } + Thread.sleep(4000L); + + List samples = collector.collect(); + + GaugeMetricSample p95Sample = samples.stream() + .filter(sample -> sample.getName().endsWith("p95")) + .map(sample -> (GaugeMetricSample) sample) + .findFirst() + .orElse(null); + + GaugeMetricSample p99Sample = samples.stream() + .filter(sample -> sample.getName().endsWith("p99")) + .map(sample -> (GaugeMetricSample) sample) + .findFirst() + .orElse(null); + + Assertions.assertNotNull(p95Sample); + Assertions.assertNotNull(p99Sample); + + double p95 = p95Sample.applyAsDouble(); + double p99 = p99Sample.applyAsDouble(); + + //An error of less than 5% is allowed + System.out.println(Math.abs(1 - p95 / manualP95)); + Assertions.assertTrue(Math.abs(1 - p95 / manualP95) < 0.05); + Assertions.assertTrue(Math.abs(1 - p99 / manualP99) < 0.05); + } + + public static class TestRequestEvent extends RequestEvent { + private long rt; + + public TestRequestEvent(ApplicationModel applicationModel, TypeWrapper typeWrapper) { + super(applicationModel, typeWrapper); + } + + public void setRt(long rt) { + this.rt = rt; + } + + @Override + public TimePair getTimePair() { + return new TestTimePair(rt); + } + + } + + public static class TestTimePair extends TimePair { + + long rt; + + public TestTimePair(long rt) { + super(rt); + this.rt = rt; + } + + @Override + public long calc() { + return this.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 new file mode 100644 index 0000000000..6451214e55 --- /dev/null +++ b/dubbo-metrics/dubbo-metrics-default/src/test/java/org/apache/dubbo/metrics/collector/DefaultCollectorTest.java @@ -0,0 +1,244 @@ +/* + * 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.collector; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.constants.CommonConstants; +import org.apache.dubbo.config.ApplicationConfig; +import org.apache.dubbo.metrics.TestMetricsInvoker; +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.ServiceKeyMetric; +import org.apache.dubbo.metrics.model.key.MetricsKey; +import org.apache.dubbo.metrics.model.key.MetricsKeyWrapper; +import org.apache.dubbo.metrics.model.key.MetricsLevel; +import org.apache.dubbo.metrics.model.key.MetricsPlaceValue; +import org.apache.dubbo.metrics.model.key.TypeWrapper; +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.rpc.AppResponse; +import org.apache.dubbo.rpc.AsyncRpcResult; +import org.apache.dubbo.rpc.Result; +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.FrameworkModel; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.util.List; +import java.util.Map; +import java.util.concurrent.atomic.AtomicLong; +import java.util.stream.Collectors; + +import static org.apache.dubbo.common.constants.CommonConstants.GROUP_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.VERSION_KEY; +import static org.apache.dubbo.common.constants.MetricsConstants.TAG_APPLICATION_NAME; +import static org.apache.dubbo.metrics.DefaultConstants.METRIC_FILTER_EVENT; +import static org.apache.dubbo.metrics.model.key.MetricsKey.METRIC_REQUESTS; +import static org.apache.dubbo.metrics.model.key.MetricsKey.METRIC_REQUESTS_PROCESSING; +import static org.apache.dubbo.metrics.model.key.MetricsKey.METRIC_REQUESTS_SUCCEED; +import static org.apache.dubbo.metrics.model.key.MetricsKey.METRIC_REQUESTS_TIMEOUT; +import static org.apache.dubbo.metrics.model.key.MetricsKey.METRIC_REQUESTS_TOTAL_FAILED; + + +class DefaultCollectorTest { + + private ApplicationModel applicationModel; + + private String interfaceName; + private String methodName; + private String group; + private String version; + private RpcInvocation invocation; + private String side; + + MetricsDispatcher metricsDispatcher; + DefaultMetricsCollector defaultCollector; + + MetricsFilter metricsFilter; + + @BeforeEach + public void setup() { + FrameworkModel frameworkModel = FrameworkModel.defaultModel(); + applicationModel = frameworkModel.newApplication(); + ApplicationConfig config = new ApplicationConfig(); + config.setName("MockMetrics"); + + applicationModel.getApplicationConfigManager().setApplication(config); + metricsDispatcher = applicationModel.getBeanFactory().getOrRegisterBean(MetricsDispatcher.class); + defaultCollector = applicationModel.getBeanFactory().getBean(DefaultMetricsCollector.class); + defaultCollector.setCollectEnabled(true); + + interfaceName = "org.apache.dubbo.MockInterface"; + methodName = "mockMethod"; + group = "mockGroup"; + version = "1.0.0"; + invocation = new RpcInvocation(methodName, interfaceName, "serviceKey", null, null); + invocation.setTargetServiceUniqueName(group + "/" + interfaceName + ":" + version); + invocation.setAttachment(GROUP_KEY, group); + invocation.setAttachment(VERSION_KEY, version); + side = CommonConstants.CONSUMER; + invocation.setInvoker(new TestMetricsInvoker(side)); + invocation.setTargetServiceUniqueName(group + "/" + interfaceName + ":" + version); + RpcContext.getServiceContext().setUrl(URL.valueOf("test://test:11/test?accesslog=true&group=dubbo&version=1.1&side=" + side)); + + metricsFilter = new MetricsFilter(); + metricsFilter.setApplicationModel(applicationModel); + } + + @Test + void testListener() { + DefaultMetricsCollector metricsCollector = new DefaultMetricsCollector(); + RequestEvent event = RequestEvent.toRequestEvent(applicationModel, invocation); + RequestBeforeEvent beforeEvent = new RequestBeforeEvent(applicationModel, new TypeWrapper(MetricsLevel.METHOD, MetricsKey.METRIC_REQUESTS)); + Assertions.assertTrue(metricsCollector.isSupport(event)); + Assertions.assertTrue(metricsCollector.isSupport(beforeEvent)); + } + + @AfterEach + public void teardown() { + applicationModel.destroy(); + } + + /** + * No rt metrics because Aggregate calc + */ + @Test + void testRequestEventNoRt() { + + applicationModel.getBeanFactory().getOrRegisterBean(MetricsDispatcher.class); + DefaultMetricsCollector collector = applicationModel.getBeanFactory().getOrRegisterBean(DefaultMetricsCollector.class); + collector.setCollectEnabled(true); + + metricsFilter.invoke(new TestMetricsInvoker(side), invocation); + try { + Thread.sleep(50); + } catch (InterruptedException e) { + e.printStackTrace(); + } + AppResponse mockRpcResult = new AppResponse(); +// mockRpcResult.setException(new RpcException("hessian")); + Result result = AsyncRpcResult.newDefaultAsyncResult(mockRpcResult, invocation); + metricsFilter.onResponse(result, new TestMetricsInvoker(side), invocation); + + RequestEvent eventObj = (RequestEvent) invocation.get(METRIC_FILTER_EVENT); + long c1 = eventObj.getTimePair().calc(); + + // push finish rt +1 + List metricSamples = collector.collect(); + //num(total+success+processing) + rt(5) = 8 + Assertions.assertEquals(8, metricSamples.size()); + List metricsNames = metricSamples.stream().map(MetricSample::getName).collect(Collectors.toList()); + // No error will contain total+success+processing + String REQUESTS = new MetricsKeyWrapper(METRIC_REQUESTS, MetricsPlaceValue.of(side, MetricsLevel.SERVICE)).targetKey(); + String SUCCEED = new MetricsKeyWrapper(METRIC_REQUESTS_SUCCEED, MetricsPlaceValue.of(side, MetricsLevel.SERVICE)).targetKey(); + String PROCESSING = new MetricsKeyWrapper(METRIC_REQUESTS_PROCESSING, MetricsPlaceValue.of(side, MetricsLevel.SERVICE)).targetKey(); + Assertions.assertTrue(metricsNames.contains(REQUESTS)); + Assertions.assertTrue(metricsNames.contains(SUCCEED)); + Assertions.assertTrue(metricsNames.contains(PROCESSING)); + for (MetricSample metricSample : metricSamples) { + if (metricSample instanceof GaugeMetricSample) { + GaugeMetricSample gaugeMetricSample = (GaugeMetricSample) metricSample; + Object objVal = gaugeMetricSample.getValue(); + if (objVal instanceof Map) { + Map value = (Map) objVal; + if (metricSample.getName().equals(REQUESTS)) { + Assertions.assertTrue(value.values().stream().allMatch(atomicLong -> atomicLong.intValue() == 1)); + } + if (metricSample.getName().equals(PROCESSING)) { + Assertions.assertTrue(value.values().stream().allMatch(atomicLong -> atomicLong.intValue() == 0)); + } + } + } else { + AtomicLong value = (AtomicLong) ((CounterMetricSample) metricSample).getValue(); + if (metricSample.getName().equals(SUCCEED)) { + Assertions.assertEquals(1, value.intValue()); + } + } + } + + metricsFilter.invoke(new TestMetricsInvoker(side), invocation); + try { + Thread.sleep(50); + } catch (InterruptedException e) { + e.printStackTrace(); + } + metricsFilter.onError(new RpcException(RpcException.TIMEOUT_EXCEPTION, "timeout"), new TestMetricsInvoker(side), invocation); + eventObj = (RequestEvent) invocation.get(METRIC_FILTER_EVENT); + long c2 = eventObj.getTimePair().calc(); + metricSamples = collector.collect(); + + // num(total+success+error+total_error+processing) + rt(5) = 5 + Assertions.assertEquals(10, metricSamples.size()); + + String TIMEOUT = new MetricsKeyWrapper(METRIC_REQUESTS_TIMEOUT, MetricsPlaceValue.of(side, MetricsLevel.SERVICE)).targetKey(); + String TOTAL_FAILED = new MetricsKeyWrapper(METRIC_REQUESTS_TOTAL_FAILED, MetricsPlaceValue.of(side, MetricsLevel.SERVICE)).targetKey(); + for (MetricSample metricSample : metricSamples) { + if (metricSample instanceof GaugeMetricSample) { + GaugeMetricSample gaugeMetricSample = (GaugeMetricSample) metricSample; + Object objVal = gaugeMetricSample.getValue(); + if (objVal instanceof Map) { + Map value = (Map) ((GaugeMetricSample) metricSample).getValue(); + if (metricSample.getName().equals(REQUESTS)) { + Assertions.assertTrue(value.values().stream().allMatch(atomicLong -> atomicLong.intValue() == 2)); + } + if (metricSample.getName().equals(REQUESTS)) { + Assertions.assertTrue(value.values().stream().allMatch(atomicLong -> atomicLong.intValue() == 2)); + } + if (metricSample.getName().equals(PROCESSING)) { + Assertions.assertTrue(value.values().stream().allMatch(atomicLong -> atomicLong.intValue() == 0)); + } + if (metricSample.getName().equals(TIMEOUT)) { + Assertions.assertTrue(value.values().stream().allMatch(atomicLong -> atomicLong.intValue() == 1)); + } + if (metricSample.getName().equals(TOTAL_FAILED)) { + Assertions.assertTrue(value.values().stream().allMatch(atomicLong -> atomicLong.intValue() == 1)); + } + } + } else { + AtomicLong value = (AtomicLong) ((CounterMetricSample) metricSample).getValue(); + if (metricSample.getName().equals(SUCCEED)) { + Assertions.assertEquals(1, value.intValue()); + } + } + } + + + // calc rt + for (MetricSample sample : metricSamples) { + Map tags = sample.getTags(); + Assertions.assertEquals(tags.get(TAG_APPLICATION_NAME), applicationModel.getApplicationName()); + } + + Map sampleMap = metricSamples.stream().filter(metricSample -> metricSample instanceof GaugeMetricSample).collect(Collectors.toMap(MetricSample::getName, k -> ((GaugeMetricSample) k).applyAsLong())); + + Assertions.assertEquals(sampleMap.get(new MetricsKeyWrapper(MetricsKey.METRIC_RT_LAST, MetricsPlaceValue.of(side, MetricsLevel.SERVICE)).targetKey()), c2); + Assertions.assertEquals(sampleMap.get(new MetricsKeyWrapper(MetricsKey.METRIC_RT_MIN, MetricsPlaceValue.of(side, MetricsLevel.SERVICE)).targetKey()), Math.min(c1, c2)); + Assertions.assertEquals(sampleMap.get(new MetricsKeyWrapper(MetricsKey.METRIC_RT_MAX, MetricsPlaceValue.of(side, MetricsLevel.SERVICE)).targetKey()), Math.max(c1, c2)); + Assertions.assertEquals(sampleMap.get(new MetricsKeyWrapper(MetricsKey.METRIC_RT_AVG, MetricsPlaceValue.of(side, MetricsLevel.SERVICE)).targetKey()), (c1 + c2) / 2); + Assertions.assertEquals(sampleMap.get(new MetricsKeyWrapper(MetricsKey.METRIC_RT_SUM, MetricsPlaceValue.of(side, MetricsLevel.SERVICE)).targetKey()), c1 + c2); + } + +} diff --git a/dubbo-metrics/dubbo-metrics-default/src/test/java/org/apache/dubbo/metrics/collector/sample/ThreadPoolMetricsSamplerTest.java b/dubbo-metrics/dubbo-metrics-default/src/test/java/org/apache/dubbo/metrics/collector/sample/ThreadPoolMetricsSamplerTest.java new file mode 100644 index 0000000000..4b336d91f6 --- /dev/null +++ b/dubbo-metrics/dubbo-metrics-default/src/test/java/org/apache/dubbo/metrics/collector/sample/ThreadPoolMetricsSamplerTest.java @@ -0,0 +1,180 @@ +/* + * 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.collector.sample; + +import org.apache.dubbo.common.beans.factory.ScopeBeanFactory; +import org.apache.dubbo.common.extension.ExtensionLoader; +import org.apache.dubbo.common.store.DataStore; +import org.apache.dubbo.common.threadpool.manager.FrameworkExecutorRepository; +import org.apache.dubbo.metrics.collector.DefaultMetricsCollector; +import org.apache.dubbo.metrics.model.ThreadPoolMetric; +import org.apache.dubbo.metrics.model.sample.GaugeMetricSample; +import org.apache.dubbo.metrics.model.sample.MetricSample; +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; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +import java.lang.reflect.Field; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadPoolExecutor; + +import static org.apache.dubbo.common.constants.CommonConstants.CONSUMER_SHARED_EXECUTOR_SERVICE_COMPONENT_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.EXECUTOR_SERVICE_COMPONENT_KEY; +import static org.mockito.Mockito.when; + +@SuppressWarnings("all") +public class ThreadPoolMetricsSamplerTest { + + ThreadPoolMetricsSampler sampler; + + @BeforeEach + void setUp() { + DefaultMetricsCollector collector = new DefaultMetricsCollector(); + sampler = new ThreadPoolMetricsSampler(collector); + } + + @Test + void testSample() { + + ExecutorService executorService = java.util.concurrent.Executors.newFixedThreadPool(5); + ThreadPoolExecutor threadPoolExecutor = (ThreadPoolExecutor) executorService; + sampler.addExecutors("testPool", executorService); + + List metricSamples = sampler.sample(); + + Assertions.assertEquals(6, metricSamples.size()); + + boolean coreSizeFound = false; + boolean maxSizeFound = false; + boolean activeSizeFound = false; + boolean threadCountFound = false; + boolean queueSizeFound = false; + boolean largestSizeFound = false; + + for (MetricSample sample : metricSamples) { + ThreadPoolMetric threadPoolMetric = ((ThreadPoolMetric) ((GaugeMetricSample) sample).getValue()); + switch (sample.getName()) { + case "dubbo.thread.pool.core.size": + coreSizeFound = true; + Assertions.assertEquals(5, threadPoolMetric.getCorePoolSize()); + break; + case "dubbo.thread.pool.largest.size": + largestSizeFound = true; + Assertions.assertEquals(0, threadPoolMetric.getLargestPoolSize()); + break; + case "dubbo.thread.pool.max.size": + maxSizeFound = true; + Assertions.assertEquals(5, threadPoolMetric.getMaximumPoolSize()); + break; + case "dubbo.thread.pool.active.size": + activeSizeFound = true; + Assertions.assertEquals(0, threadPoolMetric.getActiveCount()); + break; + case "dubbo.thread.pool.thread.count": + threadCountFound = true; + Assertions.assertEquals(0, threadPoolMetric.getPoolSize()); + break; + case "dubbo.thread.pool.queue.size": + queueSizeFound = true; + Assertions.assertEquals(0, threadPoolMetric.getQueueSize()); + break; + } + } + + Assertions.assertTrue(coreSizeFound); + Assertions.assertTrue(maxSizeFound); + Assertions.assertTrue(activeSizeFound); + Assertions.assertTrue(threadCountFound); + Assertions.assertTrue(queueSizeFound); + Assertions.assertTrue(largestSizeFound); + + executorService.shutdown(); + } + + private DefaultMetricsCollector collector; + + private ThreadPoolMetricsSampler sampler2; + + @Mock + private ApplicationModel applicationModel; + + @Mock + ScopeBeanFactory scopeBeanFactory; + + @Mock + private DataStore dataStore; + + @Mock + private FrameworkExecutorRepository frameworkExecutorRepository; + + @Mock + private ExtensionLoader extensionLoader; + + @BeforeEach + public void setUp2() { + MockitoAnnotations.openMocks(this); + + collector = new DefaultMetricsCollector(); + sampler2 = new ThreadPoolMetricsSampler(collector); + + when(scopeBeanFactory.getBean(FrameworkExecutorRepository.class)).thenReturn(new FrameworkExecutorRepository()); + + collector.collectApplication(applicationModel); + when(applicationModel.getBeanFactory()).thenReturn(scopeBeanFactory); + when(applicationModel.getExtensionLoader(DataStore.class)).thenReturn(extensionLoader); + when(extensionLoader.getDefaultExtension()).thenReturn(dataStore); + } + + @Test + public void testRegistryDefaultSampleThreadPoolExecutor() throws NoSuchFieldException, IllegalAccessException { + + Map serverExecutors = new HashMap<>(); + Map clientExecutors = new HashMap<>(); + + ExecutorService serverExecutor = Executors.newFixedThreadPool(5); + ExecutorService clientExecutor = Executors.newFixedThreadPool(5); + + serverExecutors.put("server1", serverExecutor); + clientExecutors.put("client1", clientExecutor); + + when(dataStore.get(EXECUTOR_SERVICE_COMPONENT_KEY)).thenReturn(serverExecutors); + when(dataStore.get(CONSUMER_SHARED_EXECUTOR_SERVICE_COMPONENT_KEY)).thenReturn(clientExecutors); + + when(frameworkExecutorRepository.getSharedExecutor()).thenReturn(Executors.newFixedThreadPool(5)); + + sampler2.registryDefaultSampleThreadPoolExecutor(); + + Field f = ThreadPoolMetricsSampler.class.getDeclaredField("sampleThreadPoolExecutor"); + f.setAccessible(true); + Map executors = (Map) f.get(sampler2); + + Assertions.assertEquals(3, executors.size()); + Assertions.assertTrue(executors.containsKey("DubboServerHandler-server1")); + Assertions.assertTrue(executors.containsKey("DubboClientHandler-client1")); + Assertions.assertTrue(executors.containsKey("sharedExecutor")); + + serverExecutor.shutdown(); + clientExecutor.shutdown(); + } +} diff --git a/dubbo-metrics/dubbo-metrics-default/src/test/java/org/apache/dubbo/metrics/filter/MetricsFilterTest.java b/dubbo-metrics/dubbo-metrics-default/src/test/java/org/apache/dubbo/metrics/filter/MetricsFilterTest.java index e8d0cb8b9f..393124175e 100644 --- a/dubbo-metrics/dubbo-metrics-default/src/test/java/org/apache/dubbo/metrics/filter/MetricsFilterTest.java +++ b/dubbo-metrics/dubbo-metrics-default/src/test/java/org/apache/dubbo/metrics/filter/MetricsFilterTest.java @@ -46,7 +46,10 @@ import java.util.stream.Collectors; import static org.apache.dubbo.common.constants.CommonConstants.$INVOKE; import static org.apache.dubbo.common.constants.CommonConstants.GENERIC_PARAMETER_DESC; -import static org.apache.dubbo.common.constants.MetricsConstants.*; +import static org.apache.dubbo.common.constants.MetricsConstants.TAG_GROUP_KEY; +import static org.apache.dubbo.common.constants.MetricsConstants.TAG_INTERFACE_KEY; +import static org.apache.dubbo.common.constants.MetricsConstants.TAG_METHOD_KEY; +import static org.apache.dubbo.common.constants.MetricsConstants.TAG_VERSION_KEY; import static org.mockito.BDDMockito.given; import static org.mockito.Mockito.mock; @@ -80,7 +83,7 @@ class MetricsFilterTest { filter = new MetricsFilter(); collector = applicationModel.getBeanFactory().getOrRegisterBean(DefaultMetricsCollector.class); - if(!initApplication.get()) { + if (!initApplication.get()) { collector.collectApplication(applicationModel); initApplication.set(true); } @@ -105,6 +108,8 @@ class MetricsFilterTest { Assertions.assertTrue(metricsMap.isEmpty()); } + + @Test void testUnknownFailedRequests() { collector.setCollectEnabled(true); @@ -260,14 +265,13 @@ class MetricsFilterTest { } @Test - public void testErrors(){ + public void testErrors() { testFilterError(RpcException.SERIALIZATION_EXCEPTION, MetricsKey.METRIC_REQUESTS_CODEC_FAILED.formatName(side)); testFilterError(RpcException.NETWORK_EXCEPTION, MetricsKey.METRIC_REQUESTS_NETWORK_FAILED.formatName(side)); } - - private void testFilterError(int errorCode,MetricsKey metricsKey){ + private void testFilterError(int errorCode, MetricsKey metricsKey) { setup(); collector.setCollectEnabled(true); given(invoker.invoke(invocation)).willThrow(new RpcException(errorCode)); diff --git a/dubbo-metrics/dubbo-metrics-default/src/test/java/org/apache/dubbo/metrics/metrics/collector/DefaultMetricsCollectorTest.java b/dubbo-metrics/dubbo-metrics-default/src/test/java/org/apache/dubbo/metrics/metrics/collector/DefaultMetricsCollectorTest.java deleted file mode 100644 index d492c21e9e..0000000000 --- a/dubbo-metrics/dubbo-metrics-default/src/test/java/org/apache/dubbo/metrics/metrics/collector/DefaultMetricsCollectorTest.java +++ /dev/null @@ -1,209 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.dubbo.metrics.metrics.collector; - -import org.apache.dubbo.common.URL; -import org.apache.dubbo.common.constants.CommonConstants; -import org.apache.dubbo.config.ApplicationConfig; -import org.apache.dubbo.metrics.TestMetricsInvoker; -import org.apache.dubbo.metrics.collector.DefaultMetricsCollector; -import org.apache.dubbo.metrics.collector.sample.MethodMetricsSampler; -import org.apache.dubbo.metrics.event.MethodEvent; -import org.apache.dubbo.metrics.event.MetricsEvent; -import org.apache.dubbo.metrics.event.RTEvent; -import org.apache.dubbo.metrics.listener.MetricsListener; -import org.apache.dubbo.metrics.model.key.MetricsKey; -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.rpc.RpcContext; -import org.apache.dubbo.rpc.RpcInvocation; -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; -import org.junit.jupiter.api.Test; - -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -import static org.apache.dubbo.common.constants.CommonConstants.*; -import static org.apache.dubbo.common.constants.MetricsConstants.TAG_GROUP_KEY; -import static org.apache.dubbo.common.constants.MetricsConstants.TAG_INTERFACE_KEY; -import static org.apache.dubbo.common.constants.MetricsConstants.TAG_METHOD_KEY; -import static org.apache.dubbo.common.constants.MetricsConstants.TAG_VERSION_KEY; - -class DefaultMetricsCollectorTest { - - private FrameworkModel frameworkModel; - private ApplicationModel applicationModel; - private String interfaceName; - private String methodName; - private String group; - private String version; - private RpcInvocation invocation; - private String side; - - @BeforeEach - public void setup() { - frameworkModel = FrameworkModel.defaultModel(); - applicationModel = frameworkModel.newApplication(); - ApplicationConfig config = new ApplicationConfig(); - config.setName("MockMetrics"); - - applicationModel.getApplicationConfigManager().setApplication(config); - - interfaceName = "org.apache.dubbo.MockInterface"; - methodName = "mockMethod"; - group = "mockGroup"; - version = "1.0.0"; - - invocation = new RpcInvocation(methodName, interfaceName, "serviceKey", null, null); - invocation.setTargetServiceUniqueName(group + "/" + interfaceName + ":" + version); - invocation.setAttachment(GROUP_KEY, group); - invocation.setAttachment(VERSION_KEY, version); - side = CommonConstants.CONSUMER; - - invocation.setInvoker(new TestMetricsInvoker(side)); - RpcContext.getServiceContext().setUrl(URL.valueOf("test://test:11/test?accesslog=true&group=dubbo&version=1.1&side=" + side)); - - } - - @AfterEach - public void teardown() { - applicationModel.destroy(); - } - - @Test - @SuppressWarnings("rawtypes") - void testRequestsMetrics() { - DefaultMetricsCollector collector = new DefaultMetricsCollector(); - collector.setCollectEnabled(true); - collector.setApplicationName(applicationModel.getApplicationName()); - - MethodMetricsSampler methodMetricsCountSampler = collector.getMethodSampler(); - - methodMetricsCountSampler.incOnEvent(invocation, MetricsEvent.Type.TOTAL.getNameByType(side)); - methodMetricsCountSampler.incOnEvent(invocation, MetricsEvent.Type.PROCESSING.getNameByType(side)); - methodMetricsCountSampler.incOnEvent(invocation, MetricsEvent.Type.SUCCEED.getNameByType(side)); - methodMetricsCountSampler.incOnEvent(invocation, MetricsEvent.Type.UNKNOWN_FAILED.getNameByType(side)); - - List samples = collector.collect(); - for (MetricSample sample : samples) { - if(sample instanceof GaugeMetricSample) { - GaugeMetricSample gaugeSample = (GaugeMetricSample) sample; - Assertions.assertEquals(gaugeSample.applyAsLong(), 1); - }else if(sample instanceof CounterMetricSample){ - CounterMetricSample counterMetricSample = (CounterMetricSample) sample; - Assertions.assertEquals(counterMetricSample.getValue().longValue(), 1); - } - - Map tags = sample.getTags(); - Assertions.assertEquals(tags.get(TAG_INTERFACE_KEY), interfaceName); - Assertions.assertEquals(tags.get(TAG_METHOD_KEY), methodName); - Assertions.assertEquals(tags.get(TAG_GROUP_KEY), group); - Assertions.assertEquals(tags.get(TAG_VERSION_KEY), version); - - } - - methodMetricsCountSampler.dec(invocation, MetricsEvent.Type.PROCESSING.getNameByType(side)); - samples = collector.collect(); - - Map sampleMap = samples.stream().collect(Collectors.toMap(MetricSample::getName, k -> { - if(k instanceof GaugeMetricSample){ - return ((GaugeMetricSample) k).applyAsLong(); - }else if(k instanceof CounterMetricSample){ - return ((CounterMetricSample)k).getValue().longValue(); - }else{ - throw new RuntimeException("un support sample type"); - } - })); - - Assertions.assertEquals(sampleMap.get(MetricsKey.METRIC_REQUESTS_PROCESSING.getNameByType(side)), 0L); - } - - @Test - void testRTMetrics() { - DefaultMetricsCollector collector = new DefaultMetricsCollector(); - collector.setCollectEnabled(true); - MethodMetricsSampler methodMetricsCountSampler = collector.getMethodSampler(); - String applicationName = applicationModel.getApplicationName(); - - collector.setApplicationName(applicationName); - - methodMetricsCountSampler.addRT(invocation, 10L); - methodMetricsCountSampler.addRT(invocation, 0L); - - List samples = collector.collect(); - for (MetricSample sample : samples) { - Map tags = sample.getTags(); - - Assertions.assertEquals(tags.get(TAG_INTERFACE_KEY), interfaceName); - Assertions.assertEquals(tags.get(TAG_METHOD_KEY), methodName); - Assertions.assertEquals(tags.get(TAG_GROUP_KEY), group); - Assertions.assertEquals(tags.get(TAG_VERSION_KEY), version); - } - - @SuppressWarnings("rawtypes") - Map sampleMap = samples.stream().collect(Collectors.toMap(MetricSample::getName, k -> ((GaugeMetricSample) k).applyAsLong())); - - Assertions.assertEquals(sampleMap.get(MetricsKey.METRIC_RT_LAST.getNameByType(side)), 0L); - Assertions.assertEquals(sampleMap.get(MetricsKey.METRIC_RT_MIN.getNameByType(side)), 0L); - Assertions.assertEquals(sampleMap.get(MetricsKey.METRIC_RT_MAX.getNameByType(side)), 10L); - Assertions.assertEquals(sampleMap.get(MetricsKey.METRIC_RT_AVG.getNameByType(side)), 5L); - Assertions.assertEquals(sampleMap.get(MetricsKey.METRIC_RT_SUM.getNameByType(side)), 10L); - } - - @Test - void testListener() { - DefaultMetricsCollector collector = new DefaultMetricsCollector(); - MethodMetricsSampler methodMetricsCountSampler = collector.getMethodSampler(); - collector.setCollectEnabled(true); - - MockListener mockListener = new MockListener(); - collector.addListener(mockListener); - collector.setApplicationName(applicationModel.getApplicationName()); - - methodMetricsCountSampler.incOnEvent(invocation, MetricsEvent.Type.TOTAL.getNameByType(side)); - Assertions.assertNotNull(mockListener.getCurEvent()); - Assertions.assertTrue(mockListener.getCurEvent() instanceof MethodEvent); - Assertions.assertEquals(((MethodEvent) mockListener.getCurEvent()).getType(), - MetricsEvent.Type.TOTAL.getNameByType(side)); - - methodMetricsCountSampler.addRT(invocation, 5L); - Assertions.assertTrue(mockListener.getCurEvent() instanceof RTEvent); - Assertions.assertEquals(((RTEvent) mockListener.getCurEvent()).getRt(), 5L); - } - - static class MockListener implements MetricsListener { - - private MetricsEvent curEvent; - - @Override - public void onEvent(MetricsEvent event) { - curEvent = event; - } - - public MetricsEvent getCurEvent() { - return curEvent; - } - } -} diff --git a/dubbo-metrics/dubbo-metrics-default/src/test/java/org/apache/dubbo/metrics/sampler/CountSamplerTest.java b/dubbo-metrics/dubbo-metrics-default/src/test/java/org/apache/dubbo/metrics/sampler/CountSamplerTest.java deleted file mode 100644 index b56d194c76..0000000000 --- a/dubbo-metrics/dubbo-metrics-default/src/test/java/org/apache/dubbo/metrics/sampler/CountSamplerTest.java +++ /dev/null @@ -1,192 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.dubbo.metrics.sampler; - -import org.apache.dubbo.metrics.collector.sample.MetricsCountSampleConfigurer; -import org.apache.dubbo.metrics.collector.sample.MetricsCountSampler; -import org.apache.dubbo.metrics.collector.sample.SimpleMetricsCountSampler; -import org.apache.dubbo.metrics.model.Metric; -import org.apache.dubbo.metrics.model.key.MetricsKey; -import org.apache.dubbo.metrics.model.sample.GaugeMetricSample; -import org.apache.dubbo.metrics.model.sample.MetricSample; - -import org.junit.Test; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeEach; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.function.ToDoubleFunction; -import java.util.stream.Collectors; - -import static org.apache.dubbo.metrics.model.MetricsCategory.RT; - -public class CountSamplerTest { - String side = "consumer"; - - public RequestMetricsCountSampler sampler = new RequestMetricsCountSampler(); - - @BeforeEach - public void before() { - sampler = new RequestMetricsCountSampler(); - } - - @Test - public void rtTest() { - String applicationName = "test"; - - sampler.addRT(applicationName, RTType.METHOD_REQUEST, 2L); - @SuppressWarnings("rawtypes") - Map collect = getCollect(RTType.METHOD_REQUEST); - - Assertions.assertNotNull(collect); - - Assertions.assertTrue(null != collect.get(MetricsKey.METRIC_RT_LAST.getNameByType(side)) && collect.get( - MetricsKey.METRIC_RT_LAST.getNameByType(side)).applyAsLong() == 2); - Assertions.assertTrue(null != collect.get(MetricsKey.METRIC_RT_MIN.getNameByType(side)) && collect.get( - MetricsKey.METRIC_RT_MIN.getNameByType(side)).applyAsLong() == 2); - Assertions.assertTrue(null != collect.get(MetricsKey.METRIC_RT_MAX.getNameByType(side)) && collect.get( - MetricsKey.METRIC_RT_MAX.getNameByType(side)).applyAsLong() == 2); - Assertions.assertTrue(null != collect.get(MetricsKey.METRIC_RT_AVG.getNameByType(side)) && collect.get( - MetricsKey.METRIC_RT_AVG.getNameByType(side)).applyAsLong() == 2); - Assertions.assertTrue(null != collect.get(MetricsKey.METRIC_RT_SUM.getNameByType(side)) && collect.get( - MetricsKey.METRIC_RT_SUM.getNameByType(side)).applyAsLong() == 2); - - sampler.addRT(applicationName, RTType.METHOD_REQUEST, 1L); - collect = getCollect(RTType.METHOD_REQUEST); - - Assertions.assertTrue( - null != collect.get(MetricsKey.METRIC_RT_LAST.getNameByType(side)) && collect.get( - MetricsKey.METRIC_RT_LAST.getNameByType(side)).applyAsLong() == 1); - Assertions.assertTrue( - null != collect.get(MetricsKey.METRIC_RT_MIN.getNameByType(side)) && collect.get( - MetricsKey.METRIC_RT_MIN.getNameByType(side)).applyAsLong() == 1); - Assertions.assertTrue( - null != collect.get(MetricsKey.METRIC_RT_MAX.getNameByType(side)) && collect.get( - MetricsKey.METRIC_RT_MAX.getNameByType(side)).applyAsLong() == 2); - Assertions.assertTrue( - null != collect.get(MetricsKey.METRIC_RT_AVG.getNameByType(side)) && collect.get( - MetricsKey.METRIC_RT_AVG.getNameByType(side)).applyAsLong() == 1); - Assertions.assertTrue( - null != collect.get(MetricsKey.METRIC_RT_SUM.getNameByType(side)) && collect.get( - MetricsKey.METRIC_RT_SUM.getNameByType(side)).applyAsLong() == 3); - - sampler.addRT(applicationName, RTType.APPLICATION, 4L); - collect = getCollect(RTType.APPLICATION); - - Assertions.assertTrue( - null != collect.get(MetricsKey.METRIC_RT_LAST.getNameByType(side)) && collect.get( - MetricsKey.METRIC_RT_LAST.getNameByType(side)).applyAsLong() == 4); - Assertions.assertTrue( - null != collect.get(MetricsKey.METRIC_RT_MIN.getNameByType(side)) && collect.get( - MetricsKey.METRIC_RT_MIN.getNameByType(side)).applyAsLong() == 4); - Assertions.assertTrue( - null != collect.get(MetricsKey.METRIC_RT_MAX.getNameByType(side)) && collect.get( - MetricsKey.METRIC_RT_MAX.getNameByType(side)).applyAsLong() == 4); - Assertions.assertTrue( - null != collect.get(MetricsKey.METRIC_RT_AVG.getNameByType(side)) && collect.get( - MetricsKey.METRIC_RT_AVG.getNameByType(side)).applyAsLong() == 4); - Assertions.assertTrue( - null != collect.get(MetricsKey.METRIC_RT_SUM.getNameByType(side)) && collect.get( - MetricsKey.METRIC_RT_SUM.getNameByType(side)).applyAsLong() == 4); - } - - @SuppressWarnings("rawtypes") - private Map getCollect(RTType rtType) { - List> metricSamples = sampler.collectRT( - new MetricsCountSampler.MetricSampleFactory>() { - @Override - public GaugeMetricSample newInstance(MetricsKey key, RequestMethodMetrics metric, T value, ToDoubleFunction apply) { - return new GaugeMetricSample<>(key.getNameByType(side), key.getDescription(), - metric.getTags(), RT, value, apply); - } - }, rtType); - - return metricSamples.stream() - .collect(Collectors.toMap(MetricSample::getName, v -> v)); - } - - public class RequestMetricsCountSampler extends SimpleMetricsCountSampler { - - @Override - public List sample() { - return null; - } - - @Override - protected void countConfigure( - MetricsCountSampleConfigurer sampleConfigure) { - sampleConfigure.configureMetrics( - configure -> new RequestMethodMetrics(configure.getSource())); - sampleConfigure.configureEventHandler(configure -> { - System.out.println("generic event"); - }); - } - - @Override - public void rtConfigure( - MetricsCountSampleConfigurer sampleConfigure) { - sampleConfigure.configureMetrics(configure -> new RequestMethodMetrics(configure.getSource())); - sampleConfigure.configureEventHandler(configure -> { - System.out.println("rt event"); - }); - } - } - - enum RTType { - METHOD_REQUEST, - APPLICATION - } - - static class RequestMethodMetrics implements Metric { - - private final String applicationName; - - public RequestMethodMetrics(String applicationName) { - this.applicationName = applicationName; - } - - @Override - public Map getTags() { - Map tags = new HashMap<>(); - tags.put("serviceName", "test"); - tags.put("version", "1.0.0"); - tags.put("uptime", "20220202"); - return tags; - } - - @Override - public boolean equals(Object o) { - if (this == o) - return true; - if (!(o instanceof RequestMethodMetrics)) - return false; - RequestMethodMetrics that = (RequestMethodMetrics) o; - return Objects.equals(applicationName, that.applicationName); - } - - @Override - public int hashCode() { - return Objects.hash(applicationName); - } - } - -} - diff --git a/dubbo-metrics/dubbo-metrics-metadata/src/main/java/org/apache/dubbo/metrics/metadata/MetadataMetricsConstants.java b/dubbo-metrics/dubbo-metrics-metadata/src/main/java/org/apache/dubbo/metrics/metadata/MetadataMetricsConstants.java index 4b3f650899..14fc3b8dab 100644 --- a/dubbo-metrics/dubbo-metrics-metadata/src/main/java/org/apache/dubbo/metrics/metadata/MetadataMetricsConstants.java +++ b/dubbo-metrics/dubbo-metrics-metadata/src/main/java/org/apache/dubbo/metrics/metadata/MetadataMetricsConstants.java @@ -18,8 +18,9 @@ package org.apache.dubbo.metrics.metadata; import org.apache.dubbo.metrics.model.key.MetricsKey; +import org.apache.dubbo.metrics.model.key.MetricsKeyWrapper; import org.apache.dubbo.metrics.model.key.MetricsLevel; -import org.apache.dubbo.metrics.model.key.MetricsPlaceType; +import org.apache.dubbo.metrics.model.key.MetricsPlaceValue; import java.util.Arrays; import java.util.List; @@ -36,16 +37,18 @@ import static org.apache.dubbo.metrics.model.key.MetricsKey.STORE_PROVIDER_METAD public interface MetadataMetricsConstants { - MetricsPlaceType OP_TYPE_PUSH = MetricsPlaceType.of("push", MetricsLevel.APP); - MetricsPlaceType OP_TYPE_SUBSCRIBE = MetricsPlaceType.of("subscribe", MetricsLevel.APP); - MetricsPlaceType OP_TYPE_STORE_PROVIDER_INTERFACE = MetricsPlaceType.of("store.provider.interface", MetricsLevel.SERVICE); + MetricsPlaceValue OP_TYPE_PUSH = MetricsPlaceValue.of("push", MetricsLevel.APP); + MetricsPlaceValue OP_TYPE_SUBSCRIBE = MetricsPlaceValue.of("subscribe", MetricsLevel.APP); + MetricsPlaceValue OP_TYPE_STORE_PROVIDER_INTERFACE = MetricsPlaceValue.of("store.provider.interface", MetricsLevel.SERVICE); // App-level List APP_LEVEL_KEYS = Arrays.asList(METADATA_PUSH_METRIC_NUM, METADATA_PUSH_METRIC_NUM_SUCCEED, METADATA_PUSH_METRIC_NUM_FAILED, METADATA_SUBSCRIBE_METRIC_NUM, METADATA_SUBSCRIBE_METRIC_NUM_SUCCEED, METADATA_SUBSCRIBE_METRIC_NUM_FAILED); // Service-level - List SERVICE_LEVEL_KEYS = Arrays.asList(STORE_PROVIDER_METADATA, - STORE_PROVIDER_METADATA_SUCCEED, STORE_PROVIDER_METADATA_FAILED + List SERVICE_LEVEL_KEYS = Arrays.asList( + new MetricsKeyWrapper(STORE_PROVIDER_METADATA, OP_TYPE_STORE_PROVIDER_INTERFACE), + new MetricsKeyWrapper(STORE_PROVIDER_METADATA_SUCCEED, OP_TYPE_STORE_PROVIDER_INTERFACE), + new MetricsKeyWrapper(STORE_PROVIDER_METADATA_FAILED, OP_TYPE_STORE_PROVIDER_INTERFACE) ); } diff --git a/dubbo-metrics/dubbo-metrics-metadata/src/main/java/org/apache/dubbo/metrics/metadata/collector/MetadataMetricsCollector.java b/dubbo-metrics/dubbo-metrics-metadata/src/main/java/org/apache/dubbo/metrics/metadata/collector/MetadataMetricsCollector.java index e7ac434c5a..6281efebc4 100644 --- a/dubbo-metrics/dubbo-metrics-metadata/src/main/java/org/apache/dubbo/metrics/metadata/collector/MetadataMetricsCollector.java +++ b/dubbo-metrics/dubbo-metrics-metadata/src/main/java/org/apache/dubbo/metrics/metadata/collector/MetadataMetricsCollector.java @@ -25,11 +25,9 @@ import org.apache.dubbo.metrics.data.ApplicationStatComposite; import org.apache.dubbo.metrics.data.BaseStatComposite; import org.apache.dubbo.metrics.data.RtStatComposite; import org.apache.dubbo.metrics.data.ServiceStatComposite; -import org.apache.dubbo.metrics.event.MetricsEvent; -import org.apache.dubbo.metrics.event.TimeCounterEvent; import org.apache.dubbo.metrics.metadata.MetadataMetricsConstants; import org.apache.dubbo.metrics.metadata.event.MetadataEvent; -import org.apache.dubbo.metrics.metadata.event.MetadataMetricsEventMulticaster; +import org.apache.dubbo.metrics.metadata.event.MetadataSubDispatcher; import org.apache.dubbo.metrics.model.MetricsCategory; import org.apache.dubbo.metrics.model.sample.MetricSample; import org.apache.dubbo.rpc.model.ApplicationModel; @@ -47,7 +45,7 @@ import static org.apache.dubbo.metrics.metadata.MetadataMetricsConstants.OP_TYPE * Registry implementation of {@link MetricsCollector} */ @Activate -public class MetadataMetricsCollector extends CombMetricsCollector { +public class MetadataMetricsCollector extends CombMetricsCollector { private Boolean collectEnabled = null; private final ApplicationModel applicationModel; @@ -55,13 +53,21 @@ public class MetadataMetricsCollector extends CombMetricsCollector { 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 dd2662db64..4c12bbc426 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 @@ -19,17 +19,17 @@ package org.apache.dubbo.metrics.metadata; import org.apache.dubbo.config.ApplicationConfig; import org.apache.dubbo.metrics.event.MetricsDispatcher; +import org.apache.dubbo.metrics.event.MetricsEvent; import org.apache.dubbo.metrics.event.MetricsEventBus; import org.apache.dubbo.metrics.metadata.collector.MetadataMetricsCollector; import org.apache.dubbo.metrics.metadata.event.MetadataEvent; +import org.apache.dubbo.metrics.model.TimePair; import org.apache.dubbo.metrics.model.key.MetricsKey; import org.apache.dubbo.metrics.model.key.MetricsKeyWrapper; -import org.apache.dubbo.metrics.model.TimePair; import org.apache.dubbo.metrics.model.sample.GaugeMetricSample; import org.apache.dubbo.metrics.model.sample.MetricSample; 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; @@ -37,6 +37,7 @@ import org.junit.jupiter.api.Test; import java.util.List; import java.util.Map; +import java.util.NoSuchElementException; import java.util.Objects; import java.util.stream.Collectors; @@ -50,6 +51,8 @@ class MetadataMetricsCollectorTest { private ApplicationModel applicationModel; + private MetadataMetricsCollector collector; + @BeforeEach public void setup() { FrameworkModel frameworkModel = FrameworkModel.defaultModel(); @@ -58,9 +61,22 @@ class MetadataMetricsCollectorTest { config.setName("MockMetrics"); applicationModel.getApplicationConfigManager().setApplication(config); + applicationModel.getBeanFactory().getOrRegisterBean(MetricsDispatcher.class); + collector = applicationModel.getBeanFactory().getOrRegisterBean(MetadataMetricsCollector.class); + collector.setCollectEnabled(true); } + @Test + void testListener() { + MetadataEvent event = MetadataEvent.toPushEvent(applicationModel); + MetricsEvent otherEvent = new MetricsEvent(applicationModel,null){ + }; + Assertions.assertTrue(collector.isSupport(event)); + Assertions.assertFalse(collector.isSupport(otherEvent)); + } + + @AfterEach public void teardown() { applicationModel.destroy(); @@ -68,10 +84,7 @@ class MetadataMetricsCollectorTest { @Test void testPushMetrics() { - - applicationModel.getBeanFactory().getOrRegisterBean(MetricsDispatcher.class); - MetadataMetricsCollector collector = applicationModel.getBeanFactory().getOrRegisterBean(MetadataMetricsCollector.class); - collector.setCollectEnabled(true); +// MetadataMetricsCollector collector = getCollector(); MetadataEvent pushEvent = MetadataEvent.toPushEvent(applicationModel); MetricsEventBus.post(pushEvent, @@ -129,10 +142,7 @@ class MetadataMetricsCollectorTest { @Test void testSubscribeMetrics() { - - applicationModel.getBeanFactory().getOrRegisterBean(MetricsDispatcher.class); - MetadataMetricsCollector collector = applicationModel.getBeanFactory().getOrRegisterBean(MetadataMetricsCollector.class); - collector.setCollectEnabled(true); +// MetadataMetricsCollector collector = getCollector(); MetadataEvent subscribeEvent = MetadataEvent.toSubscribeEvent(applicationModel); MetricsEventBus.post(subscribeEvent, @@ -191,10 +201,7 @@ class MetadataMetricsCollectorTest { @Test void testStoreProviderMetadataMetrics() { - - applicationModel.getBeanFactory().getOrRegisterBean(MetricsDispatcher.class); - MetadataMetricsCollector collector = applicationModel.getBeanFactory().getOrRegisterBean(MetadataMetricsCollector.class); - collector.setCollectEnabled(true); +// MetadataMetricsCollector collector = getCollector(); String serviceKey = "store.provider.test"; MetadataEvent metadataEvent = MetadataEvent.toServiceSubscribeEvent(applicationModel, serviceKey); @@ -252,4 +259,54 @@ class MetadataMetricsCollectorTest { Assertions.assertEquals(sampleMap.get(new MetricsKeyWrapper(MetricsKey.METRIC_RT_SUM, OP_TYPE_STORE_PROVIDER_INTERFACE).targetKey()), c1 + c2); } + @Test + void testMetadataPushNum() { + + for (int i = 0; i < 10; i++) { + MetadataEvent event = MetadataEvent.toPushEvent(applicationModel); + if(i %2 ==0 ) { + MetricsEventBus.post(event,() -> true, r -> r); + }else { + MetricsEventBus.post(event,() -> false, r -> r); + } + } + + List samples = collector.collect(); + + GaugeMetricSample totalNum = getSample(MetricsKey.METADATA_PUSH_METRIC_NUM.getName(), samples); + GaugeMetricSample succeedNum = getSample(MetricsKey.METADATA_PUSH_METRIC_NUM_SUCCEED.getName(), samples); + GaugeMetricSample failedNum = getSample(MetricsKey.METADATA_PUSH_METRIC_NUM_FAILED.getName(), samples); + + Assertions.assertEquals(10,totalNum.applyAsLong()); + Assertions.assertEquals(5,succeedNum.applyAsLong()); + Assertions.assertEquals(5,failedNum.applyAsLong()); + } + + @Test + void testSubscribeSum(){ + + for (int i = 0; i < 10; i++) { + MetadataEvent event = MetadataEvent.toSubscribeEvent(applicationModel); + if(i %2 ==0 ) { + MetricsEventBus.post(event,() -> true, r -> r); + }else { + MetricsEventBus.post(event,() -> false, r -> r); + } + } + + List samples = collector.collect(); + + GaugeMetricSample totalNum = getSample(MetricsKey.METADATA_SUBSCRIBE_METRIC_NUM.getName(), samples); + GaugeMetricSample succeedNum = getSample(MetricsKey.METADATA_SUBSCRIBE_METRIC_NUM_SUCCEED.getName(), samples); + GaugeMetricSample failedNum = getSample(MetricsKey.METADATA_SUBSCRIBE_METRIC_NUM_FAILED.getName(), samples); + + Assertions.assertEquals(10,totalNum.applyAsLong()); + Assertions.assertEquals(5,succeedNum.applyAsLong()); + Assertions.assertEquals(5,failedNum.applyAsLong()); + } + + GaugeMetricSample getSample(String name, List samples) { + return (GaugeMetricSample) samples.stream().filter(metricSample -> metricSample.getName().equals(name)).findFirst().orElseThrow(NoSuchElementException::new); + } + } diff --git a/dubbo-metrics/dubbo-metrics-metadata/src/test/java/org/apache/dubbo/metrics/metadata/MetadataStatCompositeTest.java b/dubbo-metrics/dubbo-metrics-metadata/src/test/java/org/apache/dubbo/metrics/metadata/MetadataStatCompositeTest.java index 52b7741a26..bf1a021d63 100644 --- a/dubbo-metrics/dubbo-metrics-metadata/src/test/java/org/apache/dubbo/metrics/metadata/MetadataStatCompositeTest.java +++ b/dubbo-metrics/dubbo-metrics-metadata/src/test/java/org/apache/dubbo/metrics/metadata/MetadataStatCompositeTest.java @@ -40,10 +40,17 @@ public class MetadataStatCompositeTest { private final BaseStatComposite statComposite = new BaseStatComposite() { @Override - protected void init(ApplicationStatComposite applicationStatComposite, ServiceStatComposite - serviceStatComposite, RtStatComposite rtStatComposite) { + protected void init(ApplicationStatComposite applicationStatComposite) { applicationStatComposite.init(MetadataMetricsConstants.APP_LEVEL_KEYS); - serviceStatComposite.init(MetadataMetricsConstants.SERVICE_LEVEL_KEYS); + } + + @Override + protected void init(ServiceStatComposite serviceStatComposite) { + serviceStatComposite.initWrapper(MetadataMetricsConstants.SERVICE_LEVEL_KEYS); + } + + @Override + protected void init(RtStatComposite rtStatComposite) { rtStatComposite.init(OP_TYPE_PUSH, OP_TYPE_SUBSCRIBE, OP_TYPE_STORE_PROVIDER_INTERFACE); } }; diff --git a/dubbo-metrics/dubbo-metrics-registry/src/main/java/org/apache/dubbo/metrics/registry/RegistryMetricsConstants.java b/dubbo-metrics/dubbo-metrics-registry/src/main/java/org/apache/dubbo/metrics/registry/RegistryMetricsConstants.java index 58d46c2294..e7adbc9622 100644 --- a/dubbo-metrics/dubbo-metrics-registry/src/main/java/org/apache/dubbo/metrics/registry/RegistryMetricsConstants.java +++ b/dubbo-metrics/dubbo-metrics-registry/src/main/java/org/apache/dubbo/metrics/registry/RegistryMetricsConstants.java @@ -18,8 +18,9 @@ package org.apache.dubbo.metrics.registry; import org.apache.dubbo.metrics.model.key.MetricsKey; +import org.apache.dubbo.metrics.model.key.MetricsKeyWrapper; import org.apache.dubbo.metrics.model.key.MetricsLevel; -import org.apache.dubbo.metrics.model.key.MetricsPlaceType; +import org.apache.dubbo.metrics.model.key.MetricsPlaceValue; import java.util.Arrays; import java.util.List; @@ -45,12 +46,12 @@ import static org.apache.dubbo.metrics.model.key.MetricsKey.SUBSCRIBE_METRIC_NUM public interface RegistryMetricsConstants { - MetricsPlaceType OP_TYPE_REGISTER = MetricsPlaceType.of("register", MetricsLevel.APP); - MetricsPlaceType OP_TYPE_SUBSCRIBE = MetricsPlaceType.of("subscribe", MetricsLevel.APP); - MetricsPlaceType OP_TYPE_NOTIFY = MetricsPlaceType.of("notify", MetricsLevel.APP); - MetricsPlaceType OP_TYPE_DIRECTORY = MetricsPlaceType.of("directory", MetricsLevel.APP); - MetricsPlaceType OP_TYPE_REGISTER_SERVICE = MetricsPlaceType.of("register.service", MetricsLevel.SERVICE); - MetricsPlaceType OP_TYPE_SUBSCRIBE_SERVICE = MetricsPlaceType.of("subscribe.service", MetricsLevel.SERVICE); + MetricsPlaceValue OP_TYPE_REGISTER = MetricsPlaceValue.of("register", MetricsLevel.APP); + MetricsPlaceValue OP_TYPE_SUBSCRIBE = MetricsPlaceValue.of("subscribe", MetricsLevel.APP); + MetricsPlaceValue OP_TYPE_NOTIFY = MetricsPlaceValue.of("notify", MetricsLevel.APP); + MetricsPlaceValue OP_TYPE_DIRECTORY = MetricsPlaceValue.of("directory", MetricsLevel.APP); + MetricsPlaceValue OP_TYPE_REGISTER_SERVICE = MetricsPlaceValue.of("register.service", MetricsLevel.SERVICE); + MetricsPlaceValue OP_TYPE_SUBSCRIBE_SERVICE = MetricsPlaceValue.of("subscribe.service", MetricsLevel.SERVICE); // App-level List APP_LEVEL_KEYS = Arrays.asList(REGISTER_METRIC_REQUESTS, REGISTER_METRIC_REQUESTS_SUCCEED, REGISTER_METRIC_REQUESTS_FAILED, @@ -58,11 +59,17 @@ public interface RegistryMetricsConstants { NOTIFY_METRIC_REQUESTS); // Service-level - List SERVICE_LEVEL_KEYS = Arrays.asList(NOTIFY_METRIC_NUM_LAST, - SERVICE_REGISTER_METRIC_REQUESTS, SERVICE_REGISTER_METRIC_REQUESTS_SUCCEED, SERVICE_REGISTER_METRIC_REQUESTS_FAILED, - SERVICE_SUBSCRIBE_METRIC_NUM, SERVICE_SUBSCRIBE_METRIC_NUM_SUCCEED, SERVICE_SUBSCRIBE_METRIC_NUM_FAILED, - DIRECTORY_METRIC_NUM_VALID, DIRECTORY_METRIC_NUM_TO_RECONNECT, DIRECTORY_METRIC_NUM_DISABLE, DIRECTORY_METRIC_NUM_ALL + List SERVICE_LEVEL_KEYS = Arrays.asList( + new MetricsKeyWrapper(NOTIFY_METRIC_NUM_LAST, OP_TYPE_NOTIFY), + new MetricsKeyWrapper(SERVICE_REGISTER_METRIC_REQUESTS, OP_TYPE_REGISTER_SERVICE), + new MetricsKeyWrapper(SERVICE_REGISTER_METRIC_REQUESTS_SUCCEED, OP_TYPE_REGISTER_SERVICE), + new MetricsKeyWrapper(SERVICE_REGISTER_METRIC_REQUESTS_FAILED, OP_TYPE_REGISTER_SERVICE), + new MetricsKeyWrapper(SERVICE_SUBSCRIBE_METRIC_NUM, OP_TYPE_SUBSCRIBE_SERVICE), + new MetricsKeyWrapper(SERVICE_SUBSCRIBE_METRIC_NUM_SUCCEED, OP_TYPE_SUBSCRIBE_SERVICE), + new MetricsKeyWrapper(SERVICE_SUBSCRIBE_METRIC_NUM_FAILED, OP_TYPE_SUBSCRIBE_SERVICE), + new MetricsKeyWrapper(DIRECTORY_METRIC_NUM_VALID, OP_TYPE_DIRECTORY), + new MetricsKeyWrapper(DIRECTORY_METRIC_NUM_TO_RECONNECT, OP_TYPE_DIRECTORY), + new MetricsKeyWrapper(DIRECTORY_METRIC_NUM_DISABLE, OP_TYPE_DIRECTORY), + new MetricsKeyWrapper(DIRECTORY_METRIC_NUM_ALL, OP_TYPE_DIRECTORY) ); - - } diff --git a/dubbo-metrics/dubbo-metrics-registry/src/main/java/org/apache/dubbo/metrics/registry/collector/RegistryMetricsCollector.java b/dubbo-metrics/dubbo-metrics-registry/src/main/java/org/apache/dubbo/metrics/registry/collector/RegistryMetricsCollector.java index 6f79d83bb0..eddcaf1af3 100644 --- a/dubbo-metrics/dubbo-metrics-registry/src/main/java/org/apache/dubbo/metrics/registry/collector/RegistryMetricsCollector.java +++ b/dubbo-metrics/dubbo-metrics-registry/src/main/java/org/apache/dubbo/metrics/registry/collector/RegistryMetricsCollector.java @@ -25,13 +25,11 @@ import org.apache.dubbo.metrics.data.ApplicationStatComposite; import org.apache.dubbo.metrics.data.BaseStatComposite; import org.apache.dubbo.metrics.data.RtStatComposite; import org.apache.dubbo.metrics.data.ServiceStatComposite; -import org.apache.dubbo.metrics.event.MetricsEvent; -import org.apache.dubbo.metrics.event.TimeCounterEvent; import org.apache.dubbo.metrics.model.MetricsCategory; import org.apache.dubbo.metrics.model.sample.MetricSample; import org.apache.dubbo.metrics.registry.RegistryMetricsConstants; import org.apache.dubbo.metrics.registry.event.RegistryEvent; -import org.apache.dubbo.metrics.registry.event.RegistryMetricsEventMulticaster; +import org.apache.dubbo.metrics.registry.event.RegistrySubDispatcher; import org.apache.dubbo.rpc.model.ApplicationModel; import java.util.ArrayList; @@ -49,7 +47,7 @@ import static org.apache.dubbo.metrics.registry.RegistryMetricsConstants.OP_TYPE * Registry implementation of {@link MetricsCollector} */ @Activate -public class RegistryMetricsCollector extends CombMetricsCollector { +public class RegistryMetricsCollector extends CombMetricsCollector { private Boolean collectEnabled = null; private final ApplicationModel applicationModel; @@ -57,13 +55,21 @@ public class RegistryMetricsCollector extends CombMetricsCollector { @@ -83,24 +84,24 @@ public final class RegistryMetricsEventMulticaster extends SimpleMetricsEventMul // MetricsNotifyListener MetricsCat APPLICATION_NOTIFY_POST = new MetricsCat(MetricsKey.NOTIFY_METRIC_REQUESTS, MetricsApplicationListener::onPostEventBuild); MetricsCat APPLICATION_NOTIFY_FINISH = new MetricsCat(MetricsKey.NOTIFY_METRIC_NUM_LAST, - (key, placeType, collector) -> AbstractMetricsListener.onFinish(key, + (key, placeType, collector) -> AbstractMetricsKeyListener.onFinish(key, event -> { collector.addRt(event.appName(), placeType.getType(), event.getTimePair().calc()); Map lastNumMap = Collections.unmodifiableMap(event.getAttachmentValue(ATTACHMENT_KEY_LAST_NUM_MAP)); lastNumMap.forEach( - (k, v) -> collector.setNum(key, event.appName(), k, v)); + (k, v) -> collector.setNum(new MetricsKeyWrapper(key, OP_TYPE_NOTIFY), event.appName(), k, v)); } )); - MetricsCat APPLICATION_DIRECTORY_POST = new MetricsCat(MetricsKey.DIRECTORY_METRIC_NUM_VALID, (key, placeType, collector) -> AbstractMetricsListener.onEvent(key, + MetricsCat APPLICATION_DIRECTORY_POST = new MetricsCat(MetricsKey.DIRECTORY_METRIC_NUM_VALID, (key, placeType, collector) -> AbstractMetricsKeyListener.onEvent(key, event -> { Map> summaryMap = event.getAttachmentValue(ATTACHMENT_DIRECTORY_MAP); summaryMap.forEach((metricsKey, map) -> map.forEach( - (k, v) -> collector.setNum(metricsKey, event.appName(), k, v))); + (k, v) -> collector.setNum(new MetricsKeyWrapper(key, OP_TYPE_DIRECTORY), event.appName(), k, v))); } )); diff --git a/dubbo-metrics/dubbo-metrics-registry/src/test/java/org/apache/dubbo/metrics/registry/metrics/collector/RegistryMetricsCollectorTest.java b/dubbo-metrics/dubbo-metrics-registry/src/test/java/org/apache/dubbo/metrics/registry/metrics/collector/RegistryMetricsCollectorTest.java index 7c3012795b..2c042c9114 100644 --- a/dubbo-metrics/dubbo-metrics-registry/src/test/java/org/apache/dubbo/metrics/registry/metrics/collector/RegistryMetricsCollectorTest.java +++ b/dubbo-metrics/dubbo-metrics-registry/src/test/java/org/apache/dubbo/metrics/registry/metrics/collector/RegistryMetricsCollectorTest.java @@ -20,9 +20,9 @@ package org.apache.dubbo.metrics.registry.metrics.collector; import org.apache.dubbo.config.ApplicationConfig; import org.apache.dubbo.metrics.event.MetricsDispatcher; import org.apache.dubbo.metrics.event.MetricsEventBus; -import org.apache.dubbo.metrics.model.key.MetricsKeyWrapper; -import org.apache.dubbo.metrics.model.key.MetricsKey; import org.apache.dubbo.metrics.model.TimePair; +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 org.apache.dubbo.metrics.model.sample.MetricSample; import org.apache.dubbo.metrics.registry.collector.RegistryMetricsCollector; @@ -34,6 +34,7 @@ import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; @@ -48,6 +49,7 @@ import static org.apache.dubbo.metrics.registry.RegistryMetricsConstants.OP_TYPE class RegistryMetricsCollectorTest { private ApplicationModel applicationModel; + private RegistryMetricsCollector collector; @BeforeEach public void setup() { @@ -57,7 +59,9 @@ class RegistryMetricsCollectorTest { config.setName("MockMetrics"); applicationModel.getApplicationConfigManager().setApplication(config); - + applicationModel.getBeanFactory().getOrRegisterBean(MetricsDispatcher.class); + collector = applicationModel.getBeanFactory().getOrRegisterBean(RegistryMetricsCollector.class); + collector.setCollectEnabled(true); } @AfterEach @@ -68,10 +72,6 @@ class RegistryMetricsCollectorTest { @Test void testRegisterMetrics() { - applicationModel.getBeanFactory().getOrRegisterBean(MetricsDispatcher.class); - RegistryMetricsCollector collector = applicationModel.getBeanFactory().getOrRegisterBean(RegistryMetricsCollector.class); - collector.setCollectEnabled(true); - RegistryEvent registryEvent = RegistryEvent.toRegisterEvent(applicationModel); MetricsEventBus.post(registryEvent, () -> { @@ -130,9 +130,6 @@ class RegistryMetricsCollectorTest { @Test void testServicePushMetrics() { - applicationModel.getBeanFactory().getOrRegisterBean(MetricsDispatcher.class); - RegistryMetricsCollector collector = applicationModel.getBeanFactory().getOrRegisterBean(RegistryMetricsCollector.class); - collector.setCollectEnabled(true); String serviceName = "demo.gameService"; RegistryEvent registryEvent = RegistryEvent.toRsEvent(applicationModel, serviceName, 2); @@ -195,9 +192,6 @@ class RegistryMetricsCollectorTest { @Test void testServiceSubscribeMetrics() { - applicationModel.getBeanFactory().getOrRegisterBean(MetricsDispatcher.class); - RegistryMetricsCollector collector = applicationModel.getBeanFactory().getOrRegisterBean(RegistryMetricsCollector.class); - collector.setCollectEnabled(true); String serviceName = "demo.gameService"; RegistryEvent subscribeEvent = RegistryEvent.toSsEvent(applicationModel, serviceName); @@ -255,4 +249,28 @@ class RegistryMetricsCollectorTest { Assertions.assertEquals(sampleMap.get(new MetricsKeyWrapper(MetricsKey.METRIC_RT_AVG, OP_TYPE_SUBSCRIBE_SERVICE).targetKey()), (c1 + c2) / 2); Assertions.assertEquals(sampleMap.get(new MetricsKeyWrapper(MetricsKey.METRIC_RT_SUM, OP_TYPE_SUBSCRIBE_SERVICE).targetKey()), c1 + c2); } + + + @Test + public void testNotify() { + MetricsEventBus.post(RegistryEvent.toNotifyEvent(applicationModel), + () -> { + try { + Thread.sleep(50L); + } catch (InterruptedException e) { + e.printStackTrace(); + } + Map lastNumMap = new HashMap<>(); + // 1 different services + lastNumMap.put("demo.service1", 3); + lastNumMap.put("demo.service2", 4); + lastNumMap.put("demo.service3", 5); + return lastNumMap; + } + ); + List metricSamples = collector.collect(); + // num(total+service*3) + rt(5) = 9 + Assertions.assertEquals(9, metricSamples.size()); + + } } 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 new file mode 100644 index 0000000000..553283c672 --- /dev/null +++ b/dubbo-metrics/dubbo-metrics-registry/src/test/java/org/apache/dubbo/metrics/registry/metrics/collector/RegistryMetricsTest.java @@ -0,0 +1,358 @@ +/* + * 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.registry.metrics.collector; + +import org.apache.dubbo.config.ApplicationConfig; +import org.apache.dubbo.config.MetricsConfig; +import org.apache.dubbo.config.context.ConfigManager; +import org.apache.dubbo.config.nested.AggregationConfig; +import org.apache.dubbo.metrics.model.key.MetricsKey; +import org.apache.dubbo.metrics.model.sample.GaugeMetricSample; +import org.apache.dubbo.metrics.model.sample.MetricSample; +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; + +import java.util.List; +import java.util.NoSuchElementException; +import java.util.Optional; +import java.util.concurrent.*; + +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; + + +public class RegistryMetricsTest { + + ApplicationModel applicationModel; + + RegistryMetricsCollector collector; + + String REGISTER = "register"; + + @BeforeEach + void setUp() { + this.applicationModel = getApplicationModel(); + this.collector = getTestCollector(this.applicationModel); + this.collector.setCollectEnabled(true); + } + + @Test + void testRegisterRequestsCount() { + + for (int i = 0; i < 10; i++) { + RegistryEvent event = applicationRegister(); + if (i % 2 == 0) { + eventSuccess(event); + } else { + eventFailed(event); + } + } + List samples = collector.collect(); + + GaugeMetricSample succeedRequests = getSample(MetricsKey.REGISTER_METRIC_REQUESTS_SUCCEED.getName(), samples); + GaugeMetricSample failedRequests = getSample(MetricsKey.REGISTER_METRIC_REQUESTS_FAILED.getName(), samples); + GaugeMetricSample totalRequests = getSample(MetricsKey.REGISTER_METRIC_REQUESTS.getName(), samples); + + Assertions.assertEquals(5L, succeedRequests.applyAsLong()); + Assertions.assertEquals(5L, failedRequests.applyAsLong()); + Assertions.assertEquals(10L, totalRequests.applyAsLong()); + } + + @Test + void testLastResponseTime() { + long waitTime = 2000; + + RegistryEvent event = applicationRegister(); + await(waitTime); + eventSuccess(event); + + GaugeMetricSample sample = getSample(MetricsKey.METRIC_RT_LAST.getNameByType(REGISTER), collector.collect()); + // 20% deviation is allowed + Assertions.assertTrue(considerEquals(waitTime, sample.applyAsLong(), 0.2)); + + RegistryEvent event1 = applicationRegister(); + await(waitTime / 2); + eventSuccess(event1); + + sample = getSample(MetricsKey.METRIC_RT_LAST.getNameByType(REGISTER), collector.collect()); + Assertions.assertTrue(considerEquals((double) waitTime / 2, sample.applyAsLong(), 0.2)); + + RegistryEvent event2 = applicationRegister(); + await(waitTime); + eventFailed(event2); + + sample = getSample(MetricsKey.METRIC_RT_LAST.getNameByType(REGISTER), collector.collect()); + Assertions.assertTrue(considerEquals((double) waitTime, sample.applyAsLong(), 0.2)); + } + + @Test + void testMinResponseTime() throws InterruptedException { + long waitTime = 2000L; + + RegistryEvent event = applicationRegister(); + await(waitTime); + eventSuccess(event); + + RegistryEvent event1 = applicationRegister(); + await(waitTime); + + RegistryEvent event2 = applicationRegister(); + await(waitTime); + + eventSuccess(event1); + eventSuccess(event2); + + GaugeMetricSample sample = getSample(MetricsKey.METRIC_RT_MIN.getNameByType(REGISTER), collector.collect()); + Assertions.assertTrue(considerEquals(waitTime, sample.applyAsLong(), 0.2)); + + RegistryEvent event3 = applicationRegister(); + Thread.sleep(waitTime / 2); + eventSuccess(event3); + + sample = getSample(MetricsKey.METRIC_RT_MIN.getNameByType(REGISTER), collector.collect()); + Assertions.assertTrue(considerEquals((double) waitTime / 2, sample.applyAsLong(), 0.2)); + } + + @Test + void testMaxResponseTime() { + long waitTime = 1000L; + + RegistryEvent event = applicationRegister(); + await(waitTime); + eventSuccess(event); + + GaugeMetricSample sample = getSample(MetricsKey.METRIC_RT_MAX.getNameByType(REGISTER), collector.collect()); + Assertions.assertTrue(considerEquals(waitTime, sample.applyAsLong(), 0.2)); + + RegistryEvent event1 = applicationRegister(); + await(waitTime * 2); + eventSuccess(event1); + + sample = getSample(MetricsKey.METRIC_RT_MAX.getNameByType(REGISTER), collector.collect()); + Assertions.assertTrue(considerEquals(waitTime * 2, sample.applyAsLong(), 0.2)); + + sample = getSample(MetricsKey.METRIC_RT_MAX.getNameByType(REGISTER), collector.collect()); + RegistryEvent event2 = applicationRegister(); + eventSuccess(event2); + Assertions.assertTrue(considerEquals(waitTime * 2, sample.applyAsLong(), 0.2)); + } + + @Test + void testSumResponseTime() { + long waitTime = 1000; + + RegistryEvent event = applicationRegister(); + RegistryEvent event1 = applicationRegister(); + RegistryEvent event2 = applicationRegister(); + + await(waitTime); + + eventSuccess(event); + eventFailed(event1); + + GaugeMetricSample sample = getSample(MetricsKey.METRIC_RT_SUM.getNameByType(REGISTER), collector.collect()); + Assertions.assertTrue(considerEquals(waitTime * 2, sample.applyAsLong(), 0.2)); + + await(waitTime); + eventSuccess(event2); + + sample = getSample(MetricsKey.METRIC_RT_SUM.getNameByType(REGISTER), collector.collect()); + Assertions.assertTrue(considerEquals(waitTime * 4, sample.applyAsLong(), 0.2)); + } + + @Test + void testAvgResponseTime() { + long waitTime = 1000; + + RegistryEvent event = applicationRegister(); + RegistryEvent event1 = applicationRegister(); + RegistryEvent event2 = applicationRegister(); + + await(waitTime); + + eventSuccess(event); + eventFailed(event1); + + GaugeMetricSample sample = getSample(MetricsKey.METRIC_RT_AVG.getNameByType(REGISTER), collector.collect()); + Assertions.assertTrue(considerEquals(waitTime, sample.applyAsLong(), 0.2)); + + await(waitTime); + eventSuccess(event2); + + sample = getSample(MetricsKey.METRIC_RT_AVG.getNameByType(REGISTER), collector.collect()); + Assertions.assertTrue(considerEquals((double) waitTime * 4 / 3, sample.applyAsLong(), 0.2)); + } + + @Test + void testServiceRegisterCount() { + + for (int i = 0; i < 10; i++) { + RegistryEvent event = serviceRegister(); + if (i % 2 == 0) { + eventSuccess(event); + } else { + eventFailed(event); + } + } + List samples = collector.collect(); + + GaugeMetricSample succeedRequests = getSample(MetricsKey.SERVICE_REGISTER_METRIC_REQUESTS_SUCCEED.getName(), samples); + GaugeMetricSample failedRequests = getSample(MetricsKey.SERVICE_REGISTER_METRIC_REQUESTS_FAILED.getName(), samples); + GaugeMetricSample totalRequests = getSample(MetricsKey.SERVICE_REGISTER_METRIC_REQUESTS.getName(), samples); + + Assertions.assertEquals(5L, succeedRequests.applyAsLong()); + Assertions.assertEquals(5L, failedRequests.applyAsLong()); + Assertions.assertEquals(10L, totalRequests.applyAsLong()); + + } + + @Test + void testServiceSubscribeCount() { + + for (int i = 0; i < 10; i++) { + RegistryEvent event = serviceSubscribe(); + if (i % 2 == 0) { + eventSuccess(event); + } else { + eventFailed(event); + } + } + List samples = collector.collect(); + + GaugeMetricSample succeedRequests = getSample(MetricsKey.SUBSCRIBE_METRIC_NUM_SUCCEED.getName(), samples); + GaugeMetricSample failedRequests = getSample(MetricsKey.SUBSCRIBE_METRIC_NUM_FAILED.getName(), samples); + GaugeMetricSample totalRequests = getSample(MetricsKey.SUBSCRIBE_METRIC_NUM.getName(), samples); + + Assertions.assertEquals(5L, succeedRequests.applyAsLong()); + Assertions.assertEquals(5L, failedRequests.applyAsLong()); + Assertions.assertEquals(10L, totalRequests.applyAsLong()); + } + + + GaugeMetricSample getSample(String name, List samples) { + return (GaugeMetricSample) samples.stream().filter(metricSample -> metricSample.getName().equals(name)).findFirst().orElseThrow(NoSuchElementException::new); + } + + RegistryEvent applicationRegister() { + RegistryEvent event = registerEvent(); + collector.onEvent(event); + return event; + } + + RegistryEvent serviceRegister() { + RegistryEvent event = rsEvent(); + collector.onEvent(event); + return event; + } + + RegistryEvent serviceSubscribe() { + RegistryEvent event = subscribeEvent(); + collector.onEvent(event); + return event; + } + + boolean considerEquals(double expected, double trueValue, double allowedErrorRatio) { + return Math.abs(1 - expected / trueValue) <= allowedErrorRatio; + } + + void eventSuccess(RegistryEvent event) { + collector.onEventFinish(event); + } + + void eventFailed(RegistryEvent event) { + collector.onEventError(event); + } + + RegistryEvent registerEvent() { + RegistryEvent event = RegistryEvent.toRegisterEvent(applicationModel); + event.setAvailable(true); + return event; + } + + RegistryEvent rsEvent() { + RegistryEvent event = RegistryEvent.toRsEvent(applicationModel, "TestServiceInterface1", 1); + event.setAvailable(true); + return event; + } + + RegistryEvent subscribeEvent() { + RegistryEvent event = RegistryEvent.toSubscribeEvent(applicationModel); + event.setAvailable(true); + return event; + } + + ApplicationModel getApplicationModel() { + return spy(new FrameworkModel().newApplication()); + } + + void await(long millis) { + + CountDownLatch latch = new CountDownLatch(1); + + ScheduledFuture future = TimeController.executor.schedule(latch::countDown, millis, TimeUnit.MILLISECONDS); + try { + latch.await(); + } catch (InterruptedException e) { + future.cancel(true); + Thread.currentThread().interrupt(); + } + } + + RegistryMetricsCollector getTestCollector(ApplicationModel applicationModel) { + + ApplicationConfig applicationConfig = new ApplicationConfig("TestApp"); + ConfigManager configManager = spy(new ConfigManager(applicationModel)); + MetricsConfig metricsConfig = spy(new MetricsConfig()); + + configManager.setApplication(applicationConfig); + configManager.setMetrics(metricsConfig); + + when(metricsConfig.getAggregation()).thenReturn(new AggregationConfig()); + when(applicationModel.getApplicationConfigManager()).thenReturn(configManager); + when(applicationModel.NotExistApplicationConfig()).thenReturn(false); + when(configManager.getApplication()).thenReturn(Optional.of(applicationConfig)); + + return new RegistryMetricsCollector(applicationModel); + } + + + /** + * make the control of thread sleep time more precise + */ + static class TimeController { + + private static final ScheduledExecutorService executor = Executors.newScheduledThreadPool(1); + + public static void sleep(long milliseconds) { + CountDownLatch latch = new CountDownLatch(1); + ScheduledFuture future = executor.schedule(latch::countDown, milliseconds, TimeUnit.MILLISECONDS); + try { + latch.await(); + } catch (InterruptedException e) { + future.cancel(true); + Thread.currentThread().interrupt(); + } + } + } + +} diff --git a/dubbo-metrics/dubbo-metrics-registry/src/test/java/org/apache/dubbo/metrics/registry/metrics/collector/RegistryStatCompositeTest.java b/dubbo-metrics/dubbo-metrics-registry/src/test/java/org/apache/dubbo/metrics/registry/metrics/collector/RegistryStatCompositeTest.java index ba44ab6c15..ebd4c599e6 100644 --- a/dubbo-metrics/dubbo-metrics-registry/src/test/java/org/apache/dubbo/metrics/registry/metrics/collector/RegistryStatCompositeTest.java +++ b/dubbo-metrics/dubbo-metrics-registry/src/test/java/org/apache/dubbo/metrics/registry/metrics/collector/RegistryStatCompositeTest.java @@ -21,15 +21,22 @@ import org.apache.dubbo.metrics.data.ApplicationStatComposite; import org.apache.dubbo.metrics.data.BaseStatComposite; import org.apache.dubbo.metrics.data.RtStatComposite; import org.apache.dubbo.metrics.data.ServiceStatComposite; +import org.apache.dubbo.metrics.model.MetricsCategory; import org.apache.dubbo.metrics.model.container.LongContainer; +import org.apache.dubbo.metrics.model.sample.GaugeMetricSample; +import org.apache.dubbo.metrics.model.sample.MetricSample; import org.apache.dubbo.metrics.registry.RegistryMetricsConstants; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; +import java.util.List; import java.util.Map; import java.util.Optional; import java.util.concurrent.ConcurrentHashMap; +import static org.apache.dubbo.metrics.model.key.MetricsKey.METRIC_RT_AVG; +import static org.apache.dubbo.metrics.model.key.MetricsKey.METRIC_RT_MAX; +import static org.apache.dubbo.metrics.model.key.MetricsKey.METRIC_RT_MIN; import static org.apache.dubbo.metrics.model.key.MetricsKey.REGISTER_METRIC_REQUESTS; import static org.apache.dubbo.metrics.registry.RegistryMetricsConstants.OP_TYPE_NOTIFY; import static org.apache.dubbo.metrics.registry.RegistryMetricsConstants.OP_TYPE_REGISTER; @@ -37,14 +44,23 @@ import static org.apache.dubbo.metrics.registry.RegistryMetricsConstants.OP_TYPE import static org.apache.dubbo.metrics.registry.RegistryMetricsConstants.OP_TYPE_SUBSCRIBE; import static org.apache.dubbo.metrics.registry.RegistryMetricsConstants.OP_TYPE_SUBSCRIBE_SERVICE; + public class RegistryStatCompositeTest { private final String applicationName = "app1"; private final BaseStatComposite statComposite = new BaseStatComposite() { @Override - protected void init(ApplicationStatComposite applicationStatComposite, ServiceStatComposite serviceStatComposite, RtStatComposite rtStatComposite) { + protected void init(ApplicationStatComposite applicationStatComposite) { applicationStatComposite.init(RegistryMetricsConstants.APP_LEVEL_KEYS); - serviceStatComposite.init(RegistryMetricsConstants.SERVICE_LEVEL_KEYS); + } + + @Override + protected void init(ServiceStatComposite serviceStatComposite) { + serviceStatComposite.initWrapper(RegistryMetricsConstants.SERVICE_LEVEL_KEYS); + } + + @Override + protected void init(RtStatComposite rtStatComposite) { rtStatComposite.init(OP_TYPE_REGISTER, OP_TYPE_SUBSCRIBE, OP_TYPE_NOTIFY, OP_TYPE_REGISTER_SERVICE, OP_TYPE_SUBSCRIBE_SERVICE); } }; @@ -52,10 +68,10 @@ public class RegistryStatCompositeTest { @Test void testInit() { Assertions.assertEquals(statComposite.getApplicationStatComposite().getApplicationNumStats().size(), RegistryMetricsConstants.APP_LEVEL_KEYS.size()); - //(rt)5 * (register,subscribe,notify,register.service,subscribe.service)5 + //(rt)5 * (applicationRegister,subscribe,notify,applicationRegister.service,subscribe.service) Assertions.assertEquals(5 * 5, statComposite.getRtStatComposite().getRtStats().size()); statComposite.getApplicationStatComposite().getApplicationNumStats().values().forEach((v -> - Assertions.assertEquals(v, new ConcurrentHashMap<>()))); + Assertions.assertEquals(v, new ConcurrentHashMap<>()))); statComposite.getRtStatComposite().getRtStats().forEach(rtContainer -> { for (Map.Entry entry : rtContainer.entrySet()) { @@ -77,4 +93,42 @@ public class RegistryStatCompositeTest { Optional> subContainer = statComposite.getRtStatComposite().getRtStats().stream().filter(longContainer -> longContainer.specifyType(OP_TYPE_NOTIFY.getType())).findFirst(); subContainer.ifPresent(v -> Assertions.assertEquals(10L, v.get(applicationName).longValue())); } + + @Test + @SuppressWarnings("rawtypes") + void testCalcServiceKeyRt() { + String applicationName = "TestApp"; + String serviceKey = "TestService"; + String registryOpType = OP_TYPE_REGISTER_SERVICE.getType(); + Long responseTime1 = 100L; + Long responseTime2 = 200L; + + statComposite.calcServiceKeyRt(applicationName, serviceKey, registryOpType, responseTime1); + statComposite.calcServiceKeyRt(applicationName, serviceKey, registryOpType, responseTime2); + + List exportedRtMetrics = statComposite.export(MetricsCategory.RT); + + GaugeMetricSample minSample = (GaugeMetricSample) exportedRtMetrics.stream() + .filter(sample -> sample.getTags().containsValue(applicationName)) + .filter(sample -> sample.getName().equals(METRIC_RT_MIN.getNameByType("register.service"))) + .findFirst().orElse(null); + GaugeMetricSample maxSample = (GaugeMetricSample) exportedRtMetrics.stream() + .filter(sample -> sample.getTags().containsValue(applicationName)) + .filter(sample -> sample.getName().equals(METRIC_RT_MAX.getNameByType("register.service"))) + .findFirst().orElse(null); + GaugeMetricSample avgSample = (GaugeMetricSample) exportedRtMetrics.stream() + .filter(sample -> sample.getTags().containsValue(applicationName)) + .filter(sample -> sample.getName().equals(METRIC_RT_AVG.getNameByType("register.service"))) + .findFirst().orElse(null); + + Assertions.assertNotNull(minSample); + Assertions.assertNotNull(maxSample); + Assertions.assertNotNull(avgSample); + + Assertions.assertEquals(responseTime1, minSample.applyAsLong()); + Assertions.assertEquals(responseTime2, maxSample.applyAsLong()); + Assertions.assertEquals((responseTime1 + responseTime2) / 2, avgSample.applyAsLong()); + } + + } diff --git a/dubbo-metrics/pom.xml b/dubbo-metrics/pom.xml index d5527ecf7c..04abd6e077 100644 --- a/dubbo-metrics/pom.xml +++ b/dubbo-metrics/pom.xml @@ -23,6 +23,7 @@ dubbo-metrics-registry dubbo-metrics-metadata dubbo-metrics-prometheus + dubbo-metrics-config-center org.apache.dubbo diff --git a/dubbo-monitor/dubbo-monitor-api/src/main/java/org/apache/dubbo/monitor/support/MonitorFilter.java b/dubbo-monitor/dubbo-monitor-api/src/main/java/org/apache/dubbo/monitor/support/MonitorFilter.java index 7e50cc800b..f8afc4a588 100644 --- a/dubbo-monitor/dubbo-monitor-api/src/main/java/org/apache/dubbo/monitor/support/MonitorFilter.java +++ b/dubbo-monitor/dubbo-monitor-api/src/main/java/org/apache/dubbo/monitor/support/MonitorFilter.java @@ -31,6 +31,8 @@ import org.apache.dubbo.rpc.Invoker; import org.apache.dubbo.rpc.Result; import org.apache.dubbo.rpc.RpcContext; import org.apache.dubbo.rpc.RpcException; +import org.apache.dubbo.rpc.model.ProviderModel; +import org.apache.dubbo.rpc.model.ServiceModel; import org.apache.dubbo.rpc.support.RpcUtils; import java.util.concurrent.ConcurrentHashMap; @@ -97,6 +99,11 @@ public class MonitorFilter implements Filter, Filter.Listener { // count up getConcurrent(invoker, invocation).incrementAndGet(); } + ServiceModel serviceModel = invoker.getUrl().getServiceModel(); + if (serviceModel instanceof ProviderModel) { + ((ProviderModel) serviceModel).updateLastInvokeTime(); + } + // proceed invocation chain return invoker.invoke(invocation); } diff --git a/dubbo-plugin/dubbo-qos-api/src/main/java/org/apache/dubbo/qos/api/QosConfiguration.java b/dubbo-plugin/dubbo-qos-api/src/main/java/org/apache/dubbo/qos/api/QosConfiguration.java index 476079aa14..69f9b10e19 100644 --- a/dubbo-plugin/dubbo-qos-api/src/main/java/org/apache/dubbo/qos/api/QosConfiguration.java +++ b/dubbo-plugin/dubbo-qos-api/src/main/java/org/apache/dubbo/qos/api/QosConfiguration.java @@ -38,6 +38,9 @@ public class QosConfiguration { // the default value is Cmd.PermissionLevel.PUBLIC, can only access PUBLIC level cmd private PermissionLevel anonymousAccessPermissionLevel = PermissionLevel.PUBLIC; + // the allow commands for anonymous access, the delimiter is colon(,) + private String anonymousAllowCommands; + private QosConfiguration() { } @@ -46,6 +49,7 @@ public class QosConfiguration { this.acceptForeignIp = builder.isAcceptForeignIp(); this.acceptForeignIpWhitelist = builder.getAcceptForeignIpWhitelist(); this.anonymousAccessPermissionLevel = builder.getAnonymousAccessPermissionLevel(); + this.anonymousAllowCommands = builder.getAnonymousAllowCommands(); buildPredicate(); } @@ -93,6 +97,10 @@ public class QosConfiguration { return acceptForeignIp; } + public String getAnonymousAllowCommands() { + return anonymousAllowCommands; + } + public static Builder builder() { return new Builder(); } @@ -103,6 +111,7 @@ public class QosConfiguration { private boolean acceptForeignIp; private String acceptForeignIpWhitelist; private PermissionLevel anonymousAccessPermissionLevel = PermissionLevel.PUBLIC; + private String anonymousAllowCommands; private Builder() { } @@ -127,6 +136,11 @@ public class QosConfiguration { return this; } + public Builder anonymousAllowCommands(String anonymousAllowCommands) { + this.anonymousAllowCommands = anonymousAllowCommands; + return this; + } + public QosConfiguration build() { return new QosConfiguration(this); } @@ -146,5 +160,9 @@ public class QosConfiguration { public PermissionLevel getAnonymousAccessPermissionLevel() { return anonymousAccessPermissionLevel; } + + public String getAnonymousAllowCommands() { + return anonymousAllowCommands; + } } } diff --git a/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/command/impl/GracefulShutdown.java b/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/command/impl/GracefulShutdown.java new file mode 100644 index 0000000000..c4fa69557d --- /dev/null +++ b/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/command/impl/GracefulShutdown.java @@ -0,0 +1,47 @@ +/* + * 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.qos.command.impl; + +import org.apache.dubbo.qos.api.BaseCommand; +import org.apache.dubbo.qos.api.Cmd; +import org.apache.dubbo.qos.api.CommandContext; +import org.apache.dubbo.qos.api.PermissionLevel; +import org.apache.dubbo.rpc.model.FrameworkModel; + +@Cmd(name = "gracefulShutdown", + summary = "Gracefully shutdown servers", + example = {"gracefulShutdown"}, + requiredPermissionLevel = PermissionLevel.PRIVATE) +public class GracefulShutdown implements BaseCommand { + private final Offline offline; + private final FrameworkModel frameworkModel; + + public GracefulShutdown(FrameworkModel frameworkModel) { + this.offline = new Offline(frameworkModel); + this.frameworkModel = frameworkModel; + } + + @Override + public String execute(CommandContext commandContext, String[] args) { + offline.execute(commandContext, new String[0]); + for (org.apache.dubbo.rpc.GracefulShutdown gracefulShutdown : + org.apache.dubbo.rpc.GracefulShutdown.getGracefulShutdowns(frameworkModel)) { + gracefulShutdown.readonly(); + } + return "OK"; + } +} diff --git a/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/permission/DefaultAnonymousAccessPermissionChecker.java b/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/permission/DefaultAnonymousAccessPermissionChecker.java index 8efd756e00..61736f2247 100644 --- a/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/permission/DefaultAnonymousAccessPermissionChecker.java +++ b/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/permission/DefaultAnonymousAccessPermissionChecker.java @@ -16,13 +16,16 @@ */ package org.apache.dubbo.qos.permission; -import io.netty.channel.Channel; +import org.apache.dubbo.common.utils.StringUtils; import org.apache.dubbo.qos.api.CommandContext; import org.apache.dubbo.qos.api.PermissionLevel; import org.apache.dubbo.qos.api.QosConfiguration; +import io.netty.channel.Channel; + import java.net.InetAddress; import java.net.InetSocketAddress; +import java.util.Arrays; import java.util.Optional; public class DefaultAnonymousAccessPermissionChecker implements PermissionChecker { @@ -37,6 +40,15 @@ public class DefaultAnonymousAccessPermissionChecker implements PermissionChecke .orElse(null); QosConfiguration qosConfiguration = commandContext.getQosConfiguration(); + String anonymousAllowCommands = qosConfiguration.getAnonymousAllowCommands(); + if (StringUtils.isNotEmpty(anonymousAllowCommands) && + Arrays.stream(anonymousAllowCommands.split(",")) + .filter(StringUtils::isNotEmpty) + .map(String::trim) + .anyMatch(cmd -> cmd.equals(commandContext.getCommandName()))) { + return true; + } + PermissionLevel currentLevel = qosConfiguration.getAnonymousAccessPermissionLevel(); // Local has private permission diff --git a/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/protocol/QosProtocolWrapper.java b/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/protocol/QosProtocolWrapper.java index ef2f35c3dd..127fa8bb42 100644 --- a/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/protocol/QosProtocolWrapper.java +++ b/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/protocol/QosProtocolWrapper.java @@ -40,6 +40,7 @@ import java.util.concurrent.atomic.AtomicBoolean; import static org.apache.dubbo.common.constants.LoggerCodeConstants.QOS_FAILED_START_SERVER; import static org.apache.dubbo.common.constants.QosConstants.ACCEPT_FOREIGN_IP; import static org.apache.dubbo.common.constants.QosConstants.ACCEPT_FOREIGN_IP_WHITELIST; +import static org.apache.dubbo.common.constants.QosConstants.ANONYMOUS_ACCESS_ALLOW_COMMANDS; import static org.apache.dubbo.common.constants.QosConstants.ANONYMOUS_ACCESS_PERMISSION_LEVEL; import static org.apache.dubbo.common.constants.QosConstants.QOS_ENABLE; import static org.apache.dubbo.common.constants.QosConstants.QOS_HOST; @@ -119,6 +120,7 @@ public class QosProtocolWrapper implements Protocol, ScopeModelAware { boolean acceptForeignIp = Boolean.parseBoolean(url.getParameter(ACCEPT_FOREIGN_IP, "false")); String acceptForeignIpWhitelist = url.getParameter(ACCEPT_FOREIGN_IP_WHITELIST, StringUtils.EMPTY_STRING); String anonymousAccessPermissionLevel = url.getParameter(ANONYMOUS_ACCESS_PERMISSION_LEVEL, PermissionLevel.PUBLIC.name()); + String anonymousAllowCommands = url.getParameter(ANONYMOUS_ACCESS_ALLOW_COMMANDS, StringUtils.EMPTY_STRING); Server server = frameworkModel.getBeanFactory().getBean(Server.class); if (server.isStarted()) { @@ -130,6 +132,7 @@ public class QosProtocolWrapper implements Protocol, ScopeModelAware { server.setAcceptForeignIp(acceptForeignIp); server.setAcceptForeignIpWhitelist(acceptForeignIpWhitelist); server.setAnonymousAccessPermissionLevel(anonymousAccessPermissionLevel); + server.setAnonymousAllowCommands(anonymousAllowCommands); server.start(); } catch (Throwable throwable) { diff --git a/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/server/Server.java b/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/server/Server.java index 4dc03d1cd7..65e7e3b9fa 100644 --- a/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/server/Server.java +++ b/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/server/Server.java @@ -58,6 +58,8 @@ public class Server { private String anonymousAccessPermissionLevel = PermissionLevel.NONE.name(); + private String anonymousAllowCommands = StringUtils.EMPTY_STRING; + private EventLoopGroup boss; private EventLoopGroup worker; @@ -108,6 +110,7 @@ public class Server { .acceptForeignIp(acceptForeignIp) .acceptForeignIpWhitelist(acceptForeignIpWhitelist) .anonymousAccessPermissionLevel(anonymousAccessPermissionLevel) + .anonymousAllowCommands(anonymousAllowCommands) .build() )); } @@ -167,6 +170,10 @@ public class Server { this.anonymousAccessPermissionLevel = anonymousAccessPermissionLevel; } + public void setAnonymousAllowCommands(String anonymousAllowCommands) { + this.anonymousAllowCommands = anonymousAllowCommands; + } + public String getWelcome() { return welcome; } diff --git a/dubbo-plugin/dubbo-qos/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.qos.api.BaseCommand b/dubbo-plugin/dubbo-qos/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.qos.api.BaseCommand index 78825644ed..d575733b46 100644 --- a/dubbo-plugin/dubbo-qos/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.qos.api.BaseCommand +++ b/dubbo-plugin/dubbo-qos/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.qos.api.BaseCommand @@ -36,3 +36,4 @@ serializeCheckStatus=org.apache.dubbo.qos.command.impl.SerializeCheckStatus serializeWarnedClasses=org.apache.dubbo.qos.command.impl.SerializeWarnedClasses getConfig=org.apache.dubbo.qos.command.impl.GetConfig getAddress=org.apache.dubbo.qos.command.impl.GetAddress +gracefulShutdown=org.apache.dubbo.qos.command.impl.GracefulShutdown diff --git a/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/command/util/CommandHelperTest.java b/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/command/util/CommandHelperTest.java index a06a76408c..0370e519ef 100644 --- a/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/command/util/CommandHelperTest.java +++ b/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/command/util/CommandHelperTest.java @@ -30,6 +30,7 @@ import org.apache.dubbo.qos.command.impl.GetConfig; import org.apache.dubbo.qos.command.impl.GetEnabledRouterSnapshot; import org.apache.dubbo.qos.command.impl.GetRecentRouterSnapshot; import org.apache.dubbo.qos.command.impl.GetRouterSnapshot; +import org.apache.dubbo.qos.command.impl.GracefulShutdown; import org.apache.dubbo.qos.command.impl.Help; import org.apache.dubbo.qos.command.impl.InvokeTelnet; import org.apache.dubbo.qos.command.impl.Live; @@ -123,6 +124,7 @@ class CommandHelperTest { expectedClasses.add(SerializeWarnedClasses.class); expectedClasses.add(GetConfig.class); expectedClasses.add(GetAddress.class); + expectedClasses.add(GracefulShutdown.class); assertThat(classes, containsInAnyOrder(expectedClasses.toArray(new Class[0]))); } diff --git a/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/permission/DefaultAnonymousAccessPermissionCheckerTest.java b/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/permission/DefaultAnonymousAccessPermissionCheckerTest.java index 11f466ca39..eef2013fde 100644 --- a/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/permission/DefaultAnonymousAccessPermissionCheckerTest.java +++ b/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/permission/DefaultAnonymousAccessPermissionCheckerTest.java @@ -16,10 +16,11 @@ */ package org.apache.dubbo.qos.permission; -import io.netty.channel.Channel; import org.apache.dubbo.qos.api.CommandContext; import org.apache.dubbo.qos.api.PermissionLevel; import org.apache.dubbo.qos.api.QosConfiguration; + +import io.netty.channel.Channel; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.mockito.Mockito; @@ -79,5 +80,26 @@ class DefaultAnonymousAccessPermissionCheckerTest { Assertions.assertTrue(checker.access(commandContext, PermissionLevel.PUBLIC)); Assertions.assertTrue(checker.access(commandContext, PermissionLevel.PROTECTED)); Assertions.assertFalse(checker.access(commandContext, PermissionLevel.PRIVATE)); + + Mockito.when(qosConfiguration.getAcceptForeignIpWhitelistPredicate()).thenReturn(ip -> false); + Mockito.when(qosConfiguration.getAnonymousAllowCommands()).thenReturn("test1,test2"); + + Mockito.when(commandContext.getCommandName()).thenReturn("test1"); + Assertions.assertTrue(checker.access(commandContext, PermissionLevel.NONE)); + Assertions.assertTrue(checker.access(commandContext, PermissionLevel.PUBLIC)); + Assertions.assertTrue(checker.access(commandContext, PermissionLevel.PROTECTED)); + Assertions.assertTrue(checker.access(commandContext, PermissionLevel.PRIVATE)); + + Mockito.when(commandContext.getCommandName()).thenReturn("test2"); + Assertions.assertTrue(checker.access(commandContext, PermissionLevel.NONE)); + Assertions.assertTrue(checker.access(commandContext, PermissionLevel.PUBLIC)); + Assertions.assertTrue(checker.access(commandContext, PermissionLevel.PROTECTED)); + Assertions.assertTrue(checker.access(commandContext, PermissionLevel.PRIVATE)); + + Mockito.when(commandContext.getCommandName()).thenReturn("test"); + Assertions.assertTrue(checker.access(commandContext, PermissionLevel.NONE)); + Assertions.assertFalse(checker.access(commandContext, PermissionLevel.PUBLIC)); + Assertions.assertFalse(checker.access(commandContext, PermissionLevel.PROTECTED)); + Assertions.assertFalse(checker.access(commandContext, PermissionLevel.PRIVATE)); } } diff --git a/dubbo-plugin/dubbo-spring-security/src/main/java/org/apache/dubbo/spring/security/filter/ContextHolderAuthenticationPrepareFilter.java b/dubbo-plugin/dubbo-spring-security/src/main/java/org/apache/dubbo/spring/security/filter/ContextHolderAuthenticationPrepareFilter.java index 5d70dc9858..e2a8fe0bc6 100644 --- a/dubbo-plugin/dubbo-spring-security/src/main/java/org/apache/dubbo/spring/security/filter/ContextHolderAuthenticationPrepareFilter.java +++ b/dubbo-plugin/dubbo-spring-security/src/main/java/org/apache/dubbo/spring/security/filter/ContextHolderAuthenticationPrepareFilter.java @@ -18,6 +18,7 @@ package org.apache.dubbo.spring.security.filter; import org.apache.dubbo.common.constants.CommonConstants; import org.apache.dubbo.common.extension.Activate; +import org.apache.dubbo.common.utils.StringUtils; import org.apache.dubbo.rpc.Invocation; import org.apache.dubbo.rpc.Invoker; import org.apache.dubbo.rpc.Result; @@ -52,6 +53,12 @@ public class ContextHolderAuthenticationPrepareFilter implements ClusterFilter{ Authentication authentication = context.getAuthentication(); - invocation.setObjectAttachment(SecurityNames.SECURITY_AUTHENTICATION_CONTEXT_KEY, mapper.serialize(authentication)); + String content = mapper.serialize(authentication); + + if (StringUtils.isBlank(content)) { + return; + } + + invocation.setObjectAttachment(SecurityNames.SECURITY_AUTHENTICATION_CONTEXT_KEY, content); } } diff --git a/dubbo-plugin/dubbo-spring-security/src/main/java/org/apache/dubbo/spring/security/filter/ContextHolderAuthenticationResolverFilter.java b/dubbo-plugin/dubbo-spring-security/src/main/java/org/apache/dubbo/spring/security/filter/ContextHolderAuthenticationResolverFilter.java index 092cfe018f..acd5026409 100644 --- a/dubbo-plugin/dubbo-spring-security/src/main/java/org/apache/dubbo/spring/security/filter/ContextHolderAuthenticationResolverFilter.java +++ b/dubbo-plugin/dubbo-spring-security/src/main/java/org/apache/dubbo/spring/security/filter/ContextHolderAuthenticationResolverFilter.java @@ -53,7 +53,13 @@ public class ContextHolderAuthenticationResolverFilter implements Filter { if (StringUtils.isBlank(authenticationJSON)) { return; } + Authentication authentication = mapper.deserialize(authenticationJSON, Authentication.class); + + if (authentication == null) { + return; + } + SecurityContextHolder.getContext().setAuthentication(authentication); } diff --git a/dubbo-plugin/dubbo-spring-security/src/main/java/org/apache/dubbo/spring/security/jackson/ObjectMapperCodec.java b/dubbo-plugin/dubbo-spring-security/src/main/java/org/apache/dubbo/spring/security/jackson/ObjectMapperCodec.java index a97e520d65..97d1048bba 100644 --- a/dubbo-plugin/dubbo-spring-security/src/main/java/org/apache/dubbo/spring/security/jackson/ObjectMapperCodec.java +++ b/dubbo-plugin/dubbo-spring-security/src/main/java/org/apache/dubbo/spring/security/jackson/ObjectMapperCodec.java @@ -20,6 +20,9 @@ package org.apache.dubbo.spring.security.jackson; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.module.SimpleModule; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import org.apache.dubbo.common.constants.LoggerCodeConstants; +import org.apache.dubbo.common.logger.ErrorTypeAwareLogger; +import org.apache.dubbo.common.logger.LoggerFactory; import org.apache.dubbo.common.utils.ClassUtils; import org.apache.dubbo.common.utils.StringUtils; import org.springframework.security.jackson2.CoreJackson2Module; @@ -30,6 +33,8 @@ import java.util.function.Consumer; public class ObjectMapperCodec { + private static final ErrorTypeAwareLogger logger = LoggerFactory.getErrorTypeAwareLogger(ObjectMapperCodec.class); + private final ObjectMapper mapper = new ObjectMapper(); public ObjectMapperCodec() { @@ -38,7 +43,6 @@ public class ObjectMapperCodec { public T deserialize(byte[] bytes, Class clazz) { try { - if (bytes == null || bytes.length == 0) { return null; } @@ -46,9 +50,9 @@ public class ObjectMapperCodec { return mapper.readValue(bytes, clazz); } catch (Exception exception) { - throw new RuntimeException( - String.format("objectMapper! deserialize error %s", exception)); + logger.warn(LoggerCodeConstants.COMMON_JSON_CONVERT_EXCEPTION, "objectMapper! deserialize error, you can try to customize the ObjectMapperCodecCustomer.","","", exception); } + return null; } public T deserialize(String content, Class clazz) { @@ -68,8 +72,10 @@ public class ObjectMapperCodec { return mapper.writeValueAsString(object); } catch (Exception ex) { - throw new RuntimeException(String.format("objectMapper! serialize error %s", ex)); + logger.warn(LoggerCodeConstants.COMMON_JSON_CONVERT_EXCEPTION, "objectMapper! serialize error, you can try to customize the ObjectMapperCodecCustomer.","","", ex); + } + return null; } public ObjectMapperCodec addModule(SimpleModule simpleModule) { diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryProtocol.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryProtocol.java index c19cae36d3..0d36bb0a18 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryProtocol.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryProtocol.java @@ -16,18 +16,7 @@ */ package org.apache.dubbo.registry.integration; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; - import org.apache.dubbo.common.URL; -import org.apache.dubbo.common.config.ConfigurationUtils; import org.apache.dubbo.common.config.configcenter.DynamicConfiguration; import org.apache.dubbo.common.deploy.ApplicationDeployer; import org.apache.dubbo.common.logger.ErrorTypeAwareLogger; @@ -71,13 +60,26 @@ import org.apache.dubbo.rpc.model.ScopeModelUtil; import org.apache.dubbo.rpc.protocol.InvokerWrapper; import org.apache.dubbo.rpc.support.ProtocolUtils; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; + +import static org.apache.dubbo.common.constants.CommonConstants.ANYHOST_KEY; import static org.apache.dubbo.common.constants.CommonConstants.APPLICATION_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.BACKGROUND_KEY; import static org.apache.dubbo.common.constants.CommonConstants.CLUSTER_KEY; import static org.apache.dubbo.common.constants.CommonConstants.COMMA_SPLIT_PATTERN; import static org.apache.dubbo.common.constants.CommonConstants.CONSUMER; -import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_SERVER_SHUTDOWN_TIMEOUT; import static org.apache.dubbo.common.constants.CommonConstants.DUBBO_VERSION_KEY; import static org.apache.dubbo.common.constants.CommonConstants.ENABLED_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.EXECUTOR_MANAGEMENT_MODE; import static org.apache.dubbo.common.constants.CommonConstants.EXTRA_KEYS_KEY; import static org.apache.dubbo.common.constants.CommonConstants.GROUP_KEY; import static org.apache.dubbo.common.constants.CommonConstants.HIDE_KEY_PREFIX; @@ -86,8 +88,11 @@ import static org.apache.dubbo.common.constants.CommonConstants.IPV6_KEY; import static org.apache.dubbo.common.constants.CommonConstants.LOADBALANCE_KEY; import static org.apache.dubbo.common.constants.CommonConstants.METHODS_KEY; import static org.apache.dubbo.common.constants.CommonConstants.MONITOR_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.PACKABLE_METHOD_FACTORY_KEY; import static org.apache.dubbo.common.constants.CommonConstants.PATH_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.PID_KEY; import static org.apache.dubbo.common.constants.CommonConstants.PROTOCOL_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.REGISTRY_LOCAL_FILE_CACHE_ENABLED; import static org.apache.dubbo.common.constants.CommonConstants.REGISTRY_PROTOCOL_LISTENER_KEY; import static org.apache.dubbo.common.constants.CommonConstants.RELEASE_KEY; import static org.apache.dubbo.common.constants.CommonConstants.SIDE_KEY; @@ -105,6 +110,7 @@ import static org.apache.dubbo.common.constants.RegistryConstants.CATEGORY_KEY; import static org.apache.dubbo.common.constants.RegistryConstants.CONFIGURATORS_CATEGORY; import static org.apache.dubbo.common.constants.RegistryConstants.DYNAMIC_KEY; import static org.apache.dubbo.common.constants.RegistryConstants.OVERRIDE_PROTOCOL; +import static org.apache.dubbo.common.constants.RegistryConstants.REGISTER_MODE_KEY; import static org.apache.dubbo.common.constants.RegistryConstants.REGISTRY_KEY; import static org.apache.dubbo.common.constants.RegistryConstants.SERVICE_REGISTRY_PROTOCOL; import static org.apache.dubbo.common.utils.StringUtils.isEmpty; @@ -144,7 +150,7 @@ public class RegistryProtocol implements Protocol, ScopeModelAware { public static final String[] DEFAULT_REGISTER_PROVIDER_KEYS = { APPLICATION_KEY, CODEC_KEY, EXCHANGER_KEY, SERIALIZATION_KEY, PREFER_SERIALIZATION_KEY, CLUSTER_KEY, CONNECTIONS_KEY, DEPRECATED_KEY, GROUP_KEY, LOADBALANCE_KEY, MOCK_KEY, PATH_KEY, TIMEOUT_KEY, TOKEN_KEY, VERSION_KEY, WARMUP_KEY, - WEIGHT_KEY, DUBBO_VERSION_KEY, RELEASE_KEY, SIDE_KEY, IPV6_KEY + WEIGHT_KEY, DUBBO_VERSION_KEY, RELEASE_KEY, SIDE_KEY, IPV6_KEY, PACKABLE_METHOD_FACTORY_KEY }; public static final String[] DEFAULT_REGISTER_CONSUMER_KEYS = { @@ -426,7 +432,7 @@ public class RegistryProtocol implements Protocol, ScopeModelAware { if (!registryUrl.getParameter(SIMPLIFIED_KEY, false)) { return providerUrl.removeParameters(getFilteredKeys(providerUrl)).removeParameters( MONITOR_KEY, BIND_IP_KEY, BIND_PORT_KEY, QOS_ENABLE, QOS_HOST, QOS_PORT, ACCEPT_FOREIGN_IP, VALIDATION_KEY, - INTERFACES); + INTERFACES, REGISTER_MODE_KEY, PID_KEY, REGISTRY_LOCAL_FILE_CACHE_ENABLED, EXECUTOR_MANAGEMENT_MODE, BACKGROUND_KEY, ANYHOST_KEY); } else { String extraKeys = registryUrl.getParameter(EXTRA_KEYS_KEY, ""); // if path is not the same as interface name then we should keep INTERFACE_KEY, @@ -701,6 +707,11 @@ public class RegistryProtocol implements Protocol, ScopeModelAware { public void unexport() { exporter.unexport(); } + + @Override + public void unregister() { + exporter.unregister(); + } } /** @@ -905,6 +916,7 @@ public class RegistryProtocol implements Protocol, ScopeModelAware { private URL registerUrl; private NotifyListener notifyListener; + private final AtomicBoolean unregistered = new AtomicBoolean(false); public ExporterChangeableWrapper(Exporter exporter, Invoker originInvoker) { this.exporter = exporter; @@ -928,57 +940,60 @@ public class RegistryProtocol implements Protocol, ScopeModelAware { } @Override - public void unexport() { - String key = getCacheKey(this.originInvoker); - bounds.remove(key); - - Registry registry = RegistryProtocol.this.getRegistry(getRegistryUrl(originInvoker)); - try { - registry.unregister(registerUrl); - } catch (Throwable t) { - logger.warn(INTERNAL_ERROR, "unknown error in registry module", "", t.getMessage(), t); - } - try { - if (subscribeUrl != null) { - Map> overrideListeners = getProviderConfigurationListener(subscribeUrl).getOverrideListeners(); - Set listeners = overrideListeners.get(subscribeUrl); - if(listeners != null){ - if (listeners.remove(notifyListener)) { - if (!registry.isServiceDiscovery()) { - registry.unsubscribe(subscribeUrl, notifyListener); - } - ApplicationModel applicationModel = getApplicationModel(registerUrl.getScopeModel()); - if (applicationModel.getModelEnvironment().getConfiguration().convert(Boolean.class, ENABLE_CONFIGURATION_LISTEN, true)) { - for (ModuleModel moduleModel : applicationModel.getPubModuleModels()) { - if (moduleModel.getServiceRepository().getExportedServices().size() > 0) { - moduleModel.getExtensionLoader(GovernanceRuleRepository.class).getDefaultExtension() - .removeListener(subscribeUrl.getServiceKey() + CONFIGURATORS_SUFFIX, - serviceConfigurationListeners.remove(subscribeUrl.getServiceKey())); - } - } - } - } - if (listeners.isEmpty()) { - overrideListeners.remove(subscribeUrl); - } - } - } - } catch (Throwable t) { - logger.warn(INTERNAL_ERROR, "unknown error in registry module", "", t.getMessage(), t); - } - - //TODO wait for shutdown timeout is a bit strange - int timeout = DEFAULT_SERVER_SHUTDOWN_TIMEOUT; - if (subscribeUrl != null) { - timeout = ConfigurationUtils.getServerShutdownTimeout(subscribeUrl.getScopeModel()); - } - executor.schedule(() -> { + public synchronized void unregister() { + if (unregistered.compareAndSet(false, true)) { + Registry registry = RegistryProtocol.this.getRegistry(getRegistryUrl(originInvoker)); try { - exporter.unexport(); + registry.unregister(registerUrl); } catch (Throwable t) { logger.warn(INTERNAL_ERROR, "unknown error in registry module", "", t.getMessage(), t); } - }, timeout, TimeUnit.MILLISECONDS); + try { + if (subscribeUrl != null) { + Map> overrideListeners = getProviderConfigurationListener(subscribeUrl).getOverrideListeners(); + Set listeners = overrideListeners.get(subscribeUrl); + if (listeners != null) { + if (listeners.remove(notifyListener)) { + if (!registry.isServiceDiscovery()) { + registry.unsubscribe(subscribeUrl, notifyListener); + } + ApplicationModel applicationModel = getApplicationModel(registerUrl.getScopeModel()); + if (applicationModel.getModelEnvironment().getConfiguration().convert(Boolean.class, ENABLE_CONFIGURATION_LISTEN, true)) { + for (ModuleModel moduleModel : applicationModel.getPubModuleModels()) { + if (moduleModel.getServiceRepository().getExportedServices().size() > 0) { + moduleModel.getExtensionLoader(GovernanceRuleRepository.class).getDefaultExtension() + .removeListener(subscribeUrl.getServiceKey() + CONFIGURATORS_SUFFIX, + serviceConfigurationListeners.remove(subscribeUrl.getServiceKey())); + } + } + } + } + if (listeners.isEmpty()) { + overrideListeners.remove(subscribeUrl); + } + } + } + } catch (Throwable t) { + logger.warn(INTERNAL_ERROR, "unknown error in registry module", "", t.getMessage(), t); + } + } + } + + @Override + public synchronized void unexport() { + String key = getCacheKey(this.originInvoker); + bounds.remove(key); + + unregister(); + doUnExport(); + } + + private void doUnExport() { + try { + exporter.unexport(); + } catch (Throwable t) { + logger.warn(INTERNAL_ERROR, "unknown error in registry module", "", t.getMessage(), t); + } } public void setSubscribeUrl(URL subscribeUrl) { diff --git a/dubbo-registry/dubbo-registry-nacos/src/main/java/org/apache/dubbo/registry/nacos/NacosConnectionManager.java b/dubbo-registry/dubbo-registry-nacos/src/main/java/org/apache/dubbo/registry/nacos/NacosConnectionManager.java index 913809a5a6..2082abd2b0 100644 --- a/dubbo-registry/dubbo-registry-nacos/src/main/java/org/apache/dubbo/registry/nacos/NacosConnectionManager.java +++ b/dubbo-registry/dubbo-registry-nacos/src/main/java/org/apache/dubbo/registry/nacos/NacosConnectionManager.java @@ -16,13 +16,6 @@ */ package org.apache.dubbo.registry.nacos; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Properties; -import java.util.Set; -import java.util.concurrent.ThreadLocalRandom; - import org.apache.dubbo.common.URL; import org.apache.dubbo.common.constants.LoggerCodeConstants; import org.apache.dubbo.common.logger.ErrorTypeAwareLogger; @@ -35,7 +28,13 @@ import com.alibaba.nacos.api.PropertyKeyConst; import com.alibaba.nacos.api.exception.NacosException; import com.alibaba.nacos.api.naming.NamingService; -import static com.alibaba.nacos.api.PropertyKeyConst.NAMING_LOAD_CACHE_AT_START; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.Set; +import java.util.concurrent.ThreadLocalRandom; + import static com.alibaba.nacos.api.PropertyKeyConst.PASSWORD; import static com.alibaba.nacos.api.PropertyKeyConst.SERVER_ADDR; import static com.alibaba.nacos.api.PropertyKeyConst.USERNAME; @@ -199,8 +198,6 @@ public class NacosConnectionManager { if (StringUtils.isNotEmpty(url.getPassword())) { properties.put(PASSWORD, url.getPassword()); } - - putPropertyIfAbsent(url, properties, NAMING_LOAD_CACHE_AT_START, "true"); } private void putPropertyIfAbsent(URL url, Properties properties, String propertyName, String defaultValue) { diff --git a/dubbo-registry/dubbo-registry-nacos/src/test/java/org/apache/dubbo/registry/nacos/MockNamingService.java b/dubbo-registry/dubbo-registry-nacos/src/test/java/org/apache/dubbo/registry/nacos/MockNamingService.java index b7c62f9c11..e611bae357 100644 --- a/dubbo-registry/dubbo-registry-nacos/src/test/java/org/apache/dubbo/registry/nacos/MockNamingService.java +++ b/dubbo-registry/dubbo-registry-nacos/src/test/java/org/apache/dubbo/registry/nacos/MockNamingService.java @@ -92,6 +92,11 @@ public class MockNamingService implements NamingService { } + @Override + public void batchDeregisterInstance(String s, String s1, List list) throws NacosException { + + } + @Override public List getAllInstances(String serviceName) { return null; diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/support/header/HeaderExchangeHandler.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/support/header/HeaderExchangeHandler.java index ef0420f8f4..fd9d660d05 100644 --- a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/support/header/HeaderExchangeHandler.java +++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/support/header/HeaderExchangeHandler.java @@ -38,6 +38,7 @@ import java.net.InetSocketAddress; import java.util.concurrent.CompletionStage; import static org.apache.dubbo.common.constants.CommonConstants.READONLY_EVENT; +import static org.apache.dubbo.common.constants.CommonConstants.WRITEABLE_EVENT; import static org.apache.dubbo.common.constants.LoggerCodeConstants.TRANSPORT_FAILED_RESPONSE; import static org.apache.dubbo.common.constants.LoggerCodeConstants.TRANSPORT_UNSUPPORTED_MESSAGE; @@ -75,6 +76,11 @@ public class HeaderExchangeHandler implements ChannelHandlerDelegate { void handlerEvent(Channel channel, Request req) throws RemotingException { if (req.getData() != null && req.getData().equals(READONLY_EVENT)) { channel.setAttribute(Constants.CHANNEL_ATTRIBUTE_READONLY_KEY, Boolean.TRUE); + logger.info("ChannelReadOnly set true for channel: " + channel); + } + if (req.getData() != null && req.getData().equals(WRITEABLE_EVENT)) { + channel.removeAttribute(Constants.CHANNEL_ATTRIBUTE_READONLY_KEY); + logger.info("ChannelReadOnly set false for channel: " + channel); } } diff --git a/dubbo-remoting/dubbo-remoting-netty4/src/main/java/org/apache/dubbo/remoting/transport/netty4/NettyChannelHandler.java b/dubbo-remoting/dubbo-remoting-netty4/src/main/java/org/apache/dubbo/remoting/transport/netty4/NettyChannelHandler.java new file mode 100644 index 0000000000..cfedb14371 --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-netty4/src/main/java/org/apache/dubbo/remoting/transport/netty4/NettyChannelHandler.java @@ -0,0 +1,77 @@ +/* + * 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.remoting.transport.netty4; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.logger.Logger; +import org.apache.dubbo.common.logger.LoggerFactory; +import org.apache.dubbo.common.utils.NetUtils; +import org.apache.dubbo.remoting.Channel; +import org.apache.dubbo.remoting.ChannelHandler; + +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelInboundHandlerAdapter; + +import java.net.InetSocketAddress; +import java.util.Map; + +public class NettyChannelHandler extends ChannelInboundHandlerAdapter { + private static final Logger logger = LoggerFactory.getLogger(NettyChannelHandler.class); + + private final Map dubboChannels; + + private final URL url; + private final ChannelHandler handler; + + public NettyChannelHandler(Map dubboChannels, URL url, ChannelHandler handler) { + this.dubboChannels = dubboChannels; + this.url = url; + this.handler = handler; + } + + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { + super.channelActive(ctx); + NettyChannel channel = NettyChannel.getOrAddChannel(ctx.channel(), url, handler); + if (channel != null) { + dubboChannels.put(NetUtils.toAddressString((InetSocketAddress) ctx.channel().remoteAddress()), channel); + handler.connected(channel); + + if (logger.isInfoEnabled()) { + logger.info("The connection of " + channel.getRemoteAddress() + " -> " + channel.getLocalAddress() + " is established."); + } + } + } + + @Override + public void channelInactive(ChannelHandlerContext ctx) throws Exception { + super.channelInactive(ctx); + NettyChannel channel = NettyChannel.getOrAddChannel(ctx.channel(), url, handler); + try { + dubboChannels.remove(NetUtils.toAddressString((InetSocketAddress) ctx.channel().remoteAddress())); + if (channel != null) { + handler.disconnected(channel); + if (logger.isInfoEnabled()) { + logger.info("The connection of " + channel.getRemoteAddress() + " -> " + channel.getLocalAddress() + " is disconnected."); + } + } + } finally { + NettyChannel.removeChannel(ctx.channel()); + } + } + +} diff --git a/dubbo-remoting/dubbo-remoting-netty4/src/main/java/org/apache/dubbo/remoting/transport/netty4/NettyPortUnificationServer.java b/dubbo-remoting/dubbo-remoting-netty4/src/main/java/org/apache/dubbo/remoting/transport/netty4/NettyPortUnificationServer.java index 239367320a..42d8d89895 100644 --- a/dubbo-remoting/dubbo-remoting-netty4/src/main/java/org/apache/dubbo/remoting/transport/netty4/NettyPortUnificationServer.java +++ b/dubbo-remoting/dubbo-remoting-netty4/src/main/java/org/apache/dubbo/remoting/transport/netty4/NettyPortUnificationServer.java @@ -122,10 +122,11 @@ public class NettyPortUnificationServer extends AbstractPortUnificationServer { protected void initChannel(SocketChannel ch) throws Exception { // Do not add idle state handler here, because it should be added in the protocol handler. final ChannelPipeline p = ch.pipeline(); - final NettyPortUnificationServerHandler puHandler; - puHandler = new NettyPortUnificationServerHandler(getUrl(), true, getProtocols(), - NettyPortUnificationServer.this, NettyPortUnificationServer.this.dubboChannels, + NettyChannelHandler nettyChannelHandler = new NettyChannelHandler(dubboChannels, getUrl(), NettyPortUnificationServer.this); + NettyPortUnificationServerHandler puHandler = new NettyPortUnificationServerHandler(getUrl(), true, getProtocols(), + NettyPortUnificationServer.this, getSupportedUrls(), getSupportedHandlers()); + p.addLast("channel-handler", nettyChannelHandler); p.addLast("negotiation-protocol", puHandler); } }); diff --git a/dubbo-remoting/dubbo-remoting-netty4/src/main/java/org/apache/dubbo/remoting/transport/netty4/NettyPortUnificationServerHandler.java b/dubbo-remoting/dubbo-remoting-netty4/src/main/java/org/apache/dubbo/remoting/transport/netty4/NettyPortUnificationServerHandler.java index 5d02ea4e16..cb7e672c67 100644 --- a/dubbo-remoting/dubbo-remoting-netty4/src/main/java/org/apache/dubbo/remoting/transport/netty4/NettyPortUnificationServerHandler.java +++ b/dubbo-remoting/dubbo-remoting-netty4/src/main/java/org/apache/dubbo/remoting/transport/netty4/NettyPortUnificationServerHandler.java @@ -22,8 +22,6 @@ import org.apache.dubbo.common.logger.ErrorTypeAwareLogger; import org.apache.dubbo.common.logger.LoggerFactory; import org.apache.dubbo.common.ssl.CertManager; import org.apache.dubbo.common.ssl.ProviderCert; -import org.apache.dubbo.common.utils.NetUtils; -import org.apache.dubbo.remoting.Channel; import org.apache.dubbo.remoting.ChannelHandler; import org.apache.dubbo.remoting.api.ProtocolDetector; import org.apache.dubbo.remoting.api.WireProtocol; @@ -39,7 +37,6 @@ import io.netty.handler.ssl.SslHandler; import io.netty.handler.ssl.SslHandshakeCompletionEvent; import javax.net.ssl.SSLSession; -import java.net.InetSocketAddress; import java.util.List; import java.util.Map; import java.util.Set; @@ -54,19 +51,17 @@ public class NettyPortUnificationServerHandler extends ByteToMessageDecoder { private final ChannelHandler handler; private final boolean detectSsl; private final List protocols; - private final Map dubboChannels; private final Map urlMapper; private final Map handlerMapper; public NettyPortUnificationServerHandler(URL url, boolean detectSsl, List protocols, ChannelHandler handler, - Map dubboChannels, Map urlMapper, Map handlerMapper) { + Map urlMapper, Map handlerMapper) { this.url = url; this.protocols = protocols; this.detectSsl = detectSsl; this.handler = handler; - this.dubboChannels = dubboChannels; this.urlMapper = urlMapper; this.handlerMapper = handlerMapper; } @@ -76,16 +71,6 @@ public class NettyPortUnificationServerHandler extends ByteToMessageDecoder { LOGGER.error(INTERNAL_ERROR, "unknown error in remoting module", "", "Unexpected exception from downstream before protocol detected.", cause); } - @Override - public void channelActive(ChannelHandlerContext ctx) throws Exception { - super.channelActive(ctx); - NettyChannel channel = NettyChannel.getOrAddChannel(ctx.channel(), url, handler); - if (channel != null) { - // this is needed by some test cases - dubboChannels.put(NetUtils.toAddressString((InetSocketAddress) ctx.channel().remoteAddress()), channel); - } - } - @Override public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { if (evt instanceof SslHandshakeCompletionEvent) { @@ -162,7 +147,7 @@ public class NettyPortUnificationServerHandler extends ByteToMessageDecoder { p.addLast("ssl", sslContext.newHandler(ctx.alloc())); p.addLast("unificationA", new NettyPortUnificationServerHandler(url, false, protocols, - handler, dubboChannels, urlMapper, handlerMapper)); + handler, urlMapper, handlerMapper)); p.remove(this); } diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/Exporter.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/Exporter.java index d02a4050dc..9b87ddb5d9 100644 --- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/Exporter.java +++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/Exporter.java @@ -41,4 +41,9 @@ public interface Exporter { */ void unexport(); + /** + * unregister from registry + */ + void unregister(); + } diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/GracefulShutdown.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/GracefulShutdown.java new file mode 100644 index 0000000000..e8bdb38044 --- /dev/null +++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/GracefulShutdown.java @@ -0,0 +1,31 @@ +/* + * 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; + +import org.apache.dubbo.rpc.model.FrameworkModel; + +import java.util.List; + +public interface GracefulShutdown { + void readonly(); + + void writeable(); + + static List getGracefulShutdowns(FrameworkModel frameworkModel) { + return frameworkModel.getBeanFactory().getBeansOfType(GracefulShutdown.class); + } +} diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/listener/ListenerExporterWrapper.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/listener/ListenerExporterWrapper.java index 972f5cbc56..025459588d 100644 --- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/listener/ListenerExporterWrapper.java +++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/listener/ListenerExporterWrapper.java @@ -62,6 +62,11 @@ public class ListenerExporterWrapper implements Exporter { } } + @Override + public void unregister() { + exporter.unregister(); + } + private void listenerEvent(Consumer consumer) { if (CollectionUtils.isNotEmpty(listeners)) { RuntimeException exception = null; diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/protocol/AbstractExporter.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/protocol/AbstractExporter.java index 2378b2458b..b7f6c03e30 100644 --- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/protocol/AbstractExporter.java +++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/protocol/AbstractExporter.java @@ -60,6 +60,11 @@ public abstract class AbstractExporter implements Exporter { afterUnExport(); } + @Override + public void unregister() { + + } + /** * subclasses need to override this method to destroy resources. */ diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DecodeableRpcResult.java b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DecodeableRpcResult.java index 90b32cdf87..ef3b89bb31 100644 --- a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DecodeableRpcResult.java +++ b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DecodeableRpcResult.java @@ -124,7 +124,14 @@ public class DecodeableRpcResult extends AppResponse implements Codec, Decodeabl if (!hasDecoded && channel != null && inputStream != null) { try { if (invocation != null) { - Configuration systemConfiguration = ConfigurationUtils.getSystemConfiguration(channel.getUrl().getScopeModel()); + Configuration systemConfiguration = null; + try { + systemConfiguration = ConfigurationUtils.getSystemConfiguration(channel.getUrl().getScopeModel()); + } catch (Exception e) { + // Because the Environment may be destroyed during the offline process, the configuration cannot be obtained. + // Exceptions are ignored here, and normal decoding is guaranteed. + } + if (systemConfiguration == null || systemConfiguration.getBoolean(SERIALIZATION_SECURITY_CHECK_KEY, true)) { Object serializationTypeObj = invocation.get(SERIALIZATION_ID_KEY); if (serializationTypeObj != null) { diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboGracefulShutdown.java b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboGracefulShutdown.java new file mode 100644 index 0000000000..f1a324e01a --- /dev/null +++ b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboGracefulShutdown.java @@ -0,0 +1,81 @@ +/* + * 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.protocol.dubbo; + +import org.apache.dubbo.common.Version; +import org.apache.dubbo.common.logger.ErrorTypeAwareLogger; +import org.apache.dubbo.common.logger.LoggerFactory; +import org.apache.dubbo.remoting.Channel; +import org.apache.dubbo.remoting.Constants; +import org.apache.dubbo.remoting.RemotingException; +import org.apache.dubbo.remoting.exchange.Request; +import org.apache.dubbo.rpc.GracefulShutdown; +import org.apache.dubbo.rpc.ProtocolServer; + +import java.nio.channels.ClosedChannelException; +import java.util.Collection; + +import static org.apache.dubbo.common.constants.CommonConstants.READONLY_EVENT; +import static org.apache.dubbo.common.constants.CommonConstants.WRITEABLE_EVENT; +import static org.apache.dubbo.common.constants.LoggerCodeConstants.TRANSPORT_FAILED_CLOSE_STREAM; + +public class DubboGracefulShutdown implements GracefulShutdown { + private static final ErrorTypeAwareLogger logger = LoggerFactory.getErrorTypeAwareLogger(DubboGracefulShutdown.class); + private final DubboProtocol dubboProtocol; + + public DubboGracefulShutdown(DubboProtocol dubboProtocol) { + this.dubboProtocol = dubboProtocol; + } + + @Override + public void readonly() { + sendEvent(READONLY_EVENT); + } + + @Override + public void writeable() { + sendEvent(WRITEABLE_EVENT); + } + + private void sendEvent(String event) { + try { + for (ProtocolServer server : dubboProtocol.getServers()) { + Collection channels = server.getRemotingServer().getChannels(); + Request request = new Request(); + request.setEvent(event); + request.setTwoWay(false); + request.setVersion(Version.getProtocolVersion()); + + for (Channel channel : channels) { + try { + if (channel.isConnected()) { + channel.send(request, channel.getUrl().getParameter(Constants.CHANNEL_READONLYEVENT_SENT_KEY, true)); + } + } catch (RemotingException e) { + if (e.getCause() instanceof ClosedChannelException) { + // ignore ClosedChannelException which means the connection has been closed. + continue; + } + logger.warn(TRANSPORT_FAILED_CLOSE_STREAM, "", "", "send cannot write message error.", e); + } + } + } + } catch (Throwable e) { + logger.warn(TRANSPORT_FAILED_CLOSE_STREAM, "", "", "send cannot write message error.", e); + } + } +} diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboProtocol.java b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboProtocol.java index 0e10031e4a..3c0138e0d6 100644 --- a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboProtocol.java +++ b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboProtocol.java @@ -235,6 +235,7 @@ public class DubboProtocol extends AbstractProtocol { } }; this.frameworkModel = frameworkModel; + this.frameworkModel.getBeanFactory().registerBean(new DubboGracefulShutdown(this)); } /** diff --git a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/NettyHttpRestServer.java b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/NettyHttpRestServer.java index d65c368ce6..af3b4f80e2 100644 --- a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/NettyHttpRestServer.java +++ b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/NettyHttpRestServer.java @@ -35,6 +35,7 @@ import org.apache.dubbo.rpc.protocol.rest.handler.NettyHttpHandler; import org.apache.dubbo.rpc.protocol.rest.netty.NettyServer; import org.apache.dubbo.rpc.protocol.rest.netty.RestHttpRequestDecoder; import org.apache.dubbo.rpc.protocol.rest.netty.UnSharedHandlerCreator; +import org.apache.dubbo.rpc.protocol.rest.netty.ssl.SslServerTlsHandler; import java.util.ArrayList; import java.util.Arrays; @@ -124,15 +125,15 @@ public class NettyHttpRestServer implements RestProtocolServer { @Override public List getUnSharedHandlers(URL url) { return Arrays.asList( - // TODO add SslServerTlsHandler -// channelPipeline.addLast(ch.pipeline().addLast("negotiation", new SslServerTlsHandler(url))); - + // add SslServerTlsHandler + new SslServerTlsHandler(url), new HttpRequestDecoder( url.getParameter(RestConstant.MAX_INITIAL_LINE_LENGTH_PARAM, RestConstant.MAX_INITIAL_LINE_LENGTH), url.getParameter(RestConstant.MAX_HEADER_SIZE_PARAM, RestConstant.MAX_HEADER_SIZE), url.getParameter(RestConstant.MAX_CHUNK_SIZE_PARAM, RestConstant.MAX_CHUNK_SIZE)), new HttpObjectAggregator(url.getParameter(RestConstant.MAX_REQUEST_SIZE_PARAM, RestConstant.MAX_REQUEST_SIZE)), - new HttpResponseEncoder(), new RestHttpRequestDecoder(new NettyHttpHandler(pathAndInvokerMapper, exceptionMapper), url)); + new HttpResponseEncoder(), new RestHttpRequestDecoder(new NettyHttpHandler(pathAndInvokerMapper, exceptionMapper), url)) + ; } }; } diff --git a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/PathAndInvokerMapper.java b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/PathAndInvokerMapper.java index ce3a187e70..1d7aa3de05 100644 --- a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/PathAndInvokerMapper.java +++ b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/PathAndInvokerMapper.java @@ -65,17 +65,17 @@ public class PathAndInvokerMapper { * @param port * @return */ - public InvokerAndRestMethodMetadataPair getRestMethodMetadata(String path, String version, String group, Integer port) { + public InvokerAndRestMethodMetadataPair getRestMethodMetadata(String path, String version, String group, Integer port,String method) { - PathMatcher pathMather = PathMatcher.getInvokeCreatePathMatcher(path, version, group, port); + PathMatcher pathMather = PathMatcher.getInvokeCreatePathMatcher(path, version, group, port,method); // first search from pathToServiceMapNoPathVariable if (pathToServiceMapNoPathVariable.containsKey(pathMather)) { return pathToServiceMapNoPathVariable.get(pathMather); } - // second search from pathToServiceMapNoPathVariable + // second search from pathToServiceMapContainPathVariable if (pathToServiceMapContainPathVariable.containsKey(pathMather)) { return pathToServiceMapContainPathVariable.get(pathMather); } diff --git a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/RestRPCInvocationUtil.java b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/RestRPCInvocationUtil.java index 8388e1fe88..1d0221a587 100644 --- a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/RestRPCInvocationUtil.java +++ b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/RestRPCInvocationUtil.java @@ -134,8 +134,9 @@ public class RestRPCInvocationUtil { String path = request.getPath(); String version = request.getHeader(RestHeaderEnum.VERSION.getHeader()); String group = request.getHeader(RestHeaderEnum.GROUP.getHeader()); + String method = request.getMethod(); - return pathAndInvokerMapper.getRestMethodMetadata(path, version, group, null); + return pathAndInvokerMapper.getRestMethodMetadata(path, version, group, null, method); } diff --git a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/RpcExceptionMapper.java b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/RpcExceptionMapper.java index a50a2dda5a..fe07516ba4 100644 --- a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/RpcExceptionMapper.java +++ b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/RpcExceptionMapper.java @@ -16,30 +16,30 @@ */ package org.apache.dubbo.rpc.protocol.rest; +import org.apache.dubbo.common.utils.ClassUtils; import org.apache.dubbo.rpc.RpcException; import org.apache.dubbo.rpc.protocol.rest.exception.mapper.ExceptionHandler; +import org.apache.dubbo.rpc.protocol.rest.util.ConstraintViolationExceptionConvert; -import javax.validation.ConstraintViolation; -import javax.validation.ConstraintViolationException; public class RpcExceptionMapper implements ExceptionHandler { - protected Object handleConstraintViolationException(ConstraintViolationException cve) { - ViolationReport report = new ViolationReport(); - for (ConstraintViolation cv : cve.getConstraintViolations()) { - report.addConstraintViolation(new RestConstraintViolation( - cv.getPropertyPath().toString(), - cv.getMessage(), - cv.getInvalidValue() == null ? "null" : cv.getInvalidValue().toString())); - } - return report; - } @Override public Object result(RpcException e) { - if (e.getCause() instanceof ConstraintViolationException) { - return handleConstraintViolationException((ConstraintViolationException) e.getCause()); + + // javax dependency judge + if (violationDependency()) { + // ConstraintViolationException judge + if (ConstraintViolationExceptionConvert.needConvert(e)) { + return ConstraintViolationExceptionConvert.handleConstraintViolationException(e); + } } + return "Internal server error: " + e.getMessage(); } + + private boolean violationDependency() { + return ClassUtils.isPresent("javax.validation.ConstraintViolationException", RpcExceptionMapper.class.getClassLoader()); + } } diff --git a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/annotation/ParamParserManager.java b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/annotation/ParamParserManager.java index fb865bf417..5c0dbaa236 100644 --- a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/annotation/ParamParserManager.java +++ b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/annotation/ParamParserManager.java @@ -56,6 +56,7 @@ public class ParamParserManager { paramParser.parse(parseContext, args.get(i)); } } + // TODO add param require or default & body arg size pre judge return parseContext.getArgs().toArray(new Object[0]); } @@ -86,5 +87,8 @@ public class ParamParserManager { } } + // TODO add param require or default + + } } diff --git a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/handler/NettyHttpHandler.java b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/handler/NettyHttpHandler.java index a3243685ab..7edf7c4ddf 100644 --- a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/handler/NettyHttpHandler.java +++ b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/handler/NettyHttpHandler.java @@ -104,6 +104,16 @@ public class NettyHttpHandler implements HttpHandler returnType) { + private MediaType getAcceptMediaType(RequestFacade request, Class returnType) { String accept = request.getHeader(RestHeaderEnum.ACCEPT.getHeader()); MediaType mediaType = MediaTypeUtil.convertMediaType(returnType, accept); return mediaType; @@ -176,7 +186,7 @@ public class NettyHttpHandler implements HttpHandler returnType) { try { // media type judge - getAcceptMediaType(requestFacade,returnType); + getAcceptMediaType(requestFacade, returnType); } catch (UnSupportContentTypeException e) { // return type judge MediaType mediaType = HttpMessageCodecManager.typeSupport(returnType); diff --git a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/netty/ssl/SslContexts.java b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/netty/ssl/SslContexts.java new file mode 100644 index 0000000000..12dd3d712b --- /dev/null +++ b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/netty/ssl/SslContexts.java @@ -0,0 +1,158 @@ +/* + * 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.protocol.rest.netty.ssl; + +import io.netty.handler.ssl.ClientAuth; +import io.netty.handler.ssl.OpenSsl; +import io.netty.handler.ssl.SslContext; +import io.netty.handler.ssl.SslContextBuilder; +import io.netty.handler.ssl.SslProvider; +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.logger.ErrorTypeAwareLogger; +import org.apache.dubbo.common.logger.LoggerFactory; +import org.apache.dubbo.common.ssl.AuthPolicy; +import org.apache.dubbo.common.ssl.Cert; +import org.apache.dubbo.common.ssl.CertManager; +import org.apache.dubbo.common.ssl.ProviderCert; + +import javax.net.ssl.SSLException; +import java.io.IOException; +import java.io.InputStream; +import java.security.Provider; +import java.security.Security; + +import static org.apache.dubbo.common.constants.LoggerCodeConstants.TRANSPORT_FAILED_CLOSE_STREAM; + +public class SslContexts { + + private static final ErrorTypeAwareLogger logger = LoggerFactory.getErrorTypeAwareLogger(SslContexts.class); + + public static SslContext buildServerSslContext(ProviderCert providerConnectionConfig) { + SslContextBuilder sslClientContextBuilder; + InputStream serverKeyCertChainPathStream = null; + InputStream serverPrivateKeyPathStream = null; + InputStream serverTrustCertStream = null; + try { + serverKeyCertChainPathStream = providerConnectionConfig.getKeyCertChainInputStream(); + serverPrivateKeyPathStream = providerConnectionConfig.getPrivateKeyInputStream(); + serverTrustCertStream = providerConnectionConfig.getTrustCertInputStream(); + String password = providerConnectionConfig.getPassword(); + if (password != null) { + sslClientContextBuilder = SslContextBuilder.forServer(serverKeyCertChainPathStream, + serverPrivateKeyPathStream, password); + } else { + sslClientContextBuilder = SslContextBuilder.forServer(serverKeyCertChainPathStream, + serverPrivateKeyPathStream); + } + + if (serverTrustCertStream != null) { + sslClientContextBuilder.trustManager(serverTrustCertStream); + if (providerConnectionConfig.getAuthPolicy() == AuthPolicy.CLIENT_AUTH) { + sslClientContextBuilder.clientAuth(ClientAuth.REQUIRE); + } else { + sslClientContextBuilder.clientAuth(ClientAuth.OPTIONAL); + } + } + } catch (Exception e) { + throw new IllegalArgumentException("Could not find certificate file or the certificate is invalid.", e); + } finally { + safeCloseStream(serverTrustCertStream); + safeCloseStream(serverKeyCertChainPathStream); + safeCloseStream(serverPrivateKeyPathStream); + } + try { + return sslClientContextBuilder.sslProvider(findSslProvider()).build(); + } catch (SSLException e) { + throw new IllegalStateException("Build SslSession failed.", e); + } + } + + public static SslContext buildClientSslContext(URL url) { + CertManager certManager = url.getOrDefaultFrameworkModel().getBeanFactory().getBean(CertManager.class); + Cert consumerConnectionConfig = certManager.getConsumerConnectionConfig(url); + if (consumerConnectionConfig == null) { + return null; + } + + SslContextBuilder builder = SslContextBuilder.forClient(); + InputStream clientTrustCertCollectionPath = null; + InputStream clientCertChainFilePath = null; + InputStream clientPrivateKeyFilePath = null; + try { + clientTrustCertCollectionPath = consumerConnectionConfig.getTrustCertInputStream(); + if (clientTrustCertCollectionPath != null) { + builder.trustManager(clientTrustCertCollectionPath); + } + + clientCertChainFilePath = consumerConnectionConfig.getKeyCertChainInputStream(); + clientPrivateKeyFilePath = consumerConnectionConfig.getPrivateKeyInputStream(); + if (clientCertChainFilePath != null && clientPrivateKeyFilePath != null) { + String password = consumerConnectionConfig.getPassword(); + if (password != null) { + builder.keyManager(clientCertChainFilePath, clientPrivateKeyFilePath, password); + } else { + builder.keyManager(clientCertChainFilePath, clientPrivateKeyFilePath); + } + } + } catch (Exception e) { + throw new IllegalArgumentException("Could not find certificate file or find invalid certificate.", e); + } finally { + safeCloseStream(clientTrustCertCollectionPath); + safeCloseStream(clientCertChainFilePath); + safeCloseStream(clientPrivateKeyFilePath); + } + try { + return builder.sslProvider(findSslProvider()).build(); + } catch (SSLException e) { + throw new IllegalStateException("Build SslSession failed.", e); + } + } + + /** + * Returns OpenSSL if available, otherwise returns the JDK provider. + */ + private static SslProvider findSslProvider() { + if (OpenSsl.isAvailable()) { + logger.debug("Using OPENSSL provider."); + return SslProvider.OPENSSL; + } + if (checkJdkProvider()) { + logger.debug("Using JDK provider."); + return SslProvider.JDK; + } + throw new IllegalStateException( + "Could not find any valid TLS provider, please check your dependency or deployment environment, " + + "usually netty-tcnative, Conscrypt, or Jetty NPN/ALPN is needed."); + } + + private static boolean checkJdkProvider() { + Provider[] jdkProviders = Security.getProviders("SSLContext.TLS"); + return (jdkProviders != null && jdkProviders.length > 0); + } + + private static void safeCloseStream(InputStream stream) { + if (stream == null) { + return; + } + try { + stream.close(); + } catch (IOException e) { + logger.warn(TRANSPORT_FAILED_CLOSE_STREAM, "", "", "Failed to close a stream.", e); + } + } + +} diff --git a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/netty/ssl/SslServerTlsHandler.java b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/netty/ssl/SslServerTlsHandler.java new file mode 100644 index 0000000000..756c429c40 --- /dev/null +++ b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/netty/ssl/SslServerTlsHandler.java @@ -0,0 +1,123 @@ +/* + * 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.protocol.rest.netty.ssl; + +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelPipeline; +import io.netty.handler.codec.ByteToMessageDecoder; +import io.netty.handler.ssl.SslContext; +import io.netty.handler.ssl.SslHandler; +import io.netty.handler.ssl.SslHandshakeCompletionEvent; +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.logger.ErrorTypeAwareLogger; +import org.apache.dubbo.common.logger.LoggerFactory; +import org.apache.dubbo.common.ssl.AuthPolicy; +import org.apache.dubbo.common.ssl.CertManager; +import org.apache.dubbo.common.ssl.ProviderCert; + +import javax.net.ssl.SSLSession; +import java.util.List; + +import static org.apache.dubbo.common.constants.LoggerCodeConstants.INTERNAL_ERROR; + +public class SslServerTlsHandler extends ByteToMessageDecoder { + private static final ErrorTypeAwareLogger logger = LoggerFactory.getErrorTypeAwareLogger(SslServerTlsHandler.class); + + private final URL url; + + private final boolean sslDetected; + + public SslServerTlsHandler(URL url) { + this.url = url; + this.sslDetected = false; + } + + public SslServerTlsHandler(URL url, boolean sslDetected) { + this.url = url; + this.sslDetected = sslDetected; + } + + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { + logger.error(INTERNAL_ERROR, "unknown error in remoting module", "", "TLS negotiation failed when trying to accept new connection.", cause); + } + + @Override + public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { + if (evt instanceof SslHandshakeCompletionEvent) { + SslHandshakeCompletionEvent handshakeEvent = (SslHandshakeCompletionEvent) evt; + if (handshakeEvent.isSuccess()) { + SSLSession session = ctx.pipeline().get(SslHandler.class).engine().getSession(); + logger.info("TLS negotiation succeed with: " + session.getPeerHost()); + // Remove after handshake success. + ctx.pipeline().remove(this); + } else { + logger.error(INTERNAL_ERROR, "", "", "TLS negotiation failed when trying to accept new connection.", handshakeEvent.cause()); + ctx.close(); + } + } + super.userEventTriggered(ctx, evt); + } + + @Override + protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List list) throws Exception { + // Will use the first five bytes to detect a protocol. + if (byteBuf.readableBytes() < 5) { + return; + } + + if (sslDetected) { + return; + } + + CertManager certManager = url.getOrDefaultFrameworkModel().getBeanFactory().getBean(CertManager.class); + ProviderCert providerConnectionConfig = certManager.getProviderConnectionConfig(url, channelHandlerContext.channel().remoteAddress()); + + if (providerConnectionConfig == null) { + ChannelPipeline p = channelHandlerContext.pipeline(); + p.remove(this); + return; + } + + if (isSsl(byteBuf)) { + SslContext sslContext = SslContexts.buildServerSslContext(providerConnectionConfig); + enableSsl(channelHandlerContext, sslContext); + return; + } + + if (providerConnectionConfig.getAuthPolicy() == AuthPolicy.NONE) { + ChannelPipeline p = channelHandlerContext.pipeline(); + p.remove(this); + } + + logger.error(INTERNAL_ERROR, "", "", "TLS negotiation failed when trying to accept new connection."); + channelHandlerContext.close(); + } + + private boolean isSsl(ByteBuf buf) { + return SslHandler.isEncrypted(buf); + } + + private void enableSsl(ChannelHandlerContext ctx, SslContext sslContext) { + ChannelPipeline p = ctx.pipeline(); + ctx.pipeline().addAfter(ctx.name(), null, sslContext.newHandler(ctx.alloc())); + p.addLast("unificationA", new SslServerTlsHandler(url, true)); + p.remove(this); + } + +} diff --git a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/util/ConstraintViolationExceptionConvert.java b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/util/ConstraintViolationExceptionConvert.java new file mode 100644 index 0000000000..df0e34f057 --- /dev/null +++ b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/util/ConstraintViolationExceptionConvert.java @@ -0,0 +1,53 @@ +/* + * 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.protocol.rest.util; + +import org.apache.dubbo.rpc.RpcException; +import org.apache.dubbo.rpc.protocol.rest.RestConstraintViolation; +import org.apache.dubbo.rpc.protocol.rest.ViolationReport; + +import javax.validation.ConstraintViolation; +import javax.validation.ConstraintViolationException; + +public class ConstraintViolationExceptionConvert { + + + + public static Object handleConstraintViolationException(RpcException rpcException) { + ConstraintViolationException cve = (ConstraintViolationException) rpcException.getCause(); + ViolationReport report = new ViolationReport(); + for (ConstraintViolation cv : cve.getConstraintViolations()) { + report.addConstraintViolation(new RestConstraintViolation( + cv.getPropertyPath().toString(), + cv.getMessage(), + cv.getInvalidValue() == null ? "null" : cv.getInvalidValue().toString())); + } + return report; + } + + public static boolean needConvert(RpcException e) { + return isConstraintViolationException(e); + } + + private static boolean isConstraintViolationException(RpcException e) { + try { + return e.getCause() instanceof ConstraintViolationException; + } catch (Throwable throwable) { + return false; + } + } +} diff --git a/dubbo-rpc/dubbo-rpc-rest/src/test/java/org/apache/dubbo/rpc/protocol/rest/JaxrsRestProtocolTest.java b/dubbo-rpc/dubbo-rpc-rest/src/test/java/org/apache/dubbo/rpc/protocol/rest/JaxrsRestProtocolTest.java index deca0a6937..c227ba68f2 100644 --- a/dubbo-rpc/dubbo-rpc-rest/src/test/java/org/apache/dubbo/rpc/protocol/rest/JaxrsRestProtocolTest.java +++ b/dubbo-rpc/dubbo-rpc-rest/src/test/java/org/apache/dubbo/rpc/protocol/rest/JaxrsRestProtocolTest.java @@ -46,8 +46,9 @@ import org.apache.dubbo.rpc.protocol.rest.rest.AnotherUserRestService; import org.apache.dubbo.rpc.protocol.rest.rest.AnotherUserRestServiceImpl; import org.apache.dubbo.rpc.protocol.rest.rest.HttpMethodService; import org.apache.dubbo.rpc.protocol.rest.rest.HttpMethodServiceImpl; - import org.apache.dubbo.rpc.protocol.rest.rest.RestDemoForTestException; +import org.apache.dubbo.rpc.protocol.rest.rest.RestDemoService; +import org.apache.dubbo.rpc.protocol.rest.rest.RestDemoServiceImpl; import org.hamcrest.CoreMatchers; import org.jboss.resteasy.specimpl.MultivaluedMapImpl; import org.junit.jupiter.api.AfterEach; @@ -60,7 +61,6 @@ import java.util.HashMap; import java.util.Map; import static org.apache.dubbo.remoting.Constants.SERVER_KEY; -import static org.apache.dubbo.rpc.protocol.rest.Constants.EXCEPTION_MAPPER_KEY; import static org.apache.dubbo.rpc.protocol.rest.Constants.EXTENSION_KEY; import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.is; @@ -561,6 +561,40 @@ class JaxrsRestProtocolTest { } } + @Test + void test405() { + int availablePort = NetUtils.getAvailablePort(); + URL url = URL.valueOf("rest://127.0.0.1:" + availablePort + + "/?version=1.0.0&interface=org.apache.dubbo.rpc.protocol.rest.rest.RestDemoService&" + ); + + RestDemoServiceImpl server = new RestDemoServiceImpl(); + + url = this.registerProvider(url, server, RestDemoService.class); + + Exporter exporter = protocol.export(proxy.getInvoker(server, RestDemoService.class, url)); + + URL consumer = URL.valueOf("rest://127.0.0.1:" + availablePort + + "/?version=1.0.0&interface=org.apache.dubbo.rpc.protocol.rest.rest.RestDemoForTestException&" + ); + + consumer = this.registerProvider(consumer, server, RestDemoForTestException.class); + + Invoker invoker = protocol.refer(RestDemoForTestException.class, consumer); + + + RestDemoForTestException client = proxy.getProxy(invoker); + + Assertions.assertThrows(RpcException.class, () -> { + client.testMethodDisallowed("aaa"); + + }); + + + invoker.destroy(); + exporter.unexport(); + } + private URL registerProvider(URL url, Object impl, Class interfaceClass) { ServiceDescriptor serviceDescriptor = repository.registerService(interfaceClass); ProviderModel providerModel = new ProviderModel( diff --git a/dubbo-rpc/dubbo-rpc-rest/src/test/java/org/apache/dubbo/rpc/protocol/rest/ServiceConfigTest.java b/dubbo-rpc/dubbo-rpc-rest/src/test/java/org/apache/dubbo/rpc/protocol/rest/ServiceConfigTest.java new file mode 100644 index 0000000000..e37f646c08 --- /dev/null +++ b/dubbo-rpc/dubbo-rpc-rest/src/test/java/org/apache/dubbo/rpc/protocol/rest/ServiceConfigTest.java @@ -0,0 +1,91 @@ +/* + * 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.protocol.rest; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.extension.ExtensionLoader; +import org.apache.dubbo.common.utils.NetUtils; +import org.apache.dubbo.remoting.http.RequestTemplate; +import org.apache.dubbo.remoting.http.config.HttpClientConfig; +import org.apache.dubbo.remoting.http.restclient.OKHttpRestClient; +import org.apache.dubbo.rpc.Exporter; +import org.apache.dubbo.rpc.Protocol; +import org.apache.dubbo.rpc.ProxyFactory; +import org.apache.dubbo.rpc.model.ApplicationModel; +import org.apache.dubbo.rpc.model.FrameworkModel; +import org.apache.dubbo.rpc.model.ModuleServiceRepository; +import org.apache.dubbo.rpc.model.ProviderModel; +import org.apache.dubbo.rpc.model.ServiceDescriptor; +import org.apache.dubbo.rpc.protocol.rest.constans.RestConstant; +import org.apache.dubbo.rpc.protocol.rest.mvc.SpringControllerService; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + + +public class ServiceConfigTest { + + private final Protocol protocol = ExtensionLoader.getExtensionLoader(Protocol.class).getExtension("rest"); + private final ProxyFactory proxy = ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension(); + private final ModuleServiceRepository repository = ApplicationModel.defaultModel().getDefaultModule().getServiceRepository(); + + @AfterEach + public void tearDown() { + protocol.destroy(); + FrameworkModel.destroyAll(); + } + + @Test + void testControllerService() throws Exception { + + int availablePort = NetUtils.getAvailablePort(); + URL url = URL.valueOf("rest://127.0.0.1:" + availablePort + "/?version=1.0.0&interface=org.apache.dubbo.rpc.protocol.rest.mvc.SpringControllerService"); + + SpringControllerService server = new SpringControllerService(); + + url = this.registerProvider(url, server, SpringControllerService.class); + + Exporter exporter = protocol.export(proxy.getInvoker(server, SpringControllerService.class, url)); + + OKHttpRestClient okHttpRestClient = new OKHttpRestClient(new HttpClientConfig()); + + RequestTemplate requestTemplate = new RequestTemplate(null, "GET", "127.0.0.1:" + availablePort); + requestTemplate.path("/controller/sayHello?say=dubbo"); + requestTemplate.addHeader(RestConstant.CONTENT_TYPE, "text/plain"); + requestTemplate.addHeader(RestConstant.ACCEPT, "text/plain"); + requestTemplate.addHeader(RestHeaderEnum.VERSION.getHeader(), "1.0.0"); + + byte[] body = okHttpRestClient.send(requestTemplate).get().getBody(); + + + Assertions.assertEquals("dubbo", new String(body)); + exporter.unexport(); + } + + + private URL registerProvider(URL url, Object impl, Class interfaceClass) { + ServiceDescriptor serviceDescriptor = repository.registerService(interfaceClass); + ProviderModel providerModel = new ProviderModel( + url.getServiceKey(), + impl, + serviceDescriptor, + null, + null); + repository.registerProvider(providerModel); + return url.setServiceModel(providerModel); + } +} diff --git a/dubbo-rpc/dubbo-rpc-rest/src/test/java/org/apache/dubbo/rpc/protocol/rest/mvc/SpringControllerService.java b/dubbo-rpc/dubbo-rpc-rest/src/test/java/org/apache/dubbo/rpc/protocol/rest/mvc/SpringControllerService.java new file mode 100644 index 0000000000..bf761196d4 --- /dev/null +++ b/dubbo-rpc/dubbo-rpc-rest/src/test/java/org/apache/dubbo/rpc/protocol/rest/mvc/SpringControllerService.java @@ -0,0 +1,29 @@ +/* + * 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.protocol.rest.mvc; + +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; + +@RequestMapping("/controller") +public class SpringControllerService { + + @GetMapping("/sayHello") + public String sayHello(String say) { + return say; + } +} diff --git a/dubbo-rpc/dubbo-rpc-rest/src/test/java/org/apache/dubbo/rpc/protocol/rest/rest/RestDemoForTestException.java b/dubbo-rpc/dubbo-rpc-rest/src/test/java/org/apache/dubbo/rpc/protocol/rest/rest/RestDemoForTestException.java index 718b665ce6..c6c36593f4 100644 --- a/dubbo-rpc/dubbo-rpc-rest/src/test/java/org/apache/dubbo/rpc/protocol/rest/rest/RestDemoForTestException.java +++ b/dubbo-rpc/dubbo-rpc-rest/src/test/java/org/apache/dubbo/rpc/protocol/rest/rest/RestDemoForTestException.java @@ -20,6 +20,7 @@ import javax.ws.rs.Consumes; import javax.ws.rs.GET; import javax.ws.rs.POST; import javax.ws.rs.Path; +import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; import javax.ws.rs.core.MediaType; @@ -36,4 +37,8 @@ public interface RestDemoForTestException { @Consumes({MediaType.TEXT_PLAIN}) @Path("/hello") Integer test400(@QueryParam("a")String a,@QueryParam("b") String b); + + @POST + @Path("{uid}") + String testMethodDisallowed(@PathParam("uid") String uid); } diff --git a/dubbo-rpc/dubbo-rpc-rest/src/test/java/org/apache/dubbo/rpc/protocol/rest/rest/RestDemoService.java b/dubbo-rpc/dubbo-rpc-rest/src/test/java/org/apache/dubbo/rpc/protocol/rest/rest/RestDemoService.java index 4f04bd3894..c423bbf3cf 100644 --- a/dubbo-rpc/dubbo-rpc-rest/src/test/java/org/apache/dubbo/rpc/protocol/rest/rest/RestDemoService.java +++ b/dubbo-rpc/dubbo-rpc-rest/src/test/java/org/apache/dubbo/rpc/protocol/rest/rest/RestDemoService.java @@ -42,4 +42,8 @@ public interface RestDemoService { Long testFormBody(@FormParam("number") Long number); boolean isCalled(); + + @DELETE + @Path("{uid}") + String deleteUserByUid(@PathParam("uid") String uid); } diff --git a/dubbo-rpc/dubbo-rpc-rest/src/test/java/org/apache/dubbo/rpc/protocol/rest/rest/RestDemoServiceImpl.java b/dubbo-rpc/dubbo-rpc-rest/src/test/java/org/apache/dubbo/rpc/protocol/rest/rest/RestDemoServiceImpl.java index bed70b7657..3ba0858b23 100644 --- a/dubbo-rpc/dubbo-rpc-rest/src/test/java/org/apache/dubbo/rpc/protocol/rest/rest/RestDemoServiceImpl.java +++ b/dubbo-rpc/dubbo-rpc-rest/src/test/java/org/apache/dubbo/rpc/protocol/rest/rest/RestDemoServiceImpl.java @@ -42,6 +42,11 @@ public class RestDemoServiceImpl implements RestDemoService { return called; } + @Override + public String deleteUserByUid(String uid) { + return uid; + } + @Override public Integer hello(Integer a, Integer b) { context = RpcContext.getServerAttachment().getObjectAttachments(); diff --git a/dubbo-rpc/dubbo-rpc-triple/pom.xml b/dubbo-rpc/dubbo-rpc-triple/pom.xml index 8a5a5fe380..a101d9fad9 100644 --- a/dubbo-rpc/dubbo-rpc-triple/pom.xml +++ b/dubbo-rpc/dubbo-rpc-triple/pom.xml @@ -22,6 +22,7 @@ org.apache.dubbo dubbo-rpc ${revision} + ../pom.xml dubbo-rpc-triple jar @@ -29,10 +30,6 @@ The triple protocol module false - 0.0.4.1-SNAPSHOT - 1.0.4 - 3.5.4 - 3.22.2 @@ -53,7 +50,6 @@ com.google.protobuf protobuf-java - ${protobuf-java.version} org.springframework @@ -79,7 +75,6 @@ io.reactivex.rxjava2 rxjava - 2.2.21 test @@ -89,7 +84,6 @@ io.projectreactor reactor-core - ${reactor.version} test @@ -98,7 +92,7 @@ kr.motd.maven os-maven-plugin - 1.7.1 + ${maven_os_plugin_version} initialize @@ -111,10 +105,10 @@ org.xolstice.maven.plugins protobuf-maven-plugin - 0.6.1 + ${maven_protobuf_plugin_version} - com.google.protobuf:protoc:${protobuf-java.version}:exe:${os.detected.classifier} + com.google.protobuf:protoc:${protobuf-java_version}:exe:${os.detected.classifier} diff --git a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/DefaultPackableMethodFactory.java b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/DefaultPackableMethodFactory.java new file mode 100644 index 0000000000..36fb31f736 --- /dev/null +++ b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/DefaultPackableMethodFactory.java @@ -0,0 +1,32 @@ +/* + * 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.protocol.tri; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.rpc.model.MethodDescriptor; +import org.apache.dubbo.rpc.model.PackableMethod; +import org.apache.dubbo.rpc.model.PackableMethodFactory; + +public class DefaultPackableMethodFactory implements PackableMethodFactory { + + @Override + public PackableMethod create(MethodDescriptor methodDescriptor, URL url, String contentType) { + return ReflectionPackableMethod.init(methodDescriptor, url); + } + +} diff --git a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/model/key/MetricsPlaceType.java b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/PbArrayPacker.java similarity index 59% rename from dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/model/key/MetricsPlaceType.java rename to dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/PbArrayPacker.java index 744cd55007..9a20d29f40 100644 --- a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/model/key/MetricsPlaceType.java +++ b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/PbArrayPacker.java @@ -15,27 +15,27 @@ * limitations under the License. */ -package org.apache.dubbo.metrics.model.key; +package org.apache.dubbo.rpc.protocol.tri; -public class MetricsPlaceType { +import com.google.protobuf.Message; +import org.apache.dubbo.rpc.model.Pack; - private final String type; - private final MetricsLevel metricsLevel; +public class PbArrayPacker implements Pack { - private MetricsPlaceType(String type, MetricsLevel metricsLevel) { - this.type = type; - this.metricsLevel = metricsLevel; + private static final Pack PB_PACK = o -> ((Message) o).toByteArray(); + + private final boolean singleArgument; + + public PbArrayPacker(boolean singleArgument) { + this.singleArgument = singleArgument; } - public static MetricsPlaceType of(String type, MetricsLevel metricsLevel) { - return new MetricsPlaceType(type, metricsLevel); + @Override + public byte[] pack(Object obj) throws Exception { + if (!singleArgument) { + obj = ((Object[]) obj)[0]; + } + return PB_PACK.pack(obj); } - public String getType() { - return type; - } - - public MetricsLevel getMetricsLevel() { - return metricsLevel; - } } diff --git a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/PbUnpack.java b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/PbUnpack.java index 51d5ea8227..f2aaa69dd0 100644 --- a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/PbUnpack.java +++ b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/PbUnpack.java @@ -17,12 +17,12 @@ package org.apache.dubbo.rpc.protocol.tri; -import org.apache.dubbo.rpc.model.PackableMethod; +import org.apache.dubbo.rpc.model.UnPack; import java.io.ByteArrayInputStream; import java.io.IOException; -public class PbUnpack implements PackableMethod.UnPack { +public class PbUnpack implements UnPack { private final Class clz; diff --git a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/ReflectionPackableMethod.java b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/ReflectionPackableMethod.java index ae647e5ca6..da3e67dfa4 100644 --- a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/ReflectionPackableMethod.java +++ b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/ReflectionPackableMethod.java @@ -25,9 +25,12 @@ import org.apache.dubbo.config.Constants; import org.apache.dubbo.remoting.utils.UrlUtils; import org.apache.dubbo.remoting.transport.CodecSupport; import org.apache.dubbo.rpc.model.MethodDescriptor; +import org.apache.dubbo.rpc.model.Pack; import org.apache.dubbo.rpc.model.PackableMethod; import com.google.protobuf.Message; +import org.apache.dubbo.rpc.model.UnPack; +import org.apache.dubbo.rpc.model.WrapperUnPack; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; @@ -115,11 +118,11 @@ public class ReflectionPackableMethod implements PackableMethod { } public static ReflectionPackableMethod init(MethodDescriptor methodDescriptor, URL url) { - final String serializeName = UrlUtils.serializationOrDefault(url); Object stored = methodDescriptor.getAttribute(METHOD_ATTR_PACK); if (stored != null) { return (ReflectionPackableMethod) stored; } + final String serializeName = UrlUtils.serializationOrDefault(url); final Collection allSerialize = UrlUtils.allSerializations(url); ReflectionPackableMethod reflectionPackableMethod = new ReflectionPackableMethod( methodDescriptor, url, serializeName, allSerialize); @@ -448,23 +451,6 @@ public class ReflectionPackableMethod implements PackableMethod { } - private static class PbArrayPacker implements Pack { - - private final boolean singleArgument; - - private PbArrayPacker(boolean singleArgument) { - this.singleArgument = singleArgument; - } - - @Override - public byte[] pack(Object obj) throws IOException { - if (!singleArgument) { - obj = ((Object[]) obj)[0]; - } - return PB_PACK.pack(obj); - } - } - private class WrapRequestUnpack implements WrapperUnPack { private final MultipleSerialization serialization; diff --git a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/TripleInvoker.java b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/TripleInvoker.java index 94713b3498..b6bad67e5f 100644 --- a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/TripleInvoker.java +++ b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/TripleInvoker.java @@ -42,6 +42,7 @@ import org.apache.dubbo.rpc.model.ApplicationModel; import org.apache.dubbo.rpc.model.ConsumerModel; import org.apache.dubbo.rpc.model.MethodDescriptor; import org.apache.dubbo.rpc.model.PackableMethod; +import org.apache.dubbo.rpc.model.PackableMethodFactory; import org.apache.dubbo.rpc.model.ScopeModelUtil; import org.apache.dubbo.rpc.model.ServiceDescriptor; import org.apache.dubbo.rpc.model.StubMethodDescriptor; @@ -66,6 +67,8 @@ import java.util.concurrent.Executor; import java.util.concurrent.ExecutorService; import java.util.concurrent.locks.ReentrantLock; +import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.DUBBO_PACKABLE_METHOD_FACTORY; import static org.apache.dubbo.common.constants.CommonConstants.GROUP_KEY; import static org.apache.dubbo.common.constants.CommonConstants.INTERFACE_KEY; import static org.apache.dubbo.common.constants.CommonConstants.TIMEOUT_KEY; @@ -260,7 +263,9 @@ public class TripleInvoker extends AbstractInvoker { if (methodDescriptor instanceof PackableMethod) { meta.packableMethod = (PackableMethod) methodDescriptor; } else { - meta.packableMethod = ReflectionPackableMethod.init(methodDescriptor, url); + meta.packableMethod = url.getOrDefaultFrameworkModel().getExtensionLoader(PackableMethodFactory.class) + .getExtension(ConfigurationUtils.getGlobalConfiguration(url.getApplicationModel()).getString(DUBBO_PACKABLE_METHOD_FACTORY, DEFAULT_KEY)) + .create(methodDescriptor, url, TripleConstant.CONTENT_PROTO); } meta.convertNoLowerHeader = TripleProtocol.CONVERT_NO_LOWER_HEADER; meta.ignoreDefaultVersion = TripleProtocol.IGNORE_1_0_0_VERSION; diff --git a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/call/AbstractServerCall.java b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/call/AbstractServerCall.java index 026031c8d4..623e731ec4 100644 --- a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/call/AbstractServerCall.java +++ b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/call/AbstractServerCall.java @@ -45,7 +45,6 @@ import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http2.DefaultHttp2Headers; import io.netty.util.concurrent.Future; -import java.io.IOException; import java.util.Map; import java.util.Objects; import java.util.concurrent.Executor; @@ -225,8 +224,7 @@ public abstract class AbstractServerCall implements ServerCall, ServerStream.Lis } } - protected abstract Object parseSingleMessage(byte[] data) - throws IOException, ClassNotFoundException; + protected abstract Object parseSingleMessage(byte[] data) throws Exception; @Override public final void onCancelByRemote(TriRpcStatus status) { diff --git a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/call/ReflectionAbstractServerCall.java b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/call/ReflectionAbstractServerCall.java index 214edbe3ea..7789474a70 100644 --- a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/call/ReflectionAbstractServerCall.java +++ b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/call/ReflectionAbstractServerCall.java @@ -17,7 +17,9 @@ package org.apache.dubbo.rpc.protocol.tri.call; +import io.netty.handler.codec.http.HttpHeaderNames; import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.config.ConfigurationUtils; import org.apache.dubbo.common.constants.CommonConstants; import org.apache.dubbo.common.utils.CollectionUtils; import org.apache.dubbo.rpc.HeaderFilter; @@ -27,19 +29,21 @@ import org.apache.dubbo.rpc.TriRpcStatus; import org.apache.dubbo.rpc.model.FrameworkModel; import org.apache.dubbo.rpc.model.MethodDescriptor; import org.apache.dubbo.rpc.model.MethodDescriptor.RpcType; +import org.apache.dubbo.rpc.model.PackableMethodFactory; import org.apache.dubbo.rpc.model.ProviderModel; import org.apache.dubbo.rpc.model.ServiceDescriptor; import org.apache.dubbo.rpc.protocol.tri.ClassLoadUtil; -import org.apache.dubbo.rpc.protocol.tri.ReflectionPackableMethod; import org.apache.dubbo.rpc.protocol.tri.TripleCustomerProtocolWapper; import org.apache.dubbo.rpc.protocol.tri.stream.ServerStream; import org.apache.dubbo.rpc.service.ServiceDescriptorInternalCache; -import java.io.IOException; import java.util.Arrays; import java.util.List; import java.util.concurrent.Executor; +import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.DUBBO_PACKABLE_METHOD_FACTORY; + public class ReflectionAbstractServerCall extends AbstractServerCall { private final List headerFilters; @@ -116,7 +120,10 @@ public class ReflectionAbstractServerCall extends AbstractServerCall { } } if (methodDescriptor != null) { - packableMethod = ReflectionPackableMethod.init(methodDescriptor, invoker.getUrl()); + final URL url = invoker.getUrl(); + packableMethod = frameworkModel.getExtensionLoader(PackableMethodFactory.class) + .getExtension(ConfigurationUtils.getGlobalConfiguration(url.getApplicationModel()).getString(DUBBO_PACKABLE_METHOD_FACTORY, DEFAULT_KEY)) + .create(methodDescriptor, url, (String) requestMetadata.get(HttpHeaderNames.CONTENT_TYPE.toString())); } trySetListener(); if (listener == null) { @@ -148,8 +155,7 @@ public class ReflectionAbstractServerCall extends AbstractServerCall { } @Override - protected Object parseSingleMessage(byte[] data) - throws IOException, ClassNotFoundException { + protected Object parseSingleMessage(byte[] data) throws Exception { trySetMethodDescriptor(data); trySetListener(); if (isClosed()) { @@ -161,7 +167,7 @@ public class ReflectionAbstractServerCall extends AbstractServerCall { } - private void trySetMethodDescriptor(byte[] data) throws IOException { + private void trySetMethodDescriptor(byte[] data) { if (methodDescriptor != null) { return; } @@ -185,7 +191,10 @@ public class ReflectionAbstractServerCall extends AbstractServerCall { + serviceDescriptor.getInterfaceName()), null); return; } - packableMethod = ReflectionPackableMethod.init(methodDescriptor, invoker.getUrl()); + final URL url = invoker.getUrl(); + packableMethod = frameworkModel.getExtensionLoader(PackableMethodFactory.class) + .getExtension(ConfigurationUtils.getGlobalConfiguration(url.getApplicationModel()).getString(DUBBO_PACKABLE_METHOD_FACTORY, DEFAULT_KEY)) + .create(methodDescriptor, url, (String) requestMetadata.get(HttpHeaderNames.CONTENT_TYPE.toString())); } } diff --git a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/call/StubAbstractServerCall.java b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/call/StubAbstractServerCall.java index 20b5f80a2c..6f5027abfa 100644 --- a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/call/StubAbstractServerCall.java +++ b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/call/StubAbstractServerCall.java @@ -25,7 +25,6 @@ import org.apache.dubbo.rpc.model.StubMethodDescriptor; import org.apache.dubbo.rpc.protocol.tri.stream.ServerStream; import org.apache.dubbo.rpc.stub.StubSuppliers; -import java.io.IOException; import java.util.concurrent.Executor; public class StubAbstractServerCall extends AbstractServerCall { @@ -58,7 +57,7 @@ public class StubAbstractServerCall extends AbstractServerCall { } @Override - protected Object parseSingleMessage(byte[] data) throws IOException, ClassNotFoundException { + protected Object parseSingleMessage(byte[] data) throws Exception { return packableMethod.parseRequest(data); } diff --git a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/stream/StreamUtils.java b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/stream/StreamUtils.java index 68807a45ec..07def88303 100644 --- a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/stream/StreamUtils.java +++ b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/stream/StreamUtils.java @@ -100,10 +100,13 @@ public class StreamUtils { if (TripleHeaderEnum.containsExcludeAttachments(key)) { continue; } + final Object v = entry.getValue(); + if (v == null) { + continue; + } if (needConvertHeaderKey && !key.equals(entry.getKey())) { needConvertKey.put(key, entry.getKey()); } - final Object v = entry.getValue(); convertSingleAttachment(headers, key, v); } if (!needConvertKey.isEmpty()) { diff --git a/dubbo-rpc/dubbo-rpc-triple/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.model.PackableMethodFactory b/dubbo-rpc/dubbo-rpc-triple/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.model.PackableMethodFactory new file mode 100644 index 0000000000..31e8c7ef9c --- /dev/null +++ b/dubbo-rpc/dubbo-rpc-triple/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.model.PackableMethodFactory @@ -0,0 +1 @@ +default=org.apache.dubbo.rpc.protocol.tri.DefaultPackableMethodFactory diff --git a/dubbo-rpc/dubbo-rpc-triple/src/test/java/org/apache/dubbo/rpc/protocol/tri/call/StubServerCallTest.java b/dubbo-rpc/dubbo-rpc-triple/src/test/java/org/apache/dubbo/rpc/protocol/tri/call/StubServerCallTest.java index 98949a9237..e957092140 100644 --- a/dubbo-rpc/dubbo-rpc-triple/src/test/java/org/apache/dubbo/rpc/protocol/tri/call/StubServerCallTest.java +++ b/dubbo-rpc/dubbo-rpc-triple/src/test/java/org/apache/dubbo/rpc/protocol/tri/call/StubServerCallTest.java @@ -30,7 +30,6 @@ import io.netty.util.concurrent.ImmediateEventExecutor; import org.junit.jupiter.api.Test; import org.mockito.Mockito; -import java.io.IOException; import java.util.Collections; import static org.mockito.ArgumentMatchers.any; @@ -40,7 +39,7 @@ import static org.mockito.Mockito.when; class StubServerCallTest { @Test - void doStartCall() throws IOException, ClassNotFoundException { + void doStartCall() throws Exception { Invoker invoker = Mockito.mock(Invoker.class); TripleServerStream tripleServerStream = Mockito.mock(TripleServerStream.class); ProviderModel providerModel = Mockito.mock(ProviderModel.class); diff --git a/dubbo-spring-boot/dubbo-spring-boot-observability-starter/pom.xml b/dubbo-spring-boot/dubbo-spring-boot-observability-starters/autoconfigure/pom.xml similarity index 63% rename from dubbo-spring-boot/dubbo-spring-boot-observability-starter/pom.xml rename to dubbo-spring-boot/dubbo-spring-boot-observability-starters/autoconfigure/pom.xml index ce72ee602b..1f6e2f01b1 100644 --- a/dubbo-spring-boot/dubbo-spring-boot-observability-starter/pom.xml +++ b/dubbo-spring-boot/dubbo-spring-boot-observability-starters/autoconfigure/pom.xml @@ -19,40 +19,17 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + dubbo-spring-boot-observability-starters org.apache.dubbo - dubbo-spring-boot ${revision} ../pom.xml 4.0.0 - dubbo-spring-boot-observability-starter - - - 1.10.6 - 1.0.3 - - - - - - io.micrometer - micrometer-bom - ${micrometer.version} - pom - import - - - io.micrometer - micrometer-tracing-bom - ${micrometer-tracing.version} - pom - import - - - + dubbo-spring-boot-observability-autoconfigure + io.micrometer micrometer-tracing @@ -69,14 +46,12 @@ io.micrometer micrometer-registry-prometheus - - io.prometheus - simpleclient_pushgateway - com.tdunning t-digest + + org.springframework.boot spring-boot-autoconfigure @@ -87,6 +62,28 @@ spring-boot-configuration-processor true + + org.springframework + spring-webmvc + true + + + org.springframework + spring-webflux + true + + + org.springframework.boot + spring-boot-test + test + + + org.assertj + assertj-core + test + + + io.micrometer micrometer-tracing-bridge-otel @@ -97,6 +94,27 @@ micrometer-tracing-bridge-brave true + + + + io.opentelemetry + opentelemetry-exporter-zipkin + true + + + io.zipkin.reporter2 + zipkin-reporter-brave + true + + + + + io.zipkin.reporter2 + zipkin-sender-urlconnection + true + + + org.apache.dubbo dubbo-spring-boot-starter @@ -108,6 +126,22 @@ ${project.version} true + + org.apache.dubbo + dubbo-qos + ${project.version} + true + + + + + io.prometheus + simpleclient + + + io.prometheus + simpleclient_pushgateway + - + \ No newline at end of file diff --git a/dubbo-spring-boot/dubbo-spring-boot-observability-starter/src/main/java/org/apache/dubbo/spring/boot/observability/autoconfigure/DubboMicrometerTracingAutoConfiguration.java b/dubbo-spring-boot/dubbo-spring-boot-observability-starters/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/observability/autoconfigure/DubboMicrometerTracingAutoConfiguration.java similarity index 94% rename from dubbo-spring-boot/dubbo-spring-boot-observability-starter/src/main/java/org/apache/dubbo/spring/boot/observability/autoconfigure/DubboMicrometerTracingAutoConfiguration.java rename to dubbo-spring-boot/dubbo-spring-boot-observability-starters/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/observability/autoconfigure/DubboMicrometerTracingAutoConfiguration.java index ed2553c664..4c8adef1e3 100644 --- a/dubbo-spring-boot/dubbo-spring-boot-observability-starter/src/main/java/org/apache/dubbo/spring/boot/observability/autoconfigure/DubboMicrometerTracingAutoConfiguration.java +++ b/dubbo-spring-boot/dubbo-spring-boot-observability-starters/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/observability/autoconfigure/DubboMicrometerTracingAutoConfiguration.java @@ -16,7 +16,8 @@ */ package org.apache.dubbo.spring.boot.observability.autoconfigure; -import org.apache.dubbo.spring.boot.observability.annotation.ConditionalOnDubboTracingEnable; +import org.apache.dubbo.spring.boot.observability.autoconfigure.annotation.ConditionalOnDubboTracingEnable; + import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; @@ -29,19 +30,19 @@ import org.springframework.core.annotation.Order; * this class is available starting from Boot 3.0. It's not available if you're using Boot < 3.0 */ @ConditionalOnDubboTracingEnable -@ConditionalOnClass(name = {"io.micrometer.observation.Observation","io.micrometer.tracing.Tracer","io.micrometer.tracing.propagation.Propagator"}) +@ConditionalOnClass(name = {"io.micrometer.observation.Observation", "io.micrometer.tracing.Tracer", "io.micrometer.tracing.propagation.Propagator"}) @AutoConfigureAfter(name = "org.springframework.boot.actuate.autoconfigure.tracing.MicrometerTracingAutoConfiguration") public class DubboMicrometerTracingAutoConfiguration { /** * {@code @Order} value of - * {@link #propagatingReceiverTracingObservationHandler(io.micrometer.tracing.Tracer, io.micrometer.tracing.propagation.Propagator )}. + * {@link #propagatingReceiverTracingObservationHandler(io.micrometer.tracing.Tracer, io.micrometer.tracing.propagation.Propagator)}. */ public static final int RECEIVER_TRACING_OBSERVATION_HANDLER_ORDER = 1000; /** * {@code @Order} value of - * {@link #propagatingSenderTracingObservationHandler(io.micrometer.tracing.Tracer, io.micrometer.tracing.propagation.Propagator )}. + * {@link #propagatingSenderTracingObservationHandler(io.micrometer.tracing.Tracer, io.micrometer.tracing.propagation.Propagator)}. */ public static final int SENDER_TRACING_OBSERVATION_HANDLER_ORDER = 2000; diff --git a/dubbo-spring-boot/dubbo-spring-boot-observability-starter/src/main/java/org/apache/dubbo/spring/boot/observability/autoconfigure/DubboObservationAutoConfiguration.java b/dubbo-spring-boot/dubbo-spring-boot-observability-starters/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/observability/autoconfigure/DubboObservationAutoConfiguration.java similarity index 95% rename from dubbo-spring-boot/dubbo-spring-boot-observability-starter/src/main/java/org/apache/dubbo/spring/boot/observability/autoconfigure/DubboObservationAutoConfiguration.java rename to dubbo-spring-boot/dubbo-spring-boot-observability-starters/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/observability/autoconfigure/DubboObservationAutoConfiguration.java index f87c7787a8..37f552fadf 100644 --- a/dubbo-spring-boot/dubbo-spring-boot-observability-starter/src/main/java/org/apache/dubbo/spring/boot/observability/autoconfigure/DubboObservationAutoConfiguration.java +++ b/dubbo-spring-boot/dubbo-spring-boot-observability-starters/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/observability/autoconfigure/DubboObservationAutoConfiguration.java @@ -16,21 +16,19 @@ */ package org.apache.dubbo.spring.boot.observability.autoconfigure; -import io.micrometer.core.instrument.MeterRegistry; - import org.apache.dubbo.common.logger.ErrorTypeAwareLogger; import org.apache.dubbo.common.logger.LoggerFactory; import org.apache.dubbo.qos.protocol.QosProtocolWrapper; import org.apache.dubbo.rpc.model.ApplicationModel; -import org.apache.dubbo.spring.boot.observability.annotation.ConditionalOnDubboTracingEnable; +import org.apache.dubbo.spring.boot.observability.autoconfigure.annotation.ConditionalOnDubboTracingEnable; +import io.micrometer.core.instrument.MeterRegistry; import org.springframework.beans.BeansException; import org.springframework.beans.factory.BeanFactory; -import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.beans.factory.BeanFactoryAware; +import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.beans.factory.ObjectProvider; import org.springframework.beans.factory.SmartInitializingSingleton; - import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; @@ -128,7 +126,7 @@ public class DubboObservationAutoConfiguration implements BeanFactoryAware, Smar @ConditionalOnClass(name = {"io.micrometer.tracing.handler.TracingObservationHandler", "io.micrometer.core.instrument.observation.MeterObservationHandler"}) ObservationHandlerGrouping metricsAndTracingObservationHandlerGrouping() { return new ObservationHandlerGrouping( - Arrays.asList(io.micrometer.tracing.handler.TracingObservationHandler.class, io.micrometer.core.instrument.observation.MeterObservationHandler.class)); + Arrays.asList(io.micrometer.tracing.handler.TracingObservationHandler.class, io.micrometer.core.instrument.observation.MeterObservationHandler.class)); } } @@ -157,7 +155,7 @@ public class DubboObservationAutoConfiguration implements BeanFactoryAware, Smar @Bean @ConditionalOnClass(name = {"io.micrometer.tracing.handler.TracingAwareMeterObservationHandler", "io.micrometer.tracing.Tracer"}) io.micrometer.tracing.handler.TracingAwareMeterObservationHandler tracingAwareMeterObservationHandler( - MeterRegistry meterRegistry, io.micrometer.tracing.Tracer tracer) { + MeterRegistry meterRegistry, io.micrometer.tracing.Tracer tracer) { io.micrometer.core.instrument.observation.DefaultMeterObservationHandler delegate = new io.micrometer.core.instrument.observation.DefaultMeterObservationHandler(meterRegistry); return new io.micrometer.tracing.handler.TracingAwareMeterObservationHandler<>(delegate, tracer); } diff --git a/dubbo-spring-boot/dubbo-spring-boot-observability-starter/src/main/java/org/apache/dubbo/spring/boot/observability/autoconfigure/ObservabilityUtils.java b/dubbo-spring-boot/dubbo-spring-boot-observability-starters/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/observability/autoconfigure/ObservabilityUtils.java similarity index 83% rename from dubbo-spring-boot/dubbo-spring-boot-observability-starter/src/main/java/org/apache/dubbo/spring/boot/observability/autoconfigure/ObservabilityUtils.java rename to dubbo-spring-boot/dubbo-spring-boot-observability-starters/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/observability/autoconfigure/ObservabilityUtils.java index 56ab8ec442..2d5b7e5284 100644 --- a/dubbo-spring-boot/dubbo-spring-boot-observability-starter/src/main/java/org/apache/dubbo/spring/boot/observability/autoconfigure/ObservabilityUtils.java +++ b/dubbo-spring-boot/dubbo-spring-boot-observability-starters/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/observability/autoconfigure/ObservabilityUtils.java @@ -26,14 +26,16 @@ import static org.apache.dubbo.spring.boot.util.DubboUtils.PROPERTY_NAME_SEPARAT */ public class ObservabilityUtils { - public static final String DUBBO_TRACING_PREFIX = DUBBO_PREFIX + PROPERTY_NAME_SEPARATOR + "tracing" + PROPERTY_NAME_SEPARATOR; + public static final String DUBBO_TRACING_PREFIX = DUBBO_PREFIX + PROPERTY_NAME_SEPARATOR + "tracing"; - public static final String DUBBO_TRACING_PROPAGATION = DUBBO_TRACING_PREFIX + "propagation"; + public static final String DUBBO_TRACING_PROPAGATION = DUBBO_TRACING_PREFIX + PROPERTY_NAME_SEPARATOR + "propagation"; - public static final String DUBBO_TRACING_BAGGAGE = DUBBO_TRACING_PREFIX + "baggage"; + public static final String DUBBO_TRACING_BAGGAGE = DUBBO_TRACING_PREFIX + PROPERTY_NAME_SEPARATOR + "baggage"; public static final String DUBBO_TRACING_BAGGAGE_CORRELATION = DUBBO_TRACING_BAGGAGE + PROPERTY_NAME_SEPARATOR + "correlation"; public static final String DUBBO_TRACING_BAGGAGE_ENABLED = DUBBO_TRACING_BAGGAGE + PROPERTY_NAME_SEPARATOR + "enabled"; + public static final String DUBBO_TRACING_ZIPKIN_CONFIG_PREFIX = DUBBO_TRACING_PREFIX + PROPERTY_NAME_SEPARATOR + "tracing-exporter.zipkin-config"; + } diff --git a/dubbo-spring-boot/dubbo-spring-boot-observability-starter/src/main/java/org/apache/dubbo/spring/boot/observability/autoconfigure/ObservationHandlerGrouping.java b/dubbo-spring-boot/dubbo-spring-boot-observability-starters/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/observability/autoconfigure/ObservationHandlerGrouping.java similarity index 100% rename from dubbo-spring-boot/dubbo-spring-boot-observability-starter/src/main/java/org/apache/dubbo/spring/boot/observability/autoconfigure/ObservationHandlerGrouping.java rename to dubbo-spring-boot/dubbo-spring-boot-observability-starters/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/observability/autoconfigure/ObservationHandlerGrouping.java diff --git a/dubbo-spring-boot/dubbo-spring-boot-observability-starter/src/main/java/org/apache/dubbo/spring/boot/observability/autoconfigure/ObservationRegistryPostProcessor.java b/dubbo-spring-boot/dubbo-spring-boot-observability-starters/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/observability/autoconfigure/ObservationRegistryPostProcessor.java similarity index 87% rename from dubbo-spring-boot/dubbo-spring-boot-observability-starter/src/main/java/org/apache/dubbo/spring/boot/observability/autoconfigure/ObservationRegistryPostProcessor.java rename to dubbo-spring-boot/dubbo-spring-boot-observability-starters/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/observability/autoconfigure/ObservationRegistryPostProcessor.java index 47344b3f40..1d315c2b9a 100644 --- a/dubbo-spring-boot/dubbo-spring-boot-observability-starter/src/main/java/org/apache/dubbo/spring/boot/observability/autoconfigure/ObservationRegistryPostProcessor.java +++ b/dubbo-spring-boot/dubbo-spring-boot-observability-starters/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/observability/autoconfigure/ObservationRegistryPostProcessor.java @@ -33,20 +33,21 @@ public class ObservationRegistryPostProcessor implements BeanPostProcessor { private final ObjectProvider> observationHandlers; public ObservationRegistryPostProcessor(ObjectProvider observationHandlerGrouping, - ObjectProvider> observationHandlers){ + ObjectProvider> observationHandlers) { this.observationHandlerGrouping = observationHandlerGrouping; this.observationHandlers = observationHandlers; } + @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { - if(bean instanceof ObservationRegistry){ + if (bean instanceof ObservationRegistry) { ObservationRegistry observationRegistry = (ObservationRegistry) bean; List> observationHandlerList = - observationHandlers.orderedStream().collect(Collectors.toList()); - observationHandlerGrouping.ifAvailable(grouping->{ + observationHandlers.orderedStream().collect(Collectors.toList()); + observationHandlerGrouping.ifAvailable(grouping -> { grouping.apply(observationHandlerList, - observationRegistry.observationConfig()); + observationRegistry.observationConfig()); }); } return bean; diff --git a/dubbo-spring-boot/dubbo-spring-boot-observability-starters/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/observability/autoconfigure/annotation/ConditionalOnDubboTracingEnable.java b/dubbo-spring-boot/dubbo-spring-boot-observability-starters/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/observability/autoconfigure/annotation/ConditionalOnDubboTracingEnable.java new file mode 100644 index 0000000000..eaa7d28e15 --- /dev/null +++ b/dubbo-spring-boot/dubbo-spring-boot-observability-starters/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/observability/autoconfigure/annotation/ConditionalOnDubboTracingEnable.java @@ -0,0 +1,43 @@ +/* + * 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.spring.boot.observability.autoconfigure.annotation; + +import org.apache.dubbo.spring.boot.observability.autoconfigure.ObservabilityUtils; + +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Checks whether tracing is enabled. + * It matches if the value of the {@code dubbo.tracing.enabled} property is {@code true} or if it + * is not configured. + * + * @since 3.2.0 + */ +@Target({ElementType.TYPE, ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +@Inherited +@Documented +@ConditionalOnProperty(prefix = ObservabilityUtils.DUBBO_TRACING_PREFIX, name = "enabled", matchIfMissing = true) +public @interface ConditionalOnDubboTracingEnable { +} diff --git a/dubbo-spring-boot/dubbo-spring-boot-observability-starter/src/main/java/org/apache/dubbo/spring/boot/observability/autoconfigure/brave/BraveAutoConfiguration.java b/dubbo-spring-boot/dubbo-spring-boot-observability-starters/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/observability/autoconfigure/brave/BraveAutoConfiguration.java similarity index 84% rename from dubbo-spring-boot/dubbo-spring-boot-observability-starter/src/main/java/org/apache/dubbo/spring/boot/observability/autoconfigure/brave/BraveAutoConfiguration.java rename to dubbo-spring-boot/dubbo-spring-boot-observability-starters/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/observability/autoconfigure/brave/BraveAutoConfiguration.java index b3c0bc7f8f..24be95c4ec 100644 --- a/dubbo-spring-boot/dubbo-spring-boot-observability-starter/src/main/java/org/apache/dubbo/spring/boot/observability/autoconfigure/brave/BraveAutoConfiguration.java +++ b/dubbo-spring-boot/dubbo-spring-boot-observability-starters/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/observability/autoconfigure/brave/BraveAutoConfiguration.java @@ -16,12 +16,13 @@ */ package org.apache.dubbo.spring.boot.observability.autoconfigure.brave; - - +import org.apache.dubbo.config.ApplicationConfig; +import org.apache.dubbo.rpc.model.ModuleModel; import org.apache.dubbo.spring.boot.autoconfigure.DubboConfigurationProperties; -import org.apache.dubbo.spring.boot.observability.annotation.ConditionalOnDubboTracingEnable; import org.apache.dubbo.spring.boot.observability.autoconfigure.DubboMicrometerTracingAutoConfiguration; import org.apache.dubbo.spring.boot.observability.autoconfigure.ObservabilityUtils; +import org.apache.dubbo.spring.boot.observability.autoconfigure.annotation.ConditionalOnDubboTracingEnable; + import org.springframework.beans.factory.ObjectProvider; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; @@ -32,7 +33,6 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.Ordered; import org.springframework.core.annotation.Order; -import org.springframework.core.env.Environment; import java.util.Collections; import java.util.List; @@ -43,7 +43,7 @@ import java.util.stream.Collectors; * provider Brave when you are using Boot <3.0 or you are not using spring-boot-starter-actuator */ @AutoConfiguration(before = DubboMicrometerTracingAutoConfiguration.class, afterName = "org.springframework.boot.actuate.autoconfigure.tracing.BraveAutoConfiguration") -@ConditionalOnClass(name={"io.micrometer.tracing.Tracer", "io.micrometer.tracing.brave.bridge.BraveTracer","io.micrometer.tracing.brave.bridge.BraveBaggageManager","brave.Tracing"}) +@ConditionalOnClass(name = {"io.micrometer.tracing.Tracer", "io.micrometer.tracing.brave.bridge.BraveTracer", "io.micrometer.tracing.brave.bridge.BraveBaggageManager", "brave.Tracing"}) @EnableConfigurationProperties(DubboConfigurationProperties.class) @ConditionalOnDubboTracingEnable public class BraveAutoConfiguration { @@ -55,25 +55,33 @@ public class BraveAutoConfiguration { */ private static final String DEFAULT_APPLICATION_NAME = "application"; - @Bean - @ConditionalOnMissingBean - @Order(Ordered.HIGHEST_PRECEDENCE) - io.micrometer.tracing.brave.bridge.CompositeSpanHandler compositeSpanHandler(ObjectProvider predicates, - ObjectProvider reporters, ObjectProvider filters) { - return new io.micrometer.tracing.brave.bridge.CompositeSpanHandler(predicates.orderedStream().collect(Collectors.toList()), - reporters.orderedStream().collect(Collectors.toList()), - filters.orderedStream().collect(Collectors.toList())); + private final ModuleModel moduleModel; + + public BraveAutoConfiguration(ModuleModel moduleModel) { + this.moduleModel = moduleModel; } @Bean @ConditionalOnMissingBean - public brave.Tracing braveTracing(Environment environment, List spanHandlers, - List tracingCustomizers, brave.propagation.CurrentTraceContext currentTraceContext, - brave.propagation.Propagation.Factory propagationFactory, brave.sampler.Sampler sampler) { - String applicationName = environment.getProperty("spring.application.name", DEFAULT_APPLICATION_NAME); + @Order(Ordered.HIGHEST_PRECEDENCE) + io.micrometer.tracing.brave.bridge.CompositeSpanHandler compositeSpanHandler(ObjectProvider predicates, + ObjectProvider reporters, ObjectProvider filters) { + return new io.micrometer.tracing.brave.bridge.CompositeSpanHandler(predicates.orderedStream().collect(Collectors.toList()), + reporters.orderedStream().collect(Collectors.toList()), + filters.orderedStream().collect(Collectors.toList())); + } + + @Bean + @ConditionalOnMissingBean + public brave.Tracing braveTracing(List spanHandlers, + List tracingCustomizers, brave.propagation.CurrentTraceContext currentTraceContext, + brave.propagation.Propagation.Factory propagationFactory, brave.sampler.Sampler sampler) { + String applicationName = moduleModel.getApplicationModel().getApplicationConfigManager().getApplication() + .map(ApplicationConfig::getName) + .orElse(DEFAULT_APPLICATION_NAME); brave.Tracing.Builder builder = brave.Tracing.newBuilder().currentTraceContext(currentTraceContext).traceId128Bit(true) - .supportsJoin(false).propagationFactory(propagationFactory).sampler(sampler) - .localServiceName(applicationName); + .supportsJoin(false).propagationFactory(propagationFactory).sampler(sampler) + .localServiceName(applicationName); spanHandlers.forEach(builder::addSpanHandler); for (brave.TracingCustomizer tracingCustomizer : tracingCustomizers) { tracingCustomizer.customize(builder); @@ -90,7 +98,7 @@ public class BraveAutoConfiguration { @Bean @ConditionalOnMissingBean public brave.propagation.CurrentTraceContext braveCurrentTraceContext(List scopeDecorators, - List currentTraceContextCustomizers) { + List currentTraceContextCustomizers) { brave.propagation.ThreadLocalCurrentTraceContext.Builder builder = brave.propagation.ThreadLocalCurrentTraceContext.newBuilder(); scopeDecorators.forEach(builder::addScopeDecorator); for (brave.propagation.CurrentTraceContextCustomizer currentTraceContextCustomizer : currentTraceContextCustomizers) { @@ -164,7 +172,7 @@ public class BraveAutoConfiguration { brave.baggage.BaggagePropagation.FactoryBuilder b3PropagationFactoryBuilder( ObjectProvider baggagePropagationCustomizers) { brave.propagation.Propagation.Factory delegate = - brave.propagation.B3Propagation.newFactoryBuilder().injectFormat(brave.propagation.B3Propagation.Format.SINGLE_NO_PARENT).build(); + brave.propagation.B3Propagation.newFactoryBuilder().injectFormat(brave.propagation.B3Propagation.Format.SINGLE_NO_PARENT).build(); brave.baggage.BaggagePropagation.FactoryBuilder builder = brave.baggage.BaggagePropagation.newFactoryBuilder(delegate); baggagePropagationCustomizers.orderedStream().forEach((customizer) -> customizer.customize(builder)); @@ -205,7 +213,7 @@ public class BraveAutoConfiguration { @ConditionalOnMissingBean brave.baggage.CorrelationScopeDecorator.Builder mdcCorrelationScopeDecoratorBuilder( ObjectProvider correlationScopeCustomizers) { - brave.baggage.CorrelationScopeDecorator.Builder builder = brave.context.slf4j.MDCScopeDecorator.newBuilder(); + brave.baggage.CorrelationScopeDecorator.Builder builder = brave.context.slf4j.MDCScopeDecorator.newBuilder(); correlationScopeCustomizers.orderedStream().forEach((customizer) -> customizer.customize(builder)); return builder; } diff --git a/dubbo-spring-boot/dubbo-spring-boot-observability-starters/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/observability/autoconfigure/exporter/zipkin/HttpSender.java b/dubbo-spring-boot/dubbo-spring-boot-observability-starters/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/observability/autoconfigure/exporter/zipkin/HttpSender.java new file mode 100644 index 0000000000..0bc815031f --- /dev/null +++ b/dubbo-spring-boot/dubbo-spring-boot-observability-starters/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/observability/autoconfigure/exporter/zipkin/HttpSender.java @@ -0,0 +1,145 @@ +/* + * 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.spring.boot.observability.autoconfigure.exporter.zipkin; + +import org.springframework.http.HttpHeaders; +import org.springframework.util.unit.DataSize; +import zipkin2.Call; +import zipkin2.CheckResult; +import zipkin2.codec.Encoding; +import zipkin2.reporter.BytesMessageEncoder; +import zipkin2.reporter.ClosedSenderException; +import zipkin2.reporter.Sender; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.UncheckedIOException; +import java.util.Collections; +import java.util.List; +import java.util.zip.GZIPOutputStream; + +/** + * A Zipkin {@link Sender} that uses an HTTP client to send JSON spans. Supports automatic compression with gzip. + */ +abstract class HttpSender extends Sender { + private static final DataSize MESSAGE_MAX_SIZE = DataSize.ofKilobytes(512); + + private volatile boolean closed; + + @Override + public Encoding encoding() { + return Encoding.JSON; + } + + @Override + public int messageMaxBytes() { + return (int) MESSAGE_MAX_SIZE.toBytes(); + } + + @Override + public int messageSizeInBytes(List encodedSpans) { + return encoding().listSizeInBytes(encodedSpans); + } + + @Override + public int messageSizeInBytes(int encodedSizeInBytes) { + return encoding().listSizeInBytes(encodedSizeInBytes); + } + + @Override + public CheckResult check() { + try { + sendSpans(Collections.emptyList()).execute(); + return CheckResult.OK; + } catch (IOException | RuntimeException ex) { + return CheckResult.failed(ex); + } + } + + @Override + public void close() throws IOException { + this.closed = true; + } + + /** + * The returned {@link HttpPostCall} will send span(s) as a POST to a zipkin endpoint + * when executed. + * + * @param batchedEncodedSpans list of encoded spans as a byte array + * @return an instance of a Zipkin {@link Call} which can be executed + */ + protected abstract HttpPostCall sendSpans(byte[] batchedEncodedSpans); + + @Override + public Call sendSpans(List encodedSpans) { + if (this.closed) { + throw new ClosedSenderException(); + } + return sendSpans(BytesMessageEncoder.JSON.encode(encodedSpans)); + } + + abstract static class HttpPostCall extends Call.Base { + + /** + * Only use gzip compression on data which is bigger than this in bytes. + */ + private static final DataSize COMPRESSION_THRESHOLD = DataSize.ofKilobytes(1); + + private final byte[] body; + + HttpPostCall(byte[] body) { + this.body = body; + } + + protected byte[] getBody() { + if (needsCompression()) { + return compress(this.body); + } + return this.body; + } + + protected byte[] getUncompressedBody() { + return this.body; + } + + protected HttpHeaders getDefaultHeaders() { + HttpHeaders headers = new HttpHeaders(); + headers.set("b3", "0"); + headers.set("Content-Type", "application/json"); + if (needsCompression()) { + headers.set("Content-Encoding", "gzip"); + } + return headers; + } + + private boolean needsCompression() { + return this.body.length > COMPRESSION_THRESHOLD.toBytes(); + } + + private byte[] compress(byte[] input) { + ByteArrayOutputStream result = new ByteArrayOutputStream(); + try (GZIPOutputStream gzip = new GZIPOutputStream(result)) { + gzip.write(input); + } catch (IOException ex) { + throw new UncheckedIOException(ex); + } + return result.toByteArray(); + } + + } +} diff --git a/dubbo-spring-boot/dubbo-spring-boot-observability-starters/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/observability/autoconfigure/exporter/zipkin/ZipkinAutoConfiguration.java b/dubbo-spring-boot/dubbo-spring-boot-observability-starters/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/observability/autoconfigure/exporter/zipkin/ZipkinAutoConfiguration.java new file mode 100644 index 0000000000..604e7af5da --- /dev/null +++ b/dubbo-spring-boot/dubbo-spring-boot-observability-starters/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/observability/autoconfigure/exporter/zipkin/ZipkinAutoConfiguration.java @@ -0,0 +1,68 @@ +/* + * 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.spring.boot.observability.autoconfigure.exporter.zipkin; + +import org.apache.dubbo.spring.boot.observability.autoconfigure.annotation.ConditionalOnDubboTracingEnable; +import org.apache.dubbo.spring.boot.observability.autoconfigure.exporter.zipkin.ZipkinConfigurations.BraveConfiguration; +import org.apache.dubbo.spring.boot.observability.autoconfigure.exporter.zipkin.ZipkinConfigurations.OpenTelemetryConfiguration; +import org.apache.dubbo.spring.boot.observability.autoconfigure.exporter.zipkin.ZipkinConfigurations.ReporterConfiguration; +import org.apache.dubbo.spring.boot.observability.autoconfigure.exporter.zipkin.ZipkinConfigurations.SenderConfiguration; + +import org.springframework.boot.autoconfigure.AutoConfiguration; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.autoconfigure.web.client.RestTemplateAutoConfiguration; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Import; +import zipkin2.Span; +import zipkin2.codec.BytesEncoder; +import zipkin2.codec.SpanBytesEncoder; +import zipkin2.reporter.Sender; + +import static org.apache.dubbo.spring.boot.observability.autoconfigure.ObservabilityUtils.DUBBO_TRACING_PREFIX; +import static org.apache.dubbo.spring.boot.observability.autoconfigure.ObservabilityUtils.DUBBO_TRACING_ZIPKIN_CONFIG_PREFIX; + + +/** + * {@link EnableAutoConfiguration Auto-configuration} for Zipkin. + *

+ * It uses imports on {@link ZipkinConfigurations} to guarantee the correct configuration ordering. + * Create Zipkin sender and exporter when you are using Boot < 3.0 or you are not using spring-boot-starter-actuator. + * When you use SpringBoot 3.*, priority should be given to loading S3 related configurations. Dubbo related zipkin configurations are invalid. + * + * @since 3.2.1 + */ +@AutoConfiguration(after = RestTemplateAutoConfiguration.class, afterName = "org.springframework.boot.actuate.autoconfigure.tracing.zipkin") +@ConditionalOnClass(Sender.class) +@Import({SenderConfiguration.class, + ReporterConfiguration.class, BraveConfiguration.class, + OpenTelemetryConfiguration.class}) +@ConditionalOnProperty(prefix = DUBBO_TRACING_PREFIX, name = "enabled", havingValue = "true") +@ConditionalOnDubboTracingEnable +public class ZipkinAutoConfiguration { + + @Bean + @ConditionalOnProperty(prefix = DUBBO_TRACING_ZIPKIN_CONFIG_PREFIX, name = "endpoint") + @ConditionalOnMissingBean + public BytesEncoder spanBytesEncoder() { + return SpanBytesEncoder.JSON_V2; + } + +} diff --git a/dubbo-spring-boot/dubbo-spring-boot-observability-starters/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/observability/autoconfigure/exporter/zipkin/ZipkinConfigurations.java b/dubbo-spring-boot/dubbo-spring-boot-observability-starters/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/observability/autoconfigure/exporter/zipkin/ZipkinConfigurations.java new file mode 100644 index 0000000000..3fc32ff2f4 --- /dev/null +++ b/dubbo-spring-boot/dubbo-spring-boot-observability-starters/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/observability/autoconfigure/exporter/zipkin/ZipkinConfigurations.java @@ -0,0 +1,176 @@ +/* + * 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.spring.boot.observability.autoconfigure.exporter.zipkin; + +import org.apache.dubbo.config.nested.ExporterConfig; +import org.apache.dubbo.spring.boot.autoconfigure.DubboConfigurationProperties; +import org.apache.dubbo.spring.boot.observability.autoconfigure.exporter.zipkin.customizer.ZipkinRestTemplateBuilderCustomizer; +import org.apache.dubbo.spring.boot.observability.autoconfigure.exporter.zipkin.customizer.ZipkinWebClientBuilderCustomizer; + +import io.opentelemetry.exporter.zipkin.ZipkinSpanExporter; +import org.springframework.beans.factory.ObjectProvider; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.boot.web.client.RestTemplateBuilder; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; +import org.springframework.web.client.RestTemplate; +import org.springframework.web.reactive.function.client.WebClient; +import zipkin2.Span; +import zipkin2.codec.BytesEncoder; +import zipkin2.reporter.AsyncReporter; +import zipkin2.reporter.Reporter; +import zipkin2.reporter.Sender; +import zipkin2.reporter.brave.ZipkinSpanHandler; +import zipkin2.reporter.urlconnection.URLConnectionSender; + +import java.util.concurrent.atomic.AtomicReference; + +import static org.apache.dubbo.spring.boot.observability.autoconfigure.ObservabilityUtils.DUBBO_TRACING_ZIPKIN_CONFIG_PREFIX; + +/** + * Configurations for Zipkin. Those are imported by {@link ZipkinAutoConfiguration}. + */ +class ZipkinConfigurations { + + @Configuration(proxyBeanMethods = false) + @ConditionalOnProperty(prefix = DUBBO_TRACING_ZIPKIN_CONFIG_PREFIX, name = "endpoint") + @Import({UrlConnectionSenderConfiguration.class, WebClientSenderConfiguration.class, + RestTemplateSenderConfiguration.class}) + static class SenderConfiguration { + } + + @Configuration(proxyBeanMethods = false) + @ConditionalOnClass(URLConnectionSender.class) + @EnableConfigurationProperties(DubboConfigurationProperties.class) + static class UrlConnectionSenderConfiguration { + + @Bean + @ConditionalOnMissingBean(Sender.class) + URLConnectionSender urlConnectionSender(DubboConfigurationProperties properties) { + URLConnectionSender.Builder builder = URLConnectionSender.newBuilder(); + ExporterConfig.ZipkinConfig zipkinConfig = properties.getTracing().getTracingExporter().getZipkinConfig(); + builder.connectTimeout((int) zipkinConfig.getConnectTimeout().toMillis()); + builder.readTimeout((int) zipkinConfig.getReadTimeout().toMillis()); + builder.endpoint(zipkinConfig.getEndpoint()); + return builder.build(); + } + + } + + @Configuration(proxyBeanMethods = false) + @ConditionalOnClass(RestTemplate.class) + @EnableConfigurationProperties(DubboConfigurationProperties.class) + static class RestTemplateSenderConfiguration { + + @Bean + @ConditionalOnMissingBean(Sender.class) + ZipkinRestTemplateSender restTemplateSender(DubboConfigurationProperties properties, + ObjectProvider customizers) { + ExporterConfig.ZipkinConfig zipkinConfig = properties.getTracing().getTracingExporter().getZipkinConfig(); + RestTemplateBuilder restTemplateBuilder = new RestTemplateBuilder() + .setConnectTimeout(zipkinConfig.getConnectTimeout()) + .setReadTimeout(zipkinConfig.getReadTimeout()); + restTemplateBuilder = applyCustomizers(restTemplateBuilder, customizers); + return new ZipkinRestTemplateSender(zipkinConfig.getEndpoint(), restTemplateBuilder.build()); + } + + private RestTemplateBuilder applyCustomizers(RestTemplateBuilder restTemplateBuilder, + ObjectProvider customizers) { + Iterable orderedCustomizers = () -> customizers.orderedStream() + .iterator(); + RestTemplateBuilder currentBuilder = restTemplateBuilder; + for (ZipkinRestTemplateBuilderCustomizer customizer : orderedCustomizers) { + currentBuilder = customizer.customize(currentBuilder); + } + return currentBuilder; + } + + } + + @Configuration(proxyBeanMethods = false) + @ConditionalOnClass(WebClient.class) + @EnableConfigurationProperties(DubboConfigurationProperties.class) + static class WebClientSenderConfiguration { + + @Bean + @ConditionalOnMissingBean(Sender.class) + ZipkinWebClientSender webClientSender(DubboConfigurationProperties properties, + ObjectProvider customizers) { + ExporterConfig.ZipkinConfig zipkinConfig = properties.getTracing().getTracingExporter().getZipkinConfig(); + WebClient.Builder builder = WebClient.builder(); + customizers.orderedStream().forEach((customizer) -> customizer.customize(builder)); + return new ZipkinWebClientSender(zipkinConfig.getEndpoint(), builder.build()); + } + + } + + @Configuration(proxyBeanMethods = false) + static class ReporterConfiguration { + + @Bean + @ConditionalOnMissingBean + @ConditionalOnBean(Sender.class) + AsyncReporter spanReporter(Sender sender, BytesEncoder encoder) { + return AsyncReporter.builder(sender).build(encoder); + } + + } + + @Configuration(proxyBeanMethods = false) + @ConditionalOnClass(ZipkinSpanHandler.class) + static class BraveConfiguration { + + @Bean + @ConditionalOnMissingBean + @ConditionalOnBean(Reporter.class) + ZipkinSpanHandler zipkinSpanHandler(Reporter spanReporter) { + return (ZipkinSpanHandler) ZipkinSpanHandler.newBuilder(spanReporter).build(); + } + + } + + @Configuration(proxyBeanMethods = false) + @ConditionalOnClass(ZipkinSpanExporter.class) + @ConditionalOnProperty(prefix = DUBBO_TRACING_ZIPKIN_CONFIG_PREFIX, name = "endpoint") + @EnableConfigurationProperties(DubboConfigurationProperties.class) + static class OpenTelemetryConfiguration { + + @Bean + @ConditionalOnMissingBean + ZipkinSpanExporter zipkinSpanExporter(DubboConfigurationProperties properties, BytesEncoder encoder, ObjectProvider senders) { + AtomicReference senderRef = new AtomicReference<>(); + senders.orderedStream().findFirst().ifPresent(senderRef::set); + Sender sender = senderRef.get(); + if (sender == null) { + ExporterConfig.ZipkinConfig zipkinConfig = properties.getTracing().getTracingExporter().getZipkinConfig(); + return ZipkinSpanExporter.builder() + .setEncoder(encoder) + .setEndpoint(zipkinConfig.getEndpoint()) + .setReadTimeout(zipkinConfig.getReadTimeout()) + .build(); + } + return ZipkinSpanExporter.builder().setEncoder(encoder).setSender(sender).build(); + } + + } +} diff --git a/dubbo-spring-boot/dubbo-spring-boot-observability-starters/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/observability/autoconfigure/exporter/zipkin/ZipkinRestTemplateSender.java b/dubbo-spring-boot/dubbo-spring-boot-observability-starters/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/observability/autoconfigure/exporter/zipkin/ZipkinRestTemplateSender.java new file mode 100644 index 0000000000..45eff7f6fb --- /dev/null +++ b/dubbo-spring-boot/dubbo-spring-boot-observability-starters/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/observability/autoconfigure/exporter/zipkin/ZipkinRestTemplateSender.java @@ -0,0 +1,76 @@ +/* + * 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.spring.boot.observability.autoconfigure.exporter.zipkin; + +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpMethod; +import org.springframework.web.client.RestTemplate; +import zipkin2.Call; +import zipkin2.Callback; + +class ZipkinRestTemplateSender extends HttpSender { + private final String endpoint; + + private final RestTemplate restTemplate; + + ZipkinRestTemplateSender(String endpoint, RestTemplate restTemplate) { + this.endpoint = endpoint; + this.restTemplate = restTemplate; + } + + @Override + public HttpPostCall sendSpans(byte[] batchedEncodedSpans) { + return new RestTemplateHttpPostCall(this.endpoint, batchedEncodedSpans, this.restTemplate); + } + + private static class RestTemplateHttpPostCall extends HttpPostCall { + + private final String endpoint; + + private final RestTemplate restTemplate; + + RestTemplateHttpPostCall(String endpoint, byte[] body, RestTemplate restTemplate) { + super(body); + this.endpoint = endpoint; + this.restTemplate = restTemplate; + } + + @Override + public Call clone() { + return new RestTemplateHttpPostCall(this.endpoint, getUncompressedBody(), this.restTemplate); + } + + @Override + protected Void doExecute() { + HttpEntity request = new HttpEntity<>(getBody(), getDefaultHeaders()); + this.restTemplate.exchange(this.endpoint, HttpMethod.POST, request, Void.class); + return null; + } + + @Override + protected void doEnqueue(Callback callback) { + try { + doExecute(); + callback.onSuccess(null); + } catch (Exception ex) { + callback.onError(ex); + } + } + + } +} diff --git a/dubbo-spring-boot/dubbo-spring-boot-observability-starters/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/observability/autoconfigure/exporter/zipkin/ZipkinWebClientSender.java b/dubbo-spring-boot/dubbo-spring-boot-observability-starters/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/observability/autoconfigure/exporter/zipkin/ZipkinWebClientSender.java new file mode 100644 index 0000000000..128f04431a --- /dev/null +++ b/dubbo-spring-boot/dubbo-spring-boot-observability-starters/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/observability/autoconfigure/exporter/zipkin/ZipkinWebClientSender.java @@ -0,0 +1,84 @@ +/* + * 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.spring.boot.observability.autoconfigure.exporter.zipkin; + +import org.springframework.http.HttpHeaders; +import org.springframework.http.ResponseEntity; +import org.springframework.web.reactive.function.client.WebClient; +import reactor.core.publisher.Mono; +import zipkin2.Call; +import zipkin2.Callback; + +class ZipkinWebClientSender extends HttpSender { + private final String endpoint; + + private final WebClient webClient; + + ZipkinWebClientSender(String endpoint, WebClient webClient) { + this.endpoint = endpoint; + this.webClient = webClient; + } + + @Override + public HttpPostCall sendSpans(byte[] batchedEncodedSpans) { + return new WebClientHttpPostCall(this.endpoint, batchedEncodedSpans, this.webClient); + } + + private static class WebClientHttpPostCall extends HttpPostCall { + + private final String endpoint; + + private final WebClient webClient; + + WebClientHttpPostCall(String endpoint, byte[] body, WebClient webClient) { + super(body); + this.endpoint = endpoint; + this.webClient = webClient; + } + + @Override + public Call clone() { + return new WebClientHttpPostCall(this.endpoint, getUncompressedBody(), this.webClient); + } + + @Override + protected Void doExecute() { + sendRequest().block(); + return null; + } + + @Override + protected void doEnqueue(Callback callback) { + sendRequest().subscribe((entity) -> callback.onSuccess(null), callback::onError); + } + + private Mono> sendRequest() { + return this.webClient.post() + .uri(this.endpoint) + .headers(this::addDefaultHeaders) + .bodyValue(getBody()) + .retrieve() + .toBodilessEntity(); + } + + private void addDefaultHeaders(HttpHeaders headers) { + headers.addAll(getDefaultHeaders()); + } + + } +} diff --git a/dubbo-spring-boot/dubbo-spring-boot-observability-starters/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/observability/autoconfigure/exporter/zipkin/customizer/ZipkinRestTemplateBuilderCustomizer.java b/dubbo-spring-boot/dubbo-spring-boot-observability-starters/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/observability/autoconfigure/exporter/zipkin/customizer/ZipkinRestTemplateBuilderCustomizer.java new file mode 100644 index 0000000000..db7209e46a --- /dev/null +++ b/dubbo-spring-boot/dubbo-spring-boot-observability-starters/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/observability/autoconfigure/exporter/zipkin/customizer/ZipkinRestTemplateBuilderCustomizer.java @@ -0,0 +1,38 @@ +/* + * 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.spring.boot.observability.autoconfigure.exporter.zipkin.customizer; + +import org.springframework.boot.web.client.RestTemplateBuilder; + +/** + * Callback interface that can be implemented by beans wishing to customize the + * {@link RestTemplateBuilder} used to send spans to Zipkin. + * + * @since 3.2.0 + */ +@FunctionalInterface +public interface ZipkinRestTemplateBuilderCustomizer { + + /** + * Customize the rest template builder. + * + * @param restTemplateBuilder the {@code RestTemplateBuilder} to customize + * @return the customized {@code RestTemplateBuilder} + */ + RestTemplateBuilder customize(RestTemplateBuilder restTemplateBuilder); +} diff --git a/dubbo-spring-boot/dubbo-spring-boot-observability-starters/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/observability/autoconfigure/exporter/zipkin/customizer/ZipkinWebClientBuilderCustomizer.java b/dubbo-spring-boot/dubbo-spring-boot-observability-starters/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/observability/autoconfigure/exporter/zipkin/customizer/ZipkinWebClientBuilderCustomizer.java new file mode 100644 index 0000000000..d890280529 --- /dev/null +++ b/dubbo-spring-boot/dubbo-spring-boot-observability-starters/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/observability/autoconfigure/exporter/zipkin/customizer/ZipkinWebClientBuilderCustomizer.java @@ -0,0 +1,39 @@ +/* + * 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.spring.boot.observability.autoconfigure.exporter.zipkin.customizer; + + +import org.springframework.web.reactive.function.client.WebClient; + +/** + * Callback interface that can be implemented by beans wishing to customize the + * {@link WebClient.Builder} used to send spans to Zipkin. + * + * @since 3.2.0 + */ +@FunctionalInterface +public interface ZipkinWebClientBuilderCustomizer { + + /** + * Customize the web client builder. + * + * @param webClientBuilder the {@code WebClient.Builder} to customize + */ + void customize(WebClient.Builder webClientBuilder); + +} diff --git a/dubbo-spring-boot/dubbo-spring-boot-observability-starter/src/main/java/org/apache/dubbo/spring/boot/observability/autoconfigure/otel/OpenTelemetryAutoConfiguration.java b/dubbo-spring-boot/dubbo-spring-boot-observability-starters/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/observability/autoconfigure/otel/OpenTelemetryAutoConfiguration.java similarity index 86% rename from dubbo-spring-boot/dubbo-spring-boot-observability-starter/src/main/java/org/apache/dubbo/spring/boot/observability/autoconfigure/otel/OpenTelemetryAutoConfiguration.java rename to dubbo-spring-boot/dubbo-spring-boot-observability-starters/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/observability/autoconfigure/otel/OpenTelemetryAutoConfiguration.java index b17e2cdb47..85babb77f8 100644 --- a/dubbo-spring-boot/dubbo-spring-boot-observability-starter/src/main/java/org/apache/dubbo/spring/boot/observability/autoconfigure/otel/OpenTelemetryAutoConfiguration.java +++ b/dubbo-spring-boot/dubbo-spring-boot-observability-starters/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/observability/autoconfigure/otel/OpenTelemetryAutoConfiguration.java @@ -18,10 +18,13 @@ package org.apache.dubbo.spring.boot.observability.autoconfigure.otel; import org.apache.dubbo.common.Version; +import org.apache.dubbo.config.ApplicationConfig; +import org.apache.dubbo.rpc.model.ModuleModel; import org.apache.dubbo.spring.boot.autoconfigure.DubboConfigurationProperties; -import org.apache.dubbo.spring.boot.observability.annotation.ConditionalOnDubboTracingEnable; import org.apache.dubbo.spring.boot.observability.autoconfigure.DubboMicrometerTracingAutoConfiguration; import org.apache.dubbo.spring.boot.observability.autoconfigure.ObservabilityUtils; +import org.apache.dubbo.spring.boot.observability.autoconfigure.annotation.ConditionalOnDubboTracingEnable; + import org.springframework.beans.factory.ObjectProvider; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; @@ -30,7 +33,6 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.core.env.Environment; import java.util.Collections; import java.util.List; @@ -42,8 +44,8 @@ import java.util.stream.Collectors; @AutoConfiguration(before = DubboMicrometerTracingAutoConfiguration.class, afterName = "org.springframework.boot.actuate.autoconfigure.tracing.OpenTelemetryAutoConfiguration") @ConditionalOnDubboTracingEnable @ConditionalOnClass(name = {"io.micrometer.tracing.otel.bridge.OtelTracer", - "io.opentelemetry.sdk.trace.SdkTracerProvider", "io.opentelemetry.api.OpenTelemetry" - , "io.micrometer.tracing.SpanCustomizer"}) + "io.opentelemetry.sdk.trace.SdkTracerProvider", "io.opentelemetry.api.OpenTelemetry" + , "io.micrometer.tracing.SpanCustomizer"}) @EnableConfigurationProperties(DubboConfigurationProperties.class) public class OpenTelemetryAutoConfiguration { @@ -54,24 +56,29 @@ public class OpenTelemetryAutoConfiguration { private final DubboConfigurationProperties dubboConfigProperties; - OpenTelemetryAutoConfiguration(DubboConfigurationProperties dubboConfigProperties) { + private final ModuleModel moduleModel; + + OpenTelemetryAutoConfiguration(DubboConfigurationProperties dubboConfigProperties, ModuleModel moduleModel) { this.dubboConfigProperties = dubboConfigProperties; + this.moduleModel = moduleModel; } @Bean @ConditionalOnMissingBean io.opentelemetry.api.OpenTelemetry openTelemetry(io.opentelemetry.sdk.trace.SdkTracerProvider sdkTracerProvider, io.opentelemetry.context.propagation.ContextPropagators contextPropagators) { return io.opentelemetry.sdk.OpenTelemetrySdk.builder().setTracerProvider(sdkTracerProvider).setPropagators(contextPropagators) - .build(); + .build(); } @Bean @ConditionalOnMissingBean - io.opentelemetry.sdk.trace.SdkTracerProvider otelSdkTracerProvider(Environment environment, ObjectProvider spanProcessors, + io.opentelemetry.sdk.trace.SdkTracerProvider otelSdkTracerProvider(ObjectProvider spanProcessors, io.opentelemetry.sdk.trace.samplers.Sampler sampler) { - String applicationName = environment.getProperty("spring.application.name", DEFAULT_APPLICATION_NAME); + String applicationName = moduleModel.getApplicationModel().getApplicationConfigManager().getApplication() + .map(ApplicationConfig::getName) + .orElse(DEFAULT_APPLICATION_NAME); io.opentelemetry.sdk.trace.SdkTracerProviderBuilder builder = io.opentelemetry.sdk.trace.SdkTracerProvider.builder().setSampler(sampler) - .setResource(io.opentelemetry.sdk.resources.Resource.create(io.opentelemetry.api.common.Attributes.of(io.opentelemetry.semconv.resource.attributes.ResourceAttributes.SERVICE_NAME, applicationName))); + .setResource(io.opentelemetry.sdk.resources.Resource.create(io.opentelemetry.api.common.Attributes.of(io.opentelemetry.semconv.resource.attributes.ResourceAttributes.SERVICE_NAME, applicationName))); spanProcessors.orderedStream().forEach(builder::addSpanProcessor); return builder.build(); } @@ -92,11 +99,11 @@ public class OpenTelemetryAutoConfiguration { @Bean @ConditionalOnMissingBean io.opentelemetry.sdk.trace.SpanProcessor otelSpanProcessor(ObjectProvider spanExporters, - ObjectProvider spanExportingPredicates, ObjectProvider spanReporters, - ObjectProvider spanFilters) { + ObjectProvider spanExportingPredicates, ObjectProvider spanReporters, + ObjectProvider spanFilters) { return io.opentelemetry.sdk.trace.export.BatchSpanProcessor.builder(new io.micrometer.tracing.otel.bridge.CompositeSpanExporter(spanExporters.orderedStream().collect(Collectors.toList()), - spanExportingPredicates.orderedStream().collect(Collectors.toList()), spanReporters.orderedStream().collect(Collectors.toList()), - spanFilters.orderedStream().collect(Collectors.toList()))).build(); + spanExportingPredicates.orderedStream().collect(Collectors.toList()), spanReporters.orderedStream().collect(Collectors.toList()), + spanFilters.orderedStream().collect(Collectors.toList()))).build(); } @Bean @@ -162,7 +169,7 @@ public class OpenTelemetryAutoConfiguration { io.opentelemetry.context.propagation.TextMapPropagator w3cTextMapPropagatorWithBaggage(io.micrometer.tracing.otel.bridge.OtelCurrentTraceContext otelCurrentTraceContext) { List remoteFields = this.dubboConfigProperties.getTracing().getBaggage().getRemoteFields(); return io.opentelemetry.context.propagation.TextMapPropagator.composite(io.opentelemetry.api.trace.propagation.W3CTraceContextPropagator.getInstance(), - io.opentelemetry.api.baggage.propagation.W3CBaggagePropagator.getInstance(), new io.micrometer.tracing.otel.propagation.BaggageTextMapPropagator(remoteFields, + io.opentelemetry.api.baggage.propagation.W3CBaggagePropagator.getInstance(), new io.micrometer.tracing.otel.propagation.BaggageTextMapPropagator(remoteFields, new io.micrometer.tracing.otel.bridge.OtelBaggageManager(otelCurrentTraceContext, remoteFields, Collections.emptyList()))); } diff --git a/dubbo-spring-boot/dubbo-spring-boot-observability-starter/src/main/resources/META-INF/spring.factories b/dubbo-spring-boot/dubbo-spring-boot-observability-starters/autoconfigure/src/main/resources/META-INF/spring.factories similarity index 77% rename from dubbo-spring-boot/dubbo-spring-boot-observability-starter/src/main/resources/META-INF/spring.factories rename to dubbo-spring-boot/dubbo-spring-boot-observability-starters/autoconfigure/src/main/resources/META-INF/spring.factories index b7a570ea76..a42de46c09 100644 --- a/dubbo-spring-boot/dubbo-spring-boot-observability-starter/src/main/resources/META-INF/spring.factories +++ b/dubbo-spring-boot/dubbo-spring-boot-observability-starters/autoconfigure/src/main/resources/META-INF/spring.factories @@ -2,5 +2,6 @@ org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ org.apache.dubbo.spring.boot.observability.autoconfigure.otel.OpenTelemetryAutoConfiguration,\ org.apache.dubbo.spring.boot.observability.autoconfigure.DubboMicrometerTracingAutoConfiguration,\ org.apache.dubbo.spring.boot.observability.autoconfigure.DubboObservationAutoConfiguration,\ -org.apache.dubbo.spring.boot.observability.autoconfigure.brave.BraveAutoConfiguration +org.apache.dubbo.spring.boot.observability.autoconfigure.brave.BraveAutoConfiguration,\ +org.apache.dubbo.spring.boot.observability.autoconfigure.exporter.zipkin.ZipkinAutoConfiguration diff --git a/dubbo-spring-boot/dubbo-spring-boot-observability-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/dubbo-spring-boot/dubbo-spring-boot-observability-starters/autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports similarity index 79% rename from dubbo-spring-boot/dubbo-spring-boot-observability-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports rename to dubbo-spring-boot/dubbo-spring-boot-observability-starters/autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports index 9d3769fc9c..a9e7d12337 100644 --- a/dubbo-spring-boot/dubbo-spring-boot-observability-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ b/dubbo-spring-boot/dubbo-spring-boot-observability-starters/autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -2,3 +2,4 @@ org.apache.dubbo.spring.boot.observability.autoconfigure.otel.OpenTelemetryAutoC org.apache.dubbo.spring.boot.observability.autoconfigure.DubboMicrometerTracingAutoConfiguration org.apache.dubbo.spring.boot.observability.autoconfigure.DubboObservationAutoConfiguration org.apache.dubbo.spring.boot.observability.autoconfigure.brave.BraveAutoConfiguration +org.apache.dubbo.spring.boot.observability.autoconfigure.exporter.zipkin.ZipkinAutoConfiguration \ No newline at end of file diff --git a/dubbo-spring-boot/dubbo-spring-boot-observability-starters/autoconfigure/src/test/java/org/apache/dubbo/spring/boot/observability/autoconfigure/observability/DubboMicrometerTracingAutoConfigurationTests.java b/dubbo-spring-boot/dubbo-spring-boot-observability-starters/autoconfigure/src/test/java/org/apache/dubbo/spring/boot/observability/autoconfigure/observability/DubboMicrometerTracingAutoConfigurationTests.java new file mode 100644 index 0000000000..d0e4c64b67 --- /dev/null +++ b/dubbo-spring-boot/dubbo-spring-boot-observability-starters/autoconfigure/src/test/java/org/apache/dubbo/spring/boot/observability/autoconfigure/observability/DubboMicrometerTracingAutoConfigurationTests.java @@ -0,0 +1,165 @@ +/* + * 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.spring.boot.observability.autoconfigure.observability; + +import org.apache.dubbo.spring.boot.observability.autoconfigure.DubboMicrometerTracingAutoConfiguration; + +import io.micrometer.tracing.Tracer; +import io.micrometer.tracing.handler.DefaultTracingObservationHandler; +import io.micrometer.tracing.handler.PropagatingReceiverTracingObservationHandler; +import io.micrometer.tracing.handler.PropagatingSenderTracingObservationHandler; +import io.micrometer.tracing.handler.TracingObservationHandler; +import io.micrometer.tracing.propagation.Propagator; +import org.junit.jupiter.api.Test; +import org.springframework.boot.autoconfigure.AutoConfigurations; +import org.springframework.boot.test.context.FilteredClassLoader; +import org.springframework.boot.test.context.runner.ApplicationContextRunner; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import java.util.List; +import java.util.stream.Collectors; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; + +/** + * Tests for {@link DubboMicrometerTracingAutoConfiguration} + */ +class DubboMicrometerTracingAutoConfigurationTests { + + private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() + .withConfiguration(AutoConfigurations.of(DubboMicrometerTracingAutoConfiguration.class)); + + @Test + void shouldSupplyBeans() { + this.contextRunner.withUserConfiguration(TracerConfiguration.class, PropagatorConfiguration.class) + .run((context) -> { + assertThat(context).hasSingleBean(DefaultTracingObservationHandler.class); + assertThat(context).hasSingleBean(PropagatingReceiverTracingObservationHandler.class); + assertThat(context).hasSingleBean(PropagatingSenderTracingObservationHandler.class); + }); + } + + @Test + @SuppressWarnings("rawtypes") + void shouldSupplyBeansInCorrectOrder() { + this.contextRunner.withUserConfiguration(TracerConfiguration.class, PropagatorConfiguration.class) + .run((context) -> { + List tracingObservationHandlers = context + .getBeanProvider(TracingObservationHandler.class) + .orderedStream() + .collect(Collectors.toList()); + assertThat(tracingObservationHandlers).hasSize(3); + assertThat(tracingObservationHandlers.get(0)) + .isInstanceOf(PropagatingReceiverTracingObservationHandler.class); + assertThat(tracingObservationHandlers.get(1)) + .isInstanceOf(PropagatingSenderTracingObservationHandler.class); + assertThat(tracingObservationHandlers.get(2)).isInstanceOf(DefaultTracingObservationHandler.class); + }); + } + + @Test + void shouldBackOffOnCustomBeans() { + this.contextRunner.withUserConfiguration(CustomConfiguration.class).run((context) -> { + assertThat(context).hasBean("customDefaultTracingObservationHandler"); + assertThat(context).hasSingleBean(DefaultTracingObservationHandler.class); + assertThat(context).hasBean("customPropagatingReceiverTracingObservationHandler"); + assertThat(context).hasSingleBean(PropagatingReceiverTracingObservationHandler.class); + assertThat(context).hasBean("customPropagatingSenderTracingObservationHandler"); + assertThat(context).hasSingleBean(PropagatingSenderTracingObservationHandler.class); + }); + } + + @Test + void shouldNotSupplyBeansIfMicrometerIsMissing() { + this.contextRunner.withClassLoader(new FilteredClassLoader("io.micrometer")).run((context) -> { + assertThat(context).doesNotHaveBean(DefaultTracingObservationHandler.class); + assertThat(context).doesNotHaveBean(PropagatingReceiverTracingObservationHandler.class); + assertThat(context).doesNotHaveBean(PropagatingSenderTracingObservationHandler.class); + }); + } + + @Test + void shouldNotSupplyBeansIfTracerIsMissing() { + this.contextRunner.withUserConfiguration(PropagatorConfiguration.class).run((context) -> { + assertThat(context).doesNotHaveBean(DefaultTracingObservationHandler.class); + assertThat(context).doesNotHaveBean(PropagatingReceiverTracingObservationHandler.class); + assertThat(context).doesNotHaveBean(PropagatingSenderTracingObservationHandler.class); + }); + } + + @Test + void shouldNotSupplyBeansIfPropagatorIsMissing() { + this.contextRunner.withUserConfiguration(TracerConfiguration.class).run((context) -> { + assertThat(context).doesNotHaveBean(PropagatingSenderTracingObservationHandler.class); + assertThat(context).doesNotHaveBean(PropagatingReceiverTracingObservationHandler.class); + }); + } + + @Test + void shouldNotSupplyBeansIfTracingIsDisabled() { + this.contextRunner.withUserConfiguration(TracerConfiguration.class, PropagatorConfiguration.class) + .withPropertyValues("dubbo.tracing.enabled=false") + .run((context) -> { + assertThat(context).doesNotHaveBean(DefaultTracingObservationHandler.class); + assertThat(context).doesNotHaveBean(PropagatingReceiverTracingObservationHandler.class); + assertThat(context).doesNotHaveBean(PropagatingSenderTracingObservationHandler.class); + }); + } + + @Configuration(proxyBeanMethods = false) + private static class TracerConfiguration { + + @Bean + Tracer tracer() { + return mock(Tracer.class); + } + + } + + @Configuration(proxyBeanMethods = false) + private static class PropagatorConfiguration { + + @Bean + Propagator propagator() { + return mock(Propagator.class); + } + + } + + @Configuration(proxyBeanMethods = false) + private static class CustomConfiguration { + + @Bean + DefaultTracingObservationHandler customDefaultTracingObservationHandler() { + return mock(DefaultTracingObservationHandler.class); + } + + @Bean + PropagatingReceiverTracingObservationHandler customPropagatingReceiverTracingObservationHandler() { + return mock(PropagatingReceiverTracingObservationHandler.class); + } + + @Bean + PropagatingSenderTracingObservationHandler customPropagatingSenderTracingObservationHandler() { + return mock(PropagatingSenderTracingObservationHandler.class); + } + + } +} diff --git a/dubbo-spring-boot/dubbo-spring-boot-observability-starters/dubbo-spring-boot-observability-starter/pom.xml b/dubbo-spring-boot/dubbo-spring-boot-observability-starters/dubbo-spring-boot-observability-starter/pom.xml new file mode 100644 index 0000000000..030298ed0d --- /dev/null +++ b/dubbo-spring-boot/dubbo-spring-boot-observability-starters/dubbo-spring-boot-observability-starter/pom.xml @@ -0,0 +1,40 @@ + + + + + dubbo-spring-boot-observability-starters + org.apache.dubbo + ${revision} + ../pom.xml + + 4.0.0 + + dubbo-spring-boot-observability-starter + jar + Apache Dubbo Spring Boot Observability Starter + + + + org.apache.dubbo + dubbo-spring-boot-observability-autoconfigure + ${project.version} + + + \ No newline at end of file diff --git a/dubbo-spring-boot/dubbo-spring-boot-observability-starters/dubbo-spring-boot-tracing-brave-zipkin-starter/pom.xml b/dubbo-spring-boot/dubbo-spring-boot-observability-starters/dubbo-spring-boot-tracing-brave-zipkin-starter/pom.xml new file mode 100644 index 0000000000..ac619e4302 --- /dev/null +++ b/dubbo-spring-boot/dubbo-spring-boot-observability-starters/dubbo-spring-boot-tracing-brave-zipkin-starter/pom.xml @@ -0,0 +1,49 @@ + + + + + dubbo-spring-boot-observability-starters + org.apache.dubbo + ${revision} + ../pom.xml + + 4.0.0 + + dubbo-spring-boot-tracing-brave-zipkin-starter + jar + Apache Dubbo Spring Boot Tracing Brave Zipkin Starter + + + + org.apache.dubbo + dubbo-spring-boot-observability-autoconfigure + ${project.version} + + + io.micrometer + micrometer-tracing-bridge-brave + + + io.zipkin.reporter2 + zipkin-reporter-brave + + + + \ No newline at end of file diff --git a/dubbo-spring-boot/dubbo-spring-boot-observability-starters/dubbo-spring-boot-tracing-otel-zipkin-starter/pom.xml b/dubbo-spring-boot/dubbo-spring-boot-observability-starters/dubbo-spring-boot-tracing-otel-zipkin-starter/pom.xml new file mode 100644 index 0000000000..97279d2b73 --- /dev/null +++ b/dubbo-spring-boot/dubbo-spring-boot-observability-starters/dubbo-spring-boot-tracing-otel-zipkin-starter/pom.xml @@ -0,0 +1,49 @@ + + + + + dubbo-spring-boot-observability-starters + org.apache.dubbo + ${revision} + ../pom.xml + + 4.0.0 + + dubbo-spring-boot-tracing-otel-zipkin-starter + jar + Apache Dubbo Spring Boot Tracing Otel Zipkin Starter + + + + org.apache.dubbo + dubbo-spring-boot-observability-autoconfigure + ${project.version} + + + io.micrometer + micrometer-tracing-bridge-otel + + + io.opentelemetry + opentelemetry-exporter-zipkin + + + + \ No newline at end of file diff --git a/dubbo-spring-boot/dubbo-spring-boot-observability-starters/pom.xml b/dubbo-spring-boot/dubbo-spring-boot-observability-starters/pom.xml new file mode 100644 index 0000000000..b18eedf9cf --- /dev/null +++ b/dubbo-spring-boot/dubbo-spring-boot-observability-starters/pom.xml @@ -0,0 +1,87 @@ + + + + + org.apache.dubbo + dubbo-spring-boot + ${revision} + ../pom.xml + + 4.0.0 + pom + + dubbo-spring-boot-observability-starters + + + autoconfigure + dubbo-spring-boot-tracing-otel-zipkin-starter + dubbo-spring-boot-tracing-brave-zipkin-starter + dubbo-spring-boot-observability-starter + + + + 1.10.6 + 1.0.4 + 1.25.0 + 2.16.4 + 0.16.0 + + + + + + io.micrometer + micrometer-bom + ${micrometer.version} + pom + import + + + io.micrometer + micrometer-tracing-bom + ${micrometer-tracing.version} + pom + import + + + io.opentelemetry + opentelemetry-bom + ${opentelemetry.version} + pom + import + + + io.zipkin.reporter2 + zipkin-reporter-bom + ${zipkin-reporter.version} + pom + import + + + io.prometheus + simpleclient_bom + ${prometheus-client.version} + pom + import + + + + + diff --git a/dubbo-spring-boot/pom.xml b/dubbo-spring-boot/pom.xml index 79997de27c..443343f9b4 100644 --- a/dubbo-spring-boot/pom.xml +++ b/dubbo-spring-boot/pom.xml @@ -36,11 +36,11 @@ dubbo-spring-boot-autoconfigure dubbo-spring-boot-compatible dubbo-spring-boot-starter - dubbo-spring-boot-observability-starter + dubbo-spring-boot-observability-starters - 2.7.10 + 2.7.11 ${revision} 2.20.0 diff --git a/dubbo-test/dubbo-dependencies-all/pom.xml b/dubbo-test/dubbo-dependencies-all/pom.xml index 2e0ec4eaad..30da17a3b1 100644 --- a/dubbo-test/dubbo-dependencies-all/pom.xml +++ b/dubbo-test/dubbo-dependencies-all/pom.xml @@ -161,6 +161,11 @@ org.apache.dubbo dubbo-metrics-metadata + + + org.apache.dubbo + dubbo-metrics-config-center + org.apache.dubbo dubbo-metrics-prometheus @@ -330,6 +335,18 @@ dubbo-spring-boot-starter + + org.apache.dubbo + dubbo-spring-boot-observability-autoconfigure + + + org.apache.dubbo + dubbo-spring-boot-tracing-otel-zipkin-starter + + + org.apache.dubbo + dubbo-spring-boot-tracing-brave-zipkin-starter + org.apache.dubbo dubbo-spring-boot-observability-starter diff --git a/dubbo-test/dubbo-test-check/pom.xml b/dubbo-test/dubbo-test-check/pom.xml index 35cf2ace79..30116dd7e1 100644 --- a/dubbo-test/dubbo-test-check/pom.xml +++ b/dubbo-test/dubbo-test-check/pom.xml @@ -36,7 +36,7 @@ 3.4.14 4.2.0 1.23.0 - 1.9.2 + 1.9.3 1.3 2.12.3 diff --git a/dubbo-xds/pom.xml b/dubbo-xds/pom.xml index 1263ed7d5c..b8d8a55409 100644 --- a/dubbo-xds/pom.xml +++ b/dubbo-xds/pom.xml @@ -31,8 +31,6 @@ The xDS Integration false - 3.22.2 - 1.54.0 @@ -52,19 +50,16 @@ io.grpc grpc-protobuf - ${grpc.version} io.grpc grpc-stub - ${grpc.version} io.grpc grpc-netty-shaded - ${grpc.version} @@ -75,13 +70,11 @@ com.google.protobuf protobuf-java - ${protobuf-java.version} com.google.protobuf protobuf-java-util - ${protobuf-java.version} @@ -104,18 +97,18 @@ kr.motd.maven os-maven-plugin - 1.7.1 + ${maven_os_plugin_version} org.xolstice.maven.plugins protobuf-maven-plugin - 0.6.1 + ${maven_protobuf_plugin_version} - com.google.protobuf:protoc:${protobuf-java.version}:exe:${os.detected.classifier} + com.google.protobuf:protoc:${protobuf-java_version}:exe:${os.detected.classifier} grpc-java - io.grpc:protoc-gen-grpc-java:${grpc.version}:exe:${os.detected.classifier} + io.grpc:protoc-gen-grpc-java:${grpc_version}:exe:${os.detected.classifier} diff --git a/pom.xml b/pom.xml index ac2edd363e..e54669dd0d 100644 --- a/pom.xml +++ b/pom.xml @@ -88,7 +88,7 @@ - 5.9.2 + 5.9.3 4.2.0 3.12.13 2.2 @@ -121,16 +121,22 @@ 3.5.0 9.4.51.v20230217 3.2.1 - 0.8.8 + 0.8.10 1.4.1 3.3.0 3.1.0 1.0.0 + 1.7.1 + 0.6.1 true true true true + + 1.2.2 + 3.22.3 + 1.54.0 3.3.0-beta.1-SNAPSHOT