diff --git a/.artifacts b/.artifacts index 7b113ce8ab..fcd77c4d1d 100644 --- a/.artifacts +++ b/.artifacts @@ -21,7 +21,6 @@ dubbo-auth dubbo-apache-release dubbo-all-shaded dubbo-bom -dubbo-build-tools dubbo-cluster dubbo-common dubbo-compatible @@ -66,6 +65,7 @@ dubbo-metrics-prometheus dubbo-metrics-registry dubbo-metrics-config-center dubbo-metrics-netty +dubbo-metrics-event dubbo-monitor dubbo-monitor-api dubbo-monitor-common @@ -141,3 +141,4 @@ dubbo-plugin-context dubbo-plugin-classloader-filter dubbo-plugin-proxy-bytebuddy dubbo-plugin-qos-trace +dubbo-plugin-loom diff --git a/.licenserc.yaml b/.licenserc.yaml index 3935786a0e..c82362141d 100644 --- a/.licenserc.yaml +++ b/.licenserc.yaml @@ -96,9 +96,9 @@ header: - 'dubbo-maven-plugin/src/main/java/org/apache/dubbo/maven/plugin/aot/MatchingGroupIdFilter.java' - 'dubbo-maven-plugin/src/main/java/org/apache/dubbo/maven/plugin/aot/RunArguments.java' - 'dubbo-maven-plugin/src/main/java/org/apache/dubbo/maven/plugin/aot/RunProcess.java' - - 'dubbo-native/src/main/java/org/apache/dubbo/aot/generate/BasicJsonWriter.java' - - 'dubbo-native/src/main/java/org/apache/dubbo/aot/api/ExecutableMode.java' - - 'dubbo-native/src/main/java/org/apache/dubbo/aot/api/MemberCategory.java' + - 'dubbo-plugin/dubbo-native/src/main/java/org/apache/dubbo/aot/generate/BasicJsonWriter.java' + - 'dubbo-plugin/dubbo-native/src/main/java/org/apache/dubbo/aot/api/ExecutableMode.java' + - 'dubbo-plugin/dubbo-native/src/main/java/org/apache/dubbo/aot/api/MemberCategory.java' - 'dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/aggregate/DubboMergingDigest.java' - 'dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/aggregate/DubboAbstractTDigest.java' - 'dubbo-common/src/main/java/org/apache/dubbo/common/logger/helpers/FormattingTuple.java' diff --git a/CHANGES.md b/CHANGES.md index 2c282afdf6..2983d19539 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -101,7 +101,7 @@ check 2.7.5 milestone for details. * In consumer side the app cannot catch the exception from provider that is configured serialization="kryo". #4238 * fix StringUtils#isBlank #4725 * when the interfaceName of the Reference annotation has duplicated,the exception is puzzled #4160 -* when anonymity bean is defined in spirng context,dubbo throw npe # +* when anonymity bean is defined in spring context,dubbo throw npe # * add Thread ContextClassLoader #4712 * Fix judgment ipv4 address #4729 * The compilation of static methods should be excluded when generating the proxy. #4647 diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/directory/AbstractDirectory.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/directory/AbstractDirectory.java index 4ffe016d12..dab89c0848 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/directory/AbstractDirectory.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/directory/AbstractDirectory.java @@ -224,10 +224,8 @@ public abstract class AbstractDirectory implements Directory { logger.warn(CLUSTER_NO_VALID_PROVIDER, "provider server or registry center crashed", "", "No provider available after connectivity filter for the service " + getConsumerUrl().getServiceKey() - + " All validInvokers' size: " + validInvokers.size() + " All routed invokers' size: " + routedResult.size() - + " All invokers' size: " + invokers.size() - + " from registry " + getUrl().getAddress() + + " from registry " + this + " on the consumer " + NetUtils.getLocalHost() + " using the dubbo version " + Version.getVersion() + "."); } @@ -350,6 +348,7 @@ public abstract class AbstractDirectory implements Directory { if (!invokersToReconnect.isEmpty()) { checkConnectivity(); } + MetricsEventBus.publish(RegistryEvent.refreshDirectoryEvent(applicationModel, getSummary(), getDirectoryMeta())); }, reconnectTaskPeriod, TimeUnit.MILLISECONDS); } MetricsEventBus.publish(RegistryEvent.refreshDirectoryEvent(applicationModel, getSummary(), getDirectoryMeta())); diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/directory/StaticDirectory.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/directory/StaticDirectory.java index d5ec1e512b..6fae2eeb8f 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/directory/StaticDirectory.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/directory/StaticDirectory.java @@ -27,11 +27,12 @@ import org.apache.dubbo.rpc.cluster.RouterChain; import org.apache.dubbo.rpc.cluster.SingleRouterChain; import org.apache.dubbo.rpc.cluster.router.state.BitList; -import java.util.Collections; +import java.util.HashMap; import java.util.List; import java.util.Map; import static org.apache.dubbo.common.constants.LoggerCodeConstants.CLUSTER_FAILED_SITE_SELECTION; +import static org.apache.dubbo.common.constants.RegistryConstants.REGISTER_MODE_KEY; import static org.apache.dubbo.common.constants.RegistryConstants.REGISTRY_KEY; /** @@ -130,6 +131,9 @@ public class StaticDirectory extends AbstractDirectory { @Override protected Map getDirectoryMeta() { - return Collections.singletonMap(REGISTRY_KEY, "static"); + Map metas = new HashMap<>(); + metas.put(REGISTRY_KEY, "static"); + metas.put(REGISTER_MODE_KEY, "static"); + return metas; } } diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/AbstractClusterInvokerTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/AbstractClusterInvokerTest.java index 31c3af53f2..496e4369b2 100644 --- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/AbstractClusterInvokerTest.java +++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/AbstractClusterInvokerTest.java @@ -60,7 +60,6 @@ import static org.apache.dubbo.common.constants.CommonConstants.MONITOR_KEY; import static org.apache.dubbo.common.constants.CommonConstants.PATH_KEY; import static org.apache.dubbo.common.constants.CommonConstants.PROTOCOL_KEY; import static org.apache.dubbo.rpc.cluster.Constants.CLUSTER_AVAILABLE_CHECK_KEY; -import static org.apache.dubbo.rpc.cluster.Constants.INVOCATION_NEED_MOCK; import static org.apache.dubbo.rpc.cluster.Constants.REFER_KEY; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.same; 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 dc05557f20..91c1c9ddd9 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 @@ -21,10 +21,10 @@ 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.RpcException; 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; @@ -56,6 +56,7 @@ class FailSafeClusterInvokerTest { @BeforeEach public void setUp() throws Exception { + RpcContext.removeServiceContext(); dic = mock(Directory.class); 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 ed161d7c79..bbc17745fc 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,10 +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.RpcInvocation; import org.apache.dubbo.rpc.RpcContext; -import org.apache.dubbo.rpc.cluster.Directory; import org.apache.dubbo.rpc.RpcException; +import org.apache.dubbo.rpc.RpcInvocation; +import org.apache.dubbo.rpc.cluster.Directory; import org.apache.log4j.Level; import org.junit.jupiter.api.AfterEach; @@ -38,7 +38,6 @@ 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; @@ -47,7 +46,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.*; +import static org.junit.jupiter.api.Assertions.assertFalse; import static org.mockito.BDDMockito.given; import static org.mockito.Mockito.mock; @@ -72,6 +71,7 @@ class FailbackClusterInvokerTest { @BeforeEach public void setUp() throws Exception { + RpcContext.removeServiceContext(); dic = mock(Directory.class); given(dic.getUrl()).willReturn(url); 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 f2ab8011d5..8bee034f30 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 @@ -128,6 +128,8 @@ public interface CommonConstants { String THREAD_POOL_EXHAUSTED_LISTENERS_KEY = "thread-pool-exhausted-listeners"; + String JSON_CHECK_LEVEL_KEY = "jsonCheckLevel"; + String THREADS_KEY = "threads"; String QUEUES_KEY = "queues"; @@ -643,7 +645,7 @@ public interface CommonConstants { String SERVICE_DEPLOYER_ATTRIBUTE_KEY = "serviceDeployer"; - String RESTEASY_NETTY_HTTP_REQUEST_ATTRIBUTE_KEY = "resteasyNettyHttpRequest"; + String DUBBO_MANUAL_REGISTER_KEY = "dubbo.application.manual-register"; diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/constants/MetricsConstants.java b/dubbo-common/src/main/java/org/apache/dubbo/common/constants/MetricsConstants.java index 49bd9665c7..53e377f9f9 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/constants/MetricsConstants.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/constants/MetricsConstants.java @@ -40,17 +40,19 @@ public interface MetricsConstants { String TAG_VERSION_KEY = "version"; String TAG_APPLICATION_VERSION_KEY = "application.version"; - + String TAG_KEY_KEY = "key"; - + String TAG_CONFIG_CENTER = "config.center"; - + String TAG_CHANGE_TYPE = "change.type"; String TAG_ERROR_CODE = "error"; String ENABLE_JVM_METRICS_KEY = "enable.jvm"; + String ENABLE_COLLECTOR_SYNC_KEY = "enable.collector.sync"; + String AGGREGATION_COLLECTOR_KEY = "aggregation"; String AGGREGATION_ENABLED_KEY = "aggregation.enabled"; 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 29b1993ca6..01286e6e4f 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 @@ -24,6 +24,8 @@ public interface QosConstants { String QOS_ENABLE = "qos.enable"; + String QOS_CHECK = "qos.check"; + String QOS_HOST = "qos.host"; String QOS_PORT = "qos.port"; diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/logger/ErrorTypeAwareLogger.java b/dubbo-common/src/main/java/org/apache/dubbo/common/logger/ErrorTypeAwareLogger.java index fe9ebcc774..72db45e868 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/logger/ErrorTypeAwareLogger.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/logger/ErrorTypeAwareLogger.java @@ -17,8 +17,23 @@ package org.apache.dubbo.common.logger; +import org.apache.dubbo.common.constants.LoggerCodeConstants; + /** * Logger interface with the ability of displaying solution of different types of error. + * + *

+ * This logger will log a message like this: + * + *

+ *     ... (original logging message) This may be caused by (... cause),
+ *     go to https://dubbo.apache.org/faq/[Cat]/[X] to find instructions. (... extendedInformation)
+ * 
+ * + * Where "[Cat]/[X]" is the error code ("code" in arguments). The link is clickable, leading user to + * the "Error code and its corresponding solutions" page. + * + * @see LoggerCodeConstants Detailed Format of Error Code and Error Code Constants */ public interface ErrorTypeAwareLogger extends Logger { diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/threadpool/support/AbortPolicyWithReport.java b/dubbo-common/src/main/java/org/apache/dubbo/common/threadpool/support/AbortPolicyWithReport.java index 8bb3bbfe51..8163b2b0b1 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/threadpool/support/AbortPolicyWithReport.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/threadpool/support/AbortPolicyWithReport.java @@ -145,6 +145,10 @@ public class AbortPolicyWithReport extends ThreadPoolExecutor.AbortPolicy { if (!guard.tryAcquire()) { return; } + // To avoid multiple dump, check again + if (System.currentTimeMillis() - lastPrintTime < TEN_MINUTES_MILLS) { + return; + } ExecutorService pool = Executors.newSingleThreadExecutor(); pool.execute(() -> { @@ -169,9 +173,9 @@ public class AbortPolicyWithReport extends ThreadPoolExecutor.AbortPolicy { } catch (Exception t) { logger.error(COMMON_UNEXPECTED_CREATE_DUMP, "", "", "dump jStack error", t); } finally { + lastPrintTime = System.currentTimeMillis(); guard.release(); } - lastPrintTime = System.currentTimeMillis(); }); //must shutdown thread pool ,if not will lead to OOM pool.shutdown(); diff --git a/dubbo-common/src/main/java/org/apache/dubbo/config/AbstractConfig.java b/dubbo-common/src/main/java/org/apache/dubbo/config/AbstractConfig.java index 75a80c8999..cda3390abd 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/config/AbstractConfig.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/config/AbstractConfig.java @@ -103,6 +103,11 @@ public abstract class AbstractConfig implements Serializable { protected final AtomicBoolean refreshed = new AtomicBoolean(false); + /** + * Indicate that if current config needs to being refreshed, default is true + */ + protected transient volatile boolean needRefresh = true; + /** * Is default config or not */ @@ -679,16 +684,18 @@ public abstract class AbstractConfig implements Serializable { * Dubbo config property override */ public void refresh() { - try { - // check and init before do refresh - preProcessRefresh(); - refreshWithPrefixes(getPrefixes(), getConfigMode()); - } catch (Exception e) { - logger.error(COMMON_FAILED_OVERRIDE_FIELD, "", "", "Failed to override field value of config bean: " + this, e); - throw new IllegalStateException("Failed to override field value of config bean: " + this, e); - } + if (needRefresh) { + try { + // check and init before do refresh + preProcessRefresh(); + refreshWithPrefixes(getPrefixes(), getConfigMode()); + } catch (Exception e) { + logger.error(COMMON_FAILED_OVERRIDE_FIELD, "", "", "Failed to override field value of config bean: " + this, e); + throw new IllegalStateException("Failed to override field value of config bean: " + this, e); + } - postProcessRefresh(); + postProcessRefresh(); + } refreshed.set(true); } @@ -949,6 +956,17 @@ public abstract class AbstractConfig implements Serializable { this.isDefault = isDefault; } + @Transient + @Parameter(excluded = true, attribute = false) + public boolean isNeedRefresh() { + return needRefresh; + } + + @Transient + public void setNeedRefresh(boolean needRefresh) { + this.needRefresh = needRefresh; + } + @Override public String toString() { try { 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 35703ef3f1..8f4b628637 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 @@ -60,6 +60,7 @@ import static org.apache.dubbo.common.constants.QosConstants.ACCEPT_FOREIGN_IP_W 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_CHECK; import static org.apache.dubbo.common.constants.QosConstants.QOS_ENABLE; import static org.apache.dubbo.common.constants.QosConstants.QOS_ENABLE_COMPATIBLE; import static org.apache.dubbo.common.constants.QosConstants.QOS_HOST; @@ -151,6 +152,11 @@ public class ApplicationConfig extends AbstractConfig { */ private Boolean qosEnable; + /** + * Whether qos should start success or not, will check qosEnable first + */ + private Boolean qosCheck; + /** * The qos host to listen */ @@ -448,6 +454,15 @@ public class ApplicationConfig extends AbstractConfig { this.qosEnable = qosEnable; } + @Parameter(key = QOS_CHECK) + public Boolean getQosCheck() { + return qosCheck; + } + + public void setQosCheck(Boolean qosCheck) { + this.qosCheck = qosCheck; + } + @Parameter(key = QOS_HOST) public String getQosHost() { return qosHost; diff --git a/dubbo-common/src/main/java/org/apache/dubbo/config/MetricsConfig.java b/dubbo-common/src/main/java/org/apache/dubbo/config/MetricsConfig.java index 37cd727f4c..95fb31b366 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/config/MetricsConfig.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/config/MetricsConfig.java @@ -66,6 +66,16 @@ public class MetricsConfig extends AbstractConfig { */ private Boolean enableNetty; + /** + * Enable metrics init. + */ + private Boolean enableMetricsInit; + + /** + * Enable collector sync. + */ + private Boolean enableCollectorSync; + /** * @deprecated After metrics config is refactored. * This parameter should no longer use and will be deleted in the future. @@ -99,6 +109,12 @@ public class MetricsConfig extends AbstractConfig { private Boolean enableRpc; + /** + * The level of the metrics, the value can be "SERVICE", "METHOD", default is method. + */ + private String rpcLevel; + + public MetricsConfig() { } @@ -129,6 +145,14 @@ public class MetricsConfig extends AbstractConfig { return enableJvm; } + public String getRpcLevel() { + return rpcLevel; + } + + public void setRpcLevel(String rpcLevel) { + this.rpcLevel = rpcLevel; + } + public void setEnableJvm(Boolean enableJvm) { this.enableJvm = enableJvm; } @@ -213,6 +237,22 @@ public class MetricsConfig extends AbstractConfig { this.enableThreadpool = enableThreadpool; } + public Boolean getEnableMetricsInit() { + return enableMetricsInit; + } + + public void setEnableMetricsInit(Boolean enableMetricsInit) { + this.enableMetricsInit = enableMetricsInit; + } + + public Boolean getEnableCollectorSync() { + return enableCollectorSync; + } + + public void setEnableCollectorSync(Boolean enableCollectorSync) { + this.enableCollectorSync = enableCollectorSync; + } + public Boolean getUseGlobalRegistry() { return useGlobalRegistry; } 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 c6be90b3db..20220945ae 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 @@ -26,6 +26,7 @@ import java.util.Map; import java.util.Optional; import static org.apache.dubbo.common.constants.CommonConstants.DUBBO_PROTOCOL; +import static org.apache.dubbo.common.constants.CommonConstants.JSON_CHECK_LEVEL_KEY; import static org.apache.dubbo.common.constants.CommonConstants.SSL_ENABLED_KEY; import static org.apache.dubbo.common.constants.CommonConstants.THREAD_POOL_EXHAUSTED_LISTENERS_KEY; import static org.apache.dubbo.common.constants.LoggerCodeConstants.COMMON_UNEXPECTED_EXCEPTION; @@ -229,6 +230,8 @@ public class ProtocolConfig extends AbstractConfig { */ private String extProtocol; + private String jsonCheckLevel; + public ProtocolConfig() { } @@ -331,6 +334,15 @@ public class ProtocolConfig extends AbstractConfig { this.threadname = threadname; } + @Parameter(key = JSON_CHECK_LEVEL_KEY) + public String getJsonCheckLevel() { + return jsonCheckLevel; + } + + public void setJsonCheckLevel(String jsonCheckLevel) { + this.jsonCheckLevel = jsonCheckLevel; + } + @Parameter(key = THREAD_POOL_EXHAUSTED_LISTENERS_KEY) public String getThreadPoolExhaustedListeners() { return threadPoolExhaustedListeners; diff --git a/dubbo-common/src/main/resources/security/serialize.allowlist b/dubbo-common/src/main/resources/security/serialize.allowlist index 7c781a1e56..bab3d2d932 100644 --- a/dubbo-common/src/main/resources/security/serialize.allowlist +++ b/dubbo-common/src/main/resources/security/serialize.allowlist @@ -83,6 +83,7 @@ java.util.Collections$EmptyList java.util.Collections$EmptyMap java.util.Collections$SingletonSet java.util.Collections$SingletonList +java.util.Collections$SingletonMap java.util.Collections$UnmodifiableCollection java.util.Collections$UnmodifiableList java.util.Collections$UnmodifiableMap diff --git a/dubbo-config/dubbo-config-api/pom.xml b/dubbo-config/dubbo-config-api/pom.xml index 3b00dbb1a0..8c512fe9e4 100644 --- a/dubbo-config/dubbo-config-api/pom.xml +++ b/dubbo-config/dubbo-config-api/pom.xml @@ -249,7 +249,7 @@ org.testcontainers testcontainers - 1.18.3 + 1.19.0 test diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ReferenceConfig.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ReferenceConfig.java index c11f9c3f62..9d8280d312 100644 --- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ReferenceConfig.java +++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ReferenceConfig.java @@ -228,8 +228,13 @@ public class ReferenceConfig extends ReferenceConfigBase { } if (ref == null) { - // ensure start module, compatible with old api usage - getScopeModel().getDeployer().start(); + if (getScopeModel().isLifeCycleManagedExternally()) { + // prepare model for reference + getScopeModel().getDeployer().prepare(); + } else { + // ensure start module, compatible with old api usage + getScopeModel().getDeployer().start(); + } init(check); } 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 c4bccea4c3..decd220679 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 @@ -38,11 +38,15 @@ import org.apache.dubbo.config.invoker.DelegateProviderMetaDataInvoker; import org.apache.dubbo.config.support.Parameter; import org.apache.dubbo.config.utils.ConfigValidationUtils; import org.apache.dubbo.metadata.ServiceNameMapping; +import org.apache.dubbo.metrics.event.MetricsEventBus; +import org.apache.dubbo.metrics.event.MetricsInitEvent; +import org.apache.dubbo.metrics.model.MethodMetric; import org.apache.dubbo.registry.client.metadata.MetadataUtils; import org.apache.dubbo.rpc.Exporter; import org.apache.dubbo.rpc.Invoker; import org.apache.dubbo.rpc.Protocol; import org.apache.dubbo.rpc.ProxyFactory; +import org.apache.dubbo.rpc.RpcInvocation; import org.apache.dubbo.rpc.ServerService; import org.apache.dubbo.rpc.cluster.ConfiguratorFactory; import org.apache.dubbo.rpc.model.ModuleModel; @@ -61,6 +65,7 @@ import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.TreeSet; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; @@ -294,8 +299,13 @@ public class ServiceConfig extends ServiceConfigBase { return; } - // ensure start module, compatible with old api usage - getScopeModel().getDeployer().start(); + if (getScopeModel().isLifeCycleManagedExternally()) { + // prepare model for reference + getScopeModel().getDeployer().prepare(); + } else { + // ensure start module, compatible with old api usage + getScopeModel().getDeployer().start(); + } synchronized (this) { if (this.exported) { @@ -558,6 +568,17 @@ public class ServiceConfig extends ServiceConfigBase { registerType = RegisterTypeEnum.NEVER_REGISTER; } exportUrl(url, registryURLs, registerType); + + initServiceMethodMetrics(url); + } + + private void initServiceMethodMetrics(URL url) { + String[] methods = Optional.ofNullable(url.getParameter(METHODS_KEY)).map(i -> i.split(",")).orElse(new String[]{}); + boolean serviceLevel = MethodMetric.isServiceLevel(application.getApplicationModel()); + Arrays.stream(methods).forEach(method -> { + RpcInvocation invocation = new RpcInvocation(url.getServiceKey(), url.getServiceModel(), method, interfaceName, url.getProtocolServiceKey(), null, null, null, null, null, null); + MetricsEventBus.publish(MetricsInitEvent.toMetricsInitEvent(application.getApplicationModel(), invocation, serviceLevel)); + }); } private void processServiceExecutor(URL url) { 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 dad986d200..4d81c1497b 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 @@ -391,6 +391,7 @@ public class DefaultApplicationDeployer extends AbstractDeployerThe spring config module of dubbo project false - 2.7.14 + 2.7.15 @@ -73,7 +73,7 @@ org.aspectj aspectjweaver - 1.9.20 + 1.9.20.1 test diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/ReferenceBean.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/ReferenceBean.java index edad8afd0e..28d0ef0973 100644 --- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/ReferenceBean.java +++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/ReferenceBean.java @@ -25,6 +25,7 @@ import org.apache.dubbo.common.utils.ClassUtils; import org.apache.dubbo.common.utils.StringUtils; import org.apache.dubbo.config.ReferenceConfig; import org.apache.dubbo.config.spring.aot.AotWithSpringDetector; +import org.apache.dubbo.config.spring.context.DubboConfigApplicationListener; import org.apache.dubbo.config.spring.context.DubboConfigBeanInitializer; import org.apache.dubbo.config.spring.reference.ReferenceAttributes; import org.apache.dubbo.config.spring.reference.ReferenceBeanManager; @@ -54,6 +55,7 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import static org.apache.dubbo.common.constants.LoggerCodeConstants.CONFIG_DUBBO_BEAN_INITIALIZER; import static org.apache.dubbo.common.constants.LoggerCodeConstants.PROXY_FAILED; @@ -143,6 +145,9 @@ public class ReferenceBean implements FactoryBean, //actual reference config private ReferenceConfig referenceConfig; + // ReferenceBeanManager + private ReferenceBeanManager referenceBeanManager; + // Registration sources of this reference, may be xml file or annotation location private List> sources = new ArrayList<>(); @@ -256,7 +261,7 @@ public class ReferenceBean implements FactoryBean, } Assert.notNull(this.interfaceName, "The interface name of ReferenceBean is not initialized"); - ReferenceBeanManager referenceBeanManager = beanFactory.getBean(ReferenceBeanManager.BEAN_NAME, ReferenceBeanManager.class); + this.referenceBeanManager = beanFactory.getBean(ReferenceBeanManager.BEAN_NAME, ReferenceBeanManager.class); referenceBeanManager.addReference(this); } @@ -393,7 +398,9 @@ public class ReferenceBean implements FactoryBean, private Object getCallProxy() throws Exception { if (referenceConfig == null) { - throw new IllegalStateException("ReferenceBean is not ready yet, please make sure to call reference interface method after dubbo is started."); + referenceBeanManager.initReferenceBean(this); + applicationContext.getBean(DubboConfigApplicationListener.class.getName(), DubboConfigApplicationListener.class).init(); + logger.warn(CONFIG_DUBBO_BEAN_INITIALIZER, "", "", "ReferenceBean is not ready yet, please make sure to call reference interface method after dubbo is started."); } //get reference proxy //Subclasses should synchronize on the given Object if they perform any sort of extended singleton creation phase. diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/ReferenceAnnotationBeanPostProcessor.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/ReferenceAnnotationBeanPostProcessor.java index 1e4d033b8d..0f43babab7 100644 --- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/ReferenceAnnotationBeanPostProcessor.java +++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/ReferenceAnnotationBeanPostProcessor.java @@ -110,10 +110,10 @@ public class ReferenceAnnotationBeanPostProcessor extends AbstractAnnotationBean private final ConcurrentMap injectedMethodReferenceBeanCache = new ConcurrentHashMap<>(CACHE_SIZE); - private ApplicationContext applicationContext; + protected ApplicationContext applicationContext; - private ReferenceBeanManager referenceBeanManager; - private BeanDefinitionRegistry beanDefinitionRegistry; + protected ReferenceBeanManager referenceBeanManager; + protected BeanDefinitionRegistry beanDefinitionRegistry; /** * {@link com.alibaba.dubbo.config.annotation.Reference @com.alibaba.dubbo.config.annotation.Reference} has been supported since 2.7.3 @@ -211,7 +211,7 @@ public class ReferenceAnnotationBeanPostProcessor extends AbstractAnnotationBean * @param beanName * @param beanDefinition */ - private void processReferenceAnnotatedBeanDefinition(String beanName, AnnotatedBeanDefinition beanDefinition) { + protected void processReferenceAnnotatedBeanDefinition(String beanName, AnnotatedBeanDefinition beanDefinition) { MethodMetadata factoryMethodMetadata = SpringCompatUtils.getFactoryMethodMetadata(beanDefinition); @@ -500,6 +500,9 @@ public class ReferenceAnnotationBeanPostProcessor extends AbstractAnnotationBean beanDefinition.setAttribute(ReferenceAttributes.INTERFACE_CLASS, interfaceClass); beanDefinition.setAttribute(ReferenceAttributes.INTERFACE_NAME, interfaceName); + beanDefinition.getPropertyValues().add(ReferenceAttributes.INTERFACE_CLASS, interfaceClass); + beanDefinition.getPropertyValues().add(ReferenceAttributes.INTERFACE_NAME, interfaceName); + // create decorated definition for reference bean, Avoid being instantiated when getting the beanType of ReferenceBean // see org.springframework.beans.factory.support.AbstractBeanFactory#getTypeForFactoryBean() GenericBeanDefinition targetDefinition = new GenericBeanDefinition(); diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/ServiceAnnotationPostProcessor.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/ServiceAnnotationPostProcessor.java index 43f1ae5a19..87f1e74f1f 100644 --- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/ServiceAnnotationPostProcessor.java +++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/ServiceAnnotationPostProcessor.java @@ -238,7 +238,7 @@ public class ServiceAnnotationPostProcessor implements BeanDefinitionRegistryPos } } else { if (logger.isWarnEnabled()) { - logger.warn(CONFIG_NO_ANNOTATIONS_FOUND, "No annotations were found on the class", "", "No class annotated by Dubbo @Service was found under package [" + logger.warn(CONFIG_NO_ANNOTATIONS_FOUND, "No annotations were found on the class", "", "No class annotated by Dubbo @DubboService or @Service was found under package [" + packageToScan + "], ignore re-scanned classes: " + scanExcludeFilter.getExcludedCount()); } } diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboConfigApplicationListener.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboConfigApplicationListener.java index 17343637bb..2cdf512053 100644 --- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboConfigApplicationListener.java +++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboConfigApplicationListener.java @@ -16,21 +16,22 @@ */ package org.apache.dubbo.config.spring.context; -import static org.apache.dubbo.common.constants.LoggerCodeConstants.CONFIG_DUBBO_BEAN_NOT_FOUND; -import static org.springframework.util.ObjectUtils.nullSafeEquals; - -import java.util.concurrent.atomic.AtomicBoolean; - import org.apache.dubbo.common.logger.ErrorTypeAwareLogger; import org.apache.dubbo.common.logger.LoggerFactory; import org.apache.dubbo.config.spring.context.event.DubboConfigInitEvent; import org.apache.dubbo.config.spring.util.DubboBeanUtils; import org.apache.dubbo.rpc.model.ModuleModel; + import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.context.ApplicationListener; +import java.util.concurrent.atomic.AtomicBoolean; + +import static org.apache.dubbo.common.constants.LoggerCodeConstants.CONFIG_DUBBO_BEAN_NOT_FOUND; +import static org.springframework.util.ObjectUtils.nullSafeEquals; + /** * An ApplicationListener to load config beans */ @@ -53,11 +54,15 @@ public class DubboConfigApplicationListener implements ApplicationListener contextMap = new ConcurrentHashMap<>(); + private static final Map REGISTRY_CONTEXT_MAP = new ConcurrentHashMap<>(); public DubboSpringInitializer() { } @@ -54,7 +54,7 @@ public class DubboSpringInitializer { DubboSpringInitContext context = new DubboSpringInitContext(); // Spring ApplicationContext may not ready at this moment (e.g. load from xml), so use registry as key - if (contextMap.putIfAbsent(registry, context) != null) { + if (REGISTRY_CONTEXT_MAP.putIfAbsent(registry, context) != null) { return; } @@ -66,18 +66,18 @@ public class DubboSpringInitializer { } public static boolean remove(BeanDefinitionRegistry registry) { - return contextMap.remove(registry) != null; + return REGISTRY_CONTEXT_MAP.remove(registry) != null; } public static boolean remove(ApplicationContext springContext) { AutowireCapableBeanFactory autowireCapableBeanFactory = springContext.getAutowireCapableBeanFactory(); - for (Map.Entry entry : contextMap.entrySet()) { + for (Map.Entry entry : REGISTRY_CONTEXT_MAP.entrySet()) { DubboSpringInitContext initContext = entry.getValue(); if (initContext.getApplicationContext() == springContext || initContext.getBeanFactory() == autowireCapableBeanFactory || initContext.getRegistry() == autowireCapableBeanFactory ) { - DubboSpringInitContext context = contextMap.remove(entry.getKey()); + DubboSpringInitContext context = REGISTRY_CONTEXT_MAP.remove(entry.getKey()); logger.info("Unbind " + safeGetModelDesc(context.getModuleModel()) + " from spring container: " + ObjectUtils.identityToString(entry.getKey())); return true; @@ -87,11 +87,11 @@ public class DubboSpringInitializer { } static Map getContextMap() { - return contextMap; + return REGISTRY_CONTEXT_MAP; } static DubboSpringInitContext findBySpringContext(ApplicationContext applicationContext) { - for (DubboSpringInitContext initContext : contextMap.values()) { + for (DubboSpringInitContext initContext : REGISTRY_CONTEXT_MAP.values()) { if (initContext.getApplicationContext() == applicationContext) { return initContext; } @@ -184,7 +184,7 @@ public class DubboSpringInitializer { } private static DubboSpringInitContext findContextForApplication(ApplicationModel applicationModel) { - for (DubboSpringInitContext initializationContext : contextMap.values()) { + for (DubboSpringInitContext initializationContext : REGISTRY_CONTEXT_MAP.values()) { if (initializationContext.getApplicationModel() == applicationModel) { return initializationContext; } diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/reference/ReferenceBeanManager.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/reference/ReferenceBeanManager.java index 1ebffa04ea..0e428a8647 100644 --- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/reference/ReferenceBeanManager.java +++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/reference/ReferenceBeanManager.java @@ -157,7 +157,7 @@ public class ReferenceBeanManager implements ApplicationContextAware { * @param referenceBean * @throws Exception */ - private synchronized void initReferenceBean(ReferenceBean referenceBean) throws Exception { + public synchronized void initReferenceBean(ReferenceBean referenceBean) throws Exception { if (referenceBean.getReferenceConfig() != null) { return; 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 ea3e643132..7477b12ecc 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 @@ -520,6 +520,11 @@ + + + + + @@ -1115,6 +1120,11 @@ + + + + + @@ -1692,6 +1702,11 @@ + + + + + diff --git a/dubbo-config/dubbo-config-spring/src/test/resources/META-INF/isolation/dubbo-provider.xml b/dubbo-config/dubbo-config-spring/src/test/resources/META-INF/isolation/dubbo-provider.xml index cff46ead4a..72b8007233 100644 --- a/dubbo-config/dubbo-config-spring/src/test/resources/META-INF/isolation/dubbo-provider.xml +++ b/dubbo-config/dubbo-config-spring/src/test/resources/META-INF/isolation/dubbo-provider.xml @@ -27,7 +27,7 @@ - + diff --git a/dubbo-config/dubbo-config-spring6/src/main/java/org/apache/dubbo/config/spring6/beans/factory/annotation/ReferenceAnnotationWithAotBeanPostProcessor.java b/dubbo-config/dubbo-config-spring6/src/main/java/org/apache/dubbo/config/spring6/beans/factory/annotation/ReferenceAnnotationWithAotBeanPostProcessor.java index 37d67bf2de..3104ef00c3 100644 --- a/dubbo-config/dubbo-config-spring6/src/main/java/org/apache/dubbo/config/spring6/beans/factory/annotation/ReferenceAnnotationWithAotBeanPostProcessor.java +++ b/dubbo-config/dubbo-config-spring6/src/main/java/org/apache/dubbo/config/spring6/beans/factory/annotation/ReferenceAnnotationWithAotBeanPostProcessor.java @@ -19,26 +19,17 @@ package org.apache.dubbo.config.spring6.beans.factory.annotation; import org.apache.dubbo.common.logger.ErrorTypeAwareLogger; import org.apache.dubbo.common.logger.LoggerFactory; -import org.apache.dubbo.common.utils.ArrayUtils; -import org.apache.dubbo.common.utils.Assert; import org.apache.dubbo.common.utils.ClassUtils; -import org.apache.dubbo.common.utils.StringUtils; import org.apache.dubbo.config.annotation.DubboReference; -import org.apache.dubbo.config.annotation.Reference; -import org.apache.dubbo.config.spring.Constants; import org.apache.dubbo.config.spring.ReferenceBean; -import org.apache.dubbo.config.spring.beans.factory.annotation.AbstractAnnotationBeanPostProcessor; +import org.apache.dubbo.config.spring.beans.factory.annotation.ReferenceAnnotationBeanPostProcessor; import org.apache.dubbo.config.spring.context.event.DubboConfigInitEvent; -import org.apache.dubbo.config.spring.reference.ReferenceAttributes; -import org.apache.dubbo.config.spring.reference.ReferenceBeanManager; -import org.apache.dubbo.config.spring.reference.ReferenceBeanSupport; import org.apache.dubbo.config.spring.util.SpringCompatUtils; import org.apache.dubbo.config.spring6.beans.factory.aot.ReferencedFieldValueResolver; import org.apache.dubbo.config.spring6.beans.factory.aot.ReferencedMethodArgumentsResolver; import org.apache.dubbo.config.spring6.utils.AotUtils; import org.apache.dubbo.rpc.service.Destroyable; import org.apache.dubbo.rpc.service.EchoService; -import org.apache.dubbo.rpc.service.GenericService; import org.springframework.aop.SpringProxy; import org.springframework.aop.framework.Advised; import org.springframework.aot.generate.AccessControl; @@ -51,100 +42,44 @@ import org.springframework.aot.hint.RuntimeHints; import org.springframework.aot.hint.TypeReference; import org.springframework.aot.hint.support.ClassHintUtils; import org.springframework.beans.BeansException; -import org.springframework.beans.PropertyValue; -import org.springframework.beans.PropertyValues; -import org.springframework.beans.factory.BeanCreationException; import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition; -import org.springframework.beans.factory.annotation.InjectionMetadata; import org.springframework.beans.factory.aot.AutowiredArgumentsCodeGenerator; import org.springframework.beans.factory.aot.BeanRegistrationAotContribution; import org.springframework.beans.factory.aot.BeanRegistrationAotProcessor; import org.springframework.beans.factory.aot.BeanRegistrationCode; import org.springframework.beans.factory.config.BeanDefinition; -import org.springframework.beans.factory.config.BeanDefinitionHolder; -import org.springframework.beans.factory.config.BeanFactoryPostProcessor; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.config.DependencyDescriptor; import org.springframework.beans.factory.support.AutowireCandidateResolver; -import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.beans.factory.support.DefaultListableBeanFactory; -import org.springframework.beans.factory.support.GenericBeanDefinition; import org.springframework.beans.factory.support.RegisteredBean; import org.springframework.beans.factory.support.RootBeanDefinition; -import org.springframework.context.ApplicationContext; -import org.springframework.context.ApplicationContextAware; import org.springframework.core.DecoratingProxy; import org.springframework.core.MethodParameter; import org.springframework.core.annotation.AnnotationAttributes; -import org.springframework.core.type.MethodMetadata; import org.springframework.javapoet.ClassName; import org.springframework.javapoet.CodeBlock; import org.springframework.lang.Nullable; import org.springframework.util.CollectionUtils; -import java.beans.PropertyDescriptor; -import java.lang.annotation.Annotation; import java.lang.reflect.Field; import java.lang.reflect.Member; import java.lang.reflect.Method; import java.lang.reflect.Parameter; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; -import static com.alibaba.spring.util.AnnotationUtils.getAttribute; import static org.apache.dubbo.common.constants.LoggerCodeConstants.CONFIG_DUBBO_BEAN_INITIALIZER; -import static org.apache.dubbo.common.utils.AnnotationUtils.filterDefaultValues; -import static org.springframework.util.StringUtils.hasText; /** - *

- * Step 1: - * The purpose of implementing {@link BeanFactoryPostProcessor} is to scan the registration reference bean definition earlier, - * so that it can be shared with the xml bean configuration. - *

+ * The purpose of implementing {@link BeanRegistrationAotProcessor} is to + * supplement for {@link ReferenceAnnotationBeanPostProcessor} ability of AOT. * - *

- * Step 2: - * By implementing {@link org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor}, - * inject the reference bean instance into the fields and setter methods which annotated with {@link DubboReference}. - *

- * - * @see DubboReference - * @see Reference - * @see com.alibaba.dubbo.config.annotation.Reference - * @since 2.5.7 + * @since 3.3 */ -public class ReferenceAnnotationWithAotBeanPostProcessor extends AbstractAnnotationBeanPostProcessor - implements ApplicationContextAware, BeanRegistrationAotProcessor, BeanFactoryPostProcessor { - - /** - * The bean name of {@link ReferenceAnnotationWithAotBeanPostProcessor} - */ - public static final String BEAN_NAME = ReferenceAnnotationWithAotBeanPostProcessor.class.getName(); - - /** - * Cache size - */ - private static final int CACHE_SIZE = Integer.getInteger(BEAN_NAME + ".cache.size", 32); +public class ReferenceAnnotationWithAotBeanPostProcessor extends ReferenceAnnotationBeanPostProcessor + implements BeanRegistrationAotProcessor { private final ErrorTypeAwareLogger logger = LoggerFactory.getErrorTypeAwareLogger(getClass()); - private final ConcurrentMap injectedFieldReferenceBeanCache = - new ConcurrentHashMap<>(CACHE_SIZE); - - private final ConcurrentMap injectedMethodReferenceBeanCache = - new ConcurrentHashMap<>(CACHE_SIZE); - - private ApplicationContext applicationContext; - - private ReferenceBeanManager referenceBeanManager; - private BeanDefinitionRegistry beanDefinitionRegistry; @Nullable private ConfigurableListableBeanFactory beanFactory; @@ -155,7 +90,7 @@ public class ReferenceAnnotationWithAotBeanPostProcessor extends AbstractAnnotat * {@link DubboReference @DubboReference} has been supported since 2.7.7 */ public ReferenceAnnotationWithAotBeanPostProcessor() { - super(DubboReference.class, Reference.class, com.alibaba.dubbo.config.annotation.Reference.class); + super(); } @Override @@ -192,18 +127,6 @@ public class ReferenceAnnotationWithAotBeanPostProcessor extends AbstractAnnotat } } -// if (beanFactory instanceof AbstractBeanFactory) { -// List beanPostProcessors = ((AbstractBeanFactory) beanFactory).getBeanPostProcessors(); -// for (BeanPostProcessor beanPostProcessor : beanPostProcessors) { -// if (beanPostProcessor == this) { -// // This bean has been registered as BeanPostProcessor at org.apache.dubbo.config.spring.context.DubboInfraBeanRegisterPostProcessor.postProcessBeanFactory() -// // so destroy this bean here, prevent register it as BeanPostProcessor again, avoid cause BeanPostProcessorChecker detection error -// beanDefinitionRegistry.removeBeanDefinition(BEAN_NAME); -// break; -// } -// } -// } - try { // this is an early event, it will be notified at org.springframework.context.support.AbstractApplicationContext.registerListeners() applicationContext.publishEvent(new DubboConfigInitEvent(applicationContext)); @@ -227,157 +150,6 @@ public class ReferenceAnnotationWithAotBeanPostProcessor extends AbstractAnnotat return false; } - /** - * process @DubboReference at java-config @bean method - *
-     * @Configuration
-     * public class ConsumerConfig {
-     *
-     *      @Bean
-     *      @DubboReference(group="demo", version="1.2.3")
-     *      public ReferenceBean<DemoService> demoService() {
-     *          return new ReferenceBean();
-     *      }
-     *
-     * }
-     * 
- * - * @param beanName - * @param beanDefinition - */ - private void processReferenceAnnotatedBeanDefinition(String beanName, AnnotatedBeanDefinition beanDefinition) { - - MethodMetadata factoryMethodMetadata = SpringCompatUtils.getFactoryMethodMetadata(beanDefinition); - - // Extract beanClass from generic return type of java-config bean method: ReferenceBean - // see org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.getTypeForFactoryBeanFromMethod - Class beanClass = getBeanFactory().getType(beanName); - if (beanClass == Object.class) { - beanClass = SpringCompatUtils.getGenericTypeOfReturnType(factoryMethodMetadata); - } - if (beanClass == Object.class) { - // bean class is invalid, ignore it - return; - } - - if (beanClass == null) { - String beanMethodSignature = factoryMethodMetadata.getDeclaringClassName() + "#" + factoryMethodMetadata.getMethodName() + "()"; - throw new BeanCreationException("The ReferenceBean is missing necessary generic type, which returned by the @Bean method of Java-config class. " + - "The generic type of the returned ReferenceBean must be specified as the referenced interface type, " + - "such as ReferenceBean. Please check bean method: " + beanMethodSignature); - } - - // get dubbo reference annotation attributes - Map annotationAttributes = null; - // try all dubbo reference annotation types - for (Class annotationType : getAnnotationTypes()) { - if (factoryMethodMetadata.isAnnotated(annotationType.getName())) { - // Since Spring 5.2 - // return factoryMethodMetadata.getAnnotations().get(annotationType).filterDefaultValues().asMap(); - // Compatible with Spring 4.x - annotationAttributes = factoryMethodMetadata.getAnnotationAttributes(annotationType.getName()); - annotationAttributes = filterDefaultValues(annotationType, annotationAttributes); - break; - } - } - - if (annotationAttributes != null) { - // @DubboReference on @Bean method - LinkedHashMap attributes = new LinkedHashMap<>(annotationAttributes); - // reset id attribute - attributes.put(ReferenceAttributes.ID, beanName); - // convert annotation props - ReferenceBeanSupport.convertReferenceProps(attributes, beanClass); - - // get interface - String interfaceName = (String) attributes.get(ReferenceAttributes.INTERFACE); - - // check beanClass and reference interface class - if (!StringUtils.isEquals(interfaceName, beanClass.getName()) && beanClass != GenericService.class) { - String beanMethodSignature = factoryMethodMetadata.getDeclaringClassName() + "#" + factoryMethodMetadata.getMethodName() + "()"; - throw new BeanCreationException("The 'interfaceClass' or 'interfaceName' attribute value of @DubboReference annotation " + - "is inconsistent with the generic type of the ReferenceBean returned by the bean method. " + - "The interface class of @DubboReference is: " + interfaceName + ", but return ReferenceBean<" + beanClass.getName() + ">. " + - "Please remove the 'interfaceClass' and 'interfaceName' attributes from @DubboReference annotation. " + - "Please check bean method: " + beanMethodSignature); - } - - Class interfaceClass = beanClass; - - // set attribute instead of property values - beanDefinition.setAttribute(Constants.REFERENCE_PROPS, attributes); - beanDefinition.setAttribute(ReferenceAttributes.INTERFACE_CLASS, interfaceClass); - beanDefinition.setAttribute(ReferenceAttributes.INTERFACE_NAME, interfaceName); - } else { - // raw reference bean - // the ReferenceBean is not yet initialized - beanDefinition.setAttribute(ReferenceAttributes.INTERFACE_CLASS, beanClass); - if (beanClass != GenericService.class) { - beanDefinition.setAttribute(ReferenceAttributes.INTERFACE_NAME, beanClass.getName()); - } - } - - // set id - beanDefinition.getPropertyValues().add(ReferenceAttributes.ID, beanName); - } - - @Override - public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class beanType, String beanName) { - if (beanType != null) { - if (isReferenceBean(beanDefinition)) { - //mark property value as optional - List propertyValues = beanDefinition.getPropertyValues().getPropertyValueList(); - for (PropertyValue propertyValue : propertyValues) { - propertyValue.setOptional(true); - } - } else if (isAnnotatedReferenceBean(beanDefinition)) { - // extract beanClass from java-config bean method generic return type: ReferenceBean - //Class beanClass = getBeanFactory().getType(beanName); - } else { - AnnotatedInjectionMetadata metadata = findInjectionMetadata(beanName, beanType, null); - metadata.checkConfigMembers(beanDefinition); - try { - prepareInjection(metadata); - } catch (Exception e) { - throw new IllegalStateException("Prepare dubbo reference injection element failed", e); - } - } - } - } - - /** - * Alternatives to the {@link #postProcessProperties(PropertyValues, Object, String)}, that removed as of Spring - * Framework 6.0.0, and in favor of {@link #postProcessProperties(PropertyValues, Object, String)}. - *

In order to be compatible with the lower version of Spring, it is still retained. - * - * @see #postProcessProperties - */ - public PropertyValues postProcessPropertyValues( - PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException { - return postProcessProperties(pvs, bean, beanName); - } - - /** - * Alternatives to the {@link #postProcessPropertyValues(PropertyValues, PropertyDescriptor[], Object, String)}. - * - * @see #postProcessPropertyValues - */ - @Override - public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) - throws BeansException { - try { - AnnotatedInjectionMetadata metadata = findInjectionMetadata(beanName, bean.getClass(), pvs); - prepareInjection(metadata); - metadata.inject(bean, beanName, pvs); - } catch (BeansException ex) { - throw ex; - } catch (Throwable ex) { - throw new BeanCreationException(beanName, "Injection of @" + getAnnotationType().getSimpleName() - + " dependencies is failed", ex); - } - return pvs; - } - private boolean isReferenceBean(BeanDefinition beanDefinition) { return ReferenceBean.class.getName().equals(beanDefinition.getBeanClassName()); } @@ -401,238 +173,6 @@ public class ReferenceAnnotationWithAotBeanPostProcessor extends AbstractAnnotat return metadata; } - protected void prepareInjection(AnnotatedInjectionMetadata metadata) throws BeansException { - try { - //find and register bean definition for @DubboReference/@Reference - for (AnnotatedFieldElement fieldElement : metadata.getFieldElements()) { - if (fieldElement.injectedObject != null) { - continue; - } - Class injectedType = fieldElement.field.getType(); - AnnotationAttributes attributes = fieldElement.attributes; - String referenceBeanName = registerReferenceBean(fieldElement.getPropertyName(), injectedType, attributes, fieldElement.field); - - //associate fieldElement and reference bean - fieldElement.injectedObject = referenceBeanName; - injectedFieldReferenceBeanCache.put(fieldElement, referenceBeanName); - - } - - for (AnnotatedMethodElement methodElement : metadata.getMethodElements()) { - if (methodElement.injectedObject != null) { - continue; - } - Class injectedType = methodElement.getInjectedType(); - AnnotationAttributes attributes = methodElement.attributes; - String referenceBeanName = registerReferenceBean(methodElement.getPropertyName(), injectedType, attributes, methodElement.method); - - //associate methodElement and reference bean - methodElement.injectedObject = referenceBeanName; - injectedMethodReferenceBeanCache.put(methodElement, referenceBeanName); - } - } catch (ClassNotFoundException e) { - throw new BeanCreationException("prepare reference annotation failed", e); - } - } - - public String registerReferenceBean(String propertyName, Class injectedType, Map attributes, Member member) throws BeansException { - - boolean renameable = true; - // referenceBeanName - String referenceBeanName = getAttribute(attributes, ReferenceAttributes.ID); - if (hasText(referenceBeanName)) { - renameable = false; - } else { - referenceBeanName = propertyName; - } - - String checkLocation = "Please check " + member.toString(); - - // convert annotation props - ReferenceBeanSupport.convertReferenceProps(attributes, injectedType); - - // get interface - String interfaceName = (String) attributes.get(ReferenceAttributes.INTERFACE); - if (StringUtils.isBlank(interfaceName)) { - throw new BeanCreationException("Need to specify the 'interfaceName' or 'interfaceClass' attribute of '@DubboReference' if enable generic. " + checkLocation); - } - - // check reference key - String referenceKey = ReferenceBeanSupport.generateReferenceKey(attributes, applicationContext); - - // find reference bean name by reference key - List registeredReferenceBeanNames = referenceBeanManager.getBeanNamesByKey(referenceKey); - if (registeredReferenceBeanNames.size() > 0) { - // found same name and reference key - if (registeredReferenceBeanNames.contains(referenceBeanName)) { - return referenceBeanName; - } - } - - //check bean definition - boolean isContains; - if ((isContains = beanDefinitionRegistry.containsBeanDefinition(referenceBeanName)) || beanDefinitionRegistry.isAlias(referenceBeanName)) { - String preReferenceBeanName = referenceBeanName; - if (!isContains) { - // Look in the alias for the origin bean name - String[] aliases = beanDefinitionRegistry.getAliases(referenceBeanName); - if (ArrayUtils.isNotEmpty(aliases)) { - for (String alias : aliases) { - if (beanDefinitionRegistry.containsBeanDefinition(alias)) { - preReferenceBeanName = alias; - break; - } - } - } - } - BeanDefinition prevBeanDefinition = beanDefinitionRegistry.getBeanDefinition(preReferenceBeanName); - String prevBeanType = prevBeanDefinition.getBeanClassName(); - String prevBeanDesc = referenceBeanName + "[" + prevBeanType + "]"; - String newBeanDesc = referenceBeanName + "[" + referenceKey + "]"; - - if (isReferenceBean(prevBeanDefinition)) { - //check reference key - String prevReferenceKey = ReferenceBeanSupport.generateReferenceKey(prevBeanDefinition, applicationContext); - if (StringUtils.isEquals(prevReferenceKey, referenceKey)) { - //found matched dubbo reference bean, ignore register - return referenceBeanName; - } - //get interfaceName from attribute - Assert.notNull(prevBeanDefinition, "The interface class of ReferenceBean is not initialized"); - prevBeanDesc = referenceBeanName + "[" + prevReferenceKey + "]"; - } - - // bean name from attribute 'id' or java-config bean, cannot be renamed - if (!renameable) { - throw new BeanCreationException("Already exists another bean definition with the same bean name [" + referenceBeanName + "], " + - "but cannot rename the reference bean name (specify the id attribute or java-config bean), " + - "please modify the name of one of the beans: " + - "prev: " + prevBeanDesc + ", new: " + newBeanDesc + ". " + checkLocation); - } - - // the prev bean type is different, rename the new reference bean - int index = 2; - String newReferenceBeanName = null; - while (newReferenceBeanName == null || beanDefinitionRegistry.containsBeanDefinition(newReferenceBeanName) - || beanDefinitionRegistry.isAlias(newReferenceBeanName)) { - newReferenceBeanName = referenceBeanName + "#" + index; - index++; - // double check found same name and reference key - if (registeredReferenceBeanNames.contains(newReferenceBeanName)) { - return newReferenceBeanName; - } - } - newBeanDesc = newReferenceBeanName + "[" + referenceKey + "]"; - - logger.warn(CONFIG_DUBBO_BEAN_INITIALIZER, "", "", "Already exists another bean definition with the same bean name [" + referenceBeanName + "], " + - "rename dubbo reference bean to [" + newReferenceBeanName + "]. " + - "It is recommended to modify the name of one of the beans to avoid injection problems. " + - "prev: " + prevBeanDesc + ", new: " + newBeanDesc + ". " + checkLocation); - referenceBeanName = newReferenceBeanName; - } - attributes.put(ReferenceAttributes.ID, referenceBeanName); - - // If registered matched reference before, just register alias - if (registeredReferenceBeanNames.size() > 0) { - beanDefinitionRegistry.registerAlias(registeredReferenceBeanNames.get(0), referenceBeanName); - referenceBeanManager.registerReferenceKeyAndBeanName(referenceKey, referenceBeanName); - return referenceBeanName; - } - - Class interfaceClass = injectedType; - - // TODO Only register one reference bean for same (group, interface, version) - - // Register the reference bean definition to the beanFactory - RootBeanDefinition beanDefinition = new RootBeanDefinition(); - beanDefinition.setBeanClassName(ReferenceBean.class.getName()); - beanDefinition.getPropertyValues().add(ReferenceAttributes.ID, referenceBeanName); - - // set attribute instead of property values - beanDefinition.setAttribute(Constants.REFERENCE_PROPS, attributes); - beanDefinition.setAttribute(ReferenceAttributes.INTERFACE_CLASS, interfaceClass); - beanDefinition.setAttribute(ReferenceAttributes.INTERFACE_NAME, interfaceName); -// beanDefinition.getPropertyValues().add(Constants.REFERENCE_PROPS,attributes); - beanDefinition.getPropertyValues().add(ReferenceAttributes.INTERFACE_CLASS, interfaceClass); - beanDefinition.getPropertyValues().add(ReferenceAttributes.INTERFACE_NAME, interfaceName); - // create decorated definition for reference bean, Avoid being instantiated when getting the beanType of ReferenceBean - // see org.springframework.beans.factory.support.AbstractBeanFactory#getTypeForFactoryBean() - GenericBeanDefinition targetDefinition = new GenericBeanDefinition(); - targetDefinition.setBeanClass(interfaceClass); - beanDefinition.setDecoratedDefinition(new BeanDefinitionHolder(targetDefinition, referenceBeanName + "_decorated")); - - // signal object type since Spring 5.2 - beanDefinition.setAttribute(Constants.OBJECT_TYPE_ATTRIBUTE, interfaceClass); - - beanDefinitionRegistry.registerBeanDefinition(referenceBeanName, beanDefinition); - referenceBeanManager.registerReferenceKeyAndBeanName(referenceKey, referenceBeanName); - logger.info("Register dubbo reference bean: " + referenceBeanName + " = " + referenceKey + " at " + member); - return referenceBeanName; - } - - @Override - protected Object doGetInjectedBean(AnnotationAttributes attributes, Object bean, String beanName, Class injectedType, - AnnotatedInjectElement injectedElement) throws Exception { - - if (injectedElement.injectedObject == null) { - throw new IllegalStateException("The AnnotatedInjectElement of @DubboReference should be inited before injection"); - } - - return getBeanFactory().getBean((String) injectedElement.injectedObject); - } - - @Override - public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { - this.applicationContext = applicationContext; - this.referenceBeanManager = applicationContext.getBean(ReferenceBeanManager.BEAN_NAME, ReferenceBeanManager.class); - this.beanDefinitionRegistry = (BeanDefinitionRegistry) applicationContext.getAutowireCapableBeanFactory(); - } - - @Override - public void destroy() throws Exception { - super.destroy(); - this.injectedFieldReferenceBeanCache.clear(); - this.injectedMethodReferenceBeanCache.clear(); - } - - /** - * Gets all beans of {@link ReferenceBean} - * - * @deprecated use {@link ReferenceBeanManager#getReferences()} instead - */ - @Deprecated - public Collection> getReferenceBeans() { - return Collections.emptyList(); - } - - /** - * Get {@link ReferenceBean} {@link Map} in injected field. - * - * @return non-null {@link Map} - * @since 2.5.11 - */ - public Map> getInjectedFieldReferenceBeanMap() { - Map> map = new HashMap<>(); - for (Map.Entry entry : injectedFieldReferenceBeanCache.entrySet()) { - map.put(entry.getKey(), referenceBeanManager.getById(entry.getValue())); - } - return Collections.unmodifiableMap(map); - } - - /** - * Get {@link ReferenceBean} {@link Map} in injected method. - * - * @return non-null {@link Map} - * @since 2.5.11 - */ - public Map> getInjectedMethodReferenceBeanMap() { - Map> map = new HashMap<>(); - for (Map.Entry entry : injectedMethodReferenceBeanCache.entrySet()) { - map.put(entry.getKey(), referenceBeanManager.getById(entry.getValue())); - } - return Collections.unmodifiableMap(map); - } - @Nullable private AutowireCandidateResolver getAutowireCandidateResolver() { if (this.beanFactory instanceof DefaultListableBeanFactory) { @@ -665,19 +205,19 @@ public class ReferenceAnnotationWithAotBeanPostProcessor extends AbstractAnnotat @Override public void applyTo(GenerationContext generationContext, BeanRegistrationCode beanRegistrationCode) { GeneratedClass generatedClass = generationContext.getGeneratedClasses() - .addForFeatureComponent("DubboReference", this.target, type -> { - type.addJavadoc("DubboReference for {@link $T}.", this.target); - type.addModifiers(javax.lang.model.element.Modifier.PUBLIC); - }); + .addForFeatureComponent("DubboReference", this.target, type -> { + type.addJavadoc("DubboReference for {@link $T}.", this.target); + type.addModifiers(javax.lang.model.element.Modifier.PUBLIC); + }); GeneratedMethod generateMethod = generatedClass.getMethods().add("apply", method -> { method.addJavadoc("Apply the dubbo reference."); method.addModifiers(javax.lang.model.element.Modifier.PUBLIC, - javax.lang.model.element.Modifier.STATIC); + javax.lang.model.element.Modifier.STATIC); method.addParameter(RegisteredBean.class, REGISTERED_BEAN_PARAMETER); method.addParameter(this.target, INSTANCE_PARAMETER); method.returns(this.target); method.addCode(generateMethodCode(generatedClass.getName(), - generationContext.getRuntimeHints())); + generationContext.getRuntimeHints())); }); beanRegistrationCode.addInstancePostProcessor(generateMethod.toMethodReference()); @@ -691,13 +231,13 @@ public class ReferenceAnnotationWithAotBeanPostProcessor extends AbstractAnnotat if (!CollectionUtils.isEmpty(this.annotatedInjectionMetadata.getFieldElements())) { for (AnnotatedInjectElement referenceElement : this.annotatedInjectionMetadata.getFieldElements()) { code.addStatement(generateMethodStatementForElement( - targetClassName, referenceElement, hints)); + targetClassName, referenceElement, hints)); } } if (!CollectionUtils.isEmpty(this.annotatedInjectionMetadata.getMethodElements())) { for (AnnotatedInjectElement referenceElement : this.annotatedInjectionMetadata.getMethodElements()) { code.addStatement(generateMethodStatementForElement( - targetClassName, referenceElement, hints)); + targetClassName, referenceElement, hints)); } } code.addStatement("return $L", INSTANCE_PARAMETER); @@ -723,14 +263,14 @@ public class ReferenceAnnotationWithAotBeanPostProcessor extends AbstractAnnotat if (member instanceof Field) { return generateMethodStatementForField( - targetClassName, (Field) member, attributes, injectedObject, hints); + targetClassName, (Field) member, attributes, injectedObject, hints); } if (member instanceof Method) { return generateMethodStatementForMethod( - targetClassName, (Method) member, attributes, injectedObject, hints); + targetClassName, (Method) member, attributes, injectedObject, hints); } throw new IllegalStateException( - "Unsupported member type " + member.getClass().getName()); + "Unsupported member type " + member.getClass().getName()); } private CodeBlock generateMethodStatementForField(ClassName targetClassName, @@ -738,17 +278,17 @@ public class ReferenceAnnotationWithAotBeanPostProcessor extends AbstractAnnotat hints.reflection().registerField(field); CodeBlock resolver = CodeBlock.of("$T.$L($S)", - ReferencedFieldValueResolver.class, - "forRequiredField", field.getName()); + ReferencedFieldValueResolver.class, + "forRequiredField", field.getName()); CodeBlock shortcutResolver = CodeBlock.of("$L.withShortcut($S)", resolver, injectedObject); AccessControl accessControl = AccessControl.forMember(field); if (!accessControl.isAccessibleFrom(targetClassName)) { return CodeBlock.of("$L.resolveAndSet($L, $L)", shortcutResolver, - REGISTERED_BEAN_PARAMETER, INSTANCE_PARAMETER); + REGISTERED_BEAN_PARAMETER, INSTANCE_PARAMETER); } return CodeBlock.of("$L.$L = $L.resolve($L)", INSTANCE_PARAMETER, - field.getName(), shortcutResolver, REGISTERED_BEAN_PARAMETER); + field.getName(), shortcutResolver, REGISTERED_BEAN_PARAMETER); } private CodeBlock generateMethodStatementForMethod(ClassName targetClassName, @@ -776,9 +316,9 @@ public class ReferenceAnnotationWithAotBeanPostProcessor extends AbstractAnnotat } else { hints.reflection().registerMethod(method, ExecutableMode.INTROSPECT); CodeBlock arguments = new AutowiredArgumentsCodeGenerator(this.target, - method).generateCode(method.getParameterTypes()); + method).generateCode(method.getParameterTypes()); CodeBlock injectionCode = CodeBlock.of("args -> $L.$L($L)", - INSTANCE_PARAMETER, method.getName(), arguments); + INSTANCE_PARAMETER, method.getName(), arguments); code.add(".resolve($L, $L)", REGISTERED_BEAN_PARAMETER, injectionCode); } return code.build(); @@ -832,7 +372,7 @@ public class ReferenceAnnotationWithAotBeanPostProcessor extends AbstractAnnotat private void registerProxyIfNecessary(RuntimeHints runtimeHints, DependencyDescriptor dependencyDescriptor) { if (this.candidateResolver != null) { Class proxyClass = - this.candidateResolver.getLazyResolutionProxyClass(dependencyDescriptor, null); + this.candidateResolver.getLazyResolutionProxyClass(dependencyDescriptor, null); if (proxyClass != null) { ClassHintUtils.registerProxyIfNecessary(proxyClass, runtimeHints); } diff --git a/dubbo-config/dubbo-config-spring6/src/main/java/org/apache/dubbo/config/spring6/beans/factory/annotation/ServiceAnnotationWithAotPostProcessor.java b/dubbo-config/dubbo-config-spring6/src/main/java/org/apache/dubbo/config/spring6/beans/factory/annotation/ServiceAnnotationWithAotPostProcessor.java index 03210dc72d..738b1b940a 100644 --- a/dubbo-config/dubbo-config-spring6/src/main/java/org/apache/dubbo/config/spring6/beans/factory/annotation/ServiceAnnotationWithAotPostProcessor.java +++ b/dubbo-config/dubbo-config-spring6/src/main/java/org/apache/dubbo/config/spring6/beans/factory/annotation/ServiceAnnotationWithAotPostProcessor.java @@ -18,7 +18,6 @@ package org.apache.dubbo.config.spring6.beans.factory.annotation; import org.apache.dubbo.common.logger.ErrorTypeAwareLogger; import org.apache.dubbo.common.logger.LoggerFactory; -import org.apache.dubbo.config.annotation.Service; import org.apache.dubbo.config.spring.ServiceBean; import org.apache.dubbo.config.spring.beans.factory.annotation.ServiceAnnotationPostProcessor; import org.apache.dubbo.config.spring.schema.AnnotationBeanDefinitionParser; @@ -29,21 +28,19 @@ import org.springframework.aot.hint.TypeReference; import org.springframework.beans.factory.aot.BeanRegistrationAotContribution; import org.springframework.beans.factory.aot.BeanRegistrationAotProcessor; import org.springframework.beans.factory.aot.BeanRegistrationCode; -import org.springframework.beans.factory.config.BeanFactoryPostProcessor; import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor; import org.springframework.beans.factory.support.RegisteredBean; import org.springframework.beans.factory.support.RootBeanDefinition; -import org.springframework.beans.factory.xml.BeanDefinitionParser; import java.util.Collection; /** - * A {@link BeanFactoryPostProcessor} used for processing of {@link Service @Service} annotated classes and annotated bean in java config classes. - * It's also the infrastructure class of XML {@link BeanDefinitionParser} on <dubbo:annotation /> + * The purpose of implementing {@link BeanRegistrationAotProcessor} is to + * supplement for {@link ServiceAnnotationPostProcessor} ability of AOT. * * @see AnnotationBeanDefinitionParser * @see BeanDefinitionRegistryPostProcessor - * @since 3.2 + * @since 3.3 */ public class ServiceAnnotationWithAotPostProcessor extends ServiceAnnotationPostProcessor implements BeanRegistrationAotProcessor { diff --git a/dubbo-demo/dubbo-demo-annotation/pom.xml b/dubbo-demo/dubbo-demo-annotation/pom.xml index 8e46e0d3c0..4617288ac8 100644 --- a/dubbo-demo/dubbo-demo-annotation/pom.xml +++ b/dubbo-demo/dubbo-demo-annotation/pom.xml @@ -30,7 +30,7 @@ true - 2.7.14 + 2.7.15 diff --git a/dubbo-demo/dubbo-demo-api/pom.xml b/dubbo-demo/dubbo-demo-api/pom.xml index 6b59e1a693..16851a46c4 100644 --- a/dubbo-demo/dubbo-demo-api/pom.xml +++ b/dubbo-demo/dubbo-demo-api/pom.xml @@ -36,7 +36,7 @@ true - 2.7.14 + 2.7.15 dubbo-demo-api 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 22708014b8..1eabccca2a 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 @@ -224,7 +224,7 @@ org.graalvm.buildtools native-maven-plugin - 0.9.24 + 0.9.27 ${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 0ad39765b5..32aa0f0f5b 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 @@ -222,7 +222,7 @@ org.graalvm.buildtools native-maven-plugin - 0.9.24 + 0.9.27 ${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 4497c0f756..d192153be4 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.14 + 2.7.15 true 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 1a22083b7e..6a3245c1c0 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.14 + 2.7.15 true diff --git a/dubbo-demo/dubbo-demo-spring-boot/pom.xml b/dubbo-demo/dubbo-demo-spring-boot/pom.xml index d1d011fd79..a50275da63 100644 --- a/dubbo-demo/dubbo-demo-spring-boot/pom.xml +++ b/dubbo-demo/dubbo-demo-spring-boot/pom.xml @@ -36,9 +36,9 @@ 8 8 true - 2.7.14 - 2.7.14 - 1.11.3 + 2.7.15 + 2.7.15 + 1.11.4 diff --git a/dubbo-demo/dubbo-demo-xml/pom.xml b/dubbo-demo/dubbo-demo-xml/pom.xml index aee6254372..659275d7fa 100644 --- a/dubbo-demo/dubbo-demo-xml/pom.xml +++ b/dubbo-demo/dubbo-demo-xml/pom.xml @@ -32,7 +32,7 @@ true - 2.7.14 + 2.7.15 diff --git a/dubbo-dependencies-bom/pom.xml b/dubbo-dependencies-bom/pom.xml index 37cec6bf9e..c1aa75fb04 100644 --- a/dubbo-dependencies-bom/pom.xml +++ b/dubbo-dependencies-bom/pom.xml @@ -92,17 +92,17 @@ 5.3.25 - 5.8.5 + 5.8.6 3.29.2-GA - 1.14.6 + 1.14.8 3.2.10.Final - 4.1.95.Final + 4.1.97.Final 2.2.1 2.4.4 4.5.14 4.4.16 1.2.83 - 2.0.39 + 2.0.40 3.4.14 4.3.0 2.12.0 @@ -112,12 +112,12 @@ 1.5.3 1.4.3 3.5.5 - 0.18.1 + 0.19.0 4.0.66 - 3.24.1 + 3.24.3 1.3.2 3.1.0 - 9.4.51.v20230217 + 9.4.52.v20230823 3.0.2 1.1.0.Final 5.4.3.Final @@ -129,18 +129,18 @@ 2.57 1.11.1 2.1.0 - 2.1 + 2.2 3.12.0 1.8.0 0.1.35 - 1.11.3 + 1.11.4 1.26.0 2.16.4 - 1.1.4 + 1.1.5 3.3 0.16.0 1.0.4 - 3.5.9 + 3.5.10 2.2.21 3.14.9 @@ -152,7 +152,7 @@ 2.2.4 1.8.6 1.6.1 - 1.57.2 + 1.58.0 0.8.1 1.2.2 @@ -177,7 +177,7 @@ 2.2.7 1.2.0 - 1.18.3 + 1.19.0 0.7.6 3.2.13 1.6.11 diff --git a/dubbo-distribution/dubbo-all/pom.xml b/dubbo-distribution/dubbo-all/pom.xml index be8bdbf11b..cb2990e537 100644 --- a/dubbo-distribution/dubbo-all/pom.xml +++ b/dubbo-distribution/dubbo-all/pom.xml @@ -190,6 +190,13 @@ + + org.apache.dubbo + dubbo-metrics-event + ${project.version} + compile + true + org.apache.dubbo dubbo-metrics-api @@ -697,6 +704,7 @@ org.apache.dubbo:dubbo-metadata-report-nacos org.apache.dubbo:dubbo-metadata-report-redis org.apache.dubbo:dubbo-metadata-report-zookeeper + org.apache.dubbo:dubbo-metrics-event org.apache.dubbo:dubbo-metrics-api org.apache.dubbo:dubbo-metrics-default org.apache.dubbo:dubbo-metrics-registry diff --git a/dubbo-distribution/dubbo-bom/pom.xml b/dubbo-distribution/dubbo-bom/pom.xml index 0978c711e1..ddb5faebd0 100644 --- a/dubbo-distribution/dubbo-bom/pom.xml +++ b/dubbo-distribution/dubbo-bom/pom.xml @@ -251,6 +251,11 @@ dubbo-metrics-api ${project.version} + + org.apache.dubbo + dubbo-metrics-event + ${project.version} + org.apache.dubbo dubbo-metrics-default diff --git a/dubbo-filter/dubbo-filter-validation/src/main/java/org/apache/dubbo/validation/filter/ValidationFilter.java b/dubbo-filter/dubbo-filter-validation/src/main/java/org/apache/dubbo/validation/filter/ValidationFilter.java index 7cd13982e1..ab742d3561 100644 --- a/dubbo-filter/dubbo-filter-validation/src/main/java/org/apache/dubbo/validation/filter/ValidationFilter.java +++ b/dubbo-filter/dubbo-filter-validation/src/main/java/org/apache/dubbo/validation/filter/ValidationFilter.java @@ -16,6 +16,7 @@ */ package org.apache.dubbo.validation.filter; +import org.apache.dubbo.common.URL; import org.apache.dubbo.common.extension.Activate; import org.apache.dubbo.common.utils.ConfigUtils; import org.apache.dubbo.rpc.AsyncRpcResult; @@ -82,8 +83,7 @@ public class ValidationFilter implements Filter { */ @Override public Result invoke(Invoker invoker, Invocation invocation) throws RpcException { - if (validation != null && !invocation.getMethodName().startsWith("$") - && ConfigUtils.isNotEmpty(invoker.getUrl().getMethodParameter(invocation.getMethodName(), VALIDATION_KEY))) { + if (needValidate(invoker.getUrl(), invocation.getMethodName())) { try { Validator validator = validation.getValidator(invoker.getUrl()); if (validator != null) { @@ -98,4 +98,8 @@ public class ValidationFilter implements Filter { return invoker.invoke(invocation); } + private boolean needValidate(URL url, String methodName) { + return validation != null && !methodName.startsWith("$") && ConfigUtils.isNotEmpty(url.getMethodParameter(methodName, VALIDATION_KEY)); + } + } diff --git a/dubbo-filter/dubbo-filter-validation/src/main/java/org/apache/dubbo/validation/support/jvalidation/JValidator.java b/dubbo-filter/dubbo-filter-validation/src/main/java/org/apache/dubbo/validation/support/jvalidation/JValidator.java index 7051ab2176..b55fb9a0d9 100644 --- a/dubbo-filter/dubbo-filter-validation/src/main/java/org/apache/dubbo/validation/support/jvalidation/JValidator.java +++ b/dubbo-filter/dubbo-filter-validation/src/main/java/org/apache/dubbo/validation/support/jvalidation/JValidator.java @@ -21,6 +21,7 @@ import org.apache.dubbo.common.bytecode.ClassGenerator; import org.apache.dubbo.common.logger.ErrorTypeAwareLogger; import org.apache.dubbo.common.logger.LoggerFactory; import org.apache.dubbo.common.utils.ReflectUtils; +import org.apache.dubbo.common.utils.StringUtils; import org.apache.dubbo.validation.MethodValidated; import org.apache.dubbo.validation.Validator; @@ -57,6 +58,7 @@ import java.lang.annotation.Annotation; import java.lang.reflect.Array; import java.lang.reflect.Field; import java.lang.reflect.Method; +import java.lang.reflect.Parameter; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -89,7 +91,7 @@ public class JValidator implements Validator { this.clazz = ReflectUtils.forName(url.getServiceInterface()); String jvalidation = url.getParameter("jvalidation"); ValidatorFactory factory; - if (jvalidation != null && jvalidation.length() > 0) { + if (StringUtils.isNotEmpty(jvalidation)) { factory = Validation.byProvider((Class) ReflectUtils.forName(jvalidation)).configure().buildValidatorFactory(); } else { factory = Validation.buildDefaultValidatorFactory(); @@ -111,8 +113,9 @@ public class JValidator implements Validator { parameterClass = generateMethodParameterClass(clazz, method, parameterClassName); } Object parameterBean = parameterClass.getDeclaredConstructor().newInstance(); - for (int i = 0; i < args.length; i++) { - Field field = parameterClass.getField(method.getName() + "Argument" + i); + Parameter[] parameters = method.getParameters(); + for (int i = 0; i < parameters.length; i++) { + Field field = parameterClass.getField(parameters[i].getName()); field.set(parameterBean, args[i]); } return parameterBean; @@ -129,10 +132,9 @@ public class JValidator implements Validator { * @param method invoke method * @param parameterClassName generated parameterClassName * @return Class generated methodParameterClass - * @throws Exception */ private static Class generateMethodParameterClass(Class clazz, Method method, String parameterClassName) - throws Exception { + throws Exception { ClassPool pool = ClassGenerator.getClassPool(clazz.getClassLoader()); synchronized (parameterClassName.intern()) { CtClass ctClass = null; @@ -144,28 +146,26 @@ public class JValidator implements Validator { if (null == ctClass) { ctClass = pool.makeClass(parameterClassName); ClassFile classFile = ctClass.getClassFile(); - classFile.setVersionToJava5(); ctClass.addConstructor(CtNewConstructor.defaultConstructor(pool.getCtClass(parameterClassName))); // parameter fields - Class[] parameterTypes = method.getParameterTypes(); + Parameter[] parameters = method.getParameters(); Annotation[][] parameterAnnotations = method.getParameterAnnotations(); - for (int i = 0; i < parameterTypes.length; i++) { - Class type = parameterTypes[i]; + for (int i = 0; i < parameters.length; i++) { Annotation[] annotations = parameterAnnotations[i]; AnnotationsAttribute attribute = new AnnotationsAttribute(classFile.getConstPool(), AnnotationsAttribute.visibleTag); for (Annotation annotation : annotations) { if (annotation.annotationType().isAnnotationPresent(Constraint.class)) { javassist.bytecode.annotation.Annotation ja = new javassist.bytecode.annotation.Annotation( - classFile.getConstPool(), pool.getCtClass(annotation.annotationType().getName())); + classFile.getConstPool(), pool.getCtClass(annotation.annotationType().getName())); Method[] members = annotation.annotationType().getMethods(); for (Method member : members) { if (Modifier.isPublic(member.getModifiers()) - && member.getParameterTypes().length == 0 - && member.getDeclaringClass() == annotation.annotationType()) { + && member.getParameterTypes().length == 0 + && member.getDeclaringClass() == annotation.annotationType()) { Object value = member.invoke(annotation); if (null != value) { MemberValue memberValue = createMemberValue( - classFile.getConstPool(), pool.get(member.getReturnType().getName()), value); + classFile.getConstPool(), pool.get(member.getReturnType().getName()), value); ja.addMemberValue(member.getName(), memberValue); } } @@ -173,12 +173,14 @@ public class JValidator implements Validator { attribute.addAnnotation(ja); } } - String fieldName = method.getName() + "Argument" + i; + Parameter parameter = parameters[i]; + Class type = parameter.getType(); + String fieldName = parameter.getName(); CtField ctField = CtField.make("public " + type.getCanonicalName() + " " + fieldName + ";", pool.getCtClass(parameterClassName)); ctField.getFieldInfo().addAttribute(attribute); ctClass.addField(ctField); } - return ctClass.toClass(clazz.getClassLoader(), null); + return pool.toClass(ctClass, clazz, clazz.getClassLoader(), clazz.getProtectionDomain()); } else { return Class.forName(parameterClassName, true, clazz.getClassLoader()); } @@ -187,13 +189,16 @@ public class JValidator implements Validator { private static String generateMethodParameterClassName(Class clazz, Method method) { StringBuilder builder = new StringBuilder().append(clazz.getName()) - .append('_') - .append(toUpperMethoName(method.getName())) - .append("Parameter"); + .append('_') + .append(toUpperMethodName(method.getName())) + .append("Parameter"); Class[] parameterTypes = method.getParameterTypes(); for (Class parameterType : parameterTypes) { - builder.append('_').append(parameterType.getName()); + // In order to ensure that the parameter class can be generated correctly, + // replace "." with "_" to make the package name of the generated parameter class + // consistent with the package name of the actual parameter class. + builder.append('_').append(parameterType.getName().replace(".", "_")); } return builder.toString(); @@ -201,19 +206,17 @@ public class JValidator implements Validator { private static boolean hasConstraintParameter(Method method) { Annotation[][] parameterAnnotations = method.getParameterAnnotations(); - if (parameterAnnotations != null && parameterAnnotations.length > 0) { - for (Annotation[] annotations : parameterAnnotations) { - for (Annotation annotation : annotations) { - if (annotation.annotationType().isAnnotationPresent(Constraint.class)) { - return true; - } + for (Annotation[] annotations : parameterAnnotations) { + for (Annotation annotation : annotations) { + if (annotation.annotationType().isAnnotationPresent(Constraint.class)) { + return true; } } } return false; } - private static String toUpperMethoName(String methodName) { + private static String toUpperMethodName(String methodName) { return methodName.substring(0, 1).toUpperCase() + methodName.substring(1); } @@ -263,7 +266,7 @@ public class JValidator implements Validator { if (methodClass != null) { groups.add(methodClass); } - Set> violations = new HashSet<>(); + Method method = clazz.getMethod(methodName, parameterTypes); Class[] methodClasses; if (method.isAnnotationPresent(MethodValidated.class)) { @@ -275,15 +278,16 @@ public class JValidator implements Validator { groups.add(1, clazz); // convert list to array - Class[] classgroups = groups.toArray(new Class[groups.size()]); + Class[] classGroups = groups.toArray(new Class[0]); + Set> violations = new HashSet<>(); Object parameterBean = getMethodParameterBean(clazz, method, arguments); if (parameterBean != null) { - violations.addAll(validator.validate(parameterBean, classgroups)); + violations.addAll(validator.validate(parameterBean, classGroups)); } for (Object arg : arguments) { - validate(violations, arg, classgroups); + validate(violations, arg, classGroups); } if (!violations.isEmpty()) { @@ -294,7 +298,7 @@ public class JValidator implements Validator { private Class methodClass(String methodName) { Class methodClass = null; - String methodClassName = clazz.getName() + "$" + toUpperMethoName(methodName); + String methodClassName = clazz.getName() + "$" + toUpperMethodName(methodName); Class cached = methodClassMap.get(methodClassName); if (cached != null) { return cached == clazz ? null : cached; diff --git a/dubbo-filter/dubbo-filter-validation/src/main/java/org/apache/dubbo/validation/support/jvalidation/JValidatorNew.java b/dubbo-filter/dubbo-filter-validation/src/main/java/org/apache/dubbo/validation/support/jvalidation/JValidatorNew.java index fca479c76f..b217131c82 100644 --- a/dubbo-filter/dubbo-filter-validation/src/main/java/org/apache/dubbo/validation/support/jvalidation/JValidatorNew.java +++ b/dubbo-filter/dubbo-filter-validation/src/main/java/org/apache/dubbo/validation/support/jvalidation/JValidatorNew.java @@ -21,6 +21,7 @@ import org.apache.dubbo.common.bytecode.ClassGenerator; import org.apache.dubbo.common.logger.ErrorTypeAwareLogger; import org.apache.dubbo.common.logger.LoggerFactory; import org.apache.dubbo.common.utils.ReflectUtils; +import org.apache.dubbo.common.utils.StringUtils; import org.apache.dubbo.validation.MethodValidated; import org.apache.dubbo.validation.Validator; @@ -57,6 +58,7 @@ import java.lang.annotation.Annotation; import java.lang.reflect.Array; import java.lang.reflect.Field; import java.lang.reflect.Method; +import java.lang.reflect.Parameter; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -89,7 +91,7 @@ public class JValidatorNew implements Validator { this.clazz = ReflectUtils.forName(url.getServiceInterface()); String jvalidation = url.getParameter("jvalidationNew"); ValidatorFactory factory; - if (jvalidation != null && jvalidation.length() > 0) { + if (StringUtils.isNotEmpty(jvalidation)) { factory = Validation.byProvider((Class) ReflectUtils.forName(jvalidation)).configure().buildValidatorFactory(); } else { factory = Validation.buildDefaultValidatorFactory(); @@ -111,8 +113,9 @@ public class JValidatorNew implements Validator { parameterClass = generateMethodParameterClass(clazz, method, parameterClassName); } Object parameterBean = parameterClass.getDeclaredConstructor().newInstance(); - for (int i = 0; i < args.length; i++) { - Field field = parameterClass.getField(method.getName() + "Argument" + i); + Parameter[] parameters = method.getParameters(); + for (int i = 0; i < parameters.length; i++) { + Field field = parameterClass.getField(parameters[i].getName()); field.set(parameterBean, args[i]); } return parameterBean; @@ -129,10 +132,9 @@ public class JValidatorNew implements Validator { * @param method invoke method * @param parameterClassName generated parameterClassName * @return Class generated methodParameterClass - * @throws Exception */ private static Class generateMethodParameterClass(Class clazz, Method method, String parameterClassName) - throws Exception { + throws Exception { ClassPool pool = ClassGenerator.getClassPool(clazz.getClassLoader()); synchronized (parameterClassName.intern()) { CtClass ctClass = null; @@ -144,28 +146,26 @@ public class JValidatorNew implements Validator { if (null == ctClass) { ctClass = pool.makeClass(parameterClassName); ClassFile classFile = ctClass.getClassFile(); - classFile.setVersionToJava5(); ctClass.addConstructor(CtNewConstructor.defaultConstructor(pool.getCtClass(parameterClassName))); // parameter fields - Class[] parameterTypes = method.getParameterTypes(); + Parameter[] parameters = method.getParameters(); Annotation[][] parameterAnnotations = method.getParameterAnnotations(); - for (int i = 0; i < parameterTypes.length; i++) { - Class type = parameterTypes[i]; + for (int i = 0; i < parameters.length; i++) { Annotation[] annotations = parameterAnnotations[i]; AnnotationsAttribute attribute = new AnnotationsAttribute(classFile.getConstPool(), AnnotationsAttribute.visibleTag); for (Annotation annotation : annotations) { if (annotation.annotationType().isAnnotationPresent(Constraint.class)) { javassist.bytecode.annotation.Annotation ja = new javassist.bytecode.annotation.Annotation( - classFile.getConstPool(), pool.getCtClass(annotation.annotationType().getName())); + classFile.getConstPool(), pool.getCtClass(annotation.annotationType().getName())); Method[] members = annotation.annotationType().getMethods(); for (Method member : members) { if (Modifier.isPublic(member.getModifiers()) - && member.getParameterTypes().length == 0 - && member.getDeclaringClass() == annotation.annotationType()) { + && member.getParameterTypes().length == 0 + && member.getDeclaringClass() == annotation.annotationType()) { Object value = member.invoke(annotation); if (null != value) { MemberValue memberValue = createMemberValue( - classFile.getConstPool(), pool.get(member.getReturnType().getName()), value); + classFile.getConstPool(), pool.get(member.getReturnType().getName()), value); ja.addMemberValue(member.getName(), memberValue); } } @@ -173,12 +173,14 @@ public class JValidatorNew implements Validator { attribute.addAnnotation(ja); } } - String fieldName = method.getName() + "Argument" + i; + Parameter parameter = parameters[i]; + Class type = parameter.getType(); + String fieldName = parameter.getName(); CtField ctField = CtField.make("public " + type.getCanonicalName() + " " + fieldName + ";", pool.getCtClass(parameterClassName)); ctField.getFieldInfo().addAttribute(attribute); ctClass.addField(ctField); } - return ctClass.toClass(clazz.getClassLoader(), null); + return pool.toClass(ctClass, clazz, clazz.getClassLoader(), clazz.getProtectionDomain()); } else { return Class.forName(parameterClassName, true, clazz.getClassLoader()); } @@ -187,13 +189,16 @@ public class JValidatorNew implements Validator { private static String generateMethodParameterClassName(Class clazz, Method method) { StringBuilder builder = new StringBuilder().append(clazz.getName()) - .append('_') - .append(toUpperMethoName(method.getName())) - .append("Parameter"); + .append('_') + .append(toUpperMethodName(method.getName())) + .append("Parameter"); Class[] parameterTypes = method.getParameterTypes(); for (Class parameterType : parameterTypes) { - builder.append('_').append(parameterType.getName()); + // In order to ensure that the parameter class can be generated correctly, + // replace "." with "_" to make the package name of the generated parameter class + // consistent with the package name of the actual parameter class. + builder.append('_').append(parameterType.getName().replace(".", "_")); } return builder.toString(); @@ -201,19 +206,17 @@ public class JValidatorNew implements Validator { private static boolean hasConstraintParameter(Method method) { Annotation[][] parameterAnnotations = method.getParameterAnnotations(); - if (parameterAnnotations.length > 0) { - for (Annotation[] annotations : parameterAnnotations) { - for (Annotation annotation : annotations) { - if (annotation.annotationType().isAnnotationPresent(Constraint.class)) { - return true; - } + for (Annotation[] annotations : parameterAnnotations) { + for (Annotation annotation : annotations) { + if (annotation.annotationType().isAnnotationPresent(Constraint.class)) { + return true; } } } return false; } - private static String toUpperMethoName(String methodName) { + private static String toUpperMethodName(String methodName) { return methodName.substring(0, 1).toUpperCase() + methodName.substring(1); } @@ -263,7 +266,7 @@ public class JValidatorNew implements Validator { if (methodClass != null) { groups.add(methodClass); } - Set> violations = new HashSet<>(); + Method method = clazz.getMethod(methodName, parameterTypes); Class[] methodClasses; if (method.isAnnotationPresent(MethodValidated.class)) { @@ -275,15 +278,16 @@ public class JValidatorNew implements Validator { groups.add(1, clazz); // convert list to array - Class[] classgroups = groups.toArray(new Class[groups.size()]); + Class[] classGroups = groups.toArray(new Class[0]); + Set> violations = new HashSet<>(); Object parameterBean = getMethodParameterBean(clazz, method, arguments); if (parameterBean != null) { - violations.addAll(validator.validate(parameterBean, classgroups)); + violations.addAll(validator.validate(parameterBean, classGroups)); } for (Object arg : arguments) { - validate(violations, arg, classgroups); + validate(violations, arg, classGroups); } if (!violations.isEmpty()) { @@ -294,7 +298,7 @@ public class JValidatorNew implements Validator { private Class methodClass(String methodName) { Class methodClass = null; - String methodClassName = clazz.getName() + "$" + toUpperMethoName(methodName); + String methodClassName = clazz.getName() + "$" + toUpperMethodName(methodName); Class cached = methodClassMap.get(methodClassName); if (cached != null) { return cached == clazz ? null : cached; diff --git a/dubbo-filter/dubbo-filter-validation/src/test/java/org/apache/dubbo/validation/support/jvalidation/JValidatorTest.java b/dubbo-filter/dubbo-filter-validation/src/test/java/org/apache/dubbo/validation/support/jvalidation/JValidatorTest.java index 0f04dafd6e..a434b6d7dd 100644 --- a/dubbo-filter/dubbo-filter-validation/src/test/java/org/apache/dubbo/validation/support/jvalidation/JValidatorTest.java +++ b/dubbo-filter/dubbo-filter-validation/src/test/java/org/apache/dubbo/validation/support/jvalidation/JValidatorTest.java @@ -17,17 +17,24 @@ package org.apache.dubbo.validation.support.jvalidation; import org.apache.dubbo.common.URL; +import org.apache.dubbo.validation.support.jvalidation.mock.JValidatorTestTarget; import org.apache.dubbo.validation.support.jvalidation.mock.ValidationParameter; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; +import javax.validation.ConstraintViolationException; import javax.validation.ValidationException; -import java.util.Arrays; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.instanceOf; +import static org.hamcrest.Matchers.is; + class JValidatorTest { @Test void testItWithNonExistMethod() { @@ -72,7 +79,7 @@ class JValidatorTest { void testItWithCollectionArg() throws Exception { URL url = URL.valueOf("test://test:11/org.apache.dubbo.validation.support.jvalidation.mock.JValidatorTestTarget"); JValidator jValidator = new JValidator(url); - jValidator.validate("someMethod4", new Class[]{List.class}, new Object[]{Arrays.asList("parameter")}); + jValidator.validate("someMethod4", new Class[]{List.class}, new Object[]{Collections.singletonList("parameter")}); } @Test @@ -83,4 +90,83 @@ class JValidatorTest { map.put("key", "value"); jValidator.validate("someMethod5", new Class[]{Map.class}, new Object[]{map}); } -} \ No newline at end of file + + @Test + void testItWithPrimitiveArg() { + Assertions.assertThrows(ValidationException.class, () -> { + URL url = URL.valueOf("test://test:11/org.apache.dubbo.validation.support.jvalidation.mock.JValidatorTestTarget"); + JValidator jValidator = new JValidator(url); + jValidator.validate("someMethod6", new Class[]{Integer.class, String.class, Long.class}, new Object[]{null, null, null}); + }); + } + + @Test + void testItWithPrimitiveArgWithProvidedMessage() { + URL url = URL.valueOf("test://test:11/org.apache.dubbo.validation.support.jvalidation.mock.JValidatorTestTarget"); + JValidator jValidator = new JValidator(url); + try { + jValidator.validate("someMethod6", new Class[]{Integer.class, String.class, Long.class}, new Object[]{null, "", null}); + Assertions.fail(); + } catch (Exception e) { + assertThat(e.getMessage(), containsString("string must not be blank")); + assertThat(e.getMessage(), containsString("longValue must not be null")); + } + } + + @Test + void testItWithPartialParameterValidation() { + URL url = URL.valueOf("test://test:11/org.apache.dubbo.validation.support.jvalidation.mock.JValidatorTestTarget"); + JValidator jValidator = new JValidator(url); + try { + jValidator.validate("someMethod6", new Class[]{Integer.class, String.class, Long.class}, new Object[]{null, "", null}); + Assertions.fail(); + } catch (Exception e) { + assertThat(e, instanceOf(ConstraintViolationException.class)); + ConstraintViolationException e1 = (ConstraintViolationException) e; + assertThat(e1.getConstraintViolations().size(), is(2)); + } + } + + @Test + void testItWithNestedParameterValidationWithNullParam() { + Assertions.assertThrows(ValidationException.class, () -> { + URL url = URL.valueOf("test://test:11/org.apache.dubbo.validation.support.jvalidation.mock.JValidatorTestTarget"); + JValidator jValidator = new JValidator(url); + jValidator.validate("someMethod7", new Class[]{JValidatorTestTarget.BaseParam.class}, new Object[]{null}); + }); + } + + @Test + void testItWithNestedParameterValidationWithNullNestedParam() { + URL url = URL.valueOf("test://test:11/org.apache.dubbo.validation.support.jvalidation.mock.JValidatorTestTarget"); + JValidator jValidator = new JValidator(url); + try { + JValidatorTestTarget.BaseParam param = new JValidatorTestTarget.BaseParam<>(); + jValidator.validate("someMethod7", new Class[]{JValidatorTestTarget.BaseParam.class}, new Object[]{param}); + Assertions.fail(); + } catch (Exception e) { + assertThat(e, instanceOf(ConstraintViolationException.class)); + ConstraintViolationException e1 = (ConstraintViolationException) e; + assertThat(e1.getConstraintViolations().size(), is(1)); + assertThat(e1.getMessage(), containsString("body must not be null")); + } + } + + @Test + void testItWithNestedParameterValidationWithNullNestedParams() { + URL url = URL.valueOf("test://test:11/org.apache.dubbo.validation.support.jvalidation.mock.JValidatorTestTarget"); + JValidator jValidator = new JValidator(url); + try { + JValidatorTestTarget.BaseParam param = new JValidatorTestTarget.BaseParam<>(); + param.setBody(new JValidatorTestTarget.Param()); + jValidator.validate("someMethod7", new Class[]{JValidatorTestTarget.BaseParam.class}, new Object[]{param}); + Assertions.fail(); + } catch (Exception e) { + assertThat(e, instanceOf(ConstraintViolationException.class)); + ConstraintViolationException e1 = (ConstraintViolationException) e; + assertThat(e1.getConstraintViolations().size(), is(1)); + assertThat(e1.getMessage(), containsString("name must not be null")); + } + } + +} diff --git a/dubbo-filter/dubbo-filter-validation/src/test/java/org/apache/dubbo/validation/support/jvalidation/mock/JValidatorTestTarget.java b/dubbo-filter/dubbo-filter-validation/src/test/java/org/apache/dubbo/validation/support/jvalidation/mock/JValidatorTestTarget.java index f65eb0573d..9cf5dec6f3 100644 --- a/dubbo-filter/dubbo-filter-validation/src/test/java/org/apache/dubbo/validation/support/jvalidation/mock/JValidatorTestTarget.java +++ b/dubbo-filter/dubbo-filter-validation/src/test/java/org/apache/dubbo/validation/support/jvalidation/mock/JValidatorTestTarget.java @@ -18,6 +18,9 @@ package org.apache.dubbo.validation.support.jvalidation.mock; import org.apache.dubbo.validation.MethodValidated; +import org.hibernate.validator.constraints.NotBlank; + +import javax.validation.Valid; import javax.validation.constraints.NotNull; import java.util.List; import java.util.Map; @@ -35,7 +38,42 @@ public interface JValidatorTestTarget { void someMethod5(Map map); + void someMethod6(Integer intValue, + @NotBlank(message = "string must not be blank") String string, + @NotNull(message = "longValue must not be null") Long longValue); + + void someMethod7(@NotNull BaseParam baseParam); + @interface Test2 { } + class BaseParam { + + @Valid + @NotNull(message = "body must not be null") + private T body; + + public T getBody() { + return body; + } + + public void setBody(T body) { + this.body = body; + } + } + + class Param { + + @NotNull(message = "name must not be null") + private String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + } + } diff --git a/dubbo-metrics/dubbo-metrics-api/pom.xml b/dubbo-metrics/dubbo-metrics-api/pom.xml index 3c31ae389c..3ee341dcba 100644 --- a/dubbo-metrics/dubbo-metrics-api/pom.xml +++ b/dubbo-metrics/dubbo-metrics-api/pom.xml @@ -36,6 +36,11 @@ dubbo-common ${project.parent.version} + + org.apache.dubbo + dubbo-metrics-event + ${project.parent.version} + org.apache.dubbo dubbo-rpc-api diff --git a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/aggregate/TimeWindowCounter.java b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/aggregate/TimeWindowCounter.java index 32f4e63235..8cf70c7fed 100644 --- a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/aggregate/TimeWindowCounter.java +++ b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/aggregate/TimeWindowCounter.java @@ -28,7 +28,7 @@ public class TimeWindowCounter { private final LongAdderSlidingWindow slidingWindow; - public TimeWindowCounter(int bucketNum, int timeWindowSeconds) { + public TimeWindowCounter(int bucketNum, long timeWindowSeconds) { this.slidingWindow = new LongAdderSlidingWindow(bucketNum, TimeUnit.SECONDS.toMillis(timeWindowSeconds)); } 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 02657a293f..1c3ba5b74d 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 @@ -89,6 +89,12 @@ public abstract class CombMetricsCollector extends A this.stats.incrementMethodKey(wrapper, methodMetric, size); } + + @Override + public void init(Invocation invocation, MetricsKeyWrapper wrapper) { + this.stats.initMethodKey(wrapper, invocation); + } + protected List export(MetricsCategory category) { return stats.export(category); } diff --git a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/collector/MethodMetricsCollector.java b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/collector/MethodMetricsCollector.java index d62bab1820..db07746bc8 100644 --- a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/collector/MethodMetricsCollector.java +++ b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/collector/MethodMetricsCollector.java @@ -30,5 +30,7 @@ public interface MethodMetricsCollector extends Metr void increment(MethodMetric methodMetric, MetricsKeyWrapper wrapper, int size); void addMethodRt(Invocation invocation, String registryOpType, Long responseTime); + + void init(Invocation invocation, MetricsKeyWrapper wrapper); } diff --git a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/collector/MetricsCollector.java b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/collector/MetricsCollector.java index 8675faf5f3..f8b676cd3b 100644 --- a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/collector/MetricsCollector.java +++ b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/collector/MetricsCollector.java @@ -18,6 +18,7 @@ package org.apache.dubbo.metrics.collector; import org.apache.dubbo.common.extension.SPI; +import org.apache.dubbo.metrics.event.MetricsEvent; import org.apache.dubbo.metrics.event.TimeCounterEvent; import org.apache.dubbo.metrics.listener.MetricsLifeListener; import org.apache.dubbo.metrics.model.sample.MetricSample; @@ -42,4 +43,6 @@ public interface MetricsCollector extends MetricsLif */ List collect(); + default void initMetrics(MetricsEvent event) {}; + } 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 75e5ed4904..3812a85396 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 @@ -112,6 +112,10 @@ public abstract class BaseStatComposite implements MetricsExport { methodStatComposite.incrementMethodKey(metricsKeyWrapper, methodMetric, size); } + public void initMethodKey(MetricsKeyWrapper metricsKeyWrapper, Invocation invocation) { + methodStatComposite.initMethodKey(metricsKeyWrapper, invocation); + } + @Override public List export(MetricsCategory category) { List list = new ArrayList<>(); diff --git a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/data/MethodStatComposite.java b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/data/MethodStatComposite.java index 527fb31bf3..06cd8ade6e 100644 --- a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/data/MethodStatComposite.java +++ b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/data/MethodStatComposite.java @@ -26,6 +26,7 @@ import org.apache.dubbo.metrics.model.sample.CounterMetricSample; import org.apache.dubbo.metrics.model.sample.GaugeMetricSample; import org.apache.dubbo.metrics.model.sample.MetricSample; import org.apache.dubbo.metrics.report.AbstractMetricsExport; +import org.apache.dubbo.rpc.Invocation; import org.apache.dubbo.rpc.model.ApplicationModel; import java.util.ArrayList; @@ -40,9 +41,11 @@ import java.util.concurrent.atomic.AtomicLong; * the key will not be displayed when exporting (to be optimized) */ public class MethodStatComposite extends AbstractMetricsExport { + private boolean serviceLevel; public MethodStatComposite(ApplicationModel applicationModel) { super(applicationModel); + this.serviceLevel = MethodMetric.isServiceLevel(getApplicationModel()); } private final Map> methodNumStats = new ConcurrentHashMap<>(); @@ -54,6 +57,14 @@ public class MethodStatComposite extends AbstractMetricsExport { metricsKeyWrappers.forEach(appKey -> methodNumStats.put(appKey, new ConcurrentHashMap<>())); } + public void initMethodKey(MetricsKeyWrapper wrapper, Invocation invocation) { + if (!methodNumStats.containsKey(wrapper)) { + return; + } + + methodNumStats.get(wrapper).computeIfAbsent(new MethodMetric(getApplicationModel(), invocation, serviceLevel), k -> new AtomicLong(0L)); + } + public void incrementMethodKey(MetricsKeyWrapper wrapper, MethodMetric methodMetric, int size) { if (!methodNumStats.containsKey(wrapper)) { return; 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 e6d0bae6e7..d335c0dfba 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 @@ -50,9 +50,11 @@ import java.util.stream.Collectors; */ @SuppressWarnings({"rawtypes", "unchecked"}) public class RtStatComposite extends AbstractMetricsExport { + private boolean serviceLevel; public RtStatComposite(ApplicationModel applicationModel) { super(applicationModel); + this.serviceLevel = MethodMetric.isServiceLevel(getApplicationModel()); } private final Map>> rtStats = new ConcurrentHashMap<>(); @@ -168,7 +170,7 @@ public class RtStatComposite extends AbstractMetricsExport { List actions; actions = new LinkedList<>(); for (LongContainer container : rtStats.get(registryOpType)) { - MethodMetric key = new MethodMetric(getApplicationModel(), invocation); + MethodMetric key = new MethodMetric(getApplicationModel(), invocation, serviceLevel); Number current = (Number) container.get(key); if (current == null) { container.putIfAbsent(key, container.getInitFunc().apply(key)); diff --git a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/event/MetricsInitEvent.java b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/event/MetricsInitEvent.java new file mode 100644 index 0000000000..bb01c88d7e --- /dev/null +++ b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/event/MetricsInitEvent.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.MethodMetric; +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.model.ApplicationModel; +import static org.apache.dubbo.metrics.MetricsConstants.ATTACHMENT_KEY_SERVICE; +import static org.apache.dubbo.metrics.model.key.MetricsKey.METRIC_REQUESTS; + +public class MetricsInitEvent extends TimeCounterEvent { + + private static final TypeWrapper METRIC_EVENT = new TypeWrapper(MetricsLevel.SERVICE, METRIC_REQUESTS); + + public MetricsInitEvent(ApplicationModel source,TypeWrapper typeWrapper) { + super(source,typeWrapper); + } + + public static MetricsInitEvent toMetricsInitEvent(ApplicationModel applicationModel, Invocation invocation, boolean serviceLevel) { + MethodMetric methodMetric = new MethodMetric(applicationModel, invocation, serviceLevel); + MetricsInitEvent initEvent = new MetricsInitEvent(applicationModel, METRIC_EVENT); + initEvent.putAttachment(MetricsConstants.INVOCATION, invocation); + initEvent.putAttachment(MetricsConstants.METHOD_METRICS, methodMetric); + initEvent.putAttachment(ATTACHMENT_KEY_SERVICE, MetricsSupport.getInterfaceName(invocation)); + initEvent.putAttachment(MetricsConstants.INVOCATION_SIDE, MetricsSupport.getSide(invocation)); + return initEvent; + } + + +} diff --git a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/event/SimpleMetricsEventMulticaster.java b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/event/SimpleMetricsEventMulticaster.java index e89483f8c6..ed172de6ee 100644 --- a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/event/SimpleMetricsEventMulticaster.java +++ b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/event/SimpleMetricsEventMulticaster.java @@ -40,9 +40,6 @@ public class SimpleMetricsEventMulticaster implements MetricsEventMulticaster { @Override @SuppressWarnings({"rawtypes", "unchecked"}) public void publishEvent(MetricsEvent event) { - if (event instanceof EmptyEvent) { - return; - } if (validateIfApplicationConfigExist(event)) return; for (MetricsListener listener : listeners) { if (listener.isSupport(event)) { @@ -74,9 +71,6 @@ public class SimpleMetricsEventMulticaster implements MetricsEventMulticaster { @SuppressWarnings({"rawtypes"}) private void publishTimeEvent(MetricsEvent event, Consumer consumer) { if (validateIfApplicationConfigExist(event)) return; - if (event instanceof EmptyEvent) { - return; - } if (event instanceof TimeCounterEvent) { ((TimeCounterEvent) event).getTimePair().end(); } 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 c376fdd57d..6f4ddfffcf 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,12 +17,17 @@ package org.apache.dubbo.metrics.model; +import org.apache.dubbo.common.utils.StringUtils; +import org.apache.dubbo.config.MetricsConfig; +import org.apache.dubbo.config.context.ConfigManager; +import org.apache.dubbo.metrics.model.key.MetricsLevel; import org.apache.dubbo.rpc.Invocation; import org.apache.dubbo.rpc.model.ApplicationModel; import org.apache.dubbo.rpc.support.RpcUtils; import java.util.Map; import java.util.Objects; +import java.util.Optional; import static org.apache.dubbo.common.constants.MetricsConstants.TAG_GROUP_KEY; import static org.apache.dubbo.common.constants.MetricsConstants.TAG_VERSION_KEY; @@ -36,12 +41,31 @@ public class MethodMetric extends ServiceKeyMetric { private String group; private String version; - public MethodMetric(ApplicationModel applicationModel, Invocation invocation) { + + public MethodMetric(ApplicationModel applicationModel, Invocation invocation, boolean serviceLevel) { super(applicationModel, MetricsSupport.getInterfaceName(invocation)); - this.methodName = RpcUtils.getMethodName(invocation); this.side = MetricsSupport.getSide(invocation); this.group = MetricsSupport.getGroup(invocation); this.version = MetricsSupport.getVersion(invocation); + this.methodName = serviceLevel ? null : RpcUtils.getMethodName(invocation); + } + + + public static boolean isServiceLevel(ApplicationModel applicationModel) { + if(applicationModel == null){ + return false; + } + ConfigManager applicationConfigManager = applicationModel.getApplicationConfigManager(); + if (applicationConfigManager == null) { + return false; + } + Optional metrics = applicationConfigManager.getMetrics(); + if (!metrics.isPresent()) { + return false; + } + String rpcLevel = metrics.map(MetricsConfig::getRpcLevel).orElse(MetricsLevel.METHOD.name()); + rpcLevel = StringUtils.isBlank(rpcLevel) ? MetricsLevel.METHOD.name() : rpcLevel; + return MetricsLevel.SERVICE.name().equalsIgnoreCase(rpcLevel); } public String getGroup() { @@ -82,13 +106,13 @@ public class MethodMetric extends ServiceKeyMetric { @Override public String toString() { return "MethodMetric{" + - "applicationName='" + getApplicationName() + '\'' + - ", side='" + side + '\'' + - ", interfaceName='" + getServiceKey() + '\'' + - ", methodName='" + methodName + '\'' + - ", group='" + group + '\'' + - ", version='" + version + '\'' + - '}'; + "applicationName='" + getApplicationName() + '\'' + + ", side='" + side + '\'' + + ", interfaceName='" + getServiceKey() + '\'' + + ", methodName='" + methodName + '\'' + + ", group='" + group + '\'' + + ", version='" + version + '\'' + + '}'; } @Override @@ -100,6 +124,7 @@ public class MethodMetric extends ServiceKeyMetric { } private volatile int hashCode = 0; + @Override public int hashCode() { if (hashCode == 0) { 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 404018dfb5..dfaec1fb8e 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 @@ -222,6 +222,11 @@ public class MetricsSupport { collector.increment(event.getAttachmentValue(METHOD_METRICS), new MetricsKeyWrapper(metricsKey, placeType), SELF_INCREMENT_SIZE); } + + public static void init(MetricsKey metricsKey, MetricsPlaceValue placeType, MethodMetricsCollector collector, MetricsEvent event) { + collector.init(event.getAttachmentValue(INVOCATION), new MetricsKeyWrapper(metricsKey, placeType)); + } + /** * Dec method num */ 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 deleted file mode 100644 index 300c6f4dc4..0000000000 --- a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/model/key/MetricsKey.java +++ /dev/null @@ -1,176 +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.model.key; - -/** - * Please follow a unified naming format as follows: - * dubbo_type_action_unit_otherfun - */ -public enum MetricsKey { - APPLICATION_METRIC_INFO("application.info.total", "Total Application Info"), - - CONFIGCENTER_METRIC_TOTAL("configcenter.total", "Config Changed Total"), - - // provider metrics key - METRIC_REQUESTS("requests.total", "Total Requests"), - METRIC_REQUESTS_SUCCEED("requests.succeed.total", "Total Succeed Requests"), - METRIC_REQUEST_BUSINESS_FAILED("requests.business.failed.total", "Total Failed Business Requests"), - - METRIC_REQUESTS_PROCESSING("requests.processing.total", "Processing Requests"), - METRIC_REQUESTS_TIMEOUT("requests.timeout.total", "Total Timeout Failed Requests"), - METRIC_REQUESTS_LIMIT("requests.limit.total", "Total Limit Failed Requests"), - METRIC_REQUESTS_FAILED("requests.unknown.failed.total", "Total Unknown Failed Requests"), - METRIC_REQUESTS_TOTAL_FAILED("requests.failed.total", "Total Failed Requests"), - METRIC_REQUESTS_NETWORK_FAILED("requests.failed.network.total", "Total network Failed Requests"), - METRIC_REQUESTS_SERVICE_UNAVAILABLE_FAILED("requests.failed.service.unavailable.total", "Total Service Unavailable Failed Requests"), - METRIC_REQUESTS_CODEC_FAILED("requests.failed.codec.total", "Total Codec Failed Requests"), - - METRIC_REQUESTS_TOTAL_AGG("requests.total.aggregate", "Aggregated Total Requests"), - METRIC_REQUESTS_SUCCEED_AGG("requests.succeed.aggregate", "Aggregated Succeed Requests"), - METRIC_REQUESTS_FAILED_AGG("requests.failed.aggregate", "Aggregated Failed Requests"), - METRIC_REQUEST_BUSINESS_FAILED_AGG("requests.business.failed.aggregate", "Aggregated Business Failed Requests"), - METRIC_REQUESTS_TIMEOUT_AGG("requests.timeout.failed.aggregate", "Aggregated timeout Failed Requests"), - METRIC_REQUESTS_LIMIT_AGG("requests.limit.aggregate", "Aggregated limit Requests"), - METRIC_REQUESTS_TOTAL_FAILED_AGG("requests.failed.total.aggregate", "Aggregated failed total Requests"), - METRIC_REQUESTS_NETWORK_FAILED_AGG("requests.failed.network.total.aggregate", "Aggregated failed network total Requests"), - METRIC_REQUESTS_CODEC_FAILED_AGG("requests.failed.codec.total.aggregate", "Aggregated failed codec total Requests"), - METRIC_REQUESTS_TOTAL_SERVICE_UNAVAILABLE_FAILED_AGG("requests.failed.service.unavailable.total.aggregate", "Aggregated failed codec total Requests"), - - METRIC_QPS("qps.total", "Query Per Seconds"), - METRIC_RT_LAST("rt.milliseconds.last", "Last Response Time"), - METRIC_RT_MIN("rt.milliseconds.min", "Min Response Time"), - METRIC_RT_MAX("rt.milliseconds.max", "Max Response Time"), - METRIC_RT_SUM("rt.milliseconds.sum", "Sum Response Time"), - METRIC_RT_AVG("rt.milliseconds.avg", "Average Response Time"), - METRIC_RT_P99("rt.milliseconds.p99", "Response Time P99"), - METRIC_RT_P95("rt.milliseconds.p95", "Response Time P95"), - METRIC_RT_P90("rt.milliseconds.p90", "Response Time P90"), - METRIC_RT_P50("rt.milliseconds.p50", "Response Time P50"), - METRIC_RT_MIN_AGG("rt.milliseconds.min.aggregate", "Aggregated Min Response"), - METRIC_RT_MAX_AGG("rt.milliseconds.max.aggregate", "Aggregated Max Response"), - METRIC_RT_AVG_AGG("rt.milliseconds.avg.aggregate", "Aggregated Avg Response"), - - // register metrics key - REGISTER_METRIC_REQUESTS("registry.register.requests.total", "Total Register Requests"), - REGISTER_METRIC_REQUESTS_SUCCEED("registry.register.requests.succeed.total", "Succeed Register Requests"), - REGISTER_METRIC_REQUESTS_FAILED("registry.register.requests.failed.total", "Failed Register Requests"), - METRIC_RT_HISTOGRAM("rt.milliseconds.histogram", "Response Time Histogram"), - - - GENERIC_METRIC_REQUESTS("requests.total", "Total %s Requests"), - GENERIC_METRIC_REQUESTS_SUCCEED("requests.succeed.total", "Succeed %s Requests"), - GENERIC_METRIC_REQUESTS_FAILED("requests.failed.total", "Failed %s Requests"), - - // subscribe metrics key - SUBSCRIBE_METRIC_NUM("registry.subscribe.num.total", "Total Subscribe Num"), - SUBSCRIBE_METRIC_NUM_SUCCEED("registry.subscribe.num.succeed.total", "Succeed Subscribe Num"), - SUBSCRIBE_METRIC_NUM_FAILED("registry.subscribe.num.failed.total", "Failed Subscribe Num"), - - // directory metrics key - DIRECTORY_METRIC_NUM_ALL("registry.directory.num.all", "All Directory Urls"), - DIRECTORY_METRIC_NUM_VALID("registry.directory.num.valid.total", "Valid Directory Urls"), - DIRECTORY_METRIC_NUM_TO_RECONNECT("registry.directory.num.to_reconnect.total", "ToReconnect Directory Urls"), - DIRECTORY_METRIC_NUM_DISABLE("registry.directory.num.disable.total", "Disable Directory Urls"), - - NOTIFY_METRIC_REQUESTS("registry.notify.requests.total", "Total Notify Requests"), - NOTIFY_METRIC_NUM_LAST("registry.notify.num.last", "Last Notify Nums"), - - THREAD_POOL_CORE_SIZE("thread.pool.core.size", "Thread Pool Core Size"), - THREAD_POOL_LARGEST_SIZE("thread.pool.largest.size", "Thread Pool Largest Size"), - THREAD_POOL_MAX_SIZE("thread.pool.max.size", "Thread Pool Max Size"), - THREAD_POOL_ACTIVE_SIZE("thread.pool.active.size", "Thread Pool Active Size"), - THREAD_POOL_THREAD_COUNT("thread.pool.thread.count", "Thread Pool Thread Count"), - THREAD_POOL_QUEUE_SIZE("thread.pool.queue.size", "Thread Pool Queue Size"), - THREAD_POOL_THREAD_REJECT_COUNT("thread.pool.reject.thread.count", "Thread Pool Reject Thread Count"), - - // metadata push metrics key - METADATA_PUSH_METRIC_NUM("metadata.push.num.total", "Total Push Num"), - METADATA_PUSH_METRIC_NUM_SUCCEED("metadata.push.num.succeed.total", "Succeed Push Num"), - METADATA_PUSH_METRIC_NUM_FAILED("metadata.push.num.failed.total", "Failed Push Num"), - - // metadata subscribe metrics key - METADATA_SUBSCRIBE_METRIC_NUM("metadata.subscribe.num.total", "Total Metadata Subscribe Num"), - METADATA_SUBSCRIBE_METRIC_NUM_SUCCEED("metadata.subscribe.num.succeed.total", "Succeed Metadata Subscribe Num"), - METADATA_SUBSCRIBE_METRIC_NUM_FAILED("metadata.subscribe.num.failed.total", "Failed Metadata Subscribe Num"), - - // register service metrics key - SERVICE_REGISTER_METRIC_REQUESTS("registry.total", "Total Service-Level Register Requests"), - SERVICE_REGISTER_METRIC_REQUESTS_SUCCEED("registry.succeed.total", "Succeed Service-Level Register Requests"), - SERVICE_REGISTER_METRIC_REQUESTS_FAILED("registry.failed.total", "Failed Service-Level Register Requests"), - - // subscribe metrics key - SERVICE_SUBSCRIBE_METRIC_NUM("registry.subscribe.service.num.total", "Total Service-Level Subscribe Num"), - SERVICE_SUBSCRIBE_METRIC_NUM_SUCCEED("registry.subscribe.service.num.succeed.total", "Succeed Service-Level Num"), - SERVICE_SUBSCRIBE_METRIC_NUM_FAILED("registry.subscribe.service.num.failed.total", "Failed Service-Level Num"), - // store provider metadata service key - STORE_PROVIDER_METADATA("metadata.store.provider.total", "Store Provider Metadata"), - - STORE_PROVIDER_METADATA_SUCCEED("metadata.store.provider.succeed.total", "Succeed Store Provider Metadata"), - - STORE_PROVIDER_METADATA_FAILED("metadata.store.provider.failed.total", "Failed Store Provider Metadata"), - METADATA_GIT_COMMITID_METRIC("git.commit.id", "Git Commit Id Metrics"), - - // consumer metrics key - INVOKER_NO_AVAILABLE_COUNT("consumer.invoker.no.available.count", "Request Throw No Invoker Available Exception Count"), - - // count the number of occurrences of each error code - ERROR_CODE_COUNT("dubbo.error.code.count","The Count Of Occurrences for Each Error Code"), - - // netty metrics key - NETTY_ALLOCATOR_HEAP_MEMORY_USED("netty.allocator.memory.used", "Netty Allocator Memory Used"), - NETTY_ALLOCATOR_DIRECT_MEMORY_USED("netty.allocator.direct.memory.used", "Netty Allocator Direct Memory Used"), - NETTY_ALLOCATOR_PINNED_DIRECT_MEMORY("netty.allocator.pinned.direct.memory", "Netty Allocator Pinned Direct Memory"), - NETTY_ALLOCATOR_PINNED_HEAP_MEMORY("netty.allocator.pinned.heap.memory", "Netty Allocator Pinned Heap Memory"), - NETTY_ALLOCATOR_HEAP_ARENAS_NUM("netty.allocator.heap.arenas.num", "Netty Allocator Heap Arenas Num"), - NETTY_ALLOCATOR_DIRECT_ARENAS_NUM("netty.allocator.direct.arenas.num", "Netty Allocator Direct Arenas Num"), - NETTY_ALLOCATOR_NORMAL_CACHE_SIZE("netty.allocator.normal.cache.size", "Netty Allocator Normal Cache Size"), - NETTY_ALLOCATOR_SMALL_CACHE_SIZE("netty.allocator.small.cache.size", "Netty Allocator Small Cache Size"), - NETTY_ALLOCATOR_THREAD_LOCAL_CACHES_NUM("netty.allocator.thread.local.caches.num", "Netty Allocator Thread Local Caches Num"), - NETTY_ALLOCATOR_CHUNK_SIZE("netty.allocator.chunk.size", "Netty Allocator Chunk Size"), - ; - - private String nameSuffix; - private String description; - - public final String getName() { - return "dubbo." + nameSuffix; - } - - public final String getNameByType(String type) { - return "dubbo." + type + "." + nameSuffix; - } - - public static MetricsKey getMetricsByName(String name){ - for (MetricsKey metricsKey : MetricsKey.values()) { - if (metricsKey.getName().equals(name)) { - return metricsKey; - } - } - return null; - } - - public final String getDescription() { - return this.description; - } - - - MetricsKey(String nameSuffix, String description) { - this.nameSuffix = nameSuffix; - this.description = description; - } -} 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 042bfd0e3c..095cc5f305 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 @@ -85,7 +85,7 @@ public class MetricsKeyWrapper { return metricsKey.getName(); } try { - return metricsKey.getNameByType(getType()); + return String.format(metricsKey.getName(), getType()); } catch (Exception ignore) { return metricsKey.getName(); } 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 1e3b2f4c56..ef2e173994 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 @@ -58,16 +58,6 @@ public class SimpleMetricsEventMulticasterTest { } - @Test - void testPublishEvent() { - - // emptyEvent do nothing - MetricsEvent emptyEvent = EmptyEvent.instance(); - eventMulticaster.publishEvent(emptyEvent); - Assertions.assertSame(obj, objects[0]); - - } - @Test void testPublishFinishEvent() { 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 index 4bb9245e58..a59832fd0c 100644 --- 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 @@ -18,6 +18,7 @@ package org.apache.dubbo.metrics; import org.apache.dubbo.common.constants.CommonConstants; +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; @@ -69,4 +70,28 @@ public interface DefaultConstants { new MetricsKeyWrapper(METRIC_REQUESTS_CODEC_FAILED, MetricsPlaceValue.of(CommonConstants.PROVIDER, MetricsLevel.METHOD)), new MetricsKeyWrapper(METRIC_REQUESTS_CODEC_FAILED, MetricsPlaceValue.of(CommonConstants.CONSUMER, MetricsLevel.METHOD)) ); + + List INIT_AGG_METHOD_KEYS = Arrays.asList( + MetricsKey.METRIC_REQUESTS_TOTAL_AGG, + MetricsKey.METRIC_REQUESTS_SUCCEED_AGG, + MetricsKey.METRIC_REQUESTS_FAILED_AGG, + MetricsKey.METRIC_REQUEST_BUSINESS_FAILED_AGG, + MetricsKey.METRIC_REQUESTS_TIMEOUT_AGG, + MetricsKey.METRIC_REQUESTS_LIMIT_AGG, + MetricsKey.METRIC_REQUESTS_TOTAL_FAILED_AGG, + MetricsKey.METRIC_REQUESTS_NETWORK_FAILED_AGG, + MetricsKey.METRIC_REQUESTS_CODEC_FAILED_AGG, + MetricsKey.METRIC_REQUESTS_TOTAL_SERVICE_UNAVAILABLE_FAILED_AGG + ); + + List INIT_DEFAULT_METHOD_KEYS = Arrays.asList( + MetricsKey.METRIC_REQUESTS, + MetricsKey.METRIC_REQUESTS_PROCESSING, + MetricsKey.METRIC_REQUESTS_FAILED_AGG, + MetricsKey.METRIC_REQUESTS_SUCCEED, + MetricsKey.METRIC_REQUESTS_TOTAL_FAILED, + MetricsKey.METRIC_REQUEST_BUSINESS_FAILED + ); + + } 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 7fbd4af06e..5cc6aec5d9 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 @@ -43,9 +43,11 @@ import java.util.Map; import java.util.Optional; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.TimeUnit; 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.INIT_AGG_METHOD_KEYS; 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; @@ -75,6 +77,7 @@ public class AggregateMetricsCollector implements MetricsCollector private final ConcurrentMap rtAgr = new ConcurrentHashMap<>(); + private boolean serviceLevel; public AggregateMetricsCollector(ApplicationModel applicationModel) { this.applicationModel = applicationModel; @@ -95,6 +98,7 @@ public class AggregateMetricsCollector implements MetricsCollector this.enableRt = Optional.ofNullable(aggregation.getEnableRt()).orElse(true); this.enableRequest = Optional.ofNullable(aggregation.getEnableRequest()).orElse(true); } + this.serviceLevel = MethodMetric.isServiceLevel(applicationModel); } } @@ -124,7 +128,7 @@ public class AggregateMetricsCollector implements MetricsCollector if (enableQps) { MethodMetric metric = calcWindowCounter(event, MetricsKey.METRIC_REQUESTS); TimeWindowCounter qpsCounter = ConcurrentHashMapUtils.computeIfAbsent(qps, metric, - methodMetric -> new TimeWindowCounter(bucketNum, qpsTimeWindowMillSeconds)); + methodMetric -> new TimeWindowCounter(bucketNum, TimeUnit.MILLISECONDS.toSeconds(qpsTimeWindowMillSeconds))); qpsCounter.increment(); } } @@ -156,7 +160,7 @@ public class AggregateMetricsCollector implements MetricsCollector } private void onRTEvent(RequestEvent event) { - MethodMetric metric = new MethodMetric(applicationModel, event.getAttachmentValue(MetricsConstants.INVOCATION)); + MethodMetric metric = new MethodMetric(applicationModel, event.getAttachmentValue(MetricsConstants.INVOCATION), serviceLevel); long responseTime = event.getTimePair().calc(); if (enableRt) { TimeWindowQuantile quantile = ConcurrentHashMapUtils.computeIfAbsent(rt, metric, @@ -175,7 +179,7 @@ public class AggregateMetricsCollector implements MetricsCollector 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, event.getAttachmentValue(MetricsConstants.INVOCATION)); + MethodMetric metric = new MethodMetric(applicationModel, event.getAttachmentValue(MetricsConstants.INVOCATION), serviceLevel); ConcurrentMap counter = methodTypeCounter.computeIfAbsent(metricsKeyWrapper, k -> new ConcurrentHashMap<>()); @@ -188,7 +192,7 @@ public class AggregateMetricsCollector implements MetricsCollector @Override public List collect() { List list = new ArrayList<>(); - if (!isCollectEnabled()){ + if (!isCollectEnabled()) { return list; } collectRequests(list); @@ -262,4 +266,47 @@ public class AggregateMetricsCollector implements MetricsCollector applicationModel.getBeanFactory().getBean(DefaultMetricsCollector.class).getEventMulticaster().addListener(this); } + + @Override + public void initMetrics(MetricsEvent event) { + MethodMetric metric = new MethodMetric(applicationModel, event.getAttachmentValue(MetricsConstants.INVOCATION), serviceLevel); + if (enableQps) { + initMethodMetric(event); + initQpsMetric(metric); + } + if (enableRt) { + initRtMetric(metric); + } + if (enableRtPxx) { + initRtAgrMetric(metric); + } + } + + public void initMethodMetric(MetricsEvent event) { + INIT_AGG_METHOD_KEYS.stream().forEach(key -> initWindowCounter(event, key)); + } + + public void initQpsMetric(MethodMetric metric) { + ConcurrentHashMapUtils.computeIfAbsent(qps, metric, methodMetric -> new TimeWindowCounter(bucketNum, timeWindowSeconds)); + } + + public void initRtMetric(MethodMetric metric) { + ConcurrentHashMapUtils.computeIfAbsent(rt, metric, k -> new TimeWindowQuantile(DEFAULT_COMPRESSION, bucketNum, timeWindowSeconds)); + } + + public void initRtAgrMetric(MethodMetric metric) { + ConcurrentHashMapUtils.computeIfAbsent(rtAgr, metric, k -> new TimeWindowAggregator(bucketNum, timeWindowSeconds)); + } + + public void initWindowCounter(MetricsEvent event, MetricsKey targetKey) { + + MetricsKeyWrapper metricsKeyWrapper = new MetricsKeyWrapper(targetKey, MetricsPlaceValue.of(event.getAttachmentValue(MetricsConstants.INVOCATION_SIDE), MetricsLevel.SERVICE)); + + MethodMetric metric = new MethodMetric(applicationModel, event.getAttachmentValue(MetricsConstants.INVOCATION), serviceLevel); + + ConcurrentMap counter = methodTypeCounter.computeIfAbsent(metricsKeyWrapper, k -> new ConcurrentHashMap<>()); + + ConcurrentHashMapUtils.computeIfAbsent(counter, metric, methodMetric -> new TimeWindowCounter(bucketNum, timeWindowSeconds)); + + } } 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 39376d344f..7f2d502a86 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 @@ -20,6 +20,7 @@ package org.apache.dubbo.metrics.collector; 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.MetricsConstants; import org.apache.dubbo.metrics.collector.sample.ErrorCodeSampler; import org.apache.dubbo.metrics.collector.sample.MetricsSampler; import org.apache.dubbo.metrics.collector.sample.SimpleMetricsCountSampler; @@ -30,9 +31,12 @@ 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.MetricsInitEvent; import org.apache.dubbo.metrics.event.RequestEvent; +import org.apache.dubbo.metrics.event.TimeCounterEvent; import org.apache.dubbo.metrics.model.ApplicationMetric; import org.apache.dubbo.metrics.model.MetricsCategory; +import org.apache.dubbo.metrics.model.MetricsSupport; import org.apache.dubbo.metrics.model.key.MetricsLevel; import org.apache.dubbo.metrics.model.key.MetricsPlaceValue; import org.apache.dubbo.metrics.model.sample.CounterMetricSample; @@ -41,9 +45,12 @@ import org.apache.dubbo.rpc.model.ApplicationModel; import java.util.ArrayList; import java.util.List; +import java.util.concurrent.atomic.AtomicBoolean; +import static org.apache.dubbo.metrics.DefaultConstants.INIT_DEFAULT_METHOD_KEYS; import static org.apache.dubbo.metrics.model.MetricsCategory.APPLICATION; import static org.apache.dubbo.metrics.model.key.MetricsKey.APPLICATION_METRIC_INFO; +import static org.apache.dubbo.metrics.model.key.MetricsKey.METRIC_REQUESTS_SERVICE_UNAVAILABLE_FAILED; /** * Default implementation of {@link MetricsCollector} @@ -55,6 +62,8 @@ public class DefaultMetricsCollector extends CombMetricsCollector private volatile boolean threadpoolCollectEnabled = false; + private volatile boolean metricsInitEnabled = true; + private final ThreadPoolMetricsSampler threadPoolSampler = new ThreadPoolMetricsSampler(this); private final ErrorCodeSampler errorCodeSampler; @@ -65,6 +74,11 @@ public class DefaultMetricsCollector extends CombMetricsCollector private final List samplers = new ArrayList<>(); + private final List collectors = new ArrayList<>(); + + private final AtomicBoolean initialized = new AtomicBoolean(); + + public DefaultMetricsCollector(ApplicationModel applicationModel) { super(new BaseStatComposite(applicationModel) { @Override @@ -120,6 +134,14 @@ public class DefaultMetricsCollector extends CombMetricsCollector this.threadpoolCollectEnabled = threadpoolCollectEnabled; } + public boolean isMetricsInitEnabled() { + return metricsInitEnabled; + } + + public void setMetricsInitEnabled(boolean metricsInitEnabled) { + this.metricsInitEnabled = metricsInitEnabled; + } + public void collectApplication() { this.setApplicationName(applicationModel.getApplicationName()); applicationSampler.inc(applicationName, MetricsEvent.Type.APPLICATION_INFO); @@ -146,7 +168,29 @@ public class DefaultMetricsCollector extends CombMetricsCollector @Override public boolean isSupport(MetricsEvent event) { - return event instanceof RequestEvent; + return event instanceof RequestEvent || event instanceof MetricsInitEvent; + } + + @Override + public void onEvent(TimeCounterEvent event) { + if(event instanceof MetricsInitEvent){ + if (!metricsInitEnabled) { + return; + } + if(initialized.compareAndSet(false,true)) { + collectors.addAll(applicationModel.getBeanFactory().getBeansOfType(MetricsCollector.class)); + } + collectors.stream().forEach(collector->collector.initMetrics(event)); + return; + } + super.onEvent(event); + } + + @Override + public void initMetrics(MetricsEvent event) { + MetricsPlaceValue dynamicPlaceType = MetricsPlaceValue.of(event.getAttachmentValue(MetricsConstants.INVOCATION_SIDE), MetricsLevel.METHOD); + INIT_DEFAULT_METHOD_KEYS.stream().forEach(key->MetricsSupport.init(key, dynamicPlaceType, (MethodMetricsCollector) this, event)); + MetricsSupport.init(METRIC_REQUESTS_SERVICE_UNAVAILABLE_FAILED, MetricsPlaceValue.of(CommonConstants.CONSUMER, MetricsLevel.METHOD), (MethodMetricsCollector) this, event); } public SimpleMetricsCountSampler applicationSampler = new SimpleMetricsCountSampler() { 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 872f77df1a..932c285d8e 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 @@ -48,6 +48,8 @@ public class HistogramMetricsCollector extends AbstractMetricsListener invoker, Invocation invocation) throws RpcException { @@ -63,7 +66,7 @@ public class MetricsFilter implements ScopeModelAware { if (rpcMetricsEnable) { try { RequestEvent requestEvent = RequestEvent.toRequestEvent(applicationModel, appName, metricsDispatcher, - defaultMetricsCollector, invocation, isProvider ? PROVIDER : CONSUMER); + defaultMetricsCollector, invocation, isProvider ? PROVIDER : CONSUMER, serviceLevel); MetricsEventBus.before(requestEvent); invocation.put(METRIC_FILTER_EVENT, requestEvent); } catch (Throwable t) { diff --git a/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/report/AbstractMetricsReporter.java b/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/report/AbstractMetricsReporter.java index c6eb309b36..13c8cecdc4 100644 --- a/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/report/AbstractMetricsReporter.java +++ b/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/report/AbstractMetricsReporter.java @@ -17,26 +17,26 @@ package org.apache.dubbo.metrics.report; -import io.micrometer.core.instrument.FunctionCounter; -import io.micrometer.core.instrument.binder.MeterBinder; import org.apache.dubbo.common.URL; import org.apache.dubbo.common.beans.factory.ScopeBeanFactory; import org.apache.dubbo.common.lang.ShutdownHookCallbacks; import org.apache.dubbo.common.logger.ErrorTypeAwareLogger; import org.apache.dubbo.common.logger.LoggerFactory; -import org.apache.dubbo.metrics.MetricsGlobalRegistry; import org.apache.dubbo.common.utils.NamedThreadFactory; +import org.apache.dubbo.metrics.MetricsGlobalRegistry; import org.apache.dubbo.metrics.collector.AggregateMetricsCollector; -import org.apache.dubbo.metrics.collector.MetricsCollector; import org.apache.dubbo.metrics.collector.HistogramMetricsCollector; +import org.apache.dubbo.metrics.collector.MetricsCollector; 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.model.ApplicationModel; +import io.micrometer.core.instrument.FunctionCounter; import io.micrometer.core.instrument.Gauge; import io.micrometer.core.instrument.MeterRegistry; import io.micrometer.core.instrument.Tag; +import io.micrometer.core.instrument.binder.MeterBinder; import io.micrometer.core.instrument.binder.jvm.ClassLoaderMetrics; import io.micrometer.core.instrument.binder.jvm.JvmGcMetrics; import io.micrometer.core.instrument.binder.jvm.JvmMemoryMetrics; @@ -53,6 +53,7 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import static org.apache.dubbo.common.constants.LoggerCodeConstants.COMMON_METRICS_COLLECTOR_EXCEPTION; +import static org.apache.dubbo.common.constants.MetricsConstants.ENABLE_COLLECTOR_SYNC_KEY; import static org.apache.dubbo.common.constants.MetricsConstants.ENABLE_JVM_METRICS_KEY; /** @@ -140,9 +141,12 @@ public abstract class AbstractMetricsReporter implements MetricsReporter { } private void scheduleMetricsCollectorSyncJob() { - NamedThreadFactory threadFactory = new NamedThreadFactory("metrics-collector-sync-job", true); - collectorSyncJobExecutor = Executors.newScheduledThreadPool(1, threadFactory); - collectorSyncJobExecutor.scheduleWithFixedDelay(this::refreshData, DEFAULT_SCHEDULE_INITIAL_DELAY, DEFAULT_SCHEDULE_PERIOD, TimeUnit.SECONDS); + boolean enableCollectorSync = url.getParameter(ENABLE_COLLECTOR_SYNC_KEY, true); + if (enableCollectorSync) { + NamedThreadFactory threadFactory = new NamedThreadFactory("metrics-collector-sync-job", true); + collectorSyncJobExecutor = Executors.newScheduledThreadPool(1, threadFactory); + collectorSyncJobExecutor.scheduleWithFixedDelay(this::refreshData, DEFAULT_SCHEDULE_INITIAL_DELAY, DEFAULT_SCHEDULE_PERIOD, TimeUnit.SECONDS); + } } @SuppressWarnings({"unchecked", "rawtypes"}) diff --git a/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/rpc/cluster/filter/support/MetricsClusterFilter.java b/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/rpc/cluster/filter/support/MetricsClusterFilter.java index 5634202384..9a53935032 100644 --- a/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/rpc/cluster/filter/support/MetricsClusterFilter.java +++ b/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/rpc/cluster/filter/support/MetricsClusterFilter.java @@ -23,6 +23,7 @@ import org.apache.dubbo.metrics.collector.DefaultMetricsCollector; import org.apache.dubbo.metrics.event.MetricsDispatcher; import org.apache.dubbo.metrics.event.MetricsEventBus; import org.apache.dubbo.metrics.event.RequestEvent; +import org.apache.dubbo.metrics.model.MethodMetric; import org.apache.dubbo.rpc.BaseFilter; import org.apache.dubbo.rpc.Invocation; import org.apache.dubbo.rpc.Invoker; @@ -42,6 +43,7 @@ public class MetricsClusterFilter implements ClusterFilter, BaseFilter.Listener, private DefaultMetricsCollector collector; private String appName; private MetricsDispatcher metricsDispatcher; + private boolean serviceLevel; @Override public void setApplicationModel(ApplicationModel applicationModel) { @@ -49,6 +51,7 @@ public class MetricsClusterFilter implements ClusterFilter, BaseFilter.Listener, this.collector = applicationModel.getBeanFactory().getBean(DefaultMetricsCollector.class); this.appName = applicationModel.tryGetApplicationName(); this.metricsDispatcher = applicationModel.getBeanFactory().getBean(MetricsDispatcher.class); + this.serviceLevel = MethodMetric.isServiceLevel(applicationModel); } @Override @@ -73,7 +76,7 @@ public class MetricsClusterFilter implements ClusterFilter, BaseFilter.Listener, if (t instanceof RpcException) { RpcException e = (RpcException) t; if (e.isForbidden()) { - MetricsEventBus.publish(RequestEvent.toRequestErrorEvent(applicationModel, appName, metricsDispatcher, invocation, CONSUMER_SIDE, e.getCode())); + MetricsEventBus.publish(RequestEvent.toRequestErrorEvent(applicationModel, appName, metricsDispatcher, invocation, CONSUMER_SIDE, e.getCode(), serviceLevel)); } } } 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 652d335ab8..ce34ce01fd 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 @@ -38,7 +38,6 @@ 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; @@ -90,7 +89,7 @@ class AggregateMetricsCollectorTest { public MethodMetric getTestMethodMetric() { - MethodMetric methodMetric = new MethodMetric(applicationModel, invocation); + MethodMetric methodMetric = new MethodMetric(applicationModel, invocation, MethodMetric.isServiceLevel(applicationModel)); methodMetric.setGroup("TestGroup"); methodMetric.setVersion("1.0.0"); methodMetric.setSide("PROVIDER"); @@ -141,8 +140,8 @@ class AggregateMetricsCollectorTest { @Test void testListener() { AggregateMetricsCollector metricsCollector = new AggregateMetricsCollector(applicationModel); - RequestEvent event = RequestEvent.toRequestEvent(applicationModel, null, null, null, invocation, MetricsSupport.getSide(invocation)); - RequestEvent beforeEvent = RequestEvent.toRequestErrorEvent(applicationModel, null, null, invocation, MetricsSupport.getSide(invocation), RpcException.FORBIDDEN_EXCEPTION); + RequestEvent event = RequestEvent.toRequestEvent(applicationModel, null, null, null, invocation, MetricsSupport.getSide(invocation), MethodMetric.isServiceLevel(applicationModel)); + RequestEvent beforeEvent = RequestEvent.toRequestErrorEvent(applicationModel, null, null, invocation, MetricsSupport.getSide(invocation), RpcException.FORBIDDEN_EXCEPTION, MethodMetric.isServiceLevel(applicationModel)); Assertions.assertTrue(metricsCollector.isSupport(event)); Assertions.assertTrue(metricsCollector.isSupport(beforeEvent)); @@ -200,7 +199,8 @@ class AggregateMetricsCollectorTest { when(applicationModel.getApplicationConfigManager()).thenReturn(configManager); when(applicationModel.getBeanFactory()).thenReturn(beanFactory); - when(beanFactory.getBean(DefaultMetricsCollector.class)).thenReturn(new DefaultMetricsCollector(applicationModel)); + DefaultMetricsCollector defaultMetricsCollector = new DefaultMetricsCollector(applicationModel); + when(beanFactory.getBean(DefaultMetricsCollector.class)).thenReturn(defaultMetricsCollector); when(configManager.getMetrics()).thenReturn(Optional.of(metricsConfig)); when(metricsConfig.getAggregation()).thenReturn(aggregationConfig); when(aggregationConfig.getEnabled()).thenReturn(Boolean.TRUE); @@ -249,7 +249,7 @@ class AggregateMetricsCollectorTest { rtList.add(30L); for (Long requestTime: rtList) { - RequestEvent requestEvent = RequestEvent.toRequestEvent(applicationModel, null, null, null, invocation, MetricsSupport.getSide(invocation)); + RequestEvent requestEvent = RequestEvent.toRequestEvent(applicationModel, null, null, null, invocation, MetricsSupport.getSide(invocation), MethodMetric.isServiceLevel(applicationModel)); TestRequestEvent testRequestEvent = new TestRequestEvent(requestEvent.getSource(), requestEvent.getTypeWrapper()); testRequestEvent.putAttachment(MetricsConstants.INVOCATION, invocation); testRequestEvent.putAttachment(ATTACHMENT_KEY_SERVICE, MetricsSupport.getInterfaceName(invocation)); @@ -299,7 +299,7 @@ class AggregateMetricsCollectorTest { double manualP99 = requestTimes.get((int) Math.round(p99Index)); for (Long requestTime : requestTimes) { - RequestEvent requestEvent = RequestEvent.toRequestEvent(applicationModel, null, null, null, invocation, MetricsSupport.getSide(invocation)); + RequestEvent requestEvent = RequestEvent.toRequestEvent(applicationModel, null, null, null, invocation, MetricsSupport.getSide(invocation), MethodMetric.isServiceLevel(applicationModel)); TestRequestEvent testRequestEvent = new TestRequestEvent(requestEvent.getSource(), requestEvent.getTypeWrapper()); testRequestEvent.putAttachment(MetricsConstants.INVOCATION, invocation); testRequestEvent.putAttachment(ATTACHMENT_KEY_SERVICE, MetricsSupport.getInterfaceName(invocation)); diff --git a/dubbo-metrics/dubbo-metrics-default/src/test/java/org/apache/dubbo/metrics/collector/DefaultCollectorTest.java b/dubbo-metrics/dubbo-metrics-default/src/test/java/org/apache/dubbo/metrics/collector/DefaultCollectorTest.java index 450da8a7c6..724c685da1 100644 --- a/dubbo-metrics/dubbo-metrics-default/src/test/java/org/apache/dubbo/metrics/collector/DefaultCollectorTest.java +++ b/dubbo-metrics/dubbo-metrics-default/src/test/java/org/apache/dubbo/metrics/collector/DefaultCollectorTest.java @@ -19,18 +19,21 @@ package org.apache.dubbo.metrics.collector; import org.apache.dubbo.common.URL; import org.apache.dubbo.common.constants.CommonConstants; +import org.apache.dubbo.common.logger.ErrorTypeAwareLogger; +import org.apache.dubbo.common.logger.LoggerFactory; import org.apache.dubbo.config.ApplicationConfig; +import org.apache.dubbo.metrics.MetricsConstants; import org.apache.dubbo.metrics.TestMetricsInvoker; import org.apache.dubbo.metrics.event.MetricsDispatcher; 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.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; @@ -112,8 +115,8 @@ class DefaultCollectorTest { @Test void testListener() { DefaultMetricsCollector metricsCollector = new DefaultMetricsCollector(applicationModel); - RequestEvent event = RequestEvent.toRequestEvent(applicationModel, null, null, null, invocation, MetricsSupport.getSide(invocation)); - RequestEvent beforeEvent = RequestEvent.toRequestErrorEvent(applicationModel, null, null, invocation, MetricsSupport.getSide(invocation), RpcException.FORBIDDEN_EXCEPTION); + RequestEvent event = RequestEvent.toRequestEvent(applicationModel, null, null, null, invocation, MetricsSupport.getSide(invocation), MethodMetric.isServiceLevel(applicationModel)); + RequestEvent beforeEvent = RequestEvent.toRequestErrorEvent(applicationModel, null, null, invocation, MetricsSupport.getSide(invocation), RpcException.FORBIDDEN_EXCEPTION, MethodMetric.isServiceLevel(applicationModel)); Assertions.assertTrue(metricsCollector.isSupport(event)); Assertions.assertTrue(metricsCollector.isSupport(beforeEvent)); @@ -134,6 +137,9 @@ class DefaultCollectorTest { DefaultMetricsCollector collector = applicationModel.getBeanFactory().getOrRegisterBean(DefaultMetricsCollector.class); collector.setCollectEnabled(true); + ErrorTypeAwareLogger logger = LoggerFactory.getErrorTypeAwareLogger(DefaultCollectorTest.class); + logger.warn("0-99","","","Test error code message."); + metricsFilter.invoke(new TestMetricsInvoker(side), invocation); try { Thread.sleep(50); @@ -150,8 +156,8 @@ class DefaultCollectorTest { // push finish rt +1 List metricSamples = collector.collect(); - //num(total+success+processing) + rt(5) = 8 - Assertions.assertEquals(8, metricSamples.size()); + //num(total+success+processing) + rt(5) + error code = 9 + Assertions.assertEquals(metricSamples.size(),9); 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(); @@ -192,8 +198,8 @@ class DefaultCollectorTest { long c2 = eventObj.getTimePair().calc(); metricSamples = collector.collect(); - // num(total+success+error+total_error+processing) + rt(5) = 5 - Assertions.assertEquals(10, metricSamples.size()); + // num(total+success+error+total_error+processing) + rt(5) + error code = 11 + Assertions.assertEquals(11, 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(); diff --git a/dubbo-metrics/dubbo-metrics-default/src/test/java/org/apache/dubbo/metrics/collector/InitServiceMetricsTest.java b/dubbo-metrics/dubbo-metrics-default/src/test/java/org/apache/dubbo/metrics/collector/InitServiceMetricsTest.java new file mode 100644 index 0000000000..eff1d0bc8f --- /dev/null +++ b/dubbo-metrics/dubbo-metrics-default/src/test/java/org/apache/dubbo/metrics/collector/InitServiceMetricsTest.java @@ -0,0 +1,153 @@ +/* + * 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.constants.CommonConstants; +import org.apache.dubbo.config.ApplicationConfig; +import org.apache.dubbo.config.MetricsConfig; +import org.apache.dubbo.config.nested.AggregationConfig; +import org.apache.dubbo.metrics.aggregate.TimeWindowCounter; +import org.apache.dubbo.metrics.event.MetricsEventBus; +import org.apache.dubbo.metrics.event.MetricsInitEvent; +import org.apache.dubbo.metrics.model.MethodMetric; +import org.apache.dubbo.metrics.model.ServiceKeyMetric; +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.CounterMetricSample; +import org.apache.dubbo.metrics.model.sample.GaugeMetricSample; +import org.apache.dubbo.metrics.model.sample.MetricSample; +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.metrics.DefaultConstants.INIT_AGG_METHOD_KEYS; +import static org.apache.dubbo.metrics.DefaultConstants.INIT_DEFAULT_METHOD_KEYS; +import static org.apache.dubbo.metrics.model.key.MetricsKey.METRIC_REQUESTS; +import static org.apache.dubbo.metrics.model.key.MetricsKey.METRIC_REQUESTS_PROCESSING; + +class InitServiceMetricsTest { + + private ApplicationModel applicationModel; + + private String interfaceName; + private String methodName; + private String group; + private String version; + + private String side; + + private DefaultMetricsCollector defaultCollector; + + private AggregateMetricsCollector aggregateMetricsCollector; + + @BeforeEach + public void setup() { + FrameworkModel frameworkModel = FrameworkModel.defaultModel(); + applicationModel = frameworkModel.newApplication(); + ApplicationConfig config = new ApplicationConfig(); + config.setName("MockMetrics"); + + MetricsConfig metricsConfig = new MetricsConfig(); + AggregationConfig aggregationConfig = new AggregationConfig(); + aggregationConfig.setEnabled(true); + aggregationConfig.setBucketNum(12); + aggregationConfig.setTimeWindowSeconds(120); + metricsConfig.setAggregation(aggregationConfig); + + applicationModel.getApplicationConfigManager().setMetrics(metricsConfig); + applicationModel.getApplicationConfigManager().setApplication(config); + + defaultCollector = applicationModel.getBeanFactory().getBean(DefaultMetricsCollector.class); + defaultCollector.setCollectEnabled(true); + + aggregateMetricsCollector = applicationModel.getBeanFactory().getOrRegisterBean(AggregateMetricsCollector.class); + aggregateMetricsCollector.setCollectEnabled(true); + + interfaceName = "org.apache.dubbo.MockInterface"; + methodName = "mockMethod"; + group = "mockGroup"; + version = "1.0.0"; + side = CommonConstants.PROVIDER_SIDE; + + String serviceKey=group+"/"+interfaceName+":"+version; + + String protocolServiceKey=serviceKey+":dubbo"; + + RpcInvocation invocation = new RpcInvocation(serviceKey,null,methodName,interfaceName, protocolServiceKey, null, null,null,null,null,null); + MetricsEventBus.publish(MetricsInitEvent.toMetricsInitEvent(applicationModel,invocation, MethodMetric.isServiceLevel(applicationModel))); + + } + + @AfterEach + public void teardown() { + applicationModel.destroy(); + } + + + @Test + void testMetricsInitEvent() { + + List metricSamples = defaultCollector.collect(); + //INIT_DEFAULT_METHOD_KEYS.size() = 6 + Assertions.assertEquals(INIT_DEFAULT_METHOD_KEYS.size(), metricSamples.size()); + List metricsNames = metricSamples.stream().map(MetricSample::getName).collect(Collectors.toList()); + + String REQUESTS = new MetricsKeyWrapper(METRIC_REQUESTS, 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(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; + Assertions.assertTrue(value.values().stream().allMatch(atomicLong -> atomicLong.intValue() == 0)); + } + } else { + AtomicLong value = (AtomicLong) ((CounterMetricSample) metricSample).getValue(); + Assertions.assertEquals(0, value.intValue()); + } + } + + + List samples = aggregateMetricsCollector.collect(); + //INIT_AGG_METHOD_KEYS.size(10) + qps(1) + rt(4) +rtAgr(3)= 18 + Assertions.assertEquals(INIT_AGG_METHOD_KEYS.size()+ 1+ 4+ 3, samples.size()); + + for (MetricSample metricSample : samples) { + if (metricSample instanceof GaugeMetricSample) { + GaugeMetricSample gaugeMetricSample = (GaugeMetricSample) metricSample; + Object objVal = gaugeMetricSample.getValue(); + if (objVal instanceof TimeWindowCounter) { + Assertions.assertEquals(0.0,((TimeWindowCounter) objVal).get()); + } + } + } + + } + +} diff --git a/dubbo-metrics/dubbo-metrics-default/src/test/java/org/apache/dubbo/metrics/metrics/model/MethodMetricTest.java b/dubbo-metrics/dubbo-metrics-default/src/test/java/org/apache/dubbo/metrics/metrics/model/MethodMetricTest.java index 38da8bd843..d894f15a5d 100644 --- a/dubbo-metrics/dubbo-metrics-default/src/test/java/org/apache/dubbo/metrics/metrics/model/MethodMetricTest.java +++ b/dubbo-metrics/dubbo-metrics-default/src/test/java/org/apache/dubbo/metrics/metrics/model/MethodMetricTest.java @@ -19,7 +19,9 @@ package org.apache.dubbo.metrics.metrics.model; import org.apache.dubbo.common.URL; import org.apache.dubbo.config.ApplicationConfig; +import org.apache.dubbo.config.MetricsConfig; import org.apache.dubbo.metrics.model.MethodMetric; +import org.apache.dubbo.metrics.model.key.MetricsLevel; import org.apache.dubbo.rpc.RpcContext; import org.apache.dubbo.rpc.RpcInvocation; import org.apache.dubbo.rpc.model.ApplicationModel; @@ -72,7 +74,7 @@ class MethodMetricTest { @Test void test() { - MethodMetric metric = new MethodMetric(applicationModel, invocation); + MethodMetric metric = new MethodMetric(applicationModel, invocation, MethodMetric.isServiceLevel(applicationModel)); Assertions.assertEquals(metric.getServiceKey(), interfaceName); Assertions.assertEquals(metric.getMethodName(), methodName); Assertions.assertEquals(metric.getGroup(), group); @@ -88,4 +90,24 @@ class MethodMetricTest { Assertions.assertEquals(tags.get(TAG_GROUP_KEY), group); Assertions.assertEquals(tags.get(TAG_VERSION_KEY), version); } + + @Test + void testServiceMetrics() { + MetricsConfig metricConfig = new MetricsConfig(); + applicationModel.getApplicationConfigManager().setMetrics(metricConfig); + metricConfig.setRpcLevel(MetricsLevel.SERVICE.name()); + MethodMetric metric = new MethodMetric(applicationModel, invocation, MethodMetric.isServiceLevel(applicationModel)); + Assertions.assertEquals(metric.getServiceKey(), interfaceName); + Assertions.assertNull(metric.getMethodName(), methodName); + Assertions.assertEquals(metric.getGroup(), group); + Assertions.assertEquals(metric.getVersion(), version); + + Map tags = metric.getTags(); + Assertions.assertEquals(tags.get(TAG_APPLICATION_NAME), applicationModel.getApplicationName()); + + Assertions.assertEquals(tags.get(TAG_INTERFACE_KEY), interfaceName); + Assertions.assertNull(tags.get(TAG_METHOD_KEY)); + Assertions.assertEquals(tags.get(TAG_GROUP_KEY), group); + Assertions.assertEquals(tags.get(TAG_VERSION_KEY), version); + } } diff --git a/dubbo-metrics/dubbo-metrics-event/pom.xml b/dubbo-metrics/dubbo-metrics-event/pom.xml new file mode 100644 index 0000000000..4db769019c --- /dev/null +++ b/dubbo-metrics/dubbo-metrics-event/pom.xml @@ -0,0 +1,42 @@ + + + 4.0.0 + + org.apache.dubbo + dubbo-metrics + ${revision} + ../pom.xml + + dubbo-metrics-event + jar + ${project.artifactId} + The metrics event-related api module of dubbo project + + false + + + + + org.apache.dubbo + dubbo-common + ${project.parent.version} + + + + diff --git a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/MetricsConstants.java b/dubbo-metrics/dubbo-metrics-event/src/main/java/org/apache/dubbo/metrics/MetricsConstants.java similarity index 100% rename from dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/MetricsConstants.java rename to dubbo-metrics/dubbo-metrics-event/src/main/java/org/apache/dubbo/metrics/MetricsConstants.java diff --git a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/event/MetricsEvent.java b/dubbo-metrics/dubbo-metrics-event/src/main/java/org/apache/dubbo/metrics/event/MetricsEvent.java similarity index 86% rename from dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/event/MetricsEvent.java rename to dubbo-metrics/dubbo-metrics-event/src/main/java/org/apache/dubbo/metrics/event/MetricsEvent.java index 3b22dfa818..b0e587a396 100644 --- a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/event/MetricsEvent.java +++ b/dubbo-metrics/dubbo-metrics-event/src/main/java/org/apache/dubbo/metrics/event/MetricsEvent.java @@ -19,7 +19,6 @@ package org.apache.dubbo.metrics.event; import org.apache.dubbo.common.beans.factory.ScopeBeanFactory; import org.apache.dubbo.metrics.exception.MetricsNeverHappenException; -import org.apache.dubbo.metrics.model.MethodMetric; import org.apache.dubbo.metrics.model.key.TypeWrapper; import org.apache.dubbo.rpc.model.ApplicationModel; @@ -33,13 +32,13 @@ import java.util.Map; public abstract class MetricsEvent { /** - * Metric object. (eg. {@link MethodMetric}) + * Metric object. (eg. MethodMetric) */ protected transient final ApplicationModel source; private boolean available = true; private final TypeWrapper typeWrapper; private final String appName; - private final MetricsDispatcher metricsDispatcher; + private final MetricsEventMulticaster metricsEventMulticaster; private final Map attachments = new IdentityHashMap<>(8); @@ -47,7 +46,7 @@ public abstract class MetricsEvent { this(source, null, null, typeWrapper); } - public MetricsEvent(ApplicationModel source, String appName, MetricsDispatcher metricsDispatcher, TypeWrapper typeWrapper) { + public MetricsEvent(ApplicationModel source, String appName, MetricsEventMulticaster metricsEventMulticaster, TypeWrapper typeWrapper) { this.typeWrapper = typeWrapper; if (source == null) { this.source = ApplicationModel.defaultModel(); @@ -56,20 +55,20 @@ public abstract class MetricsEvent { } else { this.source = source; } - if (metricsDispatcher == null) { + if (metricsEventMulticaster == null) { if (this.source.isDestroyed()) { - this.metricsDispatcher = null; + this.metricsEventMulticaster = null; } else { ScopeBeanFactory beanFactory = this.source.getBeanFactory(); if (beanFactory.isDestroyed()) { - this.metricsDispatcher = null; + this.metricsEventMulticaster = null; } else { - MetricsDispatcher dispatcher = beanFactory.getBean(MetricsDispatcher.class); - this.metricsDispatcher = dispatcher; + MetricsEventMulticaster dispatcher = beanFactory.getBean(MetricsEventMulticaster.class); + this.metricsEventMulticaster = dispatcher; } } } else { - this.metricsDispatcher = metricsDispatcher; + this.metricsEventMulticaster = metricsEventMulticaster; } if (appName == null) { this.appName = this.source.tryGetApplicationName(); @@ -115,8 +114,8 @@ public abstract class MetricsEvent { return source; } - public MetricsDispatcher getMetricsDispatcher() { - return metricsDispatcher; + public MetricsEventMulticaster getMetricsEventMulticaster() { + return metricsEventMulticaster; } public String appName() { diff --git a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/event/MetricsEventBus.java b/dubbo-metrics/dubbo-metrics-event/src/main/java/org/apache/dubbo/metrics/event/MetricsEventBus.java similarity index 91% rename from dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/event/MetricsEventBus.java rename to dubbo-metrics/dubbo-metrics-event/src/main/java/org/apache/dubbo/metrics/event/MetricsEventBus.java index 74ef55e4c7..2d0888d17a 100644 --- a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/event/MetricsEventBus.java +++ b/dubbo-metrics/dubbo-metrics-event/src/main/java/org/apache/dubbo/metrics/event/MetricsEventBus.java @@ -42,7 +42,7 @@ public class MetricsEventBus { if (event.getSource() == null) { return; } - MetricsDispatcher dispatcher = event.getMetricsDispatcher(); + MetricsEventMulticaster dispatcher = event.getMetricsEventMulticaster(); Optional.ofNullable(dispatcher).ifPresent(d -> { tryInvoke(() -> d.publishEvent(event)); }); @@ -106,13 +106,14 @@ public class MetricsEventBus { * eventSaveRunner saves the event, so that the calculation rt is introverted */ public static void before(MetricsEvent event) { - MetricsDispatcher dispatcher = validate(event); + MetricsEventMulticaster dispatcher = validate(event); + if (dispatcher == null) return; tryInvoke(() -> dispatcher.publishEvent(event)); } public static void after(MetricsEvent event, Object result) { - MetricsDispatcher dispatcher = validate(event); + MetricsEventMulticaster dispatcher = validate(event); if (dispatcher == null) return; tryInvoke(() -> { event.customAfterPost(result); @@ -121,13 +122,13 @@ public class MetricsEventBus { } public static void error(MetricsEvent event) { - MetricsDispatcher dispatcher = validate(event); + MetricsEventMulticaster dispatcher = validate(event); if (dispatcher == null) return; tryInvoke(() -> dispatcher.publishErrorEvent((TimeCounterEvent) event)); } - private static MetricsDispatcher validate(MetricsEvent event) { - MetricsDispatcher dispatcher = event.getMetricsDispatcher(); + private static MetricsEventMulticaster validate(MetricsEvent event) { + MetricsEventMulticaster dispatcher = event.getMetricsEventMulticaster(); if (dispatcher == null) { return null; } diff --git a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/event/MetricsEventMulticaster.java b/dubbo-metrics/dubbo-metrics-event/src/main/java/org/apache/dubbo/metrics/event/MetricsEventMulticaster.java similarity index 100% rename from dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/event/MetricsEventMulticaster.java rename to dubbo-metrics/dubbo-metrics-event/src/main/java/org/apache/dubbo/metrics/event/MetricsEventMulticaster.java diff --git a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/event/TimeCounterEvent.java b/dubbo-metrics/dubbo-metrics-event/src/main/java/org/apache/dubbo/metrics/event/TimeCounterEvent.java similarity index 95% rename from dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/event/TimeCounterEvent.java rename to dubbo-metrics/dubbo-metrics-event/src/main/java/org/apache/dubbo/metrics/event/TimeCounterEvent.java index 69e7e42925..e814465b36 100644 --- a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/event/TimeCounterEvent.java +++ b/dubbo-metrics/dubbo-metrics-event/src/main/java/org/apache/dubbo/metrics/event/TimeCounterEvent.java @@ -33,7 +33,7 @@ public abstract class TimeCounterEvent extends MetricsEvent { this.timePair = TimePair.start(); } - public TimeCounterEvent(ApplicationModel source, String appName, MetricsDispatcher metricsDispatcher, TypeWrapper typeWrapper) { + public TimeCounterEvent(ApplicationModel source, String appName,MetricsEventMulticaster metricsDispatcher, TypeWrapper typeWrapper) { super(source, appName, metricsDispatcher, typeWrapper); this.timePair = TimePair.start(); } diff --git a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/exception/MetricsNeverHappenException.java b/dubbo-metrics/dubbo-metrics-event/src/main/java/org/apache/dubbo/metrics/exception/MetricsNeverHappenException.java similarity index 100% rename from dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/exception/MetricsNeverHappenException.java rename to dubbo-metrics/dubbo-metrics-event/src/main/java/org/apache/dubbo/metrics/exception/MetricsNeverHappenException.java diff --git a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/listener/MetricsListener.java b/dubbo-metrics/dubbo-metrics-event/src/main/java/org/apache/dubbo/metrics/listener/MetricsListener.java similarity index 99% rename from dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/listener/MetricsListener.java rename to dubbo-metrics/dubbo-metrics-event/src/main/java/org/apache/dubbo/metrics/listener/MetricsListener.java index 4e355802db..3411e6f046 100644 --- a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/listener/MetricsListener.java +++ b/dubbo-metrics/dubbo-metrics-event/src/main/java/org/apache/dubbo/metrics/listener/MetricsListener.java @@ -35,5 +35,4 @@ public interface MetricsListener { */ void onEvent(E event); - } diff --git a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/model/TimePair.java b/dubbo-metrics/dubbo-metrics-event/src/main/java/org/apache/dubbo/metrics/model/TimePair.java similarity index 100% rename from dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/model/TimePair.java rename to dubbo-metrics/dubbo-metrics-event/src/main/java/org/apache/dubbo/metrics/model/TimePair.java diff --git a/dubbo-metrics/dubbo-metrics-event/src/main/java/org/apache/dubbo/metrics/model/key/MetricsKey.java b/dubbo-metrics/dubbo-metrics-event/src/main/java/org/apache/dubbo/metrics/model/key/MetricsKey.java new file mode 100644 index 0000000000..d426898255 --- /dev/null +++ b/dubbo-metrics/dubbo-metrics-event/src/main/java/org/apache/dubbo/metrics/model/key/MetricsKey.java @@ -0,0 +1,171 @@ +/* + * 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; + +public enum MetricsKey { + APPLICATION_METRIC_INFO("dubbo.application.info.total", "Total Application Info"), + + CONFIGCENTER_METRIC_TOTAL("dubbo.configcenter.total", "Config Changed Total"), + + // provider metrics key + METRIC_REQUESTS("dubbo.%s.requests.total", "Total Requests"), + METRIC_REQUESTS_SUCCEED("dubbo.%s.requests.succeed.total", "Total Succeed Requests"), + METRIC_REQUEST_BUSINESS_FAILED("dubbo.%s.requests.business.failed.total", "Total Failed Business Requests"), + + METRIC_REQUESTS_PROCESSING("dubbo.%s.requests.processing.total", "Processing Requests"), + METRIC_REQUESTS_TIMEOUT("dubbo.%s.requests.timeout.total", "Total Timeout Failed Requests"), + METRIC_REQUESTS_LIMIT("dubbo.%s.requests.limit.total", "Total Limit Failed Requests"), + METRIC_REQUESTS_FAILED("dubbo.%s.requests.unknown.failed.total", "Total Unknown Failed Requests"), + METRIC_REQUESTS_TOTAL_FAILED("dubbo.%s.requests.failed.total", "Total Failed Requests"), + METRIC_REQUESTS_NETWORK_FAILED("dubbo.%s.requests.failed.network.total", "Total network Failed Requests"), + METRIC_REQUESTS_SERVICE_UNAVAILABLE_FAILED("dubbo.%s.requests.failed.service.unavailable.total", "Total Service Unavailable Failed Requests"), + METRIC_REQUESTS_CODEC_FAILED("dubbo.%s.requests.failed.codec.total", "Total Codec Failed Requests"), + + 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_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_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"), + METRIC_RT_LAST("dubbo.%s.rt.milliseconds.last", "Last Response Time"), + METRIC_RT_MIN("dubbo.%s.rt.milliseconds.min", "Min Response Time"), + METRIC_RT_MAX("dubbo.%s.rt.milliseconds.max", "Max Response Time"), + METRIC_RT_SUM("dubbo.%s.rt.milliseconds.sum", "Sum Response Time"), + METRIC_RT_AVG("dubbo.%s.rt.milliseconds.avg", "Average Response Time"), + METRIC_RT_P99("dubbo.%s.rt.milliseconds.p99", "Response Time P99"), + METRIC_RT_P95("dubbo.%s.rt.milliseconds.p95", "Response Time P95"), + METRIC_RT_P90("dubbo.%s.rt.milliseconds.p90", "Response Time P90"), + METRIC_RT_P50("dubbo.%s.rt.milliseconds.p50", "Response Time P50"), + METRIC_RT_MIN_AGG("dubbo.%s.rt.min.milliseconds.aggregate", "Aggregated Min Response"), + METRIC_RT_MAX_AGG("dubbo.%s.rt.max.milliseconds.aggregate", "Aggregated Max Response"), + METRIC_RT_AVG_AGG("dubbo.%s.rt.avg.milliseconds.aggregate", "Aggregated Avg Response"), + + // register metrics key + REGISTER_METRIC_REQUESTS("dubbo.registry.register.requests.total", "Total Register Requests"), + REGISTER_METRIC_REQUESTS_SUCCEED("dubbo.registry.register.requests.succeed.total", "Succeed Register Requests"), + REGISTER_METRIC_REQUESTS_FAILED("dubbo.registry.register.requests.failed.total", "Failed Register Requests"), + METRIC_RT_HISTOGRAM("dubbo.%s.rt.milliseconds.histogram", "Response Time Histogram"), + + + GENERIC_METRIC_REQUESTS("dubbo.%s.requests.total", "Total %s Requests"), + GENERIC_METRIC_REQUESTS_SUCCEED("dubbo.%s.requests.succeed.total", "Succeed %s Requests"), + GENERIC_METRIC_REQUESTS_FAILED("dubbo.%s.requests.failed.total", "Failed %s Requests"), + + // subscribe metrics key + SUBSCRIBE_METRIC_NUM("dubbo.registry.subscribe.num.total", "Total Subscribe Num"), + SUBSCRIBE_METRIC_NUM_SUCCEED("dubbo.registry.subscribe.num.succeed.total", "Succeed Subscribe Num"), + SUBSCRIBE_METRIC_NUM_FAILED("dubbo.registry.subscribe.num.failed.total", "Failed Subscribe Num"), + + // directory metrics key + DIRECTORY_METRIC_NUM_ALL("dubbo.registry.directory.num.all", "All Directory Urls"), + DIRECTORY_METRIC_NUM_VALID("dubbo.registry.directory.num.valid.total", "Valid Directory Urls"), + DIRECTORY_METRIC_NUM_TO_RECONNECT("dubbo.registry.directory.num.to_reconnect.total", "ToReconnect Directory Urls"), + DIRECTORY_METRIC_NUM_DISABLE("dubbo.registry.directory.num.disable.total", "Disable Directory Urls"), + + NOTIFY_METRIC_REQUESTS("dubbo.registry.notify.requests.total", "Total Notify Requests"), + NOTIFY_METRIC_NUM_LAST("dubbo.registry.notify.num.last", "Last Notify Nums"), + + THREAD_POOL_CORE_SIZE("dubbo.thread.pool.core.size", "Thread Pool Core Size"), + THREAD_POOL_LARGEST_SIZE("dubbo.thread.pool.largest.size", "Thread Pool Largest Size"), + THREAD_POOL_MAX_SIZE("dubbo.thread.pool.max.size", "Thread Pool Max Size"), + THREAD_POOL_ACTIVE_SIZE("dubbo.thread.pool.active.size", "Thread Pool Active Size"), + THREAD_POOL_THREAD_COUNT("dubbo.thread.pool.thread.count", "Thread Pool Thread Count"), + THREAD_POOL_QUEUE_SIZE("dubbo.thread.pool.queue.size", "Thread Pool Queue Size"), + THREAD_POOL_THREAD_REJECT_COUNT("dubbo.thread.pool.reject.thread.count", "Thread Pool Reject Thread Count"), + + // metadata push metrics key + METADATA_PUSH_METRIC_NUM("dubbo.metadata.push.num.total", "Total Push Num"), + METADATA_PUSH_METRIC_NUM_SUCCEED("dubbo.metadata.push.num.succeed.total", "Succeed Push Num"), + METADATA_PUSH_METRIC_NUM_FAILED("dubbo.metadata.push.num.failed.total", "Failed Push Num"), + + // metadata subscribe metrics key + METADATA_SUBSCRIBE_METRIC_NUM("dubbo.metadata.subscribe.num.total", "Total Metadata Subscribe Num"), + METADATA_SUBSCRIBE_METRIC_NUM_SUCCEED("dubbo.metadata.subscribe.num.succeed.total", "Succeed Metadata Subscribe Num"), + METADATA_SUBSCRIBE_METRIC_NUM_FAILED("dubbo.metadata.subscribe.num.failed.total", "Failed Metadata Subscribe Num"), + + // register service metrics key + SERVICE_REGISTER_METRIC_REQUESTS("dubbo.registry.register.service.total", "Total Service-Level Register Requests"), + SERVICE_REGISTER_METRIC_REQUESTS_SUCCEED("dubbo.registry.register.service.succeed.total", "Succeed Service-Level Register Requests"), + SERVICE_REGISTER_METRIC_REQUESTS_FAILED("dubbo.registry.register.service.failed.total", "Failed Service-Level Register Requests"), + + // subscribe metrics key + SERVICE_SUBSCRIBE_METRIC_NUM("dubbo.registry.subscribe.service.num.total", "Total Service-Level Subscribe Num"), + SERVICE_SUBSCRIBE_METRIC_NUM_SUCCEED("dubbo.registry.subscribe.service.num.succeed.total", "Succeed Service-Level Num"), + SERVICE_SUBSCRIBE_METRIC_NUM_FAILED("dubbo.registry.subscribe.service.num.failed.total", "Failed Service-Level Num"), + // store provider metadata service key + STORE_PROVIDER_METADATA("dubbo.metadata.store.provider.total", "Store Provider Metadata"), + + STORE_PROVIDER_METADATA_SUCCEED("dubbo.metadata.store.provider.succeed.total", "Succeed Store Provider Metadata"), + + STORE_PROVIDER_METADATA_FAILED("dubbo.metadata.store.provider.failed.total", "Failed Store Provider Metadata"), + 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"), + + // count the number of occurrences of each error code + ERROR_CODE_COUNT("dubbo.error.code.count","The Count Of Occurrences for Each Error Code"), + + // netty metrics key + NETTY_ALLOCATOR_HEAP_MEMORY_USED("netty.allocator.memory.used", "Netty Allocator Memory Used"), + NETTY_ALLOCATOR_DIRECT_MEMORY_USED("netty.allocator.direct.memory.used", "Netty Allocator Direct Memory Used"), + NETTY_ALLOCATOR_PINNED_DIRECT_MEMORY("netty.allocator.pinned.direct.memory", "Netty Allocator Pinned Direct Memory"), + NETTY_ALLOCATOR_PINNED_HEAP_MEMORY("netty.allocator.pinned.heap.memory", "Netty Allocator Pinned Heap Memory"), + NETTY_ALLOCATOR_HEAP_ARENAS_NUM("netty.allocator.heap.arenas.num", "Netty Allocator Heap Arenas Num"), + NETTY_ALLOCATOR_DIRECT_ARENAS_NUM("netty.allocator.direct.arenas.num", "Netty Allocator Direct Arenas Num"), + NETTY_ALLOCATOR_NORMAL_CACHE_SIZE("netty.allocator.normal.cache.size", "Netty Allocator Normal Cache Size"), + NETTY_ALLOCATOR_SMALL_CACHE_SIZE("netty.allocator.small.cache.size", "Netty Allocator Small Cache Size"), + NETTY_ALLOCATOR_THREAD_LOCAL_CACHES_NUM("netty.allocator.thread.local.caches.num", "Netty Allocator Thread Local Caches Num"), + NETTY_ALLOCATOR_CHUNK_SIZE("netty.allocator.chunk.size", "Netty Allocator Chunk Size"), + ; + + private String name; + private String description; + + public final String getName() { + return this.name; + } + + public final String getNameByType(String type) { + return String.format(name, type); + } + + public static MetricsKey getMetricsByName(String name){ + for (MetricsKey metricsKey : MetricsKey.values()) { + if (metricsKey.getName().equals(name)) { + return metricsKey; + } + } + return null; + } + + public final String getDescription() { + return this.description; + } + + MetricsKey(String name, String description) { + this.name = name; + this.description = description; + } +} diff --git a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/model/key/MetricsLevel.java b/dubbo-metrics/dubbo-metrics-event/src/main/java/org/apache/dubbo/metrics/model/key/MetricsLevel.java similarity index 100% rename from dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/model/key/MetricsLevel.java rename to dubbo-metrics/dubbo-metrics-event/src/main/java/org/apache/dubbo/metrics/model/key/MetricsLevel.java diff --git a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/model/key/TypeWrapper.java b/dubbo-metrics/dubbo-metrics-event/src/main/java/org/apache/dubbo/metrics/model/key/TypeWrapper.java similarity index 100% rename from dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/model/key/TypeWrapper.java rename to dubbo-metrics/dubbo-metrics-event/src/main/java/org/apache/dubbo/metrics/model/key/TypeWrapper.java diff --git a/dubbo-metrics/dubbo-metrics-registry/src/test/java/org/apache/dubbo/metrics/registry/metrics/collector/RegistryMetricsTest.java b/dubbo-metrics/dubbo-metrics-registry/src/test/java/org/apache/dubbo/metrics/registry/metrics/collector/RegistryMetricsTest.java index 3187161fad..5610bef232 100644 --- a/dubbo-metrics/dubbo-metrics-registry/src/test/java/org/apache/dubbo/metrics/registry/metrics/collector/RegistryMetricsTest.java +++ b/dubbo-metrics/dubbo-metrics-registry/src/test/java/org/apache/dubbo/metrics/registry/metrics/collector/RegistryMetricsTest.java @@ -25,7 +25,6 @@ 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.RegistryMetricsConstants; import org.apache.dubbo.metrics.registry.collector.RegistryMetricsCollector; import org.apache.dubbo.metrics.registry.event.RegistryEvent; import org.apache.dubbo.rpc.model.ApplicationModel; @@ -222,9 +221,9 @@ public class RegistryMetricsTest { } List samples = collector.collect(); - GaugeMetricSample succeedRequests = getSample(MetricsKey.SERVICE_REGISTER_METRIC_REQUESTS_SUCCEED.getNameByType(RegistryMetricsConstants.OP_TYPE_REGISTER_SERVICE.getType()), samples); - GaugeMetricSample failedRequests = getSample(MetricsKey.SERVICE_REGISTER_METRIC_REQUESTS_FAILED.getNameByType(RegistryMetricsConstants.OP_TYPE_REGISTER_SERVICE.getType()), samples); - GaugeMetricSample totalRequests = getSample(MetricsKey.SERVICE_REGISTER_METRIC_REQUESTS.getNameByType(RegistryMetricsConstants.OP_TYPE_REGISTER_SERVICE.getType()), samples); + 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()); diff --git a/dubbo-metrics/pom.xml b/dubbo-metrics/pom.xml index 014632df63..901a7888ec 100644 --- a/dubbo-metrics/pom.xml +++ b/dubbo-metrics/pom.xml @@ -19,6 +19,7 @@ 4.0.0 dubbo-metrics-api + dubbo-metrics-event dubbo-metrics-default dubbo-metrics-registry dubbo-metrics-metadata diff --git a/dubbo-native/pom.xml b/dubbo-plugin/dubbo-native/pom.xml similarity index 95% rename from dubbo-native/pom.xml rename to dubbo-plugin/dubbo-native/pom.xml index 449148f20a..c812b98a71 100644 --- a/dubbo-native/pom.xml +++ b/dubbo-plugin/dubbo-native/pom.xml @@ -19,7 +19,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> org.apache.dubbo - dubbo-parent + dubbo-plugin ${revision} ../pom.xml @@ -35,6 +35,6 @@ dubbo-common ${project.parent.version} - + diff --git a/dubbo-native/src/main/java/org/apache/dubbo/aot/api/ConditionalDescriber.java b/dubbo-plugin/dubbo-native/src/main/java/org/apache/dubbo/aot/api/ConditionalDescriber.java similarity index 100% rename from dubbo-native/src/main/java/org/apache/dubbo/aot/api/ConditionalDescriber.java rename to dubbo-plugin/dubbo-native/src/main/java/org/apache/dubbo/aot/api/ConditionalDescriber.java diff --git a/dubbo-native/src/main/java/org/apache/dubbo/aot/api/ExecutableMode.java b/dubbo-plugin/dubbo-native/src/main/java/org/apache/dubbo/aot/api/ExecutableMode.java similarity index 100% rename from dubbo-native/src/main/java/org/apache/dubbo/aot/api/ExecutableMode.java rename to dubbo-plugin/dubbo-native/src/main/java/org/apache/dubbo/aot/api/ExecutableMode.java diff --git a/dubbo-native/src/main/java/org/apache/dubbo/aot/api/FieldDescriber.java b/dubbo-plugin/dubbo-native/src/main/java/org/apache/dubbo/aot/api/FieldDescriber.java similarity index 100% rename from dubbo-native/src/main/java/org/apache/dubbo/aot/api/FieldDescriber.java rename to dubbo-plugin/dubbo-native/src/main/java/org/apache/dubbo/aot/api/FieldDescriber.java diff --git a/dubbo-native/src/main/java/org/apache/dubbo/aot/api/JdkProxyDescriber.java b/dubbo-plugin/dubbo-native/src/main/java/org/apache/dubbo/aot/api/JdkProxyDescriber.java similarity index 100% rename from dubbo-native/src/main/java/org/apache/dubbo/aot/api/JdkProxyDescriber.java rename to dubbo-plugin/dubbo-native/src/main/java/org/apache/dubbo/aot/api/JdkProxyDescriber.java diff --git a/dubbo-native/src/main/java/org/apache/dubbo/aot/api/MemberCategory.java b/dubbo-plugin/dubbo-native/src/main/java/org/apache/dubbo/aot/api/MemberCategory.java similarity index 100% rename from dubbo-native/src/main/java/org/apache/dubbo/aot/api/MemberCategory.java rename to dubbo-plugin/dubbo-native/src/main/java/org/apache/dubbo/aot/api/MemberCategory.java diff --git a/dubbo-native/src/main/java/org/apache/dubbo/aot/api/MemberDescriber.java b/dubbo-plugin/dubbo-native/src/main/java/org/apache/dubbo/aot/api/MemberDescriber.java similarity index 100% rename from dubbo-native/src/main/java/org/apache/dubbo/aot/api/MemberDescriber.java rename to dubbo-plugin/dubbo-native/src/main/java/org/apache/dubbo/aot/api/MemberDescriber.java diff --git a/dubbo-native/src/main/java/org/apache/dubbo/aot/api/ProxyDescriberRegistrar.java b/dubbo-plugin/dubbo-native/src/main/java/org/apache/dubbo/aot/api/ProxyDescriberRegistrar.java similarity index 100% rename from dubbo-native/src/main/java/org/apache/dubbo/aot/api/ProxyDescriberRegistrar.java rename to dubbo-plugin/dubbo-native/src/main/java/org/apache/dubbo/aot/api/ProxyDescriberRegistrar.java diff --git a/dubbo-native/src/main/java/org/apache/dubbo/aot/api/ReflectionTypeDescriberRegistrar.java b/dubbo-plugin/dubbo-native/src/main/java/org/apache/dubbo/aot/api/ReflectionTypeDescriberRegistrar.java similarity index 100% rename from dubbo-native/src/main/java/org/apache/dubbo/aot/api/ReflectionTypeDescriberRegistrar.java rename to dubbo-plugin/dubbo-native/src/main/java/org/apache/dubbo/aot/api/ReflectionTypeDescriberRegistrar.java diff --git a/dubbo-native/src/main/java/org/apache/dubbo/aot/api/ResourceBundleDescriber.java b/dubbo-plugin/dubbo-native/src/main/java/org/apache/dubbo/aot/api/ResourceBundleDescriber.java similarity index 100% rename from dubbo-native/src/main/java/org/apache/dubbo/aot/api/ResourceBundleDescriber.java rename to dubbo-plugin/dubbo-native/src/main/java/org/apache/dubbo/aot/api/ResourceBundleDescriber.java diff --git a/dubbo-native/src/main/java/org/apache/dubbo/aot/api/ResourceDescriberRegistrar.java b/dubbo-plugin/dubbo-native/src/main/java/org/apache/dubbo/aot/api/ResourceDescriberRegistrar.java similarity index 100% rename from dubbo-native/src/main/java/org/apache/dubbo/aot/api/ResourceDescriberRegistrar.java rename to dubbo-plugin/dubbo-native/src/main/java/org/apache/dubbo/aot/api/ResourceDescriberRegistrar.java diff --git a/dubbo-native/src/main/java/org/apache/dubbo/aot/api/ResourcePatternDescriber.java b/dubbo-plugin/dubbo-native/src/main/java/org/apache/dubbo/aot/api/ResourcePatternDescriber.java similarity index 100% rename from dubbo-native/src/main/java/org/apache/dubbo/aot/api/ResourcePatternDescriber.java rename to dubbo-plugin/dubbo-native/src/main/java/org/apache/dubbo/aot/api/ResourcePatternDescriber.java diff --git a/dubbo-native/src/main/java/org/apache/dubbo/aot/api/TypeDescriber.java b/dubbo-plugin/dubbo-native/src/main/java/org/apache/dubbo/aot/api/TypeDescriber.java similarity index 100% rename from dubbo-native/src/main/java/org/apache/dubbo/aot/api/TypeDescriber.java rename to dubbo-plugin/dubbo-native/src/main/java/org/apache/dubbo/aot/api/TypeDescriber.java diff --git a/dubbo-native/src/main/java/org/apache/dubbo/aot/generate/AotProcessor.java b/dubbo-plugin/dubbo-native/src/main/java/org/apache/dubbo/aot/generate/AotProcessor.java similarity index 88% rename from dubbo-native/src/main/java/org/apache/dubbo/aot/generate/AotProcessor.java rename to dubbo-plugin/dubbo-native/src/main/java/org/apache/dubbo/aot/generate/AotProcessor.java index a2c15e4bf7..dfb0257ef1 100644 --- a/dubbo-native/src/main/java/org/apache/dubbo/aot/generate/AotProcessor.java +++ b/dubbo-plugin/dubbo-native/src/main/java/org/apache/dubbo/aot/generate/AotProcessor.java @@ -62,7 +62,16 @@ public class AotProcessor { private static List getTypes() { List typeDescribers = new ArrayList<>(); FrameworkModel.defaultModel().defaultApplication().getExtensionLoader(ReflectionTypeDescriberRegistrar.class).getSupportedExtensionInstances().forEach(reflectionTypeDescriberRegistrar -> { - typeDescribers.addAll(reflectionTypeDescriberRegistrar.getTypeDescribers()); + List describers = new ArrayList<>(); + try { + describers = reflectionTypeDescriberRegistrar.getTypeDescribers(); + } catch (Throwable e) { + // The ReflectionTypeDescriberRegistrar implementation classes are shaded, causing some unused classes to be loaded. + // When loading a dependent class may appear that cannot be found, it does not affect. + // ignore + } + + typeDescribers.addAll(describers); }); return typeDescribers; diff --git a/dubbo-native/src/main/java/org/apache/dubbo/aot/generate/BasicJsonWriter.java b/dubbo-plugin/dubbo-native/src/main/java/org/apache/dubbo/aot/generate/BasicJsonWriter.java similarity index 100% rename from dubbo-native/src/main/java/org/apache/dubbo/aot/generate/BasicJsonWriter.java rename to dubbo-plugin/dubbo-native/src/main/java/org/apache/dubbo/aot/generate/BasicJsonWriter.java diff --git a/dubbo-native/src/main/java/org/apache/dubbo/aot/generate/ClassSourceScanner.java b/dubbo-plugin/dubbo-native/src/main/java/org/apache/dubbo/aot/generate/ClassSourceScanner.java similarity index 100% rename from dubbo-native/src/main/java/org/apache/dubbo/aot/generate/ClassSourceScanner.java rename to dubbo-plugin/dubbo-native/src/main/java/org/apache/dubbo/aot/generate/ClassSourceScanner.java diff --git a/dubbo-native/src/main/java/org/apache/dubbo/aot/generate/ExecutableDescriber.java b/dubbo-plugin/dubbo-native/src/main/java/org/apache/dubbo/aot/generate/ExecutableDescriber.java similarity index 100% rename from dubbo-native/src/main/java/org/apache/dubbo/aot/generate/ExecutableDescriber.java rename to dubbo-plugin/dubbo-native/src/main/java/org/apache/dubbo/aot/generate/ExecutableDescriber.java diff --git a/dubbo-native/src/main/java/org/apache/dubbo/aot/generate/JarScanner.java b/dubbo-plugin/dubbo-native/src/main/java/org/apache/dubbo/aot/generate/JarScanner.java similarity index 100% rename from dubbo-native/src/main/java/org/apache/dubbo/aot/generate/JarScanner.java rename to dubbo-plugin/dubbo-native/src/main/java/org/apache/dubbo/aot/generate/JarScanner.java diff --git a/dubbo-native/src/main/java/org/apache/dubbo/aot/generate/NativeClassSourceWriter.java b/dubbo-plugin/dubbo-native/src/main/java/org/apache/dubbo/aot/generate/NativeClassSourceWriter.java similarity index 100% rename from dubbo-native/src/main/java/org/apache/dubbo/aot/generate/NativeClassSourceWriter.java rename to dubbo-plugin/dubbo-native/src/main/java/org/apache/dubbo/aot/generate/NativeClassSourceWriter.java diff --git a/dubbo-native/src/main/java/org/apache/dubbo/aot/generate/NativeConfigurationWriter.java b/dubbo-plugin/dubbo-native/src/main/java/org/apache/dubbo/aot/generate/NativeConfigurationWriter.java similarity index 100% rename from dubbo-native/src/main/java/org/apache/dubbo/aot/generate/NativeConfigurationWriter.java rename to dubbo-plugin/dubbo-native/src/main/java/org/apache/dubbo/aot/generate/NativeConfigurationWriter.java diff --git a/dubbo-native/src/main/java/org/apache/dubbo/aot/generate/ProxyConfigMetadataRepository.java b/dubbo-plugin/dubbo-native/src/main/java/org/apache/dubbo/aot/generate/ProxyConfigMetadataRepository.java similarity index 100% rename from dubbo-native/src/main/java/org/apache/dubbo/aot/generate/ProxyConfigMetadataRepository.java rename to dubbo-plugin/dubbo-native/src/main/java/org/apache/dubbo/aot/generate/ProxyConfigMetadataRepository.java diff --git a/dubbo-native/src/main/java/org/apache/dubbo/aot/generate/ProxyConfigWriter.java b/dubbo-plugin/dubbo-native/src/main/java/org/apache/dubbo/aot/generate/ProxyConfigWriter.java similarity index 100% rename from dubbo-native/src/main/java/org/apache/dubbo/aot/generate/ProxyConfigWriter.java rename to dubbo-plugin/dubbo-native/src/main/java/org/apache/dubbo/aot/generate/ProxyConfigWriter.java diff --git a/dubbo-native/src/main/java/org/apache/dubbo/aot/generate/ReflectConfigMetadataRepository.java b/dubbo-plugin/dubbo-native/src/main/java/org/apache/dubbo/aot/generate/ReflectConfigMetadataRepository.java similarity index 100% rename from dubbo-native/src/main/java/org/apache/dubbo/aot/generate/ReflectConfigMetadataRepository.java rename to dubbo-plugin/dubbo-native/src/main/java/org/apache/dubbo/aot/generate/ReflectConfigMetadataRepository.java diff --git a/dubbo-native/src/main/java/org/apache/dubbo/aot/generate/ReflectionConfigWriter.java b/dubbo-plugin/dubbo-native/src/main/java/org/apache/dubbo/aot/generate/ReflectionConfigWriter.java similarity index 100% rename from dubbo-native/src/main/java/org/apache/dubbo/aot/generate/ReflectionConfigWriter.java rename to dubbo-plugin/dubbo-native/src/main/java/org/apache/dubbo/aot/generate/ReflectionConfigWriter.java diff --git a/dubbo-native/src/main/java/org/apache/dubbo/aot/generate/ResourceConfigMetadataRepository.java b/dubbo-plugin/dubbo-native/src/main/java/org/apache/dubbo/aot/generate/ResourceConfigMetadataRepository.java similarity index 100% rename from dubbo-native/src/main/java/org/apache/dubbo/aot/generate/ResourceConfigMetadataRepository.java rename to dubbo-plugin/dubbo-native/src/main/java/org/apache/dubbo/aot/generate/ResourceConfigMetadataRepository.java diff --git a/dubbo-native/src/main/java/org/apache/dubbo/aot/generate/ResourceConfigWriter.java b/dubbo-plugin/dubbo-native/src/main/java/org/apache/dubbo/aot/generate/ResourceConfigWriter.java similarity index 100% rename from dubbo-native/src/main/java/org/apache/dubbo/aot/generate/ResourceConfigWriter.java rename to dubbo-plugin/dubbo-native/src/main/java/org/apache/dubbo/aot/generate/ResourceConfigWriter.java diff --git a/dubbo-native/src/main/java/org/apache/dubbo/aot/generate/ResourceScanner.java b/dubbo-plugin/dubbo-native/src/main/java/org/apache/dubbo/aot/generate/ResourceScanner.java similarity index 100% rename from dubbo-native/src/main/java/org/apache/dubbo/aot/generate/ResourceScanner.java rename to dubbo-plugin/dubbo-native/src/main/java/org/apache/dubbo/aot/generate/ResourceScanner.java diff --git a/dubbo-native/src/main/resources/Dockerfile b/dubbo-plugin/dubbo-native/src/main/resources/Dockerfile similarity index 100% rename from dubbo-native/src/main/resources/Dockerfile rename to dubbo-plugin/dubbo-native/src/main/resources/Dockerfile diff --git a/dubbo-native/src/test/java/org/apache/dubbo/aot/generate/ResourcePatternDescriberTest.java b/dubbo-plugin/dubbo-native/src/test/java/org/apache/dubbo/aot/generate/ResourcePatternDescriberTest.java similarity index 100% rename from dubbo-native/src/test/java/org/apache/dubbo/aot/generate/ResourcePatternDescriberTest.java rename to dubbo-plugin/dubbo-native/src/test/java/org/apache/dubbo/aot/generate/ResourcePatternDescriberTest.java diff --git a/dubbo-build-tools/pom.xml b/dubbo-plugin/dubbo-plugin-loom/pom.xml similarity index 56% rename from dubbo-build-tools/pom.xml rename to dubbo-plugin/dubbo-plugin-loom/pom.xml index 28bae806b1..e16ab7b27c 100644 --- a/dubbo-build-tools/pom.xml +++ b/dubbo-plugin/dubbo-plugin-loom/pom.xml @@ -6,7 +6,9 @@ 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. @@ -16,15 +18,30 @@ + + org.apache.dubbo + dubbo-plugin + ${revision} + ../pom.xml + 4.0.0 - org.apache.dubbo - dubbo-build-tools - 1.0.0 - jar + dubbo-plugin-loom - true + 21 + 21 + UTF-8 + UTF-8 + false - \ No newline at end of file + + + org.apache.dubbo + dubbo-common + ${project.version} + true + + + diff --git a/dubbo-plugin/dubbo-plugin-loom/src/main/java/org/apache/dubbo/common/threadpool/support/loom/VirtualThreadPool.java b/dubbo-plugin/dubbo-plugin-loom/src/main/java/org/apache/dubbo/common/threadpool/support/loom/VirtualThreadPool.java new file mode 100644 index 0000000000..c78c0b2b10 --- /dev/null +++ b/dubbo-plugin/dubbo-plugin-loom/src/main/java/org/apache/dubbo/common/threadpool/support/loom/VirtualThreadPool.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.common.threadpool.support.loom; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.threadpool.ThreadPool; + +import java.util.concurrent.Executor; +import java.util.concurrent.Executors; + +import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_THREAD_NAME; +import static org.apache.dubbo.common.constants.CommonConstants.THREAD_NAME_KEY; + +/** + * Creates a thread pool that use virtual thread + * + * @see Executors#newVirtualThreadPerTaskExecutor() + */ +public class VirtualThreadPool implements ThreadPool { + @Override + public Executor getExecutor(URL url) { + String name = url.getParameter(THREAD_NAME_KEY, (String) url.getAttribute(THREAD_NAME_KEY, DEFAULT_THREAD_NAME)); + return Executors.newThreadPerTaskExecutor( + Thread.ofVirtual() + .name(name, 1) + .factory()); + } +} diff --git a/dubbo-plugin/dubbo-plugin-loom/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.threadpool.ThreadPool b/dubbo-plugin/dubbo-plugin-loom/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.threadpool.ThreadPool new file mode 100644 index 0000000000..e9f3348ad4 --- /dev/null +++ b/dubbo-plugin/dubbo-plugin-loom/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.threadpool.ThreadPool @@ -0,0 +1 @@ +virtual=org.apache.dubbo.common.threadpool.support.loom.VirtualThreadPool diff --git a/dubbo-plugin/dubbo-plugin-loom/src/test/java/org/apache/dubbo/common/threadpool/support/loom/VirtualThreadPoolTest.java b/dubbo-plugin/dubbo-plugin-loom/src/test/java/org/apache/dubbo/common/threadpool/support/loom/VirtualThreadPoolTest.java new file mode 100644 index 0000000000..42653cd8bd --- /dev/null +++ b/dubbo-plugin/dubbo-plugin-loom/src/test/java/org/apache/dubbo/common/threadpool/support/loom/VirtualThreadPoolTest.java @@ -0,0 +1,66 @@ +/* + * 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.threadpool.support.loom; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.threadpool.ThreadPool; + +import org.hamcrest.Matchers; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.condition.EnabledForJreRange; +import org.junit.jupiter.api.condition.JRE; + +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.Executor; + +import static org.apache.dubbo.common.constants.CommonConstants.QUEUES_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.THREAD_NAME_KEY; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.startsWith; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class VirtualThreadPoolTest { + + @Test + @EnabledForJreRange(min = JRE.JAVA_21) + void getExecutor1() throws Exception { + URL url = URL.valueOf("dubbo://10.20.130.230:20880/context/path?" + + THREAD_NAME_KEY + "=demo"); + ThreadPool threadPool = new VirtualThreadPool(); + Executor executor = threadPool.getExecutor(url); + + final CountDownLatch latch = new CountDownLatch(1); + executor.execute(() -> { + Thread thread = Thread.currentThread(); + assertTrue(thread.isVirtual()); + assertThat(thread.getName(), startsWith("demo")); + latch.countDown(); + }); + + latch.await(); + assertThat(latch.getCount(), is(0L)); + } + + @Test + @EnabledForJreRange(min = JRE.JAVA_21) + void getExecutor2() { + URL url = URL.valueOf("dubbo://10.20.130.230:20880/context/path?" + QUEUES_KEY + "=1"); + ThreadPool threadPool = new VirtualThreadPool(); + assertThat(threadPool.getExecutor(url).getClass().getName(), Matchers.is("java.util.concurrent.ThreadPerTaskExecutor")); + } +} diff --git a/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/aot/QosReflectionTypeDescriberRegistrar.java b/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/aot/QosReflectionTypeDescriberRegistrar.java index d99044f744..4d2170df4f 100644 --- a/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/aot/QosReflectionTypeDescriberRegistrar.java +++ b/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/aot/QosReflectionTypeDescriberRegistrar.java @@ -19,6 +19,9 @@ package org.apache.dubbo.qos.aot; import org.apache.dubbo.aot.api.MemberCategory; import org.apache.dubbo.aot.api.ReflectionTypeDescriberRegistrar; import org.apache.dubbo.aot.api.TypeDescriber; +import org.apache.dubbo.qos.server.handler.ForeignHostPermitHandler; +import org.apache.dubbo.qos.server.handler.QosProcessHandler; +import org.apache.dubbo.qos.server.handler.TelnetIdleEventHandler; import java.nio.channels.spi.SelectorProvider; import java.util.ArrayList; @@ -33,6 +36,9 @@ public class QosReflectionTypeDescriberRegistrar implements ReflectionTypeDescri public List getTypeDescribers() { List typeDescribers = new ArrayList<>(); typeDescribers.add(buildTypeDescriberWithPublicMethod(SelectorProvider.class)); + typeDescribers.add(buildTypeDescriberWithPublicMethod(ForeignHostPermitHandler.class)); + typeDescribers.add(buildTypeDescriberWithPublicMethod(QosProcessHandler.class)); + typeDescribers.add(buildTypeDescriberWithPublicMethod(TelnetIdleEventHandler.class)); return typeDescribers; } 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 a06b246ab4..fe47762a33 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 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_CHECK; import static org.apache.dubbo.common.constants.QosConstants.QOS_ENABLE; import static org.apache.dubbo.common.constants.QosConstants.QOS_HOST; import static org.apache.dubbo.common.constants.QosConstants.QOS_PORT; @@ -95,7 +96,9 @@ public class QosProtocolWrapper implements Protocol, ScopeModelAware { return protocol.getServers(); } - private void startQosServer(URL url) { + private void startQosServer(URL url) throws RpcException { + boolean qosCheck = url.getParameter(QOS_CHECK, false); + try { if (!hasStarted.compareAndSet(false, true)) { return; @@ -131,6 +134,14 @@ public class QosProtocolWrapper implements Protocol, ScopeModelAware { } catch (Throwable throwable) { logger.warn(QOS_FAILED_START_SERVER, "", "", "Fail to start qos server: ", throwable); + try { + stopServer(); + } catch (Throwable stop) { + logger.warn(QOS_FAILED_START_SERVER, "", "", "Fail to stop qos server: ", stop); + } + if (qosCheck) { + throw new RpcException(throwable); + } } } diff --git a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/event/EmptyEvent.java b/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/server/QosBindException.java similarity index 67% rename from dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/event/EmptyEvent.java rename to dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/server/QosBindException.java index 70c9764dd3..57aecd228f 100644 --- a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/event/EmptyEvent.java +++ b/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/server/QosBindException.java @@ -14,23 +14,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -package org.apache.dubbo.metrics.event; - -import org.apache.dubbo.rpc.model.ApplicationModel; +package org.apache.dubbo.qos.server; /** - * EmptyEvent, do nothing. + * Indicate that if Qos Start failed */ -public class EmptyEvent extends MetricsEvent { - - private static final EmptyEvent empty = new EmptyEvent(null); - - private EmptyEvent(ApplicationModel source) { - super(source, null); - } - - public static EmptyEvent instance() { - return empty; +public class QosBindException extends RuntimeException { + public QosBindException(String message, Throwable cause) { + super(message, cause); } } 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 65e7e3b9fa..12c02ccea7 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 @@ -35,8 +35,6 @@ import io.netty.util.concurrent.DefaultThreadFactory; import java.util.concurrent.atomic.AtomicBoolean; -import static org.apache.dubbo.common.constants.LoggerCodeConstants.QOS_FAILED_START_SERVER; - /** * A server serves for both telnet access and http access *

    @@ -105,13 +103,13 @@ public class Server { @Override protected void initChannel(Channel ch) throws Exception { ch.pipeline().addLast(new QosProcessHandler(frameworkModel, - QosConfiguration.builder() - .welcome(welcome) - .acceptForeignIp(acceptForeignIp) - .acceptForeignIpWhitelist(acceptForeignIpWhitelist) - .anonymousAccessPermissionLevel(anonymousAccessPermissionLevel) - .anonymousAllowCommands(anonymousAllowCommands) - .build() + QosConfiguration.builder() + .welcome(welcome) + .acceptForeignIp(acceptForeignIp) + .acceptForeignIpWhitelist(acceptForeignIpWhitelist) + .anonymousAccessPermissionLevel(anonymousAccessPermissionLevel) + .anonymousAllowCommands(anonymousAllowCommands) + .build() )); } }); @@ -124,8 +122,7 @@ public class Server { logger.info("qos-server bind localhost:" + port); } catch (Throwable throwable) { - logger.error(QOS_FAILED_START_SERVER, "", "", "qos-server can not bind localhost:" + port, throwable); - throw throwable; + throw new QosBindException("qos-server can not bind localhost:" + port, throwable); } } @@ -140,6 +137,7 @@ public class Server { if (worker != null) { worker.shutdownGracefully(); } + started.set(false); } public String getHost() { diff --git a/dubbo-plugin/pom.xml b/dubbo-plugin/pom.xml index a7cf59881f..058f123403 100644 --- a/dubbo-plugin/pom.xml +++ b/dubbo-plugin/pom.xml @@ -36,6 +36,7 @@ dubbo-spring-security dubbo-qos-api dubbo-plugin-cluster-mergeable + dubbo-native dubbo-plugin-mock dubbo-plugin-router-script dubbo-plugin-router-mesh @@ -63,4 +64,16 @@ test + + + + loom + + [21,) + + + dubbo-plugin-loom + + + diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistry.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistry.java index fbc8f0e792..a61cb85bed 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistry.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistry.java @@ -134,10 +134,8 @@ public class ServiceDiscoveryRegistry extends FailbackRegistry { boolean should = PROVIDER_SIDE.equals(side); // Only register the Provider. - if (!should) { - if (logger.isDebugEnabled()) { - logger.debug(String.format("The URL[%s] should not be registered.", providerURL)); - } + if (!should && logger.isDebugEnabled()) { + logger.debug(String.format("The URL[%s] should not be registered.", providerURL)); } if (!acceptable(providerURL)) { @@ -395,7 +393,7 @@ public class ServiceDiscoveryRegistry extends FailbackRegistry { Lock mappingLock = serviceNameMapping.getMappingLock(event.getServiceKey()); try { mappingLock.lock(); - if (CollectionUtils.isEmpty(tempOldApps) && newApps.size() > 0) { + if (CollectionUtils.isEmpty(tempOldApps) && !newApps.isEmpty()) { serviceNameMapping.putCachedMapping(ServiceNameMapping.buildMappingKey(url), newApps); subscribeURLs(url, listener, newApps); oldApps = newApps; diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistryDirectory.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistryDirectory.java index 6c151a19a5..07a6bfa36a 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistryDirectory.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistryDirectory.java @@ -594,7 +594,7 @@ public class ServiceDiscoveryRegistryDirectory extends DynamicDirectory { } void addNotifyListener(ServiceDiscoveryRegistryDirectory listener) { - if (listeners.size() == 0) { + if (listeners.isEmpty()) { this.initWith(moduleModel.getApplicationModel().getApplicationName() + CONFIGURATORS_SUFFIX); } this.listeners.add(listener); @@ -602,7 +602,7 @@ public class ServiceDiscoveryRegistryDirectory extends DynamicDirectory { void removeNotifyListener(ServiceDiscoveryRegistryDirectory listener) { this.listeners.remove(listener); - if (listeners.size() == 0) { + if (listeners.isEmpty()) { this.stopListen(moduleModel.getApplicationModel().getApplicationName() + CONFIGURATORS_SUFFIX); } } @@ -703,4 +703,12 @@ public class ServiceDiscoveryRegistryDirectory extends DynamicDirectory { } } + @Override + public String toString() { + return "ServiceDiscoveryRegistryDirectory(" + + "registry: " + getUrl().getAddress() + + ", subscribed key: " + (serviceListener == null || CollectionUtils.isEmpty(serviceListener.getServiceNames()) + ? getConsumerUrl().getServiceKey() : serviceListener.getServiceNames().toString()) + + ")-" + super.toString(); + } } diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/DynamicDirectory.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/DynamicDirectory.java index 7ee4da0ed8..1f57e972d7 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/DynamicDirectory.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/DynamicDirectory.java @@ -195,7 +195,7 @@ public abstract class DynamicDirectory extends AbstractDirectory implement if (forbidden && shouldFailFast) { // 1. No service provider 2. Service providers are disabled throw new RpcException(RpcException.FORBIDDEN_EXCEPTION, "No provider available from registry " + - getUrl().getAddress() + " for service " + getConsumerUrl().getServiceKey() + " on consumer " + + this + " for service " + getConsumerUrl().getServiceKey() + " on consumer " + NetUtils.getLocalHost() + " use dubbo version " + Version.getVersion() + ", please check status of providers(disabled, not registered or in blacklist)."); } diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/Constants.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/Constants.java index 5346193900..ab75d2b183 100644 --- a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/Constants.java +++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/Constants.java @@ -130,6 +130,10 @@ public interface Constants { String BIND_PORT_KEY = "bind.port"; + String BIND_RETRY_TIMES = "bind.retry.times"; + + String BIND_RETRY_INTERVAL = "bind.retry.interval"; + String SENT_KEY = "sent"; String DISPATCHER_KEY = "dispatcher"; diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/support/DefaultFuture.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/support/DefaultFuture.java index f49ef15867..75544e9927 100644 --- a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/support/DefaultFuture.java +++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/support/DefaultFuture.java @@ -276,7 +276,7 @@ public class DefaultFuture extends CompletableFuture { private String getTimeoutMessage(boolean scan) { long nowTimestamp = System.currentTimeMillis(); - return (sent > 0 ? "Waiting server-side response timeout" : "Sending request timeout in client-side") + return (sent > 0 && sent - start < timeout ? "Waiting server-side response timeout" : "Sending request timeout in client-side") + (scan ? " by scan timer" : "") + ". start time: " + (new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date(start))) + ", end time: " + (new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date(nowTimestamp))) + "," diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/support/header/HeaderExchangeClient.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/support/header/HeaderExchangeClient.java index 0adf656604..6b9dd53e95 100644 --- a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/support/header/HeaderExchangeClient.java +++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/support/header/HeaderExchangeClient.java @@ -248,8 +248,8 @@ public class HeaderExchangeClient implements ExchangeClient { return Math.max(leastReconnectDuration, tick); } - private boolean shouldReconnect(URL url) { - return url.getParameter(Constants.RECONNECT_KEY, true); + protected boolean shouldReconnect(URL url) { + return !Boolean.FALSE.toString().equalsIgnoreCase(url.getParameter(Constants.RECONNECT_KEY)); } @Override diff --git a/dubbo-remoting/dubbo-remoting-api/src/test/java/org/apache/dubbo/remoting/exchange/support/DefaultFutureTest.java b/dubbo-remoting/dubbo-remoting-api/src/test/java/org/apache/dubbo/remoting/exchange/support/DefaultFutureTest.java index 8188720480..171d040cd9 100644 --- a/dubbo-remoting/dubbo-remoting-api/src/test/java/org/apache/dubbo/remoting/exchange/support/DefaultFutureTest.java +++ b/dubbo-remoting/dubbo-remoting-api/src/test/java/org/apache/dubbo/remoting/exchange/support/DefaultFutureTest.java @@ -86,6 +86,43 @@ class DefaultFutureTest { } } + /** + * for example, it will print like this: + * before a future is created, time is : 2023-09-03 18:20:14.535 + * after a future is timeout, time is : 2023-09-03 18:20:14.669 + *

    + * The exception info print like: + * Sending request timeout in client-side by scan timer. + * start time: 2023-09-03 18:20:14.544, end time: 2023-09-03 18:20:14.598... + */ + @Test + public void clientTimeoutSend() throws Exception { + final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS"); + System.out.println("before a future is create , time is : " + LocalDateTime.now().format(formatter)); + // timeout after 5 milliseconds. + Channel channel = new MockedChannel(); + Request request = new Request(10); + DefaultFuture f = DefaultFuture.newFuture(channel, request, 5, null); + System.gc(); // events such as Full GC will increase the time required to send messages. + + // mark the future is sent + DefaultFuture.sent(channel, request); + while (!f.isDone()) { + // spin + Thread.sleep(100); + } + System.out.println("after a future is timeout , time is : " + LocalDateTime.now().format(formatter)); + + // get operate will throw a timeout exception, because the future is timeout. + try { + f.get(); + } catch (Exception e) { + Assertions.assertTrue(e.getCause() instanceof TimeoutException, "catch exception is not timeout exception!"); + System.out.println(e.getMessage()); + Assertions.assertTrue(e.getMessage().startsWith(e.getCause().getClass().getCanonicalName() + ": Sending request timeout in client-side")); + } + } + /** * for example, it will print like this: * before a future is create , time is : 2018-06-21 15:11:31 diff --git a/dubbo-remoting/dubbo-remoting-api/src/test/java/org/apache/dubbo/remoting/exchange/support/header/HeaderExchangeClientTest.java b/dubbo-remoting/dubbo-remoting-api/src/test/java/org/apache/dubbo/remoting/exchange/support/header/HeaderExchangeClientTest.java new file mode 100644 index 0000000000..7fad611e7f --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-api/src/test/java/org/apache/dubbo/remoting/exchange/support/header/HeaderExchangeClientTest.java @@ -0,0 +1,40 @@ +/* + * 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.exchange.support.header; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.remoting.Client; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; + +public class HeaderExchangeClientTest { + @Test + void testReconnect() { + HeaderExchangeClient headerExchangeClient = new HeaderExchangeClient(Mockito.mock(Client.class), false); + + Assertions.assertTrue(headerExchangeClient.shouldReconnect(URL.valueOf("localhost"))); + Assertions.assertTrue(headerExchangeClient.shouldReconnect(URL.valueOf("localhost?reconnect=true"))); + Assertions.assertTrue(headerExchangeClient.shouldReconnect(URL.valueOf("localhost?reconnect=tRue"))); + Assertions.assertTrue(headerExchangeClient.shouldReconnect(URL.valueOf("localhost?reconnect=30000"))); + Assertions.assertTrue(headerExchangeClient.shouldReconnect(URL.valueOf("localhost?reconnect=0"))); + Assertions.assertTrue(headerExchangeClient.shouldReconnect(URL.valueOf("localhost?reconnect=-1"))); + Assertions.assertFalse(headerExchangeClient.shouldReconnect(URL.valueOf("localhost?reconnect=false"))); + Assertions.assertFalse(headerExchangeClient.shouldReconnect(URL.valueOf("localhost?reconnect=FALSE"))); + } +} diff --git a/dubbo-remoting/dubbo-remoting-http/src/main/java/org/apache/dubbo/remoting/http/restclient/HttpClientRestClient.java b/dubbo-remoting/dubbo-remoting-http/src/main/java/org/apache/dubbo/remoting/http/restclient/HttpClientRestClient.java index 0344a4aab9..f8f85411af 100644 --- a/dubbo-remoting/dubbo-remoting-http/src/main/java/org/apache/dubbo/remoting/http/restclient/HttpClientRestClient.java +++ b/dubbo-remoting/dubbo-remoting-http/src/main/java/org/apache/dubbo/remoting/http/restclient/HttpClientRestClient.java @@ -93,7 +93,8 @@ public class HttpClientRestClient implements RestClient { future.complete(new RestResult() { @Override public String getContentType() { - return response.getFirstHeader("Content-Type").getValue(); + Header header = response.getFirstHeader("Content-Type"); + return header == null ? null : header.getValue(); } @Override 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 f5fdc9a919..a7cab7b985 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 @@ -97,14 +97,14 @@ public class NettyPortUnificationServer extends AbstractPortUnificationServer { } } - public void bind() { + public void bind() throws Throwable { if (channel == null) { doOpen(); } } @Override - public void doOpen() { + public void doOpen() throws Throwable { bootstrap = new ServerBootstrap(); bossGroup = NettyEventLoopFactory.eventLoopGroup(1, EVENT_LOOP_BOSS_POOL_NAME); @@ -138,9 +138,31 @@ public class NettyPortUnificationServer extends AbstractPortUnificationServer { bindIp = ANYHOST_VALUE; } InetSocketAddress bindAddress = new InetSocketAddress(bindIp, bindPort); - ChannelFuture channelFuture = bootstrap.bind(bindAddress); - channelFuture.syncUninterruptibly(); - channel = channelFuture.channel(); + try { + ChannelFuture channelFuture = bootstrap.bind(bindAddress); + channelFuture.syncUninterruptibly(); + channel = channelFuture.channel(); + } catch (Throwable t) { + closeBootstrap(); + throw t; + } + } + + private void closeBootstrap() { + try { + if (bootstrap != null) { + long timeout = ConfigurationUtils.reCalShutdownTime(serverShutdownTimeoutMills); + long quietPeriod = Math.min(2000L, timeout); + Future bossGroupShutdownFuture = bossGroup.shutdownGracefully(quietPeriod, + timeout, MILLISECONDS); + Future workerGroupShutdownFuture = workerGroup.shutdownGracefully(quietPeriod, + timeout, MILLISECONDS); + bossGroupShutdownFuture.awaitUninterruptibly(timeout, MILLISECONDS); + workerGroupShutdownFuture.awaitUninterruptibly(timeout, MILLISECONDS); + } + } catch (Throwable e) { + logger.warn(TRANSPORT_FAILED_CLOSE, "", "", e.getMessage(), e); + } } @Override @@ -176,20 +198,7 @@ public class NettyPortUnificationServer extends AbstractPortUnificationServer { protocol.close(); } - try { - if (bootstrap != null) { - long timeout = ConfigurationUtils.reCalShutdownTime(serverShutdownTimeoutMills); - long quietPeriod = Math.min(2000L, timeout); - Future bossGroupShutdownFuture = bossGroup.shutdownGracefully(quietPeriod, - timeout, MILLISECONDS); - Future workerGroupShutdownFuture = workerGroup.shutdownGracefully(quietPeriod, - timeout, MILLISECONDS); - bossGroupShutdownFuture.awaitUninterruptibly(timeout, MILLISECONDS); - workerGroupShutdownFuture.awaitUninterruptibly(timeout, MILLISECONDS); - } - } catch (Throwable e) { - logger.warn(TRANSPORT_FAILED_CLOSE, "", "", e.getMessage(), e); - } + closeBootstrap(); } @Override diff --git a/dubbo-remoting/dubbo-remoting-netty4/src/main/java/org/apache/dubbo/remoting/transport/netty4/NettyServer.java b/dubbo-remoting/dubbo-remoting-netty4/src/main/java/org/apache/dubbo/remoting/transport/netty4/NettyServer.java index 6acf226391..d165651858 100644 --- a/dubbo-remoting/dubbo-remoting-netty4/src/main/java/org/apache/dubbo/remoting/transport/netty4/NettyServer.java +++ b/dubbo-remoting/dubbo-remoting-netty4/src/main/java/org/apache/dubbo/remoting/transport/netty4/NettyServer.java @@ -111,9 +111,14 @@ public class NettyServer extends AbstractServer { initServerBootstrap(nettyServerHandler); // bind - ChannelFuture channelFuture = bootstrap.bind(getBindAddress()); - channelFuture.syncUninterruptibly(); - channel = channelFuture.channel(); + try { + ChannelFuture channelFuture = bootstrap.bind(getBindAddress()); + channelFuture.syncUninterruptibly(); + channel = channelFuture.channel(); + } catch (Throwable t) { + closeBootstrap(); + throw t; + } // metrics if (isSupportMetrics()) { @@ -198,6 +203,17 @@ public class NettyServer extends AbstractServer { } catch (Throwable e) { logger.warn(TRANSPORT_FAILED_CLOSE, "", "", e.getMessage(), e); } + closeBootstrap(); + try { + if (channels != null) { + channels.clear(); + } + } catch (Throwable e) { + logger.warn(TRANSPORT_FAILED_CLOSE, "", "", e.getMessage(), e); + } + } + + private void closeBootstrap() { try { if (bootstrap != null) { long timeout = ConfigurationUtils.reCalShutdownTime(serverShutdownTimeoutMills); @@ -210,13 +226,6 @@ public class NettyServer extends AbstractServer { } catch (Throwable e) { logger.warn(TRANSPORT_FAILED_CLOSE, "", "", e.getMessage(), e); } - try { - if (channels != null) { - channels.clear(); - } - } catch (Throwable e) { - logger.warn(TRANSPORT_FAILED_CLOSE, "", "", e.getMessage(), e); - } } @Override diff --git a/dubbo-remoting/dubbo-remoting-netty4/src/test/java/org/apache/dubbo/remoting/transport/netty4/ConnectionTest.java b/dubbo-remoting/dubbo-remoting-netty4/src/test/java/org/apache/dubbo/remoting/transport/netty4/ConnectionTest.java index 2c230d6c61..ba9fd3eb0d 100644 --- a/dubbo-remoting/dubbo-remoting-netty4/src/test/java/org/apache/dubbo/remoting/transport/netty4/ConnectionTest.java +++ b/dubbo-remoting/dubbo-remoting-netty4/src/test/java/org/apache/dubbo/remoting/transport/netty4/ConnectionTest.java @@ -21,13 +21,13 @@ import org.apache.dubbo.common.constants.CommonConstants; import org.apache.dubbo.common.utils.NetUtils; import org.apache.dubbo.config.ApplicationConfig; import org.apache.dubbo.config.context.ConfigManager; -import org.apache.dubbo.remoting.RemotingException; import org.apache.dubbo.remoting.api.connection.AbstractConnectionClient; import org.apache.dubbo.remoting.api.connection.ConnectionManager; import org.apache.dubbo.remoting.api.connection.MultiplexProtocolConnectionManager; import org.apache.dubbo.remoting.api.pu.DefaultPuHandler; import org.apache.dubbo.rpc.model.ApplicationModel; import org.apache.dubbo.rpc.model.ModuleModel; + import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; @@ -50,7 +50,7 @@ public class ConnectionTest { private static ConnectionManager connectionManager; @BeforeAll - public static void init() throws RemotingException { + public static void init() throws Throwable { int port = NetUtils.getAvailablePort(); url = URL.valueOf("empty://127.0.0.1:" + port + "?foo=bar"); ApplicationModel applicationModel = ApplicationModel.defaultModel(); @@ -123,7 +123,7 @@ public class ConnectionTest { } @Test - void connectSyncTest() throws RemotingException { + void connectSyncTest() throws Throwable { int port = NetUtils.getAvailablePort(); URL url = URL.valueOf("empty://127.0.0.1:" + port + "?foo=bar"); NettyPortUnificationServer nettyPortUnificationServer = new NettyPortUnificationServer(url, new DefaultPuHandler()); diff --git a/dubbo-remoting/dubbo-remoting-netty4/src/test/java/org/apache/dubbo/remoting/transport/netty4/PortUnificationServerTest.java b/dubbo-remoting/dubbo-remoting-netty4/src/test/java/org/apache/dubbo/remoting/transport/netty4/PortUnificationServerTest.java index da9264a346..12f3fc8905 100644 --- a/dubbo-remoting/dubbo-remoting-netty4/src/test/java/org/apache/dubbo/remoting/transport/netty4/PortUnificationServerTest.java +++ b/dubbo-remoting/dubbo-remoting-netty4/src/test/java/org/apache/dubbo/remoting/transport/netty4/PortUnificationServerTest.java @@ -16,43 +16,25 @@ */ package org.apache.dubbo.remoting.transport.netty4; + import org.apache.dubbo.common.URL; import org.apache.dubbo.common.constants.CommonConstants; -import org.apache.dubbo.common.extension.ExtensionDirector; -import org.apache.dubbo.common.extension.ExtensionLoader; -import org.apache.dubbo.common.threadpool.manager.DefaultExecutorRepository; -import org.apache.dubbo.common.threadpool.manager.ExecutorRepository; import org.apache.dubbo.common.utils.NetUtils; import org.apache.dubbo.config.ApplicationConfig; import org.apache.dubbo.config.context.ConfigManager; -import org.apache.dubbo.config.context.ModuleConfigManager; -import org.apache.dubbo.remoting.Channel; -import org.apache.dubbo.remoting.RemotingException; -import org.apache.dubbo.remoting.api.ProtocolDetector; -import org.apache.dubbo.remoting.api.WireProtocol; -import org.apache.dubbo.remoting.api.pu.AbstractPortUnificationServer; -import org.apache.dubbo.remoting.api.pu.ChannelOperator; import org.apache.dubbo.remoting.api.pu.DefaultPuHandler; - -import org.apache.dubbo.remoting.api.ssl.ContextOperator; import org.apache.dubbo.rpc.model.ApplicationModel; import org.apache.dubbo.rpc.model.ModuleModel; + import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; -import org.mockito.Mock; -import org.mockito.Mockito; - -import java.net.InetSocketAddress; -import java.util.Collection; -import java.util.concurrent.Executors; import static org.apache.dubbo.common.constants.CommonConstants.EXECUTOR_MANAGEMENT_MODE_DEFAULT; -import static org.apache.dubbo.common.constants.CommonConstants.EXT_PROTOCOL; class PortUnificationServerTest { @Test - void testBind() throws RemotingException { + void testBind() throws Throwable { int port = NetUtils.getAvailablePort(); URL url = URL.valueOf("empty://127.0.0.1:" + port + "?foo=bar&" + EXT_PROTOCOL + "=tri"); ApplicationModel applicationModel = ApplicationModel.defaultModel(); diff --git a/dubbo-remoting/dubbo-remoting-netty4/src/test/java/org/apache/dubbo/remoting/transport/netty4/api/MultiplexProtocolConnectionManagerTest.java b/dubbo-remoting/dubbo-remoting-netty4/src/test/java/org/apache/dubbo/remoting/transport/netty4/api/MultiplexProtocolConnectionManagerTest.java index 2bceec7ab6..76a45adadd 100644 --- a/dubbo-remoting/dubbo-remoting-netty4/src/test/java/org/apache/dubbo/remoting/transport/netty4/api/MultiplexProtocolConnectionManagerTest.java +++ b/dubbo-remoting/dubbo-remoting-netty4/src/test/java/org/apache/dubbo/remoting/transport/netty4/api/MultiplexProtocolConnectionManagerTest.java @@ -21,15 +21,14 @@ import org.apache.dubbo.common.URL; import org.apache.dubbo.common.constants.CommonConstants; import org.apache.dubbo.config.ApplicationConfig; import org.apache.dubbo.config.context.ConfigManager; -import org.apache.dubbo.remoting.RemotingException; import org.apache.dubbo.remoting.api.connection.AbstractConnectionClient; import org.apache.dubbo.remoting.api.connection.ConnectionManager; import org.apache.dubbo.remoting.api.connection.MultiplexProtocolConnectionManager; import org.apache.dubbo.remoting.api.pu.DefaultPuHandler; import org.apache.dubbo.remoting.transport.netty4.NettyPortUnificationServer; - import org.apache.dubbo.rpc.model.ApplicationModel; import org.apache.dubbo.rpc.model.ModuleModel; + import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; @@ -52,7 +51,7 @@ public class MultiplexProtocolConnectionManagerTest { private static ConnectionManager connectionManager; @BeforeAll - public static void init() throws RemotingException { + public static void init() throws Throwable { ApplicationModel applicationModel = ApplicationModel.defaultModel(); ApplicationConfig applicationConfig = new ApplicationConfig("provider-app"); applicationConfig.setExecutorManagementMode(EXECUTOR_MANAGEMENT_MODE_DEFAULT); @@ -95,7 +94,7 @@ public class MultiplexProtocolConnectionManagerTest { } @Test - public void testForEachConnection() throws RemotingException { + public void testForEachConnection() throws Throwable { DefaultPuHandler handler = new DefaultPuHandler(); NettyPortUnificationServer server2 = new NettyPortUnificationServer(url2, handler); diff --git a/dubbo-remoting/dubbo-remoting-netty4/src/test/java/org/apache/dubbo/remoting/transport/netty4/api/SingleProtocolConnectionManagerTest.java b/dubbo-remoting/dubbo-remoting-netty4/src/test/java/org/apache/dubbo/remoting/transport/netty4/api/SingleProtocolConnectionManagerTest.java index bc4d548008..5369ea0f22 100644 --- a/dubbo-remoting/dubbo-remoting-netty4/src/test/java/org/apache/dubbo/remoting/transport/netty4/api/SingleProtocolConnectionManagerTest.java +++ b/dubbo-remoting/dubbo-remoting-netty4/src/test/java/org/apache/dubbo/remoting/transport/netty4/api/SingleProtocolConnectionManagerTest.java @@ -31,6 +31,7 @@ import org.apache.dubbo.remoting.transport.netty4.NettyConnectionClient; import org.apache.dubbo.remoting.transport.netty4.NettyPortUnificationServer; import org.apache.dubbo.rpc.model.ApplicationModel; import org.apache.dubbo.rpc.model.ModuleModel; + import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; @@ -51,7 +52,7 @@ public class SingleProtocolConnectionManagerTest { private static ConnectionManager connectionManager; @BeforeAll - public static void init() throws RemotingException { + public static void init() throws Throwable { int port = NetUtils.getAvailablePort(); url = URL.valueOf("empty://127.0.0.1:" + port + "?foo=bar"); ApplicationModel applicationModel = ApplicationModel.defaultModel(); diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/ExceptionFilter.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/ExceptionFilter.java index 2cadfec117..9265bad595 100644 --- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/ExceptionFilter.java +++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/ExceptionFilter.java @@ -92,7 +92,7 @@ public class ExceptionFilter implements Filter, Filter.Listener { } // directly throw if it's JDK exception String className = exception.getClass().getName(); - if (className.startsWith("java.") || className.startsWith("javax.")) { + if (className.startsWith("java.") || className.startsWith("javax.") || className.startsWith("jakarta.")) { return; } // directly throw if it's dubbo exception diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/protocol/AbstractInvoker.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/protocol/AbstractInvoker.java index b875f4eb62..555ac3ac18 100644 --- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/protocol/AbstractInvoker.java +++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/protocol/AbstractInvoker.java @@ -87,7 +87,7 @@ public abstract class AbstractInvoker implements Invoker { /** * {@link Node} destroy */ - private boolean destroyed = false; + private volatile boolean destroyed = false; /** * Whether set future to Thread Local when invocation mode is sync diff --git a/dubbo-rpc/dubbo-rpc-injvm/src/main/java/org/apache/dubbo/rpc/protocol/injvm/InjvmInvoker.java b/dubbo-rpc/dubbo-rpc-injvm/src/main/java/org/apache/dubbo/rpc/protocol/injvm/InjvmInvoker.java index ea28e91090..0ebdca71e8 100644 --- a/dubbo-rpc/dubbo-rpc-injvm/src/main/java/org/apache/dubbo/rpc/protocol/injvm/InjvmInvoker.java +++ b/dubbo-rpc/dubbo-rpc-injvm/src/main/java/org/apache/dubbo/rpc/protocol/injvm/InjvmInvoker.java @@ -20,6 +20,7 @@ import org.apache.dubbo.common.URL; import org.apache.dubbo.common.constants.CommonConstants; import org.apache.dubbo.common.threadlocal.InternalThreadLocalMap; import org.apache.dubbo.common.threadpool.manager.ExecutorRepository; +import org.apache.dubbo.common.url.component.DubboServiceAddressURL; import org.apache.dubbo.common.utils.ArrayUtils; import org.apache.dubbo.common.utils.ExecutorUtil; import org.apache.dubbo.common.utils.ReflectUtils; @@ -62,6 +63,9 @@ public class InjvmInvoker extends AbstractInvoker { private final Map> exporterMap; + private volatile Exporter exporter = null; + private volatile URL consumerUrl = null; + private final ExecutorRepository executorRepository; private final ParamDeepCopyUtil paramDeepCopyUtil; @@ -92,9 +96,11 @@ public class InjvmInvoker extends AbstractInvoker { @Override public Result doInvoke(Invocation invocation) throws Throwable { - Exporter exporter = InjvmProtocol.getExporter(exporterMap, getUrl()); if (exporter == null) { - throw new RpcException("Service [" + key + "] not found."); + exporter = InjvmProtocol.getExporter(exporterMap, getUrl()); + if (exporter == null) { + throw new RpcException("Service [" + key + "] not found."); + } } // Solve local exposure, the server opens the token, and the client call fails. Invoker invoker = exporter.getInvoker(); @@ -103,8 +109,12 @@ public class InjvmInvoker extends AbstractInvoker { if (serverHasToken) { invocation.setAttachment(Constants.TOKEN_KEY, serverURL.getParameter(Constants.TOKEN_KEY)); } + if (consumerUrl == null) { + // no need to sync, multi-objects is acceptable and will be gc-ed. + consumerUrl = new DubboServiceAddressURL(serverURL.getUrlAddress(), serverURL.getUrlParam(), getUrl(), null); + } - int timeout = RpcUtils.calculateTimeout(getUrl(), invocation, RpcUtils.getMethodName(invocation), DEFAULT_TIMEOUT); + int timeout = RpcUtils.calculateTimeout(consumerUrl, invocation, RpcUtils.getMethodName(invocation), DEFAULT_TIMEOUT); if (timeout <= 0) { return AsyncRpcResult.newDefaultAsyncResult(new RpcException(RpcException.TIMEOUT_TERMINATE, "No time left for making the following call: " + invocation.getServiceName() + "." @@ -242,7 +252,7 @@ public class InjvmInvoker extends AbstractInvoker { if (pts != null && args != null && pts.length == args.length) { realArgument = new Object[pts.length]; for (int i = 0; i < pts.length; i++) { - realArgument[i] = paramDeepCopyUtil.copy(getUrl(), args[i], pts[i]); + realArgument[i] = paramDeepCopyUtil.copy(consumerUrl, args[i], pts[i]); } } if (realArgument == null) { @@ -273,7 +283,7 @@ public class InjvmInvoker extends AbstractInvoker { Class returnType = getReturnType(consumerServiceModel, invocation.getMethodName(), desc); if (returnType != null) { Thread.currentThread().setContextClassLoader(consumerServiceModel.getClassLoader()); - value = paramDeepCopyUtil.copy(getUrl(), originValue, returnType); + value = paramDeepCopyUtil.copy(consumerUrl, originValue, returnType); } } return value; diff --git a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/RestProtocol.java b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/RestProtocol.java index d2d5d917a7..9c1fc67f95 100644 --- a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/RestProtocol.java +++ b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/RestProtocol.java @@ -18,6 +18,7 @@ package org.apache.dubbo.rpc.protocol.rest; import org.apache.dubbo.common.URL; import org.apache.dubbo.common.utils.ConcurrentHashMapUtils; +import org.apache.dubbo.common.utils.JsonCompatibilityUtil; import org.apache.dubbo.metadata.rest.ServiceRestMetadata; import org.apache.dubbo.remoting.api.pu.DefaultPuHandler; import org.apache.dubbo.remoting.exchange.PortUnificationExchanger; @@ -37,6 +38,7 @@ import org.apache.dubbo.rpc.protocol.rest.deploy.ServiceDeployerManager; import java.util.LinkedHashSet; +import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Set; @@ -47,6 +49,9 @@ import static org.apache.dubbo.common.constants.CommonConstants.INTERFACE_KEY; import static org.apache.dubbo.common.constants.CommonConstants.REST_SERVICE_DEPLOYER_URL_ATTRIBUTE_KEY; import static org.apache.dubbo.common.constants.LoggerCodeConstants.PROTOCOL_ERROR_CLOSE_CLIENT; import static org.apache.dubbo.common.constants.LoggerCodeConstants.PROTOCOL_ERROR_CLOSE_SERVER; +import static org.apache.dubbo.rpc.protocol.rest.constans.RestConstant.JSON_CHECK_LEVEL; +import static org.apache.dubbo.rpc.protocol.rest.constans.RestConstant.JSON_CHECK_LEVEL_STRICT; +import static org.apache.dubbo.rpc.protocol.rest.constans.RestConstant.JSON_CHECK_LEVEL_WARN; import static org.apache.dubbo.rpc.protocol.rest.constans.RestConstant.PATH_SEPARATOR; public class RestProtocol extends AbstractProtocol { @@ -90,6 +95,10 @@ public class RestProtocol extends AbstractProtocol { MetadataResolver.resolveProviderServiceMetadata(url.getServiceModel().getProxyObject().getClass(), url, getContextPath(url)); + // check json compatibility + String jsonCheckLevel = url.getUrlParam().getParameter(JSON_CHECK_LEVEL); + checkJsonCompatibility(invoker.getInterface(), jsonCheckLevel); + // deploy service URL newURL = ServiceDeployerManager.deploy(url, serviceRestMetadata, invoker); @@ -113,6 +122,29 @@ public class RestProtocol extends AbstractProtocol { return exporter; } + private void checkJsonCompatibility(Class clazz, String jsonCheckLevel) throws RpcException { + + if (jsonCheckLevel == null || JSON_CHECK_LEVEL_WARN.equals(jsonCheckLevel)) { + boolean compatibility = JsonCompatibilityUtil.checkClassCompatibility(clazz); + if (!compatibility) { + List unsupportedMethods = JsonCompatibilityUtil.getUnsupportedMethods(clazz); + assert unsupportedMethods != null; + logger.warn("", "", "", String.format("Interface %s does not support json serialization, the specific methods are %s.", clazz.getName(), unsupportedMethods)); + } else { + logger.debug("Check json compatibility complete, all methods of {} can be serialized using json.", clazz.getName()); + } + } else if (JSON_CHECK_LEVEL_STRICT.equals(jsonCheckLevel)) { + boolean compatibility = JsonCompatibilityUtil.checkClassCompatibility(clazz); + if (!compatibility) { + List unsupportedMethods = JsonCompatibilityUtil.getUnsupportedMethods(clazz); + assert unsupportedMethods != null; + throw new IllegalStateException(String.format("Interface %s does not support json serialization, the specific methods are %s.", clazz.getName(), unsupportedMethods)); + } else { + logger.debug("Check json compatibility complete, all methods of {} can be serialized using json.", clazz.getName()); + } + } + } + @Override protected Invoker protocolBindingRefer(final Class type, final URL url) throws RpcException { diff --git a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/constans/RestConstant.java b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/constans/RestConstant.java index fc2edc66ad..2c62f5cec0 100644 --- a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/constans/RestConstant.java +++ b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/constans/RestConstant.java @@ -57,6 +57,11 @@ public interface RestConstant { String IDLE_TIMEOUT_PARAM = "idle.timeout"; String KEEP_ALIVE_TIMEOUT_PARAM = "keep.alive.timeout"; + String JSON_CHECK_LEVEL = "jsonCheckLevel"; + String JSON_CHECK_LEVEL_DISABLED = "disabled"; + String JSON_CHECK_LEVEL_WARN = "warn"; + String JSON_CHECK_LEVEL_STRICT = "strict"; + int MAX_REQUEST_SIZE = 1024 * 1024 * 10; int MAX_INITIAL_LINE_LENGTH = 4096; int MAX_HEADER_SIZE = 8192; diff --git a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/extension/resteasy/ResteasyContext.java b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/extension/resteasy/ResteasyContext.java index 002e2e993b..2134381842 100644 --- a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/extension/resteasy/ResteasyContext.java +++ b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/extension/resteasy/ResteasyContext.java @@ -160,9 +160,9 @@ public interface ResteasyContext { } } - default DubboContainerResponseContextImpl createContainerResponseContext(RequestFacade request, HttpResponse httpResponse, BuiltResponse jaxrsResponse, ContainerResponseFilter[] responseFilters) { + default DubboContainerResponseContextImpl createContainerResponseContext(Object originRequest, RequestFacade request, HttpResponse httpResponse, BuiltResponse jaxrsResponse, ContainerResponseFilter[] responseFilters) { - NettyHttpRequest nettyHttpRequest = createNettyHttpRequest(request); + NettyHttpRequest nettyHttpRequest = originRequest == null ? createNettyHttpRequest(request) : (NettyHttpRequest) originRequest; ResponseContainerRequestContext requestContext = new ResponseContainerRequestContext(nettyHttpRequest); DubboContainerResponseContextImpl responseContext = new DubboContainerResponseContextImpl(nettyHttpRequest, httpResponse, jaxrsResponse, diff --git a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/extension/resteasy/filter/ResteasyRequestContainerFilterAdapter.java b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/extension/resteasy/filter/ResteasyRequestContainerFilterAdapter.java index 5843c69945..851da89a2f 100644 --- a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/extension/resteasy/filter/ResteasyRequestContainerFilterAdapter.java +++ b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/extension/resteasy/filter/ResteasyRequestContainerFilterAdapter.java @@ -18,7 +18,6 @@ package org.apache.dubbo.rpc.protocol.rest.extension.resteasy.filter; import org.apache.dubbo.common.URL; import org.apache.dubbo.common.extension.Activate; -import org.apache.dubbo.rpc.RpcContext; import org.apache.dubbo.rpc.protocol.rest.deploy.ServiceDeployer; import org.apache.dubbo.rpc.protocol.rest.extension.resteasy.ResteasyContext; import org.apache.dubbo.rpc.protocol.rest.filter.RestRequestFilter; @@ -30,7 +29,6 @@ import org.jboss.resteasy.specimpl.BuiltResponse; import javax.ws.rs.container.ContainerRequestFilter; import java.util.List; -import static org.apache.dubbo.common.constants.CommonConstants.RESTEASY_NETTY_HTTP_REQUEST_ATTRIBUTE_KEY; @Activate(value = "resteasy", onClass = {"javax.ws.rs.container.ContainerRequestFilter", "org.jboss.resteasy.plugins.server.netty.NettyHttpRequest", "org.jboss.resteasy.plugins.server.netty.NettyHttpResponse"}, order = Integer.MAX_VALUE - 1) @@ -55,7 +53,8 @@ public class ResteasyRequestContainerFilterAdapter implements RestRequestFilter, DubboPreMatchContainerRequestContext containerRequestContext = convertHttpRequestToContainerRequestContext(requestFacade, containerRequestFilters.toArray(new ContainerRequestFilter[0])); - RpcContext.getServiceContext().setObjectAttachment(RESTEASY_NETTY_HTTP_REQUEST_ATTRIBUTE_KEY, containerRequestContext.getHttpRequest()); + // set resteasy request for save user`s custom request attribute + restFilterContext.setOriginRequest(containerRequestContext.getHttpRequest()); try { BuiltResponse restResponse = containerRequestContext.filter(); diff --git a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/extension/resteasy/filter/ResteasyResponseContainerFilterAdapter.java b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/extension/resteasy/filter/ResteasyResponseContainerFilterAdapter.java index c6af847ece..89ea8a6e21 100644 --- a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/extension/resteasy/filter/ResteasyResponseContainerFilterAdapter.java +++ b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/extension/resteasy/filter/ResteasyResponseContainerFilterAdapter.java @@ -53,7 +53,7 @@ public class ResteasyResponseContainerFilterAdapter implements RestResponseFilte DubboBuiltResponse dubboBuiltResponse = new DubboBuiltResponse(response.getResponseBody(), response.getStatus(), response.getEntityClass()); // NettyHttpResponse wrapper HttpResponse httpResponse = new ResteasyNettyHttpResponse(response); - DubboContainerResponseContextImpl containerResponseContext = createContainerResponseContext(requestFacade, httpResponse, dubboBuiltResponse, containerRequestFilters.toArray(new ContainerResponseFilter[0])); + DubboContainerResponseContextImpl containerResponseContext = createContainerResponseContext(restFilterContext.getOriginRequest(),requestFacade, httpResponse, dubboBuiltResponse, containerRequestFilters.toArray(new ContainerResponseFilter[0])); containerResponseContext.filter(); // user reset entity diff --git a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/extension/resteasy/intercept/ResteasyWriterInterceptorAdapter.java b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/extension/resteasy/intercept/ResteasyWriterInterceptorAdapter.java index fbde93b39f..60d7b63eff 100644 --- a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/extension/resteasy/intercept/ResteasyWriterInterceptorAdapter.java +++ b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/extension/resteasy/intercept/ResteasyWriterInterceptorAdapter.java @@ -18,7 +18,6 @@ package org.apache.dubbo.rpc.protocol.rest.extension.resteasy.intercept; import org.apache.commons.io.IOUtils; import org.apache.dubbo.common.extension.Activate; -import org.apache.dubbo.rpc.RpcContext; import org.apache.dubbo.rpc.RpcInvocation; import org.apache.dubbo.rpc.protocol.rest.RestHeaderEnum; import org.apache.dubbo.rpc.protocol.rest.deploy.ServiceDeployer; @@ -41,8 +40,6 @@ import java.lang.annotation.Annotation; import java.lang.reflect.Type; import java.util.List; -import static org.apache.dubbo.common.constants.CommonConstants.RESTEASY_NETTY_HTTP_REQUEST_ATTRIBUTE_KEY; - @Activate(value = "resteasy", onClass = {"javax.ws.rs.ext.WriterInterceptorContext", "org.jboss.resteasy.plugins.server.netty.NettyHttpRequest", "org.jboss.resteasy.plugins.server.netty.NettyHttpResponse"}) public class ResteasyWriterInterceptorAdapter implements RestResponseInterceptor, ResteasyContext { @@ -67,7 +64,7 @@ public class ResteasyWriterInterceptorAdapter implements RestResponseInterceptor return; } - NettyHttpRequest nettyHttpRequest = (NettyHttpRequest) RpcContext.getServiceContext().getObjectAttachment(RESTEASY_NETTY_HTTP_REQUEST_ATTRIBUTE_KEY); + NettyHttpRequest nettyHttpRequest = (NettyHttpRequest) restResponseInterceptor.getOriginRequest(); HttpRequest restRequest = nettyHttpRequest == null ? createNettyHttpRequest(request) : nettyHttpRequest; diff --git a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/filter/ServiceInvokeRestFilter.java b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/filter/ServiceInvokeRestFilter.java index 404f8edd5a..2e97493c0e 100644 --- a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/filter/ServiceInvokeRestFilter.java +++ b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/filter/ServiceInvokeRestFilter.java @@ -63,7 +63,12 @@ public class ServiceInvokeRestFilter implements RestRequestFilter { FullHttpRequest nettyHttpRequest = nettyRequestFacade.getRequest(); - doHandler(nettyHttpRequest, restFilterContext.getResponse(), restFilterContext.getRequestFacade(), restFilterContext.getUrl(), restFilterContext.getServiceDeployer()); + doHandler(nettyHttpRequest, + restFilterContext.getResponse(), + restFilterContext.getRequestFacade(), + restFilterContext.getUrl(), + restFilterContext.getOriginRequest(), + restFilterContext.getServiceDeployer()); } @@ -72,6 +77,7 @@ public class ServiceInvokeRestFilter implements RestRequestFilter { NettyHttpResponse nettyHttpResponse, RequestFacade request, URL url, + Object originRequest,// resteasy request ServiceDeployer serviceDeployer) throws Exception { PathMatcher pathMatcher = RestRPCInvocationUtil.createPathMatcher(request); @@ -130,8 +136,12 @@ public class ServiceInvokeRestFilter implements RestRequestFilter { } try { + RestInterceptContext restFilterContext = new RestInterceptContext(url, request, nettyHttpResponse, serviceDeployer, result.getValue(), rpcInvocation); + // set filter request + restFilterContext.setOriginRequest(originRequest); + // invoke the intercept chain before Result write to response - executeResponseIntercepts(url, request, nettyHttpResponse, result.getValue(), rpcInvocation, serviceDeployer); + executeResponseIntercepts(restFilterContext); } catch (Exception exception) { logger.error("", exception.getMessage(), "", "dubbo rest protocol execute ResponseIntercepts error", exception); throw exception; @@ -215,17 +225,11 @@ public class ServiceInvokeRestFilter implements RestRequestFilter { /** * execute response Intercepts * - * @param url - * @param request - * @param nettyHttpResponse - * @param result - * @param rpcInvocation - * @param serviceDeployer + * @param restFilterContext * @throws Exception */ - public void executeResponseIntercepts(URL url, RequestFacade request, NettyHttpResponse nettyHttpResponse, Object result, RpcInvocation rpcInvocation, ServiceDeployer serviceDeployer) throws Exception { + public void executeResponseIntercepts(RestInterceptContext restFilterContext) throws Exception { - RestInterceptContext restFilterContext = new RestInterceptContext(url, request, nettyHttpResponse, serviceDeployer, result, rpcInvocation); for (RestResponseInterceptor restResponseInterceptor : restResponseInterceptors) { diff --git a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/filter/context/FilterContext.java b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/filter/context/FilterContext.java index e64d175529..d40c41e27e 100644 --- a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/filter/context/FilterContext.java +++ b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/filter/context/FilterContext.java @@ -35,4 +35,8 @@ public interface FilterContext { boolean complete(); void setComplete(boolean complete); + + Object getOriginRequest(); + + Object getOriginResponse(); } diff --git a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/filter/context/RestFilterContext.java b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/filter/context/RestFilterContext.java index a563c5e09b..bf2be29d45 100644 --- a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/filter/context/RestFilterContext.java +++ b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/filter/context/RestFilterContext.java @@ -27,6 +27,8 @@ public class RestFilterContext implements FilterContext { protected NettyHttpResponse response; protected ServiceDeployer serviceDeployer; protected boolean completed; + protected Object originRequest; + protected Object originResponse; public RestFilterContext(URL url, RequestFacade requestFacade, NettyHttpResponse response, ServiceDeployer serviceDeployer) { this.url = url; @@ -64,4 +66,25 @@ public class RestFilterContext implements FilterContext { public void setComplete(boolean complete) { this.completed = complete; } + + @Override + public Object getOriginRequest() { + return originRequest; + } + + @Override + public Object getOriginResponse() { + return originResponse; + } + + public void setOriginRequest(Object originRequest) { + if (this.originRequest != null) { + return; + } + this.originRequest = originRequest; + } + + public void setOriginResponse(Object originResponse) { + this.originResponse = originResponse; + } } 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 e24207b792..c8aff6afc2 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 @@ -32,7 +32,6 @@ import org.apache.dubbo.rpc.protocol.rest.filter.ServiceInvokeRestFilter; import org.apache.dubbo.rpc.protocol.rest.filter.context.RestFilterContext; import org.apache.dubbo.rpc.protocol.rest.netty.NettyHttpResponse; import org.apache.dubbo.rpc.protocol.rest.request.NettyRequestFacade; -import org.apache.dubbo.rpc.protocol.rest.request.RequestFacade; import java.io.IOException; import java.util.ArrayList; @@ -74,11 +73,12 @@ public class NettyHttpHandler implements HttpHandler restFilters) throws Exception { - RestFilterContext restFilterContext = new RestFilterContext(url, requestFacade, nettyHttpResponse, serviceDeployer); + public void executeFilters(RestFilterContext restFilterContext, List restFilters) throws Exception { for (RestFilter restFilter : restFilters) { restFilter.filter(restFilterContext); 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 b20734cd44..6bfbd77f20 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 @@ -43,6 +43,7 @@ import org.apache.dubbo.rpc.protocol.rest.exception.ResteasyExceptionMapper; import org.apache.dubbo.rpc.protocol.rest.exception.mapper.ExceptionHandler; import org.apache.dubbo.rpc.protocol.rest.exception.mapper.ExceptionMapper; +import org.apache.dubbo.rpc.protocol.rest.filter.TraceRequestAndResponseFilter; 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; @@ -755,7 +756,7 @@ class JaxrsRestProtocolTest { URL url = this.registerProvider(exportUrl, server, DemoService.class); - URL nettyUrl = url.addParameter(org.apache.dubbo.remoting.Constants.PAYLOAD_KEY, 1024); + URL nettyUrl = url.addParameter(org.apache.dubbo.remoting.Constants.PAYLOAD_KEY, 1024); Exporter exporter = protocol.export(proxy.getInvoker(server, DemoService.class, nettyUrl)); @@ -775,6 +776,26 @@ class JaxrsRestProtocolTest { } + + @Test + void testRequestAndResponseFilter() { + DemoService server = new DemoServiceImpl(); + + URL exportUrl = URL.valueOf("rest://127.0.0.1:" + availablePort + "/rest?interface=org.apache.dubbo.rpc.protocol.rest.DemoService&extension=" + + TraceRequestAndResponseFilter.class.getName()); + + URL nettyUrl = this.registerProvider(exportUrl, server, DemoService.class); + + Exporter exporter = protocol.export(proxy.getInvoker(server, DemoService.class, nettyUrl)); + + DemoService demoService = this.proxy.getProxy(protocol.refer(DemoService.class, nettyUrl)); + + + Assertions.assertEquals("header-result", demoService.sayHello("hello")); + 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/JsonCompatibilityCheckTest.java b/dubbo-rpc/dubbo-rpc-rest/src/test/java/org/apache/dubbo/rpc/protocol/rest/JsonCompatibilityCheckTest.java new file mode 100644 index 0000000000..2f871f2078 --- /dev/null +++ b/dubbo-rpc/dubbo-rpc-rest/src/test/java/org/apache/dubbo/rpc/protocol/rest/JsonCompatibilityCheckTest.java @@ -0,0 +1,109 @@ +/* + * 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.rpc.Exporter; +import org.apache.dubbo.rpc.Protocol; +import org.apache.dubbo.rpc.ProxyFactory; +import org.apache.dubbo.rpc.RpcException; +import org.apache.dubbo.rpc.model.ApplicationModel; +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.compatibility.RestDemoService; +import org.apache.dubbo.rpc.protocol.rest.compatibility.RestDemoServiceImpl; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import static org.apache.dubbo.rpc.protocol.rest.constans.RestConstant.JSON_CHECK_LEVEL; +import static org.apache.dubbo.rpc.protocol.rest.constans.RestConstant.JSON_CHECK_LEVEL_DISABLED; +import static org.apache.dubbo.rpc.protocol.rest.constans.RestConstant.JSON_CHECK_LEVEL_STRICT; +import static org.apache.dubbo.rpc.protocol.rest.constans.RestConstant.JSON_CHECK_LEVEL_WARN; + + +public class JsonCompatibilityCheckTest { + + private final int availablePort = NetUtils.getAvailablePort(); + private final URL exportUrl = URL.valueOf("rest://127.0.0.1:" + availablePort + "/rest?interface=org.apache.dubbo.rpc.protocol.rest.compatibility.RestDemoService"); + private final ModuleServiceRepository repository = ApplicationModel.defaultModel().getDefaultModule().getServiceRepository(); + + private final Protocol protocol = ExtensionLoader.getExtensionLoader(Protocol.class).getExtension("rest"); + private final ProxyFactory proxy = ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension(); + + + @Test + public void testJsonCheckDisabled() { + + RestDemoService server = new RestDemoServiceImpl(); + + URL url = this.registerProvider(exportUrl, server, RestDemoService.class); + + url = url.addParameter(JSON_CHECK_LEVEL, JSON_CHECK_LEVEL_DISABLED); + + Exporter exporter = protocol.export(proxy.getInvoker(server, RestDemoService.class, url)); + + exporter.unexport(); + } + + @Test + public void testJsonCheckWarn() { + RestDemoService server = new RestDemoServiceImpl(); + + URL url = this.registerProvider(exportUrl, server, RestDemoService.class); + + url = url.addParameter(JSON_CHECK_LEVEL, JSON_CHECK_LEVEL_WARN); + + Exporter exporter = protocol.export(proxy.getInvoker(server, RestDemoService.class, url)); + + exporter.unexport(); + } + + @Test + public void testJsonCheckStrict() { + RestDemoService server = new RestDemoServiceImpl(); + + URL url = this.registerProvider(exportUrl, server, RestDemoService.class); + + URL newUrl = url.addParameter(JSON_CHECK_LEVEL, JSON_CHECK_LEVEL_STRICT); + + Assertions.assertThrowsExactly(IllegalStateException.class, () -> { + Exporter exporter = null; + try { + exporter = protocol.export(proxy.getInvoker(server, RestDemoService.class, newUrl)); + } finally { + if (exporter != null) 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/compatibility/Apple.java b/dubbo-rpc/dubbo-rpc-rest/src/test/java/org/apache/dubbo/rpc/protocol/rest/compatibility/Apple.java new file mode 100644 index 0000000000..2122660f6a --- /dev/null +++ b/dubbo-rpc/dubbo-rpc-rest/src/test/java/org/apache/dubbo/rpc/protocol/rest/compatibility/Apple.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.rpc.protocol.rest.compatibility; + +public class Apple implements Fruit { + + @Override + public String sayName() { + return "This is apple"; + } +} diff --git a/dubbo-build-tools/src/main/resources/checkstyle-header.txt b/dubbo-rpc/dubbo-rpc-rest/src/test/java/org/apache/dubbo/rpc/protocol/rest/compatibility/Fruit.java similarity index 87% rename from dubbo-build-tools/src/main/resources/checkstyle-header.txt rename to dubbo-rpc/dubbo-rpc-rest/src/test/java/org/apache/dubbo/rpc/protocol/rest/compatibility/Fruit.java index d973dcedae..c7c36aa4c3 100644 --- a/dubbo-build-tools/src/main/resources/checkstyle-header.txt +++ b/dubbo-rpc/dubbo-rpc-rest/src/test/java/org/apache/dubbo/rpc/protocol/rest/compatibility/Fruit.java @@ -13,4 +13,10 @@ * 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. - */ \ No newline at end of file + */ + +package org.apache.dubbo.rpc.protocol.rest.compatibility; + +public interface Fruit { + String sayName(); +} diff --git a/dubbo-rpc/dubbo-rpc-rest/src/test/java/org/apache/dubbo/rpc/protocol/rest/compatibility/RestDemoService.java b/dubbo-rpc/dubbo-rpc-rest/src/test/java/org/apache/dubbo/rpc/protocol/rest/compatibility/RestDemoService.java new file mode 100644 index 0000000000..a487b37a47 --- /dev/null +++ b/dubbo-rpc/dubbo-rpc-rest/src/test/java/org/apache/dubbo/rpc/protocol/rest/compatibility/RestDemoService.java @@ -0,0 +1,46 @@ +/* + * 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.compatibility; + +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.core.MediaType; + +@Path("rest") +public interface RestDemoService { + @GET + @Path("hello") + @Consumes({MediaType.APPLICATION_JSON}) + String sayHello(String name); + + @GET + @Path("hi") + @Consumes({MediaType.APPLICATION_JSON}) + String sayHi(); + + @GET + @Path("fruit") + @Consumes({MediaType.APPLICATION_JSON}) + Fruit sayFruit(); + + @GET + @Path("apple") + @Consumes({MediaType.APPLICATION_JSON}) + Apple sayApple(); +} diff --git a/dubbo-rpc/dubbo-rpc-rest/src/test/java/org/apache/dubbo/rpc/protocol/rest/compatibility/RestDemoServiceImpl.java b/dubbo-rpc/dubbo-rpc-rest/src/test/java/org/apache/dubbo/rpc/protocol/rest/compatibility/RestDemoServiceImpl.java new file mode 100644 index 0000000000..f1b94f4455 --- /dev/null +++ b/dubbo-rpc/dubbo-rpc-rest/src/test/java/org/apache/dubbo/rpc/protocol/rest/compatibility/RestDemoServiceImpl.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.rpc.protocol.rest.compatibility; + +public class RestDemoServiceImpl implements RestDemoService { + @Override + public String sayHello(String name) { + return "hello"; + } + + @Override + public String sayHi() { + return "hi"; + } + + @Override + public Fruit sayFruit() { + return new Apple(); + } + + @Override + public Apple sayApple() { + return new Apple(); + } +} diff --git a/dubbo-rpc/dubbo-rpc-rest/src/test/java/org/apache/dubbo/rpc/protocol/rest/filter/TraceRequestAndResponseFilter.java b/dubbo-rpc/dubbo-rpc-rest/src/test/java/org/apache/dubbo/rpc/protocol/rest/filter/TraceRequestAndResponseFilter.java new file mode 100644 index 0000000000..b6ca0f1e9f --- /dev/null +++ b/dubbo-rpc/dubbo-rpc-rest/src/test/java/org/apache/dubbo/rpc/protocol/rest/filter/TraceRequestAndResponseFilter.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.rpc.protocol.rest.filter; + +import javax.annotation.Priority; +import javax.ws.rs.Priorities; +import javax.ws.rs.container.ContainerRequestContext; +import javax.ws.rs.container.ContainerRequestFilter; +import javax.ws.rs.container.ContainerResponseContext; +import javax.ws.rs.container.ContainerResponseFilter; +import java.io.IOException; + +@Priority(Priorities.USER) +public class TraceRequestAndResponseFilter implements ContainerRequestFilter, ContainerResponseFilter { + + @Override + public void filter(ContainerRequestContext requestContext) throws IOException { + + requestContext.getHeaders().add("test-response","header-result"); + } + + @Override + public void filter(ContainerRequestContext containerRequestContext, ContainerResponseContext containerResponseContext) throws + + IOException { + + String headerString = containerRequestContext.getHeaderString("test-response"); + containerResponseContext.setEntity(headerString); + + } +} 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 61c6870c50..b666c8c5e3 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 @@ -67,7 +67,6 @@ import java.util.Set; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutorService; import java.util.concurrent.locks.ReentrantLock; -import java.util.stream.Collectors; import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_KEY; import static org.apache.dubbo.common.constants.CommonConstants.DUBBO_PACKABLE_METHOD_FACTORY; @@ -249,7 +248,7 @@ public class TripleInvoker extends AbstractInvoker { if (methodDescriptor.isGeneric()) { Object[] args = new Object[3]; args[0] = RpcUtils.getMethodName(invocation); - args[1] = Arrays.stream(RpcUtils.getParameterTypes(invocation)).map(Class::getName).collect(Collectors.toList()); + args[1] = Arrays.stream(RpcUtils.getParameterTypes(invocation)).map(Class::getName).toArray(String[]::new); args[2] = RpcUtils.getArguments(invocation); pureArgument = args; } else { 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 8dddc8daf6..7f687a3485 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 @@ -229,6 +229,9 @@ public abstract class AbstractServerCall implements ServerCall, ServerStream.Lis @Override public final void onCancelByRemote(TriRpcStatus status) { closed = true; + if (listener == null) { + return; + } cancellationContext.cancel(status.cause); listener.onCancel(status); } diff --git a/dubbo-spring-boot/dubbo-spring-boot-starters/observability/pom.xml b/dubbo-spring-boot/dubbo-spring-boot-starters/observability/pom.xml index 1ed28d1b5a..c852e43863 100644 --- a/dubbo-spring-boot/dubbo-spring-boot-starters/observability/pom.xml +++ b/dubbo-spring-boot/dubbo-spring-boot-starters/observability/pom.xml @@ -38,9 +38,9 @@ - 1.11.3 - 1.1.4 - 1.29.0 + 1.11.4 + 1.1.5 + 1.30.1 2.16.4 0.16.0 diff --git a/dubbo-spring-boot/pom.xml b/dubbo-spring-boot/pom.xml index fe1b850dff..ac1eca90f8 100644 --- a/dubbo-spring-boot/pom.xml +++ b/dubbo-spring-boot/pom.xml @@ -41,12 +41,12 @@ - 2.7.14 + 2.7.15 ${revision} 2.20.0 - 1.14.5 + 1.14.8 diff --git a/dubbo-test/dubbo-dependencies-all/pom.xml b/dubbo-test/dubbo-dependencies-all/pom.xml index 84ce1ca939..eab84f86e9 100644 --- a/dubbo-test/dubbo-dependencies-all/pom.xml +++ b/dubbo-test/dubbo-dependencies-all/pom.xml @@ -181,6 +181,11 @@ dubbo-metrics-api ${project.version} + + org.apache.dubbo + dubbo-metrics-event + ${project.version} + org.apache.dubbo dubbo-metrics-default diff --git a/dubbo-test/dubbo-test-modules/src/test/java/org/apache/dubbo/dependency/FileTest.java b/dubbo-test/dubbo-test-modules/src/test/java/org/apache/dubbo/dependency/FileTest.java index 66c13236b6..b971b22908 100644 --- a/dubbo-test/dubbo-test-modules/src/test/java/org/apache/dubbo/dependency/FileTest.java +++ b/dubbo-test/dubbo-test-modules/src/test/java/org/apache/dubbo/dependency/FileTest.java @@ -46,13 +46,13 @@ class FileTest { static { ignoredModules.add(Pattern.compile("dubbo-apache-release")); ignoredModules.add(Pattern.compile("dubbo-all-shaded")); - ignoredModules.add(Pattern.compile("dubbo-build-tools")); ignoredModules.add(Pattern.compile("dubbo-dependencies-all")); ignoredModules.add(Pattern.compile("dubbo-parent")); ignoredModules.add(Pattern.compile("dubbo-core-spi")); ignoredModules.add(Pattern.compile("dubbo-demo.*")); ignoredModules.add(Pattern.compile("dubbo-annotation-processor")); ignoredModules.add(Pattern.compile("dubbo-config-spring6")); + ignoredModules.add(Pattern.compile("dubbo-plugin-loom.*")); ignoredArtifacts.add(Pattern.compile("dubbo-demo.*")); ignoredArtifacts.add(Pattern.compile("dubbo-test.*")); diff --git a/dubbo-xds/src/main/java/org/apache/dubbo/registry/xds/istio/IstioCitadelCertificateSigner.java b/dubbo-xds/src/main/java/org/apache/dubbo/registry/xds/istio/IstioCitadelCertificateSigner.java index 1c8a4146db..99225b0316 100644 --- a/dubbo-xds/src/main/java/org/apache/dubbo/registry/xds/istio/IstioCitadelCertificateSigner.java +++ b/dubbo-xds/src/main/java/org/apache/dubbo/registry/xds/istio/IstioCitadelCertificateSigner.java @@ -175,7 +175,7 @@ public class IstioCitadelCertificateSigner implements XdsCertificateSigner { IstioCertificateServiceGrpc.IstioCertificateServiceStub stub = IstioCertificateServiceGrpc.newStub(channel); - stub = MetadataUtils.attachHeaders(stub, header); + stub = stub.withInterceptors(MetadataUtils.newAttachHeadersInterceptor(header)); CountDownLatch countDownLatch = new CountDownLatch(1); StringBuffer publicKeyBuilder = new StringBuffer(); diff --git a/pom.xml b/pom.xml index d16af112f1..2c9918e5da 100644 --- a/pom.xml +++ b/pom.xml @@ -119,7 +119,7 @@ 3.11.0 3.2.1 3.5.0 - 9.4.51.v20230217 + 9.4.52.v20230823 3.2.1 0.8.10 1.5.0 @@ -160,9 +160,7 @@ dubbo-dependencies dubbo-metadata dubbo-metrics - dubbo-build-tools dubbo-spring-boot - dubbo-native dubbo-test dubbo-kubernetes dubbo-xds @@ -306,8 +304,8 @@ 8.45.1 - org.apache.dubbo - dubbo-build-tools + com.alibaba + dubbo-shared-resources 1.0.0