You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@dubbo.apache.org by li...@apache.org on 2021/12/27 06:23:15 UTC
[dubbo] 01/03: Merge branch '3.0' into 3.0-metadata-refactor
This is an automated email from the ASF dual-hosted git repository.
liujun pushed a commit to branch 3.0-metadata-refactor
in repository https://gitbox.apache.org/repos/asf/dubbo.git
commit 15ec53ec126e0754fdd805a3a7b96de2990068ce
Merge: f7c5e20 f06bbcc
Author: ken.lj <ke...@gmail.com>
AuthorDate: Mon Dec 27 11:41:25 2021 +0800
Merge branch '3.0' into 3.0-metadata-refactor
# Conflicts:
# dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/filter/DefaultFilterChainBuilderTest.java
# dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/route/MeshAppRuleListenerTest.java
# dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/route/StandardMeshRuleRouterFactoryTest.java
# dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/DubboMatchRequestTest.java
# dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/util/VsDestinationGroupRuleDispatcherTest.java
# dubbo-common/src/main/java/org/apache/dubbo/common/config/CompositeConfiguration.java
# dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ServiceConfig.java
# dubbo-dependencies-bom/pom.xml
# dubbo-dependencies/dubbo-dependencies-zookeeper/pom.xml
# dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/InstanceAddressURL.java
# dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistry.java
# dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/listener/ServiceInstancesChangedListener.java
# dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/ServiceInstanceMetadataUtils.java
# dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/support/AbstractRegistry.java
# dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/event/listener/ServiceInstancesChangedListenerTest.java
# dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboProtocol.java
# dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/LazyConnectExchangeClient.java
# pom.xml
.github/workflows/build-and-test-3.yml | 53 +-
compiler/pom.xml | 2 +-
.../rpc/cluster/ClusterScopeModelInitializer.java | 4 +-
.../org/apache/dubbo/rpc/cluster/Constants.java | 2 +
.../org/apache/dubbo/rpc/cluster/RouterChain.java | 43 +-
.../cluster/filter/DefaultFilterChainBuilder.java | 81 +-
.../rpc/cluster/filter/FilterChainBuilder.java | 204 ++-
.../filter/support/ConsumerContextFilter.java | 46 +-
.../router/mesh/route/MeshAppRuleListener.java | 111 +-
.../route/MeshRuleAddressListenerInterceptor.java | 60 -
.../cluster/router/mesh/route/MeshRuleCache.java | 170 ++
.../router/mesh/route/MeshRuleConstants.java | 26 +-
.../cluster/router/mesh/route/MeshRuleManager.java | 98 +-
.../cluster/router/mesh/route/MeshRuleRouter.java | 431 +++---
...terFactory.java => StandardMeshRuleRouter.java} | 27 +-
...ory.java => StandardMeshRuleRouterFactory.java} | 10 +-
.../rpc/cluster/router/mesh/rule/BaseRule.java | 10 +-
.../router/mesh/rule/VsDestinationGroup.java | 4 +
.../rule/virtualservice/DubboMatchRequest.java | 63 +-
.../mesh/rule/virtualservice/match/BoolMatch.java | 6 +-
.../rule/virtualservice/match/DoubleMatch.java | 16 +-
.../virtualservice/match/DoubleRangeMatch.java | 14 +-
.../virtualservice/match/DubboAttachmentMatch.java | 61 +-
.../rule/virtualservice/match/DubboMethodArg.java | 16 +-
.../virtualservice/match/DubboMethodMatch.java | 60 +-
.../rule/virtualservice/match/ListBoolMatch.java | 6 +-
.../rule/virtualservice/match/ListDoubleMatch.java | 6 +-
.../rule/virtualservice/match/ListStringMatch.java | 6 +-
.../rule/virtualservice/match/StringMatch.java | 27 +-
.../router/mesh/util/MeshRuleDispatcher.java | 104 ++
...roupRuleListener.java => MeshRuleListener.java} | 11 +-
.../router/mesh/util/TracingContextProvider.java | 23 +-
.../util/VsDestinationGroupRuleDispatcher.java | 53 -
.../dubbo/rpc/cluster/router/state/BitList.java | 47 +-
.../cluster/router/state/StateRouterResult.java | 30 +
.../cluster/support/FailoverClusterInvoker.java | 6 +-
.../org.apache.dubbo.registry.AddressListener | 1 -
.../org.apache.dubbo.rpc.cluster.RouterFactory | 1 -
...bbo.rpc.cluster.router.state.StateRouterFactory | 1 +
.../apache/dubbo/rpc/cluster/RouterChainTest.java | 4 +-
.../filter/DefaultFilterChainBuilderTest.java | 12 +-
.../router/mesh/route/MeshAppRuleListenerTest.java | 423 +++--
.../router/mesh/route/MeshRuleCacheTest.java | 110 ++
.../router/mesh/route/MeshRuleManagerTest.java | 350 +++--
.../router/mesh/route/MeshRuleRouterTest.java | 1637 ++++----------------
...java => StandardMeshRuleRouterFactoryTest.java} | 12 +-
.../router/mesh/rule/DestinationRuleTest.java | 6 +-
.../rule/virtualservice/DubboMatchRequestTest.java | 139 +-
.../rule/virtualservice/match/BoolMatchTest.java | 8 +-
.../rule/virtualservice/match/DoubleMatchTest.java | 30 +-
.../match/DubboAttachmentMatchTest.java | 138 +-
.../virtualservice/match/DubboMethodMatchTest.java | 27 +-
.../virtualservice/match/ListBoolMatchTest.java | 6 +-
.../virtualservice/match/ListDoubleMatchTest.java | 6 +-
.../virtualservice/match/ListStringMatchTest.java | 6 +-
.../rule/virtualservice/match/StringMatchTest.java | 32 +-
.../router/mesh/util/MeshRuleDispatcherTest.java | 213 +++
.../util/VsDestinationGroupRuleDispatcherTest.java | 75 -
.../router/mock/MockInvokersSelectorTest.java | 4 +-
.../support/FailoverClusterInvokerTest.java | 2 +-
.../support/MergeableClusterInvokerTest.java | 5 +-
.../support/wrapper/AbstractClusterTest.java | 6 +-
.../java/org/apache/dubbo/common/Experimental.java | 2 +-
.../java/org/apache/dubbo/common/URLBuilder.java | 6 +
.../org/apache/dubbo/common/bytecode/Wrapper.java | 14 +-
.../common/config/CompositeConfiguration.java | 15 +-
.../dubbo/common/config/ConfigurationCache.java | 3 +-
.../dubbo/common/config/ConfigurationUtils.java | 15 +-
.../dubbo/common/config/InmemoryConfiguration.java | 6 +-
.../configcenter/TreePathDynamicConfiguration.java | 2 +-
.../dubbo/common/constants/CommonConstants.java | 17 +
.../dubbo/common/constants/RegistryConstants.java | 6 +-
.../dubbo/common/deploy/ApplicationDeployer.java | 4 +-
.../org/apache/dubbo/common/deploy/Deployer.java | 2 -
.../dubbo/common/extension/ExtensionDirector.java | 8 +-
.../dubbo/common/extension/ExtensionLoader.java | 6 +-
.../org/apache/dubbo/common/extension/Wrapper.java | 8 +
.../extension/support/ActivateComparator.java | 6 +-
...r.java => MultiInstanceActivateComparator.java} | 41 +-
.../extension/support/WrapperComparator.java | 6 +
.../dubbo/common/json/GenericJSONConverter.java | 528 -------
.../org/apache/dubbo/common/json/J2oVisitor.java | 389 -----
.../java/org/apache/dubbo/common/json/JSON.java | 711 ---------
.../org/apache/dubbo/common/json/JSONArray.java | 184 ---
.../apache/dubbo/common/json/JSONConverter.java | 44 -
.../org/apache/dubbo/common/json/JSONObject.java | 209 ---
.../org/apache/dubbo/common/json/JSONReader.java | 68 -
.../org/apache/dubbo/common/json/JSONToken.java | 72 -
.../org/apache/dubbo/common/json/JSONVisitor.java | 107 --
.../org/apache/dubbo/common/json/JSONWriter.java | 305 ----
.../java/org/apache/dubbo/common/json/Yylex.java | 847 ----------
.../reporter/FrameworkStatusReportService.java | 5 +-
.../org/apache/dubbo/common/utils/ClassUtils.java | 74 +
.../org/apache/dubbo/config/AbstractConfig.java | 36 +-
.../dubbo/config/AbstractInterfaceConfig.java | 5 +-
.../apache/dubbo/config/AbstractMethodConfig.java | 2 +-
.../dubbo/config/AbstractReferenceConfig.java | 8 +-
.../apache/dubbo/config/AbstractServiceConfig.java | 4 +-
.../org/apache/dubbo/config/ApplicationConfig.java | 35 +-
.../apache/dubbo/config/MetadataReportConfig.java | 14 +-
.../java/org/apache/dubbo/config/MethodConfig.java | 5 +-
.../java/org/apache/dubbo/config/ModuleConfig.java | 4 +-
.../org/apache/dubbo/config/MonitorConfig.java | 2 +-
.../apache/dubbo/config/ReferenceConfigBase.java | 12 +-
.../org/apache/dubbo/config/RegistryConfig.java | 28 +-
.../org/apache/dubbo/config/ServiceConfigBase.java | 2 +-
.../config/context/ConfigConfigurationAdapter.java | 2 +-
.../dubbo/rpc/model/ModuleServiceRepository.java | 2 +
.../org/apache/dubbo/rpc/model/ScopeModelUtil.java | 5 +-
.../apache/dubbo/common/bytecode/WrapperTest.java | 5 +
.../config/EnvironmentConfigurationTest.java | 2 +-
.../common/extension/ExtensionLoaderTest.java | 33 +-
.../extension/ext6_wrap/impl/Ext6Impl3.java} | 19 +-
.../common/extension/ext6_wrap/impl/Ext6Impl4.java | 17 +-
.../extension/ext6_wrap/impl/Ext6Wrapper1.java | 2 +
.../extension/ext6_wrap/impl/Ext6Wrapper2.java | 2 +
.../impl/{Ext6Wrapper1.java => Ext6Wrapper3.java} | 7 +-
.../impl/{Ext6Wrapper1.java => Ext6Wrapper4.java} | 7 +-
.../apache/dubbo/common/json/JSONReaderTest.java | 44 -
.../org/apache/dubbo/common/json/JSONTest.java | 227 ---
.../apache/dubbo/common/json/JSONWriterTest.java | 50 -
.../apache/dubbo/rpc/model/FrameworkModelTest.java | 1 +
...che.dubbo.common.extension.ext6_wrap.WrappedExt | 4 +
.../org/apache/dubbo/config/ReferenceConfig.java | 18 +-
.../org/apache/dubbo/config/ServiceConfig.java | 24 +-
.../dubbo/config/bootstrap/DubboBootstrap.java | 30 +
.../config/deploy/DefaultApplicationDeployer.java | 12 +-
.../dubbo/config/deploy/DefaultModuleDeployer.java | 3 +-
.../ConfigurableMetadataServiceExporter.java | 3 +-
.../dubbo/config/utils/ConfigValidationUtils.java | 8 +-
.../apache/dubbo/config/AbstractConfigTest.java | 11 +-
.../dubbo/config/AbstractReferenceConfigTest.java | 4 +-
.../apache/dubbo/config/ApplicationConfigTest.java | 150 +-
.../dubbo/config/ConfigCenterConfigTest.java | 136 +-
.../apache/dubbo/config/ConsumerConfigTest.java | 157 +-
.../org/apache/dubbo/config/MethodConfigTest.java | 2 +
.../apache/dubbo/config/ProtocolConfigTest.java | 2 -
.../apache/dubbo/config/ProviderConfigTest.java | 2 +-
.../apache/dubbo/config/ReferenceConfigTest.java | 19 +-
.../org/apache/dubbo/config/ServiceConfigTest.java | 9 +-
.../AbstractRegistryCenterExporterListener.java | 34 +-
dubbo-config/dubbo-config-spring/pom.xml | 5 +
.../src/main/resources/META-INF/compat/dubbo.xsd | 22 +-
.../src/main/resources/META-INF/dubbo.xsd | 18 +-
.../support/zookeeper/CacheListener.java | 4 -
.../zookeeper/ZookeeperDynamicConfiguration.java | 7 +-
.../dubbo-demo-spring-boot-consumer/pom.xml | 7 +
.../dubbo-demo-spring-boot-provider/pom.xml | 7 +
dubbo-dependencies-bom/pom.xml | 3 +-
.../metadata/report/MetadataReportFactory.java | 9 +-
.../report/support/AbstractMetadataReport.java | 8 +-
.../dubbo/metadata/report/support/Constants.java | 8 -
.../store/redis/RedisMetadataReportTest.java | 2 +-
.../META-INF/native-image/reflect-config.json | 2 +-
.../dubbo/auth/filter/ProviderAuthFilterTest.java | 15 +-
.../org/apache/dubbo/registry/RegistryFactory.java | 3 +-
.../dubbo/registry/client/InstanceAddressURL.java | 15 +-
.../client/ServiceDiscoveryRegistryDirectory.java | 7 +-
.../listener/ServiceInstancesChangedListener.java | 14 +-
.../metadata/ServiceInstanceMetadataUtils.java | 5 +-
.../client/migration/MigrationInvoker.java | 19 +-
.../registry/integration/DynamicDirectory.java | 18 +-
.../registry/integration/RegistryDirectory.java | 1 +
.../registry/integration/RegistryProtocol.java | 2 +-
.../dubbo/registry/support/AbstractRegistry.java | 2 +-
.../registry/support/AbstractRegistryFactory.java | 4 +-
.../support/CacheableFailbackRegistry.java | 10 +-
.../registry/CacheableFailbackRegistryTest.java | 59 +
.../dubbo/registry/MockCacheableRegistryImpl.java | 12 +
.../ServiceInstancesChangedListenerTest.java | 37 +-
.../client/migration/MigrationInvokerTest.java | 3 +
.../dubbo/registry/multiple/MultipleRegistry.java | 2 +-
.../multiple/MultipleRegistry2S2RTest.java | 2 +-
.../apache/dubbo/registry/nacos/NacosRegistry.java | 5 +-
.../zookeeper/util/CuratorFrameworkUtils.java | 2 +-
.../java/org/apache/dubbo/remoting/Constants.java | 2 +-
.../telnet/support/TelnetHandlerAdapter.java | 4 +-
.../support/command/StatusTelnetHandler.java | 3 +-
.../dubbo/remoting/transport/AbstractEndpoint.java | 11 +-
.../transport/netty/NettyBackedChannelBuffer.java | 7 +-
.../support/header/HeartbeatHandlerTest.java | 19 +-
.../transport/netty/ClientReconnectTest.java | 2 +-
.../netty/NettyBackedChannelBufferTest.java | 63 +
.../remoting/transport/netty/NettyClientTest.java | 8 +-
.../transport/netty/NettyClientToServerTest.java | 4 +-
.../remoting/transport/netty/NettyStringTest.java | 4 +-
.../remoting/transport/netty/ThreadNameTest.java | 4 +-
.../transport/netty4/NettyBackedChannelBuffer.java | 8 +-
.../netty4/NettyBackedChannelBufferTest.java | 65 +
.../java/org/apache/dubbo/rpc/AsyncContext.java | 46 +
.../org/apache/dubbo/rpc/AsyncContextImpl.java | 25 +-
.../java/org/apache/dubbo/rpc/AsyncRpcResult.java | 45 +-
.../main/java/org/apache/dubbo/rpc/BaseFilter.java | 23 +
.../org/apache/dubbo/rpc/ListenableFilter.java | 3 +-
.../main/java/org/apache/dubbo/rpc/RpcContext.java | 64 +-
.../org/apache/dubbo/rpc/RpcContextAttachment.java | 24 +
.../org/apache/dubbo/rpc/RpcServiceContext.java | 28 +-
...rFilter.java => ClassLoaderCallbackFilter.java} | 33 +-
.../apache/dubbo/rpc/filter/ClassLoaderFilter.java | 40 +-
.../org/apache/dubbo/rpc/filter/ContextFilter.java | 24 +-
.../dubbo/rpc/proxy/AbstractProxyInvoker.java | 14 +-
.../rpc/proxy/javassist/JavassistProxyFactory.java | 60 +-
.../dubbo/internal/org.apache.dubbo.rpc.Filter | 3 +-
.../java/org/apache/dubbo/rpc/RpcContextTest.java | 5 +
.../dubbo/rpc/filter/ClassLoaderFilterTest.java | 4 +
.../rpc/filter/CompatibleFilterFilterTest.java | 19 +-
.../apache/dubbo/rpc/filter/ContextFilterTest.java | 6 +-
.../apache/dubbo/rpc/filter/EchoFilterTest.java | 3 +-
.../apache/dubbo/rpc/filter/TimeoutFilterTest.java | 3 +-
.../apache/dubbo/rpc/support/MockInvocation.java | 4 +-
.../rpc/protocol/dubbo/CallbackServiceCodec.java | 4 +-
.../dubbo/rpc/protocol/dubbo/DubboProtocol.java | 7 +-
.../protocol/dubbo/LazyConnectExchangeClient.java | 2 +-
.../dubbo/ReferenceCountExchangeClient.java | 21 +-
.../rpc/protocol/dubbo/DubboProtocolTest.java | 31 +-
.../dubbo/rpc/protocol/dubbo/RpcFilterTest.java | 1 +
.../rpc/protocol/tri/AbstractClientStream.java | 4 +-
.../rpc/protocol/tri/AbstractServerStream.java | 2 +-
.../dubbo/rpc/protocol/tri/AbstractStream.java | 6 +-
.../apache/dubbo/rpc/protocol/tri/Compressor.java | 5 +-
.../apache/dubbo/rpc/protocol/tri/GrpcStatus.java | 17 +-
.../dubbo/rpc/protocol/tri/IdentityCompressor.java | 3 +-
.../rpc/protocol/tri/InboundTransportObserver.java | 2 +-
.../dubbo/rpc/protocol/tri/UnaryClientStream.java | 2 +-
.../rpc/protocol/tri/command/DataQueueCommand.java | 2 +-
.../org.apache.dubbo.rpc.protocol.tri.Compressor | 1 -
.../dubbo/rpc/protocol/tri/ClientStreamTest.java | 4 +-
.../dubbo/rpc/protocol/tri/CompressorTest.java | 2 +-
.../dubbo/rpc/protocol/tri/GrpcStatusTest.java | 2 +-
.../dubbo-spring-boot-actuator/README.md | 2 +-
.../dubbo-spring-boot-actuator/pom.xml | 20 +
.../DubboEndpointAnnotationAutoConfiguration.java | 7 +
.../CompatibleOnEnabledEndpointCondition.java | 51 +-
.../dubbo-spring-boot-autoconfigure/pom.xml | 14 +
.../dubbo-spring-boot-compatible/actuator/pom.xml | 7 +
.../autoconfigure/pom.xml | 14 +
.../dubbo-spring-boot-starter/pom.xml | 13 +
dubbo-spring-boot/pom.xml | 2 +
pom.xml | 2 +-
239 files changed, 4302 insertions(+), 7078 deletions(-)
diff --cc dubbo-common/src/main/java/org/apache/dubbo/common/config/CompositeConfiguration.java
index 154a993,a1e5e0e..34e7754
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/config/CompositeConfiguration.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/config/CompositeConfiguration.java
@@@ -47,11 -47,7 +47,7 @@@ public class CompositeConfiguration imp
}
}
- public void setDynamicIncluded(boolean dynamicIncluded) {
- this.dynamicIncluded = dynamicIncluded;
- }
-
- //FIXME, consider change configList to SortedMap to replace this boolean status.
+ //FIXME, consider changing configList to SortedMap to replace this boolean status.
public boolean isDynamicIncluded() {
return dynamicIncluded;
}
diff --cc dubbo-common/src/main/java/org/apache/dubbo/common/deploy/ApplicationDeployer.java
index 0b74696,e882434..611f47c
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/deploy/ApplicationDeployer.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/deploy/ApplicationDeployer.java
@@@ -82,8 -77,10 +82,10 @@@ public interface ApplicationDeployer ex
/**
* check all module state and update application state
*/
- void checkState();
+ void checkState(ModuleModel moduleModel, DeployState moduleState);
- // module state changed callbacks
+ /**
+ * module state changed callbacks
+ */
void notifyModuleChanged(ModuleModel moduleModel, DeployState state);
}
diff --cc dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ReferenceConfig.java
index 1b62f06,5d83fed..03875d9
--- 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
@@@ -254,9 -254,8 +254,9 @@@ public class ReferenceConfig<T> extend
this.refresh();
}
- //init serviceMetadata
+ // init serviceMetadata
initServiceMetadata(consumer);
+
serviceMetadata.setServiceType(getServiceInterfaceClass());
// TODO, uncomment this line once service key is unified
serviceMetadata.setServiceKey(URL.buildKey(interfaceName, group, version));
diff --cc dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ServiceConfig.java
index 880fce3,bf7ae84..4d1420f
--- 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
@@@ -540,10 -541,9 +540,9 @@@ public class ServiceConfig<T> extends S
}
// export service
- String host = findConfiguredHosts(protocolConfig, params);
- Integer port = findConfiguredPorts(protocolConfig, name, params);
+ String host = findConfiguredHosts(protocolConfig, provider, registryURLs, params);
+ Integer port = findConfiguredPort(protocolConfig, provider, this.getExtensionLoader(Protocol.class), name, params);
URL url = new ServiceConfigURL(name, null, null, host, port, getContextPath(protocolConfig).map(p -> p + "/" + path).orElse(path), params);
- url.setScopeModel(getScopeModel());
// You can customize Configurator to append extra parameters
if (this.getExtensionLoader(ConfiguratorFactory.class)
@@@ -790,9 -765,9 +788,9 @@@
return portToRegistry;
}
- private Integer parsePort(String configPort) {
+ private static Integer parsePort(String configPort) {
Integer port = null;
- if (configPort != null && configPort.length() > 0) {
+ if (StringUtils.isNotEmpty(configPort)) {
try {
int intPort = Integer.parseInt(configPort);
if (isInvalidPort(intPort)) {
diff --cc dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/support/AbstractMetadataReport.java
index 36b99d0,093fadb..71901c5
--- a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/support/AbstractMetadataReport.java
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/support/AbstractMetadataReport.java
@@@ -71,11 -73,11 +74,8 @@@ import static org.apache.dubbo.metadata
import static org.apache.dubbo.metadata.report.support.Constants.DEFAULT_METADATA_REPORT_RETRY_PERIOD;
import static org.apache.dubbo.metadata.report.support.Constants.DEFAULT_METADATA_REPORT_RETRY_TIMES;
import static org.apache.dubbo.metadata.report.support.Constants.DUBBO_METADATA;
- import static org.apache.dubbo.metadata.report.support.Constants.RETRY_PERIOD_KEY;
- import static org.apache.dubbo.metadata.report.support.Constants.RETRY_TIMES_KEY;
- import static org.apache.dubbo.metadata.report.support.Constants.SYNC_REPORT_KEY;
import static org.apache.dubbo.metadata.report.support.Constants.USER_HOME;
-/**
- *
- */
public abstract class AbstractMetadataReport implements MetadataReport {
protected final static String DEFAULT_ROOT = "dubbo";
diff --cc dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/support/AbstractRegistry.java
index 7391fc3,cc9e6f5..a9a006e
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/support/AbstractRegistry.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/support/AbstractRegistry.java
@@@ -95,8 -94,7 +95,8 @@@ public abstract class AbstractRegistry
// Local disk cache file
private File file;
private boolean localCacheEnabled;
- private RegistryManager registryManager;
+ protected RegistryManager registryManager;
+ protected ApplicationModel applicationModel;
public AbstractRegistry(URL url) {
setUrl(url);
diff --cc dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/event/listener/ServiceInstancesChangedListenerTest.java
index cc0602e,867face..7bc53c9
--- a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/event/listener/ServiceInstancesChangedListenerTest.java
+++ b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/event/listener/ServiceInstancesChangedListenerTest.java
@@@ -14,407 -14,431 +14,422 @@@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.dubbo.registry.client.event.listener;
-
-import org.apache.dubbo.common.URL;
-import org.apache.dubbo.common.utils.StringUtils;
-import org.apache.dubbo.metadata.MetadataInfo;
-import org.apache.dubbo.metadata.MetadataService;
-import org.apache.dubbo.registry.NotifyListener;
-import org.apache.dubbo.registry.client.DefaultServiceInstance;
-import org.apache.dubbo.registry.client.InstanceAddressURL;
-import org.apache.dubbo.registry.client.ServiceDiscovery;
-import org.apache.dubbo.registry.client.ServiceInstance;
-import org.apache.dubbo.registry.client.event.ServiceInstancesChangedEvent;
-import org.apache.dubbo.registry.client.metadata.MetadataUtils;
-
-import com.google.gson.Gson;
-import org.apache.dubbo.rpc.model.ApplicationModel;
-import org.hamcrest.Matchers;
-import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.BeforeAll;
-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.mockito.ArgumentCaptor;
-import org.mockito.MockedStatic;
-import org.mockito.Mockito;
-import org.mockito.invocation.InvocationOnMock;
-import org.mockito.stubbing.Answer;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.ConcurrentMap;
-import java.util.concurrent.ThreadLocalRandom;
-
-import static org.apache.dubbo.common.constants.CommonConstants.REVISION_KEY;
-import static org.apache.dubbo.common.utils.CollectionUtils.isEmpty;
-import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.EXPORTED_SERVICES_REVISION_PROPERTY_NAME;
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-import static org.mockito.ArgumentMatchers.eq;
-
-/**
- * {@link ServiceInstancesChangedListener} Test
- *
- * @since 2.7.5
- */
-@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
-public class ServiceInstancesChangedListenerTest {
- private static Gson gson = new Gson();
-
- static List<ServiceInstance> app1Instances;
- static List<ServiceInstance> app2Instances;
- static List<ServiceInstance> app1FailedInstances;
- static List<ServiceInstance> app1FailedInstances2;
- static List<ServiceInstance> app1InstancesWithNoRevision;
-
- static String metadata_111 = "{\"app\":\"app1\",\"revision\":\"111\",\"services\":{"
- + "\"org.apache.dubbo.demo.DemoService:dubbo\":{\"name\":\"org.apache.dubbo.demo.DemoService\",\"protocol\":\"dubbo\",\"path\":\"org.apache.dubbo.demo.DemoService\",\"params\":{\"side\":\"provider\",\"release\":\"\",\"methods\":\"sayHello,sayHelloAsync\",\"deprecated\":\"false\",\"dubbo\":\"2.0.2\",\"pid\":\"72723\",\"interface\":\"org.apache.dubbo.demo.DemoService\",\"service-name-mapping\":\"true\",\"timeout\":\"3000\",\"generic\":\"false\",\"metadata-type\":\"remote\",\"delay [...]
- + "}}";
- static String metadata_222 = "{\"app\":\"app2\",\"revision\":\"333\",\"services\":{"
- + "\"org.apache.dubbo.demo.DemoService:dubbo\":{\"name\":\"org.apache.dubbo.demo.DemoService\",\"protocol\":\"dubbo\",\"path\":\"org.apache.dubbo.demo.DemoService\",\"params\":{\"side\":\"provider\",\"release\":\"\",\"methods\":\"sayHello,sayHelloAsync\",\"deprecated\":\"false\",\"dubbo\":\"2.0.2\",\"pid\":\"72723\",\"interface\":\"org.apache.dubbo.demo.DemoService\",\"service-name-mapping\":\"true\",\"timeout\":\"3000\",\"generic\":\"false\",\"metadata-type\":\"remote\",\"delay [...]
- + "\"org.apache.dubbo.demo.DemoService2:dubbo\":{\"name\":\"org.apache.dubbo.demo.DemoService2\",\"protocol\":\"dubbo\",\"path\":\"org.apache.dubbo.demo.DemoService2\",\"params\":{\"side\":\"provider\",\"release\":\"\",\"methods\":\"sayHello,sayHelloAsync\",\"deprecated\":\"false\",\"dubbo\":\"2.0.2\",\"pid\":\"72723\",\"interface\":\"org.apache.dubbo.demo.DemoService2\",\"service-name-mapping\":\"true\",\"timeout\":\"3000\",\"generic\":\"false\",\"metadata-type\":\"remote\",\"d [...]
- + "}}";
- static String metadata_333 = "{\"app\":\"app2\",\"revision\":\"333\",\"services\":{"
- + "\"org.apache.dubbo.demo.DemoService:dubbo\":{\"name\":\"org.apache.dubbo.demo.DemoService\",\"protocol\":\"dubbo\",\"path\":\"org.apache.dubbo.demo.DemoService\",\"params\":{\"side\":\"provider\",\"release\":\"\",\"methods\":\"sayHello,sayHelloAsync\",\"deprecated\":\"false\",\"dubbo\":\"2.0.2\",\"pid\":\"72723\",\"interface\":\"org.apache.dubbo.demo.DemoService\",\"service-name-mapping\":\"true\",\"timeout\":\"3000\",\"generic\":\"false\",\"metadata-type\":\"remote\",\"delay [...]
- + "\"org.apache.dubbo.demo.DemoService2:dubbo\":{\"name\":\"org.apache.dubbo.demo.DemoService2\",\"protocol\":\"dubbo\",\"path\":\"org.apache.dubbo.demo.DemoService2\",\"params\":{\"side\":\"provider\",\"release\":\"\",\"methods\":\"sayHello,sayHelloAsync\",\"deprecated\":\"false\",\"dubbo\":\"2.0.2\",\"pid\":\"72723\",\"interface\":\"org.apache.dubbo.demo.DemoService2\",\"service-name-mapping\":\"true\",\"timeout\":\"3000\",\"generic\":\"false\",\"metadata-type\":\"remote\",\"d [...]
- + "\"org.apache.dubbo.demo.DemoService3:dubbo\":{\"name\":\"org.apache.dubbo.demo.DemoService3\",\"protocol\":\"dubbo\",\"path\":\"org.apache.dubbo.demo.DemoService3\",\"params\":{\"side\":\"provider\",\"release\":\"\",\"methods\":\"sayHello,sayHelloAsync\",\"deprecated\":\"false\",\"dubbo\":\"2.0.2\",\"pid\":\"72723\",\"interface\":\"org.apache.dubbo.demo.DemoService3\",\"service-name-mapping\":\"true\",\"timeout\":\"3000\",\"generic\":\"false\",\"metadata-type\":\"remote\",\"d [...]
- + "}}";
- // failed
- static String metadata_444 = "{\"app\":\"app1\",\"revision\":\"444\",\"services\":{"
- + "\"org.apache.dubbo.demo.DemoService:dubbo\":{\"name\":\"org.apache.dubbo.demo.DemoService\",\"protocol\":\"dubbo\",\"path\":\"org.apache.dubbo.demo.DemoService\",\"params\":{\"side\":\"provider\",\"release\":\"\",\"methods\":\"sayHello,sayHelloAsync\",\"deprecated\":\"false\",\"dubbo\":\"2.0.2\",\"pid\":\"72723\",\"interface\":\"org.apache.dubbo.demo.DemoService\",\"service-name-mapping\":\"true\",\"timeout\":\"3000\",\"generic\":\"false\",\"metadata-type\":\"remote\",\"delay [...]
- + "}}";
-
- static String bad_metadatainfo = "{\"xxx\":\"yyy\"}";
-
- static String service1 = "org.apache.dubbo.demo.DemoService";
- static String service2 = "org.apache.dubbo.demo.DemoService2";
- static String service3 = "org.apache.dubbo.demo.DemoService3";
-
- static URL consumerURL = URL.valueOf("dubbo://127.0.0.1/org.apache.dubbo.demo.DemoService?registry_cluster=default");
- static URL registryURL = URL.valueOf("dubbo://127.0.0.1:2181/org.apache.dubbo.demo.RegistryService");
-
- static MetadataInfo metadataInfo_111;
- static MetadataInfo metadataInfo_222;
- static MetadataInfo metadataInfo_333;
- static MetadataInfo metadataInfo_444;
-
- static MetadataService metadataService;
-
- static ServiceDiscovery serviceDiscovery;
-
- ServiceInstancesChangedListener listener = null;
-
- @BeforeAll
- public static void setUp() {
- List<Object> urlsSameRevision = new ArrayList<>();
- urlsSameRevision.add("127.0.0.1:20880?revision=111");
- urlsSameRevision.add("127.0.0.2:20880?revision=111");
- urlsSameRevision.add("127.0.0.3:20880?revision=111");
-
- List<Object> urlsDifferentRevision = new ArrayList<>();
- urlsDifferentRevision.add("30.10.0.1:20880?revision=222");
- urlsDifferentRevision.add("30.10.0.2:20880?revision=222");
- urlsDifferentRevision.add("30.10.0.3:20880?revision=333");
- urlsDifferentRevision.add("30.10.0.4:20880?revision=333");
-
- List<Object> urlsFailedRevision = new ArrayList<>();
- urlsFailedRevision.add("30.10.0.5:20880?revision=222");
- urlsFailedRevision.add("30.10.0.6:20880?revision=222");
- urlsFailedRevision.add("30.10.0.7:20880?revision=444");// revision will fail
- urlsFailedRevision.add("30.10.0.8:20880?revision=444");// revision will fail
-
- List<Object> urlsFailedRevision2 = new ArrayList<>();
- urlsFailedRevision2.add("30.10.0.1:20880?revision=222");
- urlsFailedRevision2.add("30.10.0.2:20880?revision=222");
-
- List<Object> urlsWithoutRevision = new ArrayList<>();
- urlsWithoutRevision.add("30.10.0.1:20880");
-
- app1Instances = buildInstances(urlsSameRevision);
- app2Instances = buildInstances(urlsDifferentRevision);
- app1FailedInstances = buildInstances(urlsFailedRevision);
- app1FailedInstances2 = buildInstances(urlsFailedRevision2);
- app1InstancesWithNoRevision = buildInstances(urlsWithoutRevision);
-
- metadataInfo_111 = gson.fromJson(metadata_111, MetadataInfo.class);
- metadataInfo_222 = gson.fromJson(metadata_222, MetadataInfo.class);
- metadataInfo_333 = gson.fromJson(metadata_333, MetadataInfo.class);
- metadataInfo_444 = gson.fromJson(metadata_444, MetadataInfo.class);
-
- metadataService = Mockito.mock(MetadataService.class);
- Mockito.doReturn(metadataInfo_111).when(metadataService).getMetadataInfo("111");
- Mockito.doReturn(metadataInfo_222).when(metadataService).getMetadataInfo("222");
- Mockito.doReturn(metadataInfo_333).when(metadataService).getMetadataInfo("333");
- Mockito.doThrow(IllegalStateException.class).when(metadataService).getMetadataInfo("444");
-
- serviceDiscovery = Mockito.mock(ServiceDiscovery.class);
- Mockito.doReturn(registryURL).when(serviceDiscovery).getUrl();
- }
-
- @AfterEach
- public void tearDown() {
- if (listener != null) {
- listener.destroy();
- listener = null;
- }
- }
-
- // 正常场景。单应用app1 通知地址基本流程,只做instance-metadata关联,没有metadata内容的解析
- @Test
- @Order(1)
- public void testInstanceNotification() {
- Set<String> serviceNames = new HashSet<>();
- serviceNames.add("app1");
- ServiceDiscovery serviceDiscovery = Mockito.mock(ServiceDiscovery.class);
- listener = new ServiceInstancesChangedListener(serviceNames, serviceDiscovery);
- ServiceInstancesChangedListener spyListener = Mockito.spy(listener);
- Mockito.doReturn(metadataInfo_111).when(spyListener).getRemoteMetadata(eq("111"), Mockito.anyMap(), Mockito.any());
- ServiceInstancesChangedEvent event = new ServiceInstancesChangedEvent("app1", app1Instances);
- spyListener.onEvent(event);
-
- Map<String, List<ServiceInstance>> allInstances = spyListener.getAllInstances();
- Assertions.assertEquals(1, allInstances.size());
- Assertions.assertEquals(3, allInstances.get("app1").size());
-
- Map<String, MetadataInfo> revisionToMetadata = spyListener.getRevisionToMetadata();
- Assertions.assertEquals(1, revisionToMetadata.size());
- Assertions.assertEquals(metadataInfo_111, revisionToMetadata.get("111"));
-
-// // test app2 notification
-// Mockito.doReturn(metadataInfo_222).when(spyListener).getRemoteMetadata(eq("222"), Mockito.anyMap(), Mockito.anyList());
-// Mockito.doReturn(metadataInfo_333).when(spyListener).getRemoteMetadata(eq("333"), Mockito.anyMap(), Mockito.anyList());
-//
-// ServiceInstancesChangedEvent event_app2 = new ServiceInstancesChangedEvent("app2", app2Instances);
-// spyListener.onEvent(event_app2);
-
- }
-
- // 正常场景。单应用app1,进一步检查 metadata service 是否正确映射
- @Test
- @Order(2)
- public void testInstanceNotificationAndMetadataParse() {
- Set<String> serviceNames = new HashSet<>();
- serviceNames.add("app1");
- listener = new ServiceInstancesChangedListener(serviceNames, serviceDiscovery);
-
- try (MockedStatic<MetadataUtils> mockedMetadataUtils = Mockito.mockStatic(MetadataUtils.class)) {
- mockedMetadataUtils.when(() -> MetadataUtils.getMetadataServiceProxy(Mockito.any())).thenReturn(metadataService);
- // notify instance change
- ServiceInstancesChangedEvent event = new ServiceInstancesChangedEvent("app1", app1Instances);
- listener.onEvent(event);
-
- Map<String, List<ServiceInstance>> allInstances = listener.getAllInstances();
- Assertions.assertEquals(1, allInstances.size());
- Assertions.assertEquals(3, allInstances.get("app1").size());
-
- Map<String, MetadataInfo> revisionToMetadata = listener.getRevisionToMetadata();
- Assertions.assertEquals(1, revisionToMetadata.size());
- Assertions.assertEquals(metadataInfo_111, revisionToMetadata.get("111"));
-
- List<URL> serviceUrls = listener.getAddresses(service1 + ":dubbo", consumerURL);
- Assertions.assertEquals(3, serviceUrls.size());
- assertTrue(serviceUrls.get(0) instanceof InstanceAddressURL);
-
- assertThat(serviceUrls, Matchers.hasItem(Matchers.hasProperty("instance", Matchers.notNullValue())));
- assertThat(serviceUrls, Matchers.hasItem(Matchers.hasProperty("metadataInfo", Matchers.notNullValue())));
-
- }
- }
-
- // 正常场景。多应用,app1 app2 分别通知地址
- @Test
- @Order(3)
- public void testMultipleAppNotification() {
- Set<String> serviceNames = new HashSet<>();
- serviceNames.add("app1");
- serviceNames.add("app2");
- listener = new ServiceInstancesChangedListener(serviceNames, serviceDiscovery);
-
- try (MockedStatic<MetadataUtils> mockedMetadataUtils = Mockito.mockStatic(MetadataUtils.class)) {
- mockedMetadataUtils.when(() -> MetadataUtils.getMetadataServiceProxy(Mockito.any())).thenReturn(metadataService);
- // notify app1 instance change
- ServiceInstancesChangedEvent app1_event = new ServiceInstancesChangedEvent("app1", app1Instances);
- listener.onEvent(app1_event);
-
- // notify app2 instance change
- ServiceInstancesChangedEvent app2_event = new ServiceInstancesChangedEvent("app2", app2Instances);
- listener.onEvent(app2_event);
-
- // check
- Map<String, List<ServiceInstance>> allInstances = listener.getAllInstances();
- Assertions.assertEquals(2, allInstances.size());
- Assertions.assertEquals(3, allInstances.get("app1").size());
- Assertions.assertEquals(4, allInstances.get("app2").size());
-
- Map<String, MetadataInfo> revisionToMetadata = listener.getRevisionToMetadata();
- Assertions.assertEquals(3, revisionToMetadata.size());
- Assertions.assertEquals(metadataInfo_111, revisionToMetadata.get("111"));
- Assertions.assertEquals(metadataInfo_222, revisionToMetadata.get("222"));
- Assertions.assertEquals(metadataInfo_333, revisionToMetadata.get("333"));
-
- List<URL> serviceUrls = listener.getAddresses(service1 + ":dubbo", consumerURL);
- Assertions.assertEquals(7, serviceUrls.size());
- List<URL> serviceUrls2 = listener.getAddresses(service2 + ":dubbo", consumerURL);
- Assertions.assertEquals(4, serviceUrls2.size());
- assertTrue(serviceUrls2.get(0).getIp().contains("30.10."));
- List<URL> serviceUrls3 = listener.getAddresses(service3 + ":dubbo", consumerURL);
- Assertions.assertEquals(2, serviceUrls3.size());
- assertTrue(serviceUrls3.get(0).getIp().contains("30.10."));
- }
- }
-
- // 正常场景。多应用,app1 app2,空地址通知(边界条件)能否解析出正确的空地址列表
- @Test
- @Order(4)
- public void testMultipleAppEmptyNotification() {
- Set<String> serviceNames = new HashSet<>();
- serviceNames.add("app1");
- serviceNames.add("app2");
- listener = new ServiceInstancesChangedListener(serviceNames, serviceDiscovery);
-
- try (MockedStatic<MetadataUtils> mockedMetadataUtils = Mockito.mockStatic(MetadataUtils.class)) {
- mockedMetadataUtils.when(() -> MetadataUtils.getMetadataServiceProxy(Mockito.any())).thenReturn(metadataService);
- // notify app1 instance change
- ServiceInstancesChangedEvent app1_event = new ServiceInstancesChangedEvent("app1", app1Instances);
- listener.onEvent(app1_event);
-
- // notify app2 instance change
- ServiceInstancesChangedEvent app2_event = new ServiceInstancesChangedEvent("app2", app2Instances);
- listener.onEvent(app2_event);
-
- // empty notification
- ServiceInstancesChangedEvent app1_event_again = new ServiceInstancesChangedEvent("app1", Collections.EMPTY_LIST);
- listener.onEvent(app1_event_again);
-
- // check app1 cleared
- Map<String, List<ServiceInstance>> allInstances = listener.getAllInstances();
- Assertions.assertEquals(2, allInstances.size());
- Assertions.assertEquals(0, allInstances.get("app1").size());
- Assertions.assertEquals(4, allInstances.get("app2").size());
-
- Map<String, MetadataInfo> revisionToMetadata = listener.getRevisionToMetadata();
- Assertions.assertEquals(2, revisionToMetadata.size());
- Assertions.assertNull(revisionToMetadata.get("111"));
- Assertions.assertEquals(metadataInfo_222, revisionToMetadata.get("222"));
- Assertions.assertEquals(metadataInfo_333, revisionToMetadata.get("333"));
-
- List<URL> serviceUrls = listener.getAddresses(service1 + ":dubbo", consumerURL);
- Assertions.assertEquals(4, serviceUrls.size());
- assertTrue(serviceUrls.get(0).getIp().contains("30.10."));
- List<URL> serviceUrls2 = listener.getAddresses(service2 + ":dubbo", consumerURL);
- Assertions.assertEquals(4, serviceUrls2.size());
- assertTrue(serviceUrls2.get(0).getIp().contains("30.10."));
- List<URL> serviceUrls3 = listener.getAddresses(service3 + ":dubbo", consumerURL);
- Assertions.assertEquals(2, serviceUrls3.size());
- assertTrue(serviceUrls3.get(0).getIp().contains("30.10."));
-
- // app2 empty notification
- ServiceInstancesChangedEvent app2_event_again = new ServiceInstancesChangedEvent("app2", Collections.EMPTY_LIST);
- listener.onEvent(app2_event_again);
-
- // check app2 cleared
- Map<String, List<ServiceInstance>> allInstances_app2 = listener.getAllInstances();
- Assertions.assertEquals(2, allInstances_app2.size());
- Assertions.assertEquals(0, allInstances_app2.get("app1").size());
- Assertions.assertEquals(0, allInstances_app2.get("app2").size());
-
- Map<String, MetadataInfo> revisionToMetadata_app2 = listener.getRevisionToMetadata();
- Assertions.assertEquals(0, revisionToMetadata_app2.size());
-
- assertTrue(isEmpty(listener.getAddresses(service1 + ":dubbo", consumerURL)));
- assertTrue(isEmpty(listener.getAddresses(service2 + ":dubbo", consumerURL)));
- assertTrue(isEmpty(listener.getAddresses(service3 + ":dubbo", consumerURL)));
- }
- }
-
- // 正常场景。检查instance listener -> service listener(Directory)地址推送流程
- @Test
- @Order(5)
- public void testServiceListenerNotification() {
- Set<String> serviceNames = new HashSet<>();
- serviceNames.add("app1");
- serviceNames.add("app2");
- listener = new ServiceInstancesChangedListener(serviceNames, serviceDiscovery);
- NotifyListener demoServiceListener = Mockito.mock(NotifyListener.class);
- NotifyListener demoService2Listener = Mockito.mock(NotifyListener.class);
- listener.addListenerAndNotify(service1 + ":dubbo", demoServiceListener);
- listener.addListenerAndNotify(service2 + ":dubbo", demoService2Listener);
-
- try (MockedStatic<MetadataUtils> mockedMetadataUtils = Mockito.mockStatic(MetadataUtils.class)) {
- mockedMetadataUtils.when(() -> MetadataUtils.getMetadataServiceProxy(Mockito.any())).thenReturn(metadataService);
- // notify app1 instance change
- ServiceInstancesChangedEvent app1_event = new ServiceInstancesChangedEvent("app1", app1Instances);
- listener.onEvent(app1_event);
-
- // check
- ArgumentCaptor<List<URL>> captor = ArgumentCaptor.forClass(List.class);
- Mockito.verify(demoServiceListener, Mockito.times(1)).notify(captor.capture());
- List<URL> notifiedUrls = captor.getValue();
- Assertions.assertEquals(3, notifiedUrls.size());
- ArgumentCaptor<List<URL>> captor2 = ArgumentCaptor.forClass(List.class);
- Mockito.verify(demoService2Listener, Mockito.times(1)).notify(captor2.capture());
- List<URL> notifiedUrls2 = captor2.getValue();
- Assertions.assertEquals(0, notifiedUrls2.size());
-
- // notify app2 instance change
- ServiceInstancesChangedEvent app2_event = new ServiceInstancesChangedEvent("app2", app2Instances);
- listener.onEvent(app2_event);
-
- // check
- ArgumentCaptor<List<URL>> app2_captor = ArgumentCaptor.forClass(List.class);
- Mockito.verify(demoServiceListener, Mockito.times(2)).notify(app2_captor.capture());
- List<URL> app2_notifiedUrls = app2_captor.getValue();
- Assertions.assertEquals(7, app2_notifiedUrls.size());
- ArgumentCaptor<List<URL>> app2_captor2 = ArgumentCaptor.forClass(List.class);
- Mockito.verify(demoService2Listener, Mockito.times(2)).notify(app2_captor2.capture());
- List<URL> app2_notifiedUrls2 = app2_captor2.getValue();
- Assertions.assertEquals(4, app2_notifiedUrls2.size());
- }
-
- // test service listener still get notified when added after instance notification.
- NotifyListener demoService3Listener = Mockito.mock(NotifyListener.class);
- listener.addListenerAndNotify(service3 + ":dubbo", demoService3Listener);
- Mockito.verify(demoService3Listener, Mockito.times(1)).notify(Mockito.anyList());
- }
-
- // revision 异常场景。第一次启动,完全拿不到metadata,只能通知部分地址
- @Test
- @Order(6)
- public void testRevisionFailureOnStartup() {
- Set<String> serviceNames = new HashSet<>();
- serviceNames.add("app1");
- listener = new ServiceInstancesChangedListener(serviceNames, serviceDiscovery);
- try (MockedStatic<MetadataUtils> mockedMetadataUtils = Mockito.mockStatic(MetadataUtils.class)) {
- mockedMetadataUtils.when(() -> MetadataUtils.getMetadataServiceProxy(Mockito.any())).thenReturn(metadataService);
- // notify app1 instance change
- ServiceInstancesChangedEvent failed_revision_event = new ServiceInstancesChangedEvent("app1", app1FailedInstances);
- listener.onEvent(failed_revision_event);
-
- List<URL> serviceUrls = listener.getAddresses(service1 + ":dubbo", consumerURL);
- List<URL> serviceUrls2 = listener.getAddresses(service2 + ":dubbo", consumerURL);
-
- assertTrue(isEmpty(serviceUrls));
- assertTrue(isEmpty(serviceUrls2));
-
- Map<String, MetadataInfo> revisionToMetadata = listener.getRevisionToMetadata();
- Assertions.assertEquals(2, revisionToMetadata.size());
- Assertions.assertEquals(metadataInfo_222, revisionToMetadata.get("222"));
- Assertions.assertEquals(MetadataInfo.EMPTY, revisionToMetadata.get("444"));
- }
- }
-
- // revision 异常场景。运行中地址通知,拿不到revision就用老版本revision
- @Test
- public void testRevisionFailureOnNotification() {
- Set<String> serviceNames = new HashSet<>();
- serviceNames.add("app1");
- serviceNames.add("app2");
- listener = new ServiceInstancesChangedListener(serviceNames, serviceDiscovery);
-
- ConcurrentMap tmpProxyMap = MetadataUtils.metadataServiceProxies;
-
- try (MockedStatic<MetadataUtils> mockedMetadataUtils = Mockito.mockStatic(MetadataUtils.class)) {
- mockedMetadataUtils.when(() -> MetadataUtils.getMetadataServiceProxy(Mockito.any())).thenReturn(metadataService);
-
- // notify app1 instance change
- ServiceInstancesChangedEvent event = new ServiceInstancesChangedEvent("app1", app1Instances);
- listener.onEvent(event);
-
- Mockito.when(metadataService.getMetadataInfo("222")).thenAnswer(new Answer<MetadataInfo>() {
- @Override
- public MetadataInfo answer(InvocationOnMock invocationOnMock) throws Throwable {
- if (Thread.currentThread().getName().contains("Dubbo-metadata-retry")) {
- return metadataInfo_222;
- }
- return null;
- }
- });
-// Mockito.when(metadataService.getMetadataInfo("444")).thenAnswer(new Answer<MetadataInfo>() {
+//package org.apache.dubbo.registry.client.event.listener;
+//
+//import org.apache.dubbo.common.URL;
+//import org.apache.dubbo.common.utils.StringUtils;
+//import org.apache.dubbo.metadata.MetadataInfo;
+//import org.apache.dubbo.metadata.MetadataService;
+//import org.apache.dubbo.registry.NotifyListener;
+//import org.apache.dubbo.registry.client.DefaultServiceInstance;
+//import org.apache.dubbo.registry.client.InstanceAddressURL;
+//import org.apache.dubbo.registry.client.ServiceDiscovery;
+//import org.apache.dubbo.registry.client.ServiceInstance;
+//import org.apache.dubbo.registry.client.event.ServiceInstancesChangedEvent;
+//import org.apache.dubbo.registry.client.metadata.MetadataUtils;
+//
+//import com.google.gson.Gson;
++//import org.apache.dubbo.rpc.model.ApplicationModel;
+//import org.hamcrest.Matchers;
++//import org.junit.jupiter.api.AfterEach;
+//import org.junit.jupiter.api.Assertions;
+//import org.junit.jupiter.api.BeforeAll;
+//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.mockito.ArgumentCaptor;
+//import org.mockito.MockedStatic;
+//import org.mockito.Mockito;
+//import org.mockito.invocation.InvocationOnMock;
+//import org.mockito.stubbing.Answer;
+//
+//import java.util.ArrayList;
+//import java.util.Collections;
+//import java.util.HashMap;
+//import java.util.HashSet;
+//import java.util.List;
+//import java.util.Map;
+//import java.util.Set;
+//import java.util.concurrent.ConcurrentMap;
+//import java.util.concurrent.ThreadLocalRandom;
+//
+//import static org.apache.dubbo.common.constants.CommonConstants.REVISION_KEY;
+//import static org.apache.dubbo.common.utils.CollectionUtils.isEmpty;
+//import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.EXPORTED_SERVICES_REVISION_PROPERTY_NAME;
+//import static org.hamcrest.MatcherAssert.assertThat;
+//import static org.junit.jupiter.api.Assertions.assertTrue;
+//import static org.mockito.ArgumentMatchers.eq;
+//
+///**
+// * {@link ServiceInstancesChangedListener} Test
+// *
+// * @since 2.7.5
+// */
+//@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
+//public class ServiceInstancesChangedListenerTest {
+// private static Gson gson = new Gson();
+//
+// static List<ServiceInstance> app1Instances;
+// static List<ServiceInstance> app2Instances;
+// static List<ServiceInstance> app1FailedInstances;
+// static List<ServiceInstance> app1FailedInstances2;
+// static List<ServiceInstance> app1InstancesWithNoRevision;
+//
+// static String metadata_111 = "{\"app\":\"app1\",\"revision\":\"111\",\"services\":{"
+// + "\"org.apache.dubbo.demo.DemoService:dubbo\":{\"name\":\"org.apache.dubbo.demo.DemoService\",\"protocol\":\"dubbo\",\"path\":\"org.apache.dubbo.demo.DemoService\",\"params\":{\"side\":\"provider\",\"release\":\"\",\"methods\":\"sayHello,sayHelloAsync\",\"deprecated\":\"false\",\"dubbo\":\"2.0.2\",\"pid\":\"72723\",\"interface\":\"org.apache.dubbo.demo.DemoService\",\"service-name-mapping\":\"true\",\"timeout\":\"3000\",\"generic\":\"false\",\"metadata-type\":\"remote\",\"del [...]
+// + "}}";
+// static String metadata_222 = "{\"app\":\"app2\",\"revision\":\"333\",\"services\":{"
+// + "\"org.apache.dubbo.demo.DemoService:dubbo\":{\"name\":\"org.apache.dubbo.demo.DemoService\",\"protocol\":\"dubbo\",\"path\":\"org.apache.dubbo.demo.DemoService\",\"params\":{\"side\":\"provider\",\"release\":\"\",\"methods\":\"sayHello,sayHelloAsync\",\"deprecated\":\"false\",\"dubbo\":\"2.0.2\",\"pid\":\"72723\",\"interface\":\"org.apache.dubbo.demo.DemoService\",\"service-name-mapping\":\"true\",\"timeout\":\"3000\",\"generic\":\"false\",\"metadata-type\":\"remote\",\"del [...]
+// + "\"org.apache.dubbo.demo.DemoService2:dubbo\":{\"name\":\"org.apache.dubbo.demo.DemoService2\",\"protocol\":\"dubbo\",\"path\":\"org.apache.dubbo.demo.DemoService2\",\"params\":{\"side\":\"provider\",\"release\":\"\",\"methods\":\"sayHello,sayHelloAsync\",\"deprecated\":\"false\",\"dubbo\":\"2.0.2\",\"pid\":\"72723\",\"interface\":\"org.apache.dubbo.demo.DemoService2\",\"service-name-mapping\":\"true\",\"timeout\":\"3000\",\"generic\":\"false\",\"metadata-type\":\"remote\",\ [...]
+// + "}}";
+// static String metadata_333 = "{\"app\":\"app2\",\"revision\":\"333\",\"services\":{"
+// + "\"org.apache.dubbo.demo.DemoService:dubbo\":{\"name\":\"org.apache.dubbo.demo.DemoService\",\"protocol\":\"dubbo\",\"path\":\"org.apache.dubbo.demo.DemoService\",\"params\":{\"side\":\"provider\",\"release\":\"\",\"methods\":\"sayHello,sayHelloAsync\",\"deprecated\":\"false\",\"dubbo\":\"2.0.2\",\"pid\":\"72723\",\"interface\":\"org.apache.dubbo.demo.DemoService\",\"service-name-mapping\":\"true\",\"timeout\":\"3000\",\"generic\":\"false\",\"metadata-type\":\"remote\",\"del [...]
+// + "\"org.apache.dubbo.demo.DemoService2:dubbo\":{\"name\":\"org.apache.dubbo.demo.DemoService2\",\"protocol\":\"dubbo\",\"path\":\"org.apache.dubbo.demo.DemoService2\",\"params\":{\"side\":\"provider\",\"release\":\"\",\"methods\":\"sayHello,sayHelloAsync\",\"deprecated\":\"false\",\"dubbo\":\"2.0.2\",\"pid\":\"72723\",\"interface\":\"org.apache.dubbo.demo.DemoService2\",\"service-name-mapping\":\"true\",\"timeout\":\"3000\",\"generic\":\"false\",\"metadata-type\":\"remote\",\ [...]
+// + "\"org.apache.dubbo.demo.DemoService3:dubbo\":{\"name\":\"org.apache.dubbo.demo.DemoService3\",\"protocol\":\"dubbo\",\"path\":\"org.apache.dubbo.demo.DemoService3\",\"params\":{\"side\":\"provider\",\"release\":\"\",\"methods\":\"sayHello,sayHelloAsync\",\"deprecated\":\"false\",\"dubbo\":\"2.0.2\",\"pid\":\"72723\",\"interface\":\"org.apache.dubbo.demo.DemoService3\",\"service-name-mapping\":\"true\",\"timeout\":\"3000\",\"generic\":\"false\",\"metadata-type\":\"remote\",\ [...]
+// + "}}";
+// // failed
+// static String metadata_444 = "{\"app\":\"app1\",\"revision\":\"444\",\"services\":{"
+// + "\"org.apache.dubbo.demo.DemoService:dubbo\":{\"name\":\"org.apache.dubbo.demo.DemoService\",\"protocol\":\"dubbo\",\"path\":\"org.apache.dubbo.demo.DemoService\",\"params\":{\"side\":\"provider\",\"release\":\"\",\"methods\":\"sayHello,sayHelloAsync\",\"deprecated\":\"false\",\"dubbo\":\"2.0.2\",\"pid\":\"72723\",\"interface\":\"org.apache.dubbo.demo.DemoService\",\"service-name-mapping\":\"true\",\"timeout\":\"3000\",\"generic\":\"false\",\"metadata-type\":\"remote\",\"del [...]
+// + "}}";
+//
+// static String bad_metadatainfo = "{\"xxx\":\"yyy\"}";
+//
+// static String service1 = "org.apache.dubbo.demo.DemoService";
+// static String service2 = "org.apache.dubbo.demo.DemoService2";
+// static String service3 = "org.apache.dubbo.demo.DemoService3";
+//
+// static URL consumerURL = URL.valueOf("dubbo://127.0.0.1/org.apache.dubbo.demo.DemoService?registry_cluster=default");
++// static URL registryURL = URL.valueOf("dubbo://127.0.0.1:2181/org.apache.dubbo.demo.RegistryService");
+//
+// static MetadataInfo metadataInfo_111;
+// static MetadataInfo metadataInfo_222;
+// static MetadataInfo metadataInfo_333;
+// static MetadataInfo metadataInfo_444;
+//
+// static MetadataService metadataService;
+//
+// static ServiceDiscovery serviceDiscovery;
+//
++// ServiceInstancesChangedListener listener = null;
++//
+// @BeforeAll
+// public static void setUp() {
+// List<Object> urlsSameRevision = new ArrayList<>();
+// urlsSameRevision.add("127.0.0.1:20880?revision=111");
+// urlsSameRevision.add("127.0.0.2:20880?revision=111");
+// urlsSameRevision.add("127.0.0.3:20880?revision=111");
+//
+// List<Object> urlsDifferentRevision = new ArrayList<>();
+// urlsDifferentRevision.add("30.10.0.1:20880?revision=222");
+// urlsDifferentRevision.add("30.10.0.2:20880?revision=222");
+// urlsDifferentRevision.add("30.10.0.3:20880?revision=333");
+// urlsDifferentRevision.add("30.10.0.4:20880?revision=333");
+//
+// List<Object> urlsFailedRevision = new ArrayList<>();
+// urlsFailedRevision.add("30.10.0.5:20880?revision=222");
+// urlsFailedRevision.add("30.10.0.6:20880?revision=222");
+// urlsFailedRevision.add("30.10.0.7:20880?revision=444");// revision will fail
+// urlsFailedRevision.add("30.10.0.8:20880?revision=444");// revision will fail
+//
+// List<Object> urlsFailedRevision2 = new ArrayList<>();
+// urlsFailedRevision2.add("30.10.0.1:20880?revision=222");
+// urlsFailedRevision2.add("30.10.0.2:20880?revision=222");
+//
+// List<Object> urlsWithoutRevision = new ArrayList<>();
+// urlsWithoutRevision.add("30.10.0.1:20880");
+//
+// app1Instances = buildInstances(urlsSameRevision);
+// app2Instances = buildInstances(urlsDifferentRevision);
+// app1FailedInstances = buildInstances(urlsFailedRevision);
+// app1FailedInstances2 = buildInstances(urlsFailedRevision2);
+// app1InstancesWithNoRevision = buildInstances(urlsWithoutRevision);
+//
+// metadataInfo_111 = gson.fromJson(metadata_111, MetadataInfo.class);
+// metadataInfo_222 = gson.fromJson(metadata_222, MetadataInfo.class);
+// metadataInfo_333 = gson.fromJson(metadata_333, MetadataInfo.class);
+// metadataInfo_444 = gson.fromJson(metadata_444, MetadataInfo.class);
+//
+// metadataService = Mockito.mock(MetadataService.class);
+// Mockito.doReturn(metadataInfo_111).when(metadataService).getMetadataInfo("111");
+// Mockito.doReturn(metadataInfo_222).when(metadataService).getMetadataInfo("222");
+// Mockito.doReturn(metadataInfo_333).when(metadataService).getMetadataInfo("333");
+// Mockito.doThrow(IllegalStateException.class).when(metadataService).getMetadataInfo("444");
+//
+// serviceDiscovery = Mockito.mock(ServiceDiscovery.class);
++// Mockito.doReturn(registryURL).when(serviceDiscovery).getUrl();
++// }
++//
++// @AfterEach
++// public void tearDown() {
++// if (listener != null) {
++// listener.destroy();
++// listener = null;
++// }
+// }
+//
+// // 正常场景。单应用app1 通知地址基本流程,只做instance-metadata关联,没有metadata内容的解析
+// @Test
+// @Order(1)
+// public void testInstanceNotification() {
+// Set<String> serviceNames = new HashSet<>();
+// serviceNames.add("app1");
+// ServiceDiscovery serviceDiscovery = Mockito.mock(ServiceDiscovery.class);
- // ServiceInstancesChangedListener spyListener = Mockito.spy(new ServiceInstancesChangedListener(serviceNames, serviceDiscovery));
++// listener = new ServiceInstancesChangedListener(serviceNames, serviceDiscovery);
++// ServiceInstancesChangedListener spyListener = Mockito.spy(listener);
+// Mockito.doReturn(metadataInfo_111).when(spyListener).getRemoteMetadata(eq("111"), Mockito.anyMap(), Mockito.any());
+// ServiceInstancesChangedEvent event = new ServiceInstancesChangedEvent("app1", app1Instances);
+// spyListener.onEvent(event);
+//
+// Map<String, List<ServiceInstance>> allInstances = spyListener.getAllInstances();
+// Assertions.assertEquals(1, allInstances.size());
+// Assertions.assertEquals(3, allInstances.get("app1").size());
+//
+// Map<String, MetadataInfo> revisionToMetadata = spyListener.getRevisionToMetadata();
+// Assertions.assertEquals(1, revisionToMetadata.size());
+// Assertions.assertEquals(metadataInfo_111, revisionToMetadata.get("111"));
+//
+//// // test app2 notification
+//// Mockito.doReturn(metadataInfo_222).when(spyListener).getRemoteMetadata(eq("222"), Mockito.anyMap(), Mockito.anyList());
+//// Mockito.doReturn(metadataInfo_333).when(spyListener).getRemoteMetadata(eq("333"), Mockito.anyMap(), Mockito.anyList());
+////
+//// ServiceInstancesChangedEvent event_app2 = new ServiceInstancesChangedEvent("app2", app2Instances);
+//// spyListener.onEvent(event_app2);
+//
+// }
+//
+// // 正常场景。单应用app1,进一步检查 metadata service 是否正确映射
+// @Test
+// @Order(2)
+// public void testInstanceNotificationAndMetadataParse() {
+// Set<String> serviceNames = new HashSet<>();
+// serviceNames.add("app1");
- // ServiceInstancesChangedListener listener = new ServiceInstancesChangedListener(serviceNames, serviceDiscovery);
++// listener = new ServiceInstancesChangedListener(serviceNames, serviceDiscovery);
+//
+// try (MockedStatic<MetadataUtils> mockedMetadataUtils = Mockito.mockStatic(MetadataUtils.class)) {
+// mockedMetadataUtils.when(() -> MetadataUtils.getMetadataServiceProxy(Mockito.any())).thenReturn(metadataService);
+// // notify instance change
+// ServiceInstancesChangedEvent event = new ServiceInstancesChangedEvent("app1", app1Instances);
+// listener.onEvent(event);
+//
+// Map<String, List<ServiceInstance>> allInstances = listener.getAllInstances();
+// Assertions.assertEquals(1, allInstances.size());
+// Assertions.assertEquals(3, allInstances.get("app1").size());
+//
+// Map<String, MetadataInfo> revisionToMetadata = listener.getRevisionToMetadata();
+// Assertions.assertEquals(1, revisionToMetadata.size());
+// Assertions.assertEquals(metadataInfo_111, revisionToMetadata.get("111"));
+//
+// List<URL> serviceUrls = listener.getAddresses(service1 + ":dubbo", consumerURL);
+// Assertions.assertEquals(3, serviceUrls.size());
+// assertTrue(serviceUrls.get(0) instanceof InstanceAddressURL);
+//
+// assertThat(serviceUrls, Matchers.hasItem(Matchers.hasProperty("instance", Matchers.notNullValue())));
+// assertThat(serviceUrls, Matchers.hasItem(Matchers.hasProperty("metadataInfo", Matchers.notNullValue())));
+//
+// }
+// }
+//
+// // 正常场景。多应用,app1 app2 分别通知地址
+// @Test
+// @Order(3)
+// public void testMultipleAppNotification() {
+// Set<String> serviceNames = new HashSet<>();
+// serviceNames.add("app1");
+// serviceNames.add("app2");
- // ServiceInstancesChangedListener listener = new ServiceInstancesChangedListener(serviceNames, serviceDiscovery);
++// listener = new ServiceInstancesChangedListener(serviceNames, serviceDiscovery);
+//
+// try (MockedStatic<MetadataUtils> mockedMetadataUtils = Mockito.mockStatic(MetadataUtils.class)) {
+// mockedMetadataUtils.when(() -> MetadataUtils.getMetadataServiceProxy(Mockito.any())).thenReturn(metadataService);
+// // notify app1 instance change
+// ServiceInstancesChangedEvent app1_event = new ServiceInstancesChangedEvent("app1", app1Instances);
+// listener.onEvent(app1_event);
+//
+// // notify app2 instance change
+// ServiceInstancesChangedEvent app2_event = new ServiceInstancesChangedEvent("app2", app2Instances);
+// listener.onEvent(app2_event);
+//
+// // check
+// Map<String, List<ServiceInstance>> allInstances = listener.getAllInstances();
+// Assertions.assertEquals(2, allInstances.size());
+// Assertions.assertEquals(3, allInstances.get("app1").size());
+// Assertions.assertEquals(4, allInstances.get("app2").size());
+//
+// Map<String, MetadataInfo> revisionToMetadata = listener.getRevisionToMetadata();
+// Assertions.assertEquals(3, revisionToMetadata.size());
+// Assertions.assertEquals(metadataInfo_111, revisionToMetadata.get("111"));
+// Assertions.assertEquals(metadataInfo_222, revisionToMetadata.get("222"));
+// Assertions.assertEquals(metadataInfo_333, revisionToMetadata.get("333"));
+//
+// List<URL> serviceUrls = listener.getAddresses(service1 + ":dubbo", consumerURL);
+// Assertions.assertEquals(7, serviceUrls.size());
+// List<URL> serviceUrls2 = listener.getAddresses(service2 + ":dubbo", consumerURL);
+// Assertions.assertEquals(4, serviceUrls2.size());
+// assertTrue(serviceUrls2.get(0).getIp().contains("30.10."));
+// List<URL> serviceUrls3 = listener.getAddresses(service3 + ":dubbo", consumerURL);
+// Assertions.assertEquals(2, serviceUrls3.size());
+// assertTrue(serviceUrls3.get(0).getIp().contains("30.10."));
+// }
+// }
+//
+// // 正常场景。多应用,app1 app2,空地址通知(边界条件)能否解析出正确的空地址列表
+// @Test
+// @Order(4)
+// public void testMultipleAppEmptyNotification() {
+// Set<String> serviceNames = new HashSet<>();
+// serviceNames.add("app1");
+// serviceNames.add("app2");
- // ServiceInstancesChangedListener listener = new ServiceInstancesChangedListener(serviceNames, serviceDiscovery);
++// listener = new ServiceInstancesChangedListener(serviceNames, serviceDiscovery);
+//
+// try (MockedStatic<MetadataUtils> mockedMetadataUtils = Mockito.mockStatic(MetadataUtils.class)) {
+// mockedMetadataUtils.when(() -> MetadataUtils.getMetadataServiceProxy(Mockito.any())).thenReturn(metadataService);
+// // notify app1 instance change
+// ServiceInstancesChangedEvent app1_event = new ServiceInstancesChangedEvent("app1", app1Instances);
+// listener.onEvent(app1_event);
+//
+// // notify app2 instance change
+// ServiceInstancesChangedEvent app2_event = new ServiceInstancesChangedEvent("app2", app2Instances);
+// listener.onEvent(app2_event);
+//
+// // empty notification
+// ServiceInstancesChangedEvent app1_event_again = new ServiceInstancesChangedEvent("app1", Collections.EMPTY_LIST);
+// listener.onEvent(app1_event_again);
+//
+// // check app1 cleared
+// Map<String, List<ServiceInstance>> allInstances = listener.getAllInstances();
+// Assertions.assertEquals(2, allInstances.size());
+// Assertions.assertEquals(0, allInstances.get("app1").size());
+// Assertions.assertEquals(4, allInstances.get("app2").size());
+//
+// Map<String, MetadataInfo> revisionToMetadata = listener.getRevisionToMetadata();
+// Assertions.assertEquals(2, revisionToMetadata.size());
+// Assertions.assertNull(revisionToMetadata.get("111"));
+// Assertions.assertEquals(metadataInfo_222, revisionToMetadata.get("222"));
+// Assertions.assertEquals(metadataInfo_333, revisionToMetadata.get("333"));
+//
+// List<URL> serviceUrls = listener.getAddresses(service1 + ":dubbo", consumerURL);
+// Assertions.assertEquals(4, serviceUrls.size());
+// assertTrue(serviceUrls.get(0).getIp().contains("30.10."));
+// List<URL> serviceUrls2 = listener.getAddresses(service2 + ":dubbo", consumerURL);
+// Assertions.assertEquals(4, serviceUrls2.size());
+// assertTrue(serviceUrls2.get(0).getIp().contains("30.10."));
+// List<URL> serviceUrls3 = listener.getAddresses(service3 + ":dubbo", consumerURL);
+// Assertions.assertEquals(2, serviceUrls3.size());
+// assertTrue(serviceUrls3.get(0).getIp().contains("30.10."));
+//
+// // app2 empty notification
+// ServiceInstancesChangedEvent app2_event_again = new ServiceInstancesChangedEvent("app2", Collections.EMPTY_LIST);
+// listener.onEvent(app2_event_again);
+//
+// // check app2 cleared
+// Map<String, List<ServiceInstance>> allInstances_app2 = listener.getAllInstances();
+// Assertions.assertEquals(2, allInstances_app2.size());
+// Assertions.assertEquals(0, allInstances_app2.get("app1").size());
+// Assertions.assertEquals(0, allInstances_app2.get("app2").size());
+//
+// Map<String, MetadataInfo> revisionToMetadata_app2 = listener.getRevisionToMetadata();
+// Assertions.assertEquals(0, revisionToMetadata_app2.size());
+//
+// assertTrue(isEmpty(listener.getAddresses(service1 + ":dubbo", consumerURL)));
- // assertTrue(isEmpty(listener.getAddresses(service2+ ":dubbo", consumerURL)));
++// assertTrue(isEmpty(listener.getAddresses(service2 + ":dubbo", consumerURL)));
+// assertTrue(isEmpty(listener.getAddresses(service3 + ":dubbo", consumerURL)));
+// }
+// }
+//
+// // 正常场景。检查instance listener -> service listener(Directory)地址推送流程
+// @Test
+// @Order(5)
+// public void testServiceListenerNotification() {
+// Set<String> serviceNames = new HashSet<>();
+// serviceNames.add("app1");
+// serviceNames.add("app2");
- // ServiceInstancesChangedListener listener = new ServiceInstancesChangedListener(serviceNames, serviceDiscovery);
++// listener = new ServiceInstancesChangedListener(serviceNames, serviceDiscovery);
+// NotifyListener demoServiceListener = Mockito.mock(NotifyListener.class);
+// NotifyListener demoService2Listener = Mockito.mock(NotifyListener.class);
+// listener.addListenerAndNotify(service1 + ":dubbo", demoServiceListener);
+// listener.addListenerAndNotify(service2 + ":dubbo", demoService2Listener);
+//
+// try (MockedStatic<MetadataUtils> mockedMetadataUtils = Mockito.mockStatic(MetadataUtils.class)) {
+// mockedMetadataUtils.when(() -> MetadataUtils.getMetadataServiceProxy(Mockito.any())).thenReturn(metadataService);
+// // notify app1 instance change
+// ServiceInstancesChangedEvent app1_event = new ServiceInstancesChangedEvent("app1", app1Instances);
+// listener.onEvent(app1_event);
+//
+// // check
+// ArgumentCaptor<List<URL>> captor = ArgumentCaptor.forClass(List.class);
+// Mockito.verify(demoServiceListener, Mockito.times(1)).notify(captor.capture());
+// List<URL> notifiedUrls = captor.getValue();
+// Assertions.assertEquals(3, notifiedUrls.size());
+// ArgumentCaptor<List<URL>> captor2 = ArgumentCaptor.forClass(List.class);
+// Mockito.verify(demoService2Listener, Mockito.times(1)).notify(captor2.capture());
+// List<URL> notifiedUrls2 = captor2.getValue();
+// Assertions.assertEquals(0, notifiedUrls2.size());
+//
+// // notify app2 instance change
+// ServiceInstancesChangedEvent app2_event = new ServiceInstancesChangedEvent("app2", app2Instances);
+// listener.onEvent(app2_event);
+//
+// // check
+// ArgumentCaptor<List<URL>> app2_captor = ArgumentCaptor.forClass(List.class);
+// Mockito.verify(demoServiceListener, Mockito.times(2)).notify(app2_captor.capture());
+// List<URL> app2_notifiedUrls = app2_captor.getValue();
+// Assertions.assertEquals(7, app2_notifiedUrls.size());
+// ArgumentCaptor<List<URL>> app2_captor2 = ArgumentCaptor.forClass(List.class);
+// Mockito.verify(demoService2Listener, Mockito.times(2)).notify(app2_captor2.capture());
+// List<URL> app2_notifiedUrls2 = app2_captor2.getValue();
+// Assertions.assertEquals(4, app2_notifiedUrls2.size());
+// }
+//
+// // test service listener still get notified when added after instance notification.
+// NotifyListener demoService3Listener = Mockito.mock(NotifyListener.class);
+// listener.addListenerAndNotify(service3 + ":dubbo", demoService3Listener);
+// Mockito.verify(demoService3Listener, Mockito.times(1)).notify(Mockito.anyList());
+// }
+//
+// // revision 异常场景。第一次启动,完全拿不到metadata,只能通知部分地址
+// @Test
+// @Order(6)
+// public void testRevisionFailureOnStartup() {
+// Set<String> serviceNames = new HashSet<>();
+// serviceNames.add("app1");
- // ServiceInstancesChangedListener listener = new ServiceInstancesChangedListener(serviceNames, serviceDiscovery);
++// listener = new ServiceInstancesChangedListener(serviceNames, serviceDiscovery);
+// try (MockedStatic<MetadataUtils> mockedMetadataUtils = Mockito.mockStatic(MetadataUtils.class)) {
+// mockedMetadataUtils.when(() -> MetadataUtils.getMetadataServiceProxy(Mockito.any())).thenReturn(metadataService);
+// // notify app1 instance change
+// ServiceInstancesChangedEvent failed_revision_event = new ServiceInstancesChangedEvent("app1", app1FailedInstances);
+// listener.onEvent(failed_revision_event);
+//
+// List<URL> serviceUrls = listener.getAddresses(service1 + ":dubbo", consumerURL);
+// List<URL> serviceUrls2 = listener.getAddresses(service2 + ":dubbo", consumerURL);
+//
+// assertTrue(isEmpty(serviceUrls));
+// assertTrue(isEmpty(serviceUrls2));
+//
+// Map<String, MetadataInfo> revisionToMetadata = listener.getRevisionToMetadata();
+// Assertions.assertEquals(2, revisionToMetadata.size());
+// Assertions.assertEquals(metadataInfo_222, revisionToMetadata.get("222"));
+// Assertions.assertEquals(MetadataInfo.EMPTY, revisionToMetadata.get("444"));
+// }
+// }
+//
+// // revision 异常场景。运行中地址通知,拿不到revision就用老版本revision
+// @Test
+// public void testRevisionFailureOnNotification() {
+// Set<String> serviceNames = new HashSet<>();
+// serviceNames.add("app1");
+// serviceNames.add("app2");
- // ServiceInstancesChangedListener listener = new ServiceInstancesChangedListener(serviceNames, serviceDiscovery);
++// listener = new ServiceInstancesChangedListener(serviceNames, serviceDiscovery);
+//
+// ConcurrentMap tmpProxyMap = MetadataUtils.metadataServiceProxies;
+//
+// try (MockedStatic<MetadataUtils> mockedMetadataUtils = Mockito.mockStatic(MetadataUtils.class)) {
+// mockedMetadataUtils.when(() -> MetadataUtils.getMetadataServiceProxy(Mockito.any())).thenReturn(metadataService);
+//
+// // notify app1 instance change
+// ServiceInstancesChangedEvent event = new ServiceInstancesChangedEvent("app1", app1Instances);
+// listener.onEvent(event);
+//
+// Mockito.when(metadataService.getMetadataInfo("222")).thenAnswer(new Answer<MetadataInfo>() {
// @Override
// public MetadataInfo answer(InvocationOnMock invocationOnMock) throws Throwable {
// if (Thread.currentThread().getName().contains("Dubbo-metadata-retry")) {
@@@ -423,100 -447,93 +438,102 @@@
// return null;
// }
// });
-
- ServiceInstancesChangedEvent event2 = new ServiceInstancesChangedEvent("app2", app1FailedInstances2);
- listener.onEvent(event2);
-
- // FIXME, manually mock proxy util, for retry task will work on another thread which makes MockStatic useless.
- ConcurrentMap map = Mockito.mock(ConcurrentMap.class);
- Mockito.doReturn(metadataService).when(map).get(Mockito.any());
- Mockito.doReturn(metadataService).when(map).computeIfAbsent(Mockito.any(), Mockito.any());
- MetadataUtils.metadataServiceProxies = map;
-
- // event2 did not really take effect
- Map<String, MetadataInfo> revisionToMetadata = listener.getRevisionToMetadata();
- Assertions.assertEquals(2, revisionToMetadata.size());
- Assertions.assertEquals(metadataInfo_111, revisionToMetadata.get("111"));
- Assertions.assertEquals(MetadataInfo.EMPTY, revisionToMetadata.get("222"));
-
- Assertions.assertEquals(3, listener.getAddresses(service1 + ":dubbo", consumerURL).size());
- assertTrue(isEmpty(listener.getAddresses(service2 + ":dubbo", consumerURL)));
-
- try {
- Thread.sleep(15000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- // check recovered after retry.
- Map<String, MetadataInfo> revisionToMetadata_after_retry = listener.getRevisionToMetadata();
- Assertions.assertEquals(2, revisionToMetadata_after_retry.size());
- Assertions.assertEquals(metadataInfo_111, revisionToMetadata_after_retry.get("111"));
- Assertions.assertEquals(metadataInfo_222, revisionToMetadata_after_retry.get("222"));
-
- List<URL> serviceUrls_after_retry = listener.getAddresses(service1 + ":dubbo", consumerURL);
- Assertions.assertEquals(5, serviceUrls_after_retry.size());
- List<URL> serviceUrls2_after_retry = listener.getAddresses(service2 + ":dubbo", consumerURL);
- Assertions.assertEquals(2, serviceUrls2_after_retry.size());
- } finally {
- MetadataUtils.metadataServiceProxies = tmpProxyMap;
- }
- }
-
- // Abnormal case. Instance does not has revision
- @Test
- public void testInstanceWithoutRevision() {
- Set<String> serviceNames = new HashSet<>();
- serviceNames.add("app1");
- ServiceDiscovery serviceDiscovery = Mockito.mock(ServiceDiscovery.class);
- listener = new ServiceInstancesChangedListener(serviceNames, serviceDiscovery);
- ServiceInstancesChangedListener spyListener = Mockito.spy(listener);
- Mockito.doReturn(null).when(spyListener).getRemoteMetadata(eq(null), Mockito.anyMap(), Mockito.any());
- ServiceInstancesChangedEvent event = new ServiceInstancesChangedEvent("app1", app1InstancesWithNoRevision);
- spyListener.onEvent(event);
- // notification succeeded
- assertTrue(true);
- }
-
- @Test
- public void testSelectInstance() {
- System.out.println(ThreadLocalRandom.current().nextInt(0, 100));
- System.out.println(ThreadLocalRandom.current().nextInt(0, 100));
- System.out.println(ThreadLocalRandom.current().nextInt(0, 100));
- System.out.println(ThreadLocalRandom.current().nextInt(0, 100));
- System.out.println(ThreadLocalRandom.current().nextInt(0, 100));
- }
-
- static List<ServiceInstance> buildInstances(List<Object> rawURls) {
- List<ServiceInstance> instances = new ArrayList<>();
-
- for (Object obj : rawURls) {
- String rawURL = (String) obj;
- DefaultServiceInstance instance = new DefaultServiceInstance();
- final URL dubboUrl = URL.valueOf(rawURL);
- instance.setRawAddress(rawURL);
- instance.setHost(dubboUrl.getHost());
- instance.setEnabled(true);
- instance.setHealthy(true);
- instance.setPort(dubboUrl.getPort());
- instance.setRegistryCluster("default");
- instance.setApplicationModel(ApplicationModel.defaultModel());
-
- Map<String, String> metadata = new HashMap<>();
- if (StringUtils.isNotEmpty(dubboUrl.getParameter(REVISION_KEY))) {
- metadata.put(EXPORTED_SERVICES_REVISION_PROPERTY_NAME, dubboUrl.getParameter(REVISION_KEY));
- }
- instance.setMetadata(metadata);
-
- instances.add(instance);
- }
-
- return instances;
- }
-}
+//// Mockito.when(metadataService.getMetadataInfo("444")).thenAnswer(new Answer<MetadataInfo>() {
+//// @Override
+//// public MetadataInfo answer(InvocationOnMock invocationOnMock) throws Throwable {
+//// if (Thread.currentThread().getName().contains("Dubbo-metadata-retry")) {
+//// return metadataInfo_444;
+//// }
+//// return null;
+//// }
+//// });
+//
+// ServiceInstancesChangedEvent event2 = new ServiceInstancesChangedEvent("app2", app1FailedInstances2);
+// listener.onEvent(event2);
+//
+// // FIXME, manually mock proxy util, for retry task will work on another thread which makes MockStatic useless.
+// ConcurrentMap map = Mockito.mock(ConcurrentMap.class);
+// Mockito.doReturn(metadataService).when(map).get(Mockito.any());
+// Mockito.doReturn(metadataService).when(map).computeIfAbsent(Mockito.any(), Mockito.any());
+// MetadataUtils.metadataServiceProxies = map;
+//
+// // event2 did not really take effect
+// Map<String, MetadataInfo> revisionToMetadata = listener.getRevisionToMetadata();
+// Assertions.assertEquals(2, revisionToMetadata.size());
+// Assertions.assertEquals(metadataInfo_111, revisionToMetadata.get("111"));
+// Assertions.assertEquals(MetadataInfo.EMPTY, revisionToMetadata.get("222"));
+//
+// Assertions.assertEquals(3, listener.getAddresses(service1 + ":dubbo", consumerURL).size());
+// assertTrue(isEmpty(listener.getAddresses(service2 + ":dubbo", consumerURL)));
+//
+// try {
+// Thread.sleep(15000);
+// } catch (InterruptedException e) {
+// e.printStackTrace();
+// }
+// // check recovered after retry.
+// Map<String, MetadataInfo> revisionToMetadata_after_retry = listener.getRevisionToMetadata();
+// Assertions.assertEquals(2, revisionToMetadata_after_retry.size());
+// Assertions.assertEquals(metadataInfo_111, revisionToMetadata_after_retry.get("111"));
+// Assertions.assertEquals(metadataInfo_222, revisionToMetadata_after_retry.get("222"));
+//
+// List<URL> serviceUrls_after_retry = listener.getAddresses(service1 + ":dubbo", consumerURL);
+// Assertions.assertEquals(5, serviceUrls_after_retry.size());
+// List<URL> serviceUrls2_after_retry = listener.getAddresses(service2 + ":dubbo", consumerURL);
+// Assertions.assertEquals(2, serviceUrls2_after_retry.size());
+// } finally {
+// MetadataUtils.metadataServiceProxies = tmpProxyMap;
+// }
+// }
+//
+// // Abnormal case. Instance does not has revision
+// @Test
+// public void testInstanceWithoutRevision() {
+// Set<String> serviceNames = new HashSet<>();
+// serviceNames.add("app1");
+// ServiceDiscovery serviceDiscovery = Mockito.mock(ServiceDiscovery.class);
- // ServiceInstancesChangedListener spyListener = Mockito.spy(new ServiceInstancesChangedListener(serviceNames, serviceDiscovery));
++// listener = new ServiceInstancesChangedListener(serviceNames, serviceDiscovery);
++// ServiceInstancesChangedListener spyListener = Mockito.spy(listener);
+// Mockito.doReturn(null).when(spyListener).getRemoteMetadata(eq(null), Mockito.anyMap(), Mockito.any());
+// ServiceInstancesChangedEvent event = new ServiceInstancesChangedEvent("app1", app1InstancesWithNoRevision);
+// spyListener.onEvent(event);
+// // notification succeeded
+// assertTrue(true);
+// }
+//
+// @Test
+// public void testSelectInstance() {
+// System.out.println(ThreadLocalRandom.current().nextInt(0, 100));
+// System.out.println(ThreadLocalRandom.current().nextInt(0, 100));
+// System.out.println(ThreadLocalRandom.current().nextInt(0, 100));
+// System.out.println(ThreadLocalRandom.current().nextInt(0, 100));
+// System.out.println(ThreadLocalRandom.current().nextInt(0, 100));
+// }
+//
+// static List<ServiceInstance> buildInstances(List<Object> rawURls) {
+// List<ServiceInstance> instances = new ArrayList<>();
+//
+// for (Object obj : rawURls) {
- // String rawURL = (String)obj;
++// String rawURL = (String) obj;
+// DefaultServiceInstance instance = new DefaultServiceInstance();
+// final URL dubboUrl = URL.valueOf(rawURL);
+// instance.setRawAddress(rawURL);
+// instance.setHost(dubboUrl.getHost());
+// instance.setEnabled(true);
+// instance.setHealthy(true);
+// instance.setPort(dubboUrl.getPort());
+// instance.setRegistryCluster("default");
++// instance.setApplicationModel(ApplicationModel.defaultModel());
+//
+// Map<String, String> metadata = new HashMap<>();
+// if (StringUtils.isNotEmpty(dubboUrl.getParameter(REVISION_KEY))) {
+// metadata.put(EXPORTED_SERVICES_REVISION_PROPERTY_NAME, dubboUrl.getParameter(REVISION_KEY));
+// }
+// instance.setMetadata(metadata);
+//
+// instances.add(instance);
+// }
+//
+// return instances;
+// }
+//}
diff --cc dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboProtocol.java
index 3545e6a,eed8192..058c009
--- a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboProtocol.java
+++ b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboProtocol.java
@@@ -639,11 -638,10 +639,12 @@@ public class DubboProtocol extends Abst
ExchangeClient client;
try {
+ // Replace InstanceAddressURL with ServiceConfigURL.
- url = new ServiceConfigURL(url.getProtocol(), url.getUsername(), url.getPassword(), url.getHost(), url.getPort(), url.getPath(), url.getParameters());
++ url = new ServiceConfigURL(DubboCodec.NAME, url.getUsername(), url.getPassword(), url.getHost(), url.getPort(), url.getPath(), url.getParameters());
// connection should be lazy
if (url.getParameter(LAZY_CONNECT_KEY, false)) {
- client = new LazyConnectExchangeClient(url, requestHandler);
+ client = new LazyConnectExchangeClient(url, requestHandler, DubboCodec.NAME, url.getParameters());
+
} else {
client = Exchangers.connect(url, requestHandler);
}
diff --cc dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/LazyConnectExchangeClient.java
index c3abca2,a5bb837..87fba37
--- a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/LazyConnectExchangeClient.java
+++ b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/LazyConnectExchangeClient.java
@@@ -57,11 -59,14 +57,11 @@@ final class LazyConnectExchangeClient i
*/
private final boolean initialState;
private volatile ExchangeClient client;
- private AtomicLong warningCount = new AtomicLong(0);
+ private final AtomicLong warningCount = new AtomicLong(0);
- public LazyConnectExchangeClient(URL url, ExchangeHandler requestHandler, String codec, Map<String, String> parameters) {
+ public LazyConnectExchangeClient(URL url, ExchangeHandler requestHandler) {
// lazy connect, need set send.reconnect = true, to avoid channel bad status.
- // Parameters like 'username', 'password' and 'path' are set but will not be used in following processes.
- // The most important parameters here are 'host', port', 'parameters' and 'codec', 'codec' can also be extracted from 'parameters'
- this.url = new ServiceConfigURL(codec, url.getUsername(), url.getPassword(), url.getHost(), url.getPort(), url.getPath(), parameters)
- .addParameter(SEND_RECONNECT_KEY, Boolean.TRUE.toString());
+ this.url = url.addParameter(SEND_RECONNECT_KEY, Boolean.TRUE.toString());
this.requestHandler = requestHandler;
this.initialState = url.getParameter(LAZY_CONNECT_INITIAL_STATE_KEY, DEFAULT_LAZY_CONNECT_INITIAL_STATE);
this.requestWithWarning = url.getParameter(LAZY_REQUEST_WITH_WARNING_KEY, DEFAULT_LAZY_REQUEST_WITH_WARNING);