You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@dubbo.apache.org by me...@apache.org on 2019/08/16 06:31:51 UTC

[dubbo] branch cloud-native updated: Dubbo cloud native (#4850)

This is an automated email from the ASF dual-hosted git repository.

mercyblitz pushed a commit to branch cloud-native
in repository https://gitbox.apache.org/repos/asf/dubbo.git


The following commit(s) were added to refs/heads/cloud-native by this push:
     new 2a93324  Dubbo cloud native (#4850)
2a93324 is described below

commit 2a93324e3b671d4a00f9510ec2c1b83298da96de
Author: Mercy Ma <me...@gmail.com>
AuthorDate: Fri Aug 16 14:31:45 2019 +0800

    Dubbo cloud native (#4850)
    
    * Polish apache/dubbo#4542 : [Enhancement] Adapt the Java standard Event/Listener mechanism
    
    * Polish apache/dubbo#4541 : [Feature] Add local File System DynamicConfigurationFactory‘s extension
    
    * Polish apache#4541 : Bugfix
    
    * Polish apache/dubbo#4541 : Optimization
    
    * Polish apache/dubbo#4541 : Add the compatibility for PollingWatchService on the some platforms
    
    * Polish apache/dubbo#4541 : Add delay publish without ThreadPoolExecutor
    
    * Polish apache/dubbo#4541 : Refactor the extension name
    
    * Polish apache/dubbo#4541 : Add remove ops
    
    * Polish apache/dubbo#4541 : Add testable constructor
    
    * Polish apache/dubbo#4541 : Add getConfigGroups method
    
    * Polish apache/dubbo#4610 : [Refactor] Refactor the bootstrap module
    
    * Polish apache/dubbo#4541 : Fix the nulling URL issue
    
    * Polish apache/dubbo#4622 : [Refactor] Refactor ConfigManager
    
    * Polish apache/dubbo#4622 : [Refactor] Refactor ConfigManager
    
    * Polish apache/dubbo#4622 : Support multiple configcenters
    
    * Polish apache/dubbo#4671 : ServiceNameMapping will not map the group, version and protocol
    
    * update referenceCount log (#4683)
    
    Add comments to support multiple shared connections
    
    * Polish /apache/dubbo#4687 : Remove the duplicated test code in dubbo-config-spring (#4688)
    
    * #4685  修改代码if判断false问题 if (hasException == false)修改成if (!hasException) (#4695)
    
    * Fixed Service annotation method parameters are not in effect (#4598)
    
    * keep demo simple, and switch to use zookeeper as registry center (#4705)
    
    * keep demo simple, and switch to use zookeeper as registry center
    
    * remove comment
    
    * @Reference auto-wires the instance of generic interface #4594 (#4677)
    
    * try to shorten maven output to make travis build pass (#4710)
    
    * use CountDownLatch to check zk registry if establish connection (#4589)
    
    * Minor change
    
    * Rename the extension name of WritableMetadataService
    
    * Polish apache/dubbo#4759 : [Refactor] Change the signature of methods of MetadataService #4759
    
    * Merge remote-tracking branch 'upstream/master' into dubbo-cloud-native
    
    # Conflicts:
    #	dubbo-all/pom.xml
    #	dubbo-bom/pom.xml
    #	dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractInterfaceConfig.java
    #	dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ApplicationConfig.java
    #	dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ConfigCenterConfig.java
    #	dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ReferenceConfig.java
    #	dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/RegistryConfig.java
    #	dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ServiceConfig.java
    #	dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/ReferenceConfigTest.java
    #	dubbo-configcenter/dubbo-configcenter-api/src/main/java/org/apache/dubbo/configcenter/DynamicConfiguration.java
    #	dubbo-configcenter/dubbo-configcenter-api/src/test/java/org/apache/dubbo/configcenter/mock/MockDynamicConfiguration.java
    #	dubbo-configcenter/dubbo-configcenter-consul/src/main/java/org/apache/dubbo/configcenter/consul/ConsulDynamicConfiguration.java
    #	dubbo-configcenter/dubbo-configcenter-etcd/src/test/java/org/apache/dubbo/configcenter/support/etcd/EtcdDynamicConfigurationTest.java
    #	dubbo-configcenter/dubbo-configcenter-nacos/src/main/java/org/apache/dubbo/configcenter/support/nacos/NacosDynamicConfiguration.java
    #	dubbo-configcenter/dubbo-configcenter-nacos/src/test/java/org/apache/dubbo/configcenter/support/nacos/NacosDynamicConfigurationTest.java
    #	dubbo-configcenter/dubbo-configcenter-zookeeper/src/main/java/org/apache/dubbo/configcenter/support/zookeeper/ZookeeperDynamicConfiguration.java
    #	dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/definition/model/MethodDefinition.java
    #	dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/identifier/MetadataIdentifier.java
    #	dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/support/AbstractMetadataReport.java
    #	dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/report/identifier/MetadataIdentifierTest.java
    #	dubbo-metadata/dubbo-metadata-definition-protobuf/src/main/java/org/apache/dubbo/metadata/definition/protobuf/ProtobufTypeBuilder.java
    #	dubbo-metadata/dubbo-metadata-definition-protobuf/src/test/java/org/apache/dubbo/metadata/definition/protobuf/ProtobufTypeBuilderTest.java
    #	dubbo-metadata/pom.xml
    #	dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/AbstractConfiguratorListener.java
    #	dubbo-registry/dubbo-registry-nacos/src/main/java/org/apache/dubbo/registry/nacos/NacosRegistry.java
    #	dubbo-registry/dubbo-registry-nacos/src/main/java/org/apache/dubbo/registry/nacos/NacosRegistryFactory.java
    #	dubbo-rpc/dubbo-rpc-xml/src/main/java/org/apache/dubbo/xml/rpc/protocol/xmlrpc/XmlRpcProtocol.java
    
    * Polish apache/dubbo#3984 : Add the implementation of Page<ServiceInstance> getInstances(String serviceName, int offset, int pageSize, boolean healthyOnly)
    
    * Code merge
    
    * Fix the cases
    
    * Merge remote-tracking branch 'upstream/cloud-native' into dubbo-cloud-native
    
    # Conflicts:
    #	dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/DubboServiceProviderBootstrap.java
    #	dubbo-metadata/dubbo-metadata-definition-protobuf/pom.xml
    #	dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/support/ServiceOrientedRegistryTest.java
    #	dubbo-registry/dubbo-registry-consul/src/main/java/org/apache/dubbo/registry/consul/ConsulServiceDiscoveryFactory.java
    #	dubbo-registry/dubbo-registry-etcd3/src/main/java/org/apache/dubbo/registry/etcd/EtcdServiceDiscovery.java
    
    * Refactor ConfigManager
    
    * Refactor ConfigManager
    
    * Resolve the issues on ConfigManager
    
    * Refactor and add test-cases for ConfigManager
    
    * Polish apache/dubbo#4774 : [Feature] Dubbo Cloud Native - To Support in Spring
    
    * Polish apache/dubbo#4808 : [Feature] Add the registered/unregistered event mechanism ShutdownHook
    
    * Polish apache/dubbo#4807 : [Feature] Add the callback mechanism ShutdownHook #4807
    
    * Polish apache/dubbo#4813 : [Feature] add Prioritized implementation for ServiceInstanceCustomizer
    
    * Polish apache/dubbo#4815 : [Feature] Add the ServiceLoader for Dubbo's services or components
    
    * Polish apache/dubbo#4815 : [Feature] Add the ServiceLoader for Dubbo's services or components
    
    * Polish apache/dubbo#4813 : [Feature] add Prioritized implementation for ServiceInstanceCustomizer
    
    * Polish apache/dubbo#4807 : Add sort implementation
    
    * Refactor
    
    * Refactor
    
    * Polish apache/dubbo#4845 : [Feature] Enhance the Event-Publishing feature to original ServiceDiscovery
    
    * Merge remote-tracking branch 'upstream/cloud-native' into dubbo-cloud-native
    
    # Conflicts:
    #	dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/DefaultServiceDiscoveryFactory.java
    #	dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistry.java
---
 .../org/apache/dubbo/bootstrap/DubboBootstrap.java | 238 +++++++++++----------
 .../client/AbstractServiceDiscoveryFactory.java    |  43 +---
 .../client/DefaultServiceDiscoveryFactory.java     |   1 +
 .../client/EventPublishingServiceDiscovery.java    |  10 +-
 .../event/ServiceDiscoveryDestroyedEvent.java      |  10 +-
 .../event/ServiceDiscoveryDestroyingEvent.java     |  10 +-
 .../client/event/ServiceDiscoveryEvent.java        |  26 ++-
 .../event/ServiceDiscoveryExceptionEvent.java      |  10 +-
 .../event/ServiceDiscoveryInitializedEvent.java    |  11 +-
 .../event/ServiceDiscoveryInitializingEvent.java   |  10 +-
 .../event/listener/LoggingEventListenerTest.java   |   8 +-
 11 files changed, 180 insertions(+), 197 deletions(-)

diff --git a/dubbo-bootstrap/src/main/java/org/apache/dubbo/bootstrap/DubboBootstrap.java b/dubbo-bootstrap/src/main/java/org/apache/dubbo/bootstrap/DubboBootstrap.java
index 4ad5512..b7df466 100644
--- a/dubbo-bootstrap/src/main/java/org/apache/dubbo/bootstrap/DubboBootstrap.java
+++ b/dubbo-bootstrap/src/main/java/org/apache/dubbo/bootstrap/DubboBootstrap.java
@@ -49,14 +49,15 @@ import org.apache.dubbo.config.metadata.ConfigurableMetadataServiceExporter;
 import org.apache.dubbo.config.utils.ReferenceConfigCache;
 import org.apache.dubbo.event.EventDispatcher;
 import org.apache.dubbo.event.EventListener;
+import org.apache.dubbo.event.GenericEventListener;
 import org.apache.dubbo.metadata.MetadataService;
 import org.apache.dubbo.metadata.MetadataServiceExporter;
 import org.apache.dubbo.metadata.WritableMetadataService;
 import org.apache.dubbo.metadata.report.MetadataReportInstance;
-import org.apache.dubbo.registry.client.AbstractServiceDiscoveryFactory;
 import org.apache.dubbo.registry.client.DefaultServiceInstance;
 import org.apache.dubbo.registry.client.ServiceDiscovery;
 import org.apache.dubbo.registry.client.ServiceInstance;
+import org.apache.dubbo.registry.client.event.ServiceDiscoveryInitializingEvent;
 
 import java.io.IOException;
 import java.util.ArrayList;
@@ -65,6 +66,7 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Set;
 import java.util.SortedSet;
+import java.util.concurrent.ConcurrentSkipListSet;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.locks.Condition;
@@ -77,6 +79,7 @@ import static java.util.concurrent.Executors.newSingleThreadExecutor;
 import static org.apache.dubbo.common.config.ConfigurationUtils.parseProperties;
 import static org.apache.dubbo.common.config.configcenter.DynamicConfiguration.getDynamicConfiguration;
 import static org.apache.dubbo.common.constants.CommonConstants.METADATA_REMOTE;
+import static org.apache.dubbo.common.function.ThrowableAction.execute;
 import static org.apache.dubbo.common.utils.StringUtils.isNotEmpty;
 import static org.apache.dubbo.config.context.ConfigManager.getInstance;
 import static org.apache.dubbo.metadata.WritableMetadataService.getExtension;
@@ -88,7 +91,7 @@ import static org.apache.dubbo.remoting.Constants.CLIENT_KEY;
  *
  * @since 2.7.4
  */
-public class DubboBootstrap implements Lifecycle {
+public class DubboBootstrap extends GenericEventListener implements Lifecycle {
 
     public static final String DEFAULT_REGISTRY_ID = "REGISTRY#DEFAULT";
 
@@ -137,11 +140,23 @@ public class DubboBootstrap implements Lifecycle {
 
     private volatile MetadataServiceExporter metadataServiceExporter;
 
+    private SortedSet<ServiceDiscovery> serviceDiscoveries = new ConcurrentSkipListSet<>();
+
     public DubboBootstrap() {
         DubboShutdownHook.getDubboShutdownHook().register();
     }
 
     /**
+     * Store the {@link ServiceDiscovery} instances into {@link ServiceDiscoveryInitializingEvent}
+     *
+     * @param event {@link ServiceDiscoveryInitializingEvent}
+     * @see {@linkplan org.apache.dubbo.registry.client.EventPublishingServiceDiscovery}
+     */
+    public void onServiceDiscoveryInitializing(ServiceDiscoveryInitializingEvent event) {
+        serviceDiscoveries.add(event.getSource());
+    }
+
+    /**
      * Set only register provider or not
      *
      * @param onlyRegisterProvider if <code>true</code>, only register the provider and reduce the registries' load.
@@ -440,6 +455,8 @@ public class DubboBootstrap implements Lifecycle {
 
             initMetadataServiceExporter();
 
+            initEventListener();
+
             initialized = true;
 
             if (logger.isInfoEnabled()) {
@@ -451,22 +468,74 @@ public class DubboBootstrap implements Lifecycle {
         return this;
     }
 
-    /**
-     * Initialize {@link MetadataService} from {@link WritableMetadataService}'s extension
-     */
-    private void initMetadataService() {
-        this.metadataService = getExtension(isDefaultMetadataStorageType());
+    private void startConfigCenter() {
+        Collection<ConfigCenterConfig> configCenters = configManager.getConfigCenters();
+
+        if (CollectionUtils.isNotEmpty(configCenters)) {
+            CompositeDynamicConfiguration compositeDynamicConfiguration = new CompositeDynamicConfiguration();
+            for (ConfigCenterConfig configCenter : configCenters) {
+                configCenter.refresh();
+                compositeDynamicConfiguration.addConfiguration(prepareEnvironment(configCenter));
+            }
+            Environment.getInstance().setDynamicConfiguration(compositeDynamicConfiguration);
+        }
+        configManager.refreshAll();
+    }
+
+    private void startMetadataReport() {
+        ApplicationConfig applicationConfig = configManager.getApplication().orElseThrow(
+                () -> new IllegalStateException("There's no ApplicationConfig specified.")
+        );
+
+        String metadataType = applicationConfig.getMetadata();
+        // FIXME, multiple metadata config support.
+        Collection<MetadataReportConfig> metadataReportConfigs = configManager.getMetadataConfigs();
+        if (CollectionUtils.isEmpty(metadataReportConfigs)) {
+            if (METADATA_REMOTE.equals(metadataType)) {
+                throw new IllegalStateException("No MetadataConfig found, you must specify the remote Metadata Center address when set 'metadata=remote'.");
+            }
+            return;
+        }
+        MetadataReportConfig metadataReportConfig = metadataReportConfigs.iterator().next();
+        if (!metadataReportConfig.isValid()) {
+            return;
+        }
+
+        MetadataReportInstance.init(metadataReportConfig.toUrl());
     }
 
     /**
-     * Initialize {@link MetadataServiceExporter}
+     * For compatibility purpose, use registry as the default config center when the registry protocol is zookeeper and
+     * there's no config center specified explicitly.
      */
-    private void initMetadataServiceExporter() {
-        this.metadataServiceExporter = new ConfigurableMetadataServiceExporter()
-                .setApplicationConfig(getApplication())
-                .setRegistries(configManager.getRegistries())
-                .setProtocols(configManager.getProtocols())
-                .metadataService(metadataService);
+    private void useRegistryAsConfigCenterIfNecessary() {
+        // we use the loading status of DynamicConfiguration to decide whether ConfigCenter has been initiated.
+        if (Environment.getInstance().getDynamicConfiguration().isPresent()) {
+            return;
+        }
+
+        if (CollectionUtils.isNotEmpty(configManager.getConfigCenters())) {
+            return;
+        }
+
+        configManager.getDefaultRegistries().stream()
+                .filter(registryConfig -> registryConfig.getUseAsConfigCenter() == null || registryConfig.getUseAsConfigCenter())
+                .forEach(registryConfig -> {
+                    String protocol = registryConfig.getProtocol();
+                    String id = "config-center-" + protocol + "-" + registryConfig.getPort();
+                    ConfigCenterConfig cc = new ConfigCenterConfig();
+                    cc.setId(id);
+                    cc.setParameters(registryConfig.getParameters() == null ?
+                            new HashMap<>() :
+                            new HashMap<>(registryConfig.getParameters()));
+                    cc.getParameters().put(CLIENT_KEY, registryConfig.getClient());
+                    cc.setProtocol(registryConfig.getProtocol());
+                    cc.setAddress(registryConfig.getAddress());
+                    cc.setNamespace(registryConfig.getGroup());
+                    cc.setHighestPriority(false);
+                    configManager.addConfigCenter(cc);
+                });
+        startConfigCenter();
     }
 
     private void loadRemoteConfigs() {
@@ -503,42 +572,35 @@ public class DubboBootstrap implements Lifecycle {
         configManager.addProtocols(tmpProtocols);
     }
 
+
     /**
-     * For compatibility purpose, use registry as the default config center when the registry protocol is zookeeper and
-     * there's no config center specified explicitly.
+     * Initialize {@link MetadataService} from {@link WritableMetadataService}'s extension
      */
-    private void useRegistryAsConfigCenterIfNecessary() {
-        // we use the loading status of DynamicConfiguration to decide whether ConfigCenter has been initiated.
-        if (Environment.getInstance().getDynamicConfiguration().isPresent()) {
-            return;
-        }
+    private void initMetadataService() {
+        this.metadataService = getExtension(isDefaultMetadataStorageType());
+    }
 
-        if (CollectionUtils.isNotEmpty(configManager.getConfigCenters())) {
-            return;
-        }
+    /**
+     * Initialize {@link MetadataServiceExporter}
+     */
+    private void initMetadataServiceExporter() {
+        this.metadataServiceExporter = new ConfigurableMetadataServiceExporter()
+                .setApplicationConfig(getApplication())
+                .setRegistries(configManager.getRegistries())
+                .setProtocols(configManager.getProtocols())
+                .metadataService(metadataService);
+    }
 
-        configManager.getDefaultRegistries().stream()
-                .filter(registryConfig -> registryConfig.getUseAsConfigCenter() == null || registryConfig.getUseAsConfigCenter())
-                .forEach(registryConfig -> {
-                    String protocol = registryConfig.getProtocol();
-                    String id = "config-center-" + protocol + "-" + registryConfig.getPort();
-                    ConfigCenterConfig cc = new ConfigCenterConfig();
-                    cc.setId(id);
-                    cc.setParameters(registryConfig.getParameters() == null ?
-                            new HashMap<>() :
-                            new HashMap<>(registryConfig.getParameters()));
-                    cc.getParameters().put(CLIENT_KEY, registryConfig.getClient());
-                    cc.setProtocol(registryConfig.getProtocol());
-                    cc.setAddress(registryConfig.getAddress());
-                    cc.setNamespace(registryConfig.getGroup());
-                    cc.setHighestPriority(false);
-                    configManager.addConfigCenter(cc);
-                });
-        startConfigCenter();
+    /**
+     * Initialize {@link EventListener}
+     */
+    private void initEventListener() {
+        // Add current instance into listeners
+        addEventListener(this);
     }
 
     private Collection<ServiceDiscovery> getServiceDiscoveries() {
-        return AbstractServiceDiscoveryFactory.getDiscoveries();
+        return serviceDiscoveries;
     }
 
     /**
@@ -631,8 +693,8 @@ public class DubboBootstrap implements Lifecycle {
     public boolean isStarted() {
         return started;
     }
-
     /* serve for builder apis, begin */
+
     private ApplicationBuilder createApplicationBuilder(String name) {
         return new ApplicationBuilder().name(name);
     }
@@ -660,43 +722,7 @@ public class DubboBootstrap implements Lifecycle {
     private ConsumerBuilder createConsumerBuilder(String id) {
         return new ConsumerBuilder().id(id);
     }
-
     /* serve for builder apis, end */
-    private void startMetadataReport() {
-        ApplicationConfig applicationConfig = configManager.getApplication().orElseThrow(
-                () -> new IllegalStateException("There's no ApplicationConfig specified.")
-        );
-
-        String metadataType = applicationConfig.getMetadata();
-        // FIXME, multiple metadata config support.
-        Collection<MetadataReportConfig> metadataReportConfigs = configManager.getMetadataConfigs();
-        if (CollectionUtils.isEmpty(metadataReportConfigs)) {
-            if (METADATA_REMOTE.equals(metadataType)) {
-                throw new IllegalStateException("No MetadataConfig found, you must specify the remote Metadata Center address when set 'metadata=remote'.");
-            }
-            return;
-        }
-        MetadataReportConfig metadataReportConfig = metadataReportConfigs.iterator().next();
-        if (!metadataReportConfig.isValid()) {
-            return;
-        }
-
-        MetadataReportInstance.init(metadataReportConfig.toUrl());
-    }
-
-    private void startConfigCenter() {
-        Collection<ConfigCenterConfig> configCenters = configManager.getConfigCenters();
-
-        if (CollectionUtils.isNotEmpty(configCenters)) {
-            CompositeDynamicConfiguration compositeDynamicConfiguration = new CompositeDynamicConfiguration();
-            for (ConfigCenterConfig configCenter : configCenters) {
-                configCenter.refresh();
-                compositeDynamicConfiguration.addConfiguration(prepareEnvironment(configCenter));
-            }
-            Environment.getInstance().setDynamicConfiguration(compositeDynamicConfiguration);
-        }
-        configManager.refreshAll();
-    }
 
     private DynamicConfiguration prepareEnvironment(ConfigCenterConfig configCenter) {
         if (configCenter.isValid()) {
@@ -777,7 +803,7 @@ public class DubboBootstrap implements Lifecycle {
 
         int port = exportedURL.getPort();
 
-        ServiceInstance serviceInstance = initServiceInstance(serviceName, host, port);
+        ServiceInstance serviceInstance = createServiceInstance(serviceName, host, port);
 
         getServiceDiscoveries().forEach(serviceDiscovery -> serviceDiscovery.register(serviceInstance));
     }
@@ -801,42 +827,15 @@ public class DubboBootstrap implements Lifecycle {
         return selectedURL;
     }
 
-    /**
-     * Use rest protocol if there's one, otherwise, choose the first one available.
-     *
-     * @return
-     */
-    private String findOneProtocolForServiceInstance(Set<String> protocols) {
-        String result = null;
-        for (String protocol : protocols) {
-            if ("rest".equalsIgnoreCase(protocol)) {
-                result = protocol;
-                break;
-            }
-        }
-
-        if (result == null) {
-            for (String protocol : protocols) {
-                if (!"injvm".equalsIgnoreCase(protocol) && "registry".equalsIgnoreCase(protocol)) {
-                    result = protocol;
-                    break;
-                }
-            }
-        }
-        return result;
-    }
-
     private void unregisterServiceInstance() {
-
         if (serviceInstance != null) {
             getServiceDiscoveries().forEach(serviceDiscovery -> {
                 serviceDiscovery.unregister(serviceInstance);
             });
         }
-
     }
 
-    private ServiceInstance initServiceInstance(String serviceName, String host, int port) {
+    private ServiceInstance createServiceInstance(String serviceName, String host, int port) {
         this.serviceInstance = new DefaultServiceInstance(serviceName, host, port);
         setMetadataStorageType(serviceInstance, isDefaultMetadataStorageType());
         return this.serviceInstance;
@@ -850,6 +849,8 @@ public class DubboBootstrap implements Lifecycle {
 
         destroyReferences();
 
+        destroyServiceDiscoveries();
+
         clear();
 
         release();
@@ -871,8 +872,20 @@ public class DubboBootstrap implements Lifecycle {
         }
     }
 
+    private void destroyServiceDiscoveries() {
+        getServiceDiscoveries().forEach(serviceDiscovery -> {
+            execute(() -> {
+                serviceDiscovery.destroy();
+            });
+        });
+        if (logger.isDebugEnabled()) {
+            logger.debug(NAME + "'s all ServiceDiscoveries have been destroyed.");
+        }
+    }
+
     private void clear() {
         clearConfigs();
+        clearServiceDiscoveries();
     }
 
     private void clearConfigs() {
@@ -882,6 +895,13 @@ public class DubboBootstrap implements Lifecycle {
         }
     }
 
+    private void clearServiceDiscoveries() {
+        serviceDiscoveries.clear();
+        if (logger.isDebugEnabled()) {
+            logger.debug(NAME + "'s serviceDiscoveries have been clear.");
+        }
+    }
+
     private void release() {
         executeMutually(() -> {
             while (awaited.compareAndSet(false, true)) {
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/AbstractServiceDiscoveryFactory.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/AbstractServiceDiscoveryFactory.java
index b8d941b..f5fc291 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/AbstractServiceDiscoveryFactory.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/AbstractServiceDiscoveryFactory.java
@@ -17,51 +17,26 @@
 package org.apache.dubbo.registry.client;
 
 import org.apache.dubbo.common.URL;
-import org.apache.dubbo.common.logger.Logger;
-import org.apache.dubbo.common.logger.LoggerFactory;
 
-import java.util.Collection;
-import java.util.Collections;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 
+/**
+ * Abstract {@link ServiceDiscoveryFactory} implementation with cache, the subclass
+ * should implement {@link #createDiscovery(URL)} method to create an instance of {@link ServiceDiscovery}
+ *
+ * @see ServiceDiscoveryFactory
+ * @since 2.7.4
+ */
 public abstract class AbstractServiceDiscoveryFactory implements ServiceDiscoveryFactory {
 
-    private static final Logger logger = LoggerFactory.getLogger(AbstractServiceDiscoveryFactory.class);
-
-    private static ConcurrentMap<String, ServiceDiscovery> discoveries = new ConcurrentHashMap<>();
-
-    public static Collection<ServiceDiscovery> getDiscoveries() {
-        return Collections.unmodifiableCollection(discoveries.values());
-    }
-
-    /**
-     * Close all created registries
-     */
-    public static void destroyAll() {
-        if (logger.isInfoEnabled()) {
-            logger.info("Closing all ServiceDiscovery instances: " + getDiscoveries());
-        }
-
-        for (ServiceDiscovery discovery : getDiscoveries()) {
-            try {
-                discovery.destroy();
-            } catch (Throwable e) {
-                logger.error("Error trying to close ServiceDiscovery instance.", e);
-            }
-        }
-        discoveries.clear();
-    }
+    private final ConcurrentMap<String, ServiceDiscovery> discoveries = new ConcurrentHashMap<>();
 
-    /**
-     * @param registryURL "zookeeper://ip:port/RegistryService?xxx"
-     * @return
-     */
     @Override
     public ServiceDiscovery getServiceDiscovery(URL registryURL) {
         String key = registryURL.toServiceStringWithoutResolving();
         return discoveries.computeIfAbsent(key, k -> createDiscovery(registryURL));
     }
 
-    protected abstract ServiceDiscovery createDiscovery(URL url);
+    protected abstract ServiceDiscovery createDiscovery(URL registryURL);
 }
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/DefaultServiceDiscoveryFactory.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/DefaultServiceDiscoveryFactory.java
index c5f5fe4..68e9d86 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/DefaultServiceDiscoveryFactory.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/DefaultServiceDiscoveryFactory.java
@@ -33,6 +33,7 @@ import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoad
  * @since 2.7.4
  */
 public class DefaultServiceDiscoveryFactory extends AbstractServiceDiscoveryFactory {
+
     /**
      * Create the {@link ServiceDiscovery} by {@link URL#getProtocol() the protocol} from {@link URL connection URL}
      *
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/EventPublishingServiceDiscovery.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/EventPublishingServiceDiscovery.java
index f85138f..dc20a0f 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/EventPublishingServiceDiscovery.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/EventPublishingServiceDiscovery.java
@@ -235,9 +235,9 @@ final class EventPublishingServiceDiscovery implements ServiceDiscovery {
         }
 
         executeWithEvents(
-                of(new ServiceDiscoveryInitializingEvent(serviceDiscovery)),
+                of(new ServiceDiscoveryInitializingEvent(this, serviceDiscovery)),
                 () -> serviceDiscovery.initialize(registryURL),
-                of(new ServiceDiscoveryInitializedEvent(serviceDiscovery))
+                of(new ServiceDiscoveryInitializedEvent(this, serviceDiscovery))
         );
 
         // doesn't start -> started
@@ -257,9 +257,9 @@ final class EventPublishingServiceDiscovery implements ServiceDiscovery {
         }
 
         executeWithEvents(
-                of(new ServiceDiscoveryDestroyingEvent(serviceDiscovery)),
+                of(new ServiceDiscoveryDestroyingEvent(this, serviceDiscovery)),
                 serviceDiscovery::destroy,
-                of(new ServiceDiscoveryDestroyedEvent(serviceDiscovery))
+                of(new ServiceDiscoveryDestroyedEvent(this, serviceDiscovery))
         );
 
         // doesn't stop -> stopped
@@ -273,7 +273,7 @@ final class EventPublishingServiceDiscovery implements ServiceDiscovery {
         try {
             action.execute();
         } catch (Exception e) {
-            dispatchEvent(new ServiceDiscoveryExceptionEvent(serviceDiscovery, e));
+            dispatchEvent(new ServiceDiscoveryExceptionEvent(this, serviceDiscovery, e));
         }
         afterEvent.ifPresent(this::dispatchEvent);
     }
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryDestroyedEvent.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryDestroyedEvent.java
index 2303335..7a99fdc 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryDestroyedEvent.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryDestroyedEvent.java
@@ -26,14 +26,8 @@ import org.apache.dubbo.registry.client.ServiceDiscovery;
  */
 public class ServiceDiscoveryDestroyedEvent extends ServiceDiscoveryEvent {
 
-    /**
-     * Constructs a prototypical Event.
-     *
-     * @param serviceDiscovery The instance of {@link ServiceDiscovery} as source
-     * @throws IllegalArgumentException if source is null.
-     */
-    public ServiceDiscoveryDestroyedEvent(ServiceDiscovery serviceDiscovery) {
-        super(serviceDiscovery);
+    public ServiceDiscoveryDestroyedEvent(ServiceDiscovery source, ServiceDiscovery original) {
+        super(source, original);
     }
 
 }
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryDestroyingEvent.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryDestroyingEvent.java
index 60500ee..d6ebfd6 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryDestroyingEvent.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryDestroyingEvent.java
@@ -26,14 +26,8 @@ import org.apache.dubbo.registry.client.ServiceDiscovery;
  */
 public class ServiceDiscoveryDestroyingEvent extends ServiceDiscoveryEvent {
 
-    /**
-     * Constructs a prototypical Event.
-     *
-     * @param serviceDiscovery The instance of {@link ServiceDiscovery} as source
-     * @throws IllegalArgumentException if source is null.
-     */
-    public ServiceDiscoveryDestroyingEvent(ServiceDiscovery serviceDiscovery) {
-        super(serviceDiscovery);
+    public ServiceDiscoveryDestroyingEvent(ServiceDiscovery source, ServiceDiscovery original) {
+        super(source, original);
     }
 
 }
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryEvent.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryEvent.java
index a319fd5..afe613d 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryEvent.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryEvent.java
@@ -28,14 +28,23 @@ import org.apache.dubbo.registry.client.ServiceDiscovery;
  */
 public abstract class ServiceDiscoveryEvent extends Event {
 
+    private final ServiceDiscovery original;
+
     /**
      * Constructs a prototypical Event.
      *
-     * @param serviceDiscovery The {@link ServiceDiscovery} on which the Event initially occurred.
+     * @param source   The object on which the Event initially occurred.
+     * @param original The original {@link ServiceDiscovery}
      * @throws IllegalArgumentException if source is null.
      */
-    public ServiceDiscoveryEvent(ServiceDiscovery serviceDiscovery) {
-        super(serviceDiscovery);
+    public ServiceDiscoveryEvent(ServiceDiscovery source, ServiceDiscovery original) {
+        super(source);
+        this.original = original;
+    }
+
+    @Override
+    public ServiceDiscovery getSource() {
+        return (ServiceDiscovery) super.getSource();
     }
 
     /**
@@ -44,6 +53,15 @@ public abstract class ServiceDiscoveryEvent extends Event {
      * @return {@link ServiceDiscovery} instance
      */
     public final ServiceDiscovery getServiceDiscovery() {
-        return (ServiceDiscovery) getSource();
+        return getSource();
+    }
+
+    /**
+     * Get the original {@link ServiceDiscovery}
+     *
+     * @return the original {@link ServiceDiscovery}
+     */
+    public final ServiceDiscovery getOriginal() {
+        return original;
     }
 }
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryExceptionEvent.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryExceptionEvent.java
index 49582ab..328be1e 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryExceptionEvent.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryExceptionEvent.java
@@ -29,14 +29,8 @@ public class ServiceDiscoveryExceptionEvent extends ServiceDiscoveryEvent {
 
     private final Exception cause;
 
-    /**
-     * Constructs a prototypical Event.
-     *
-     * @param serviceDiscovery The {@link ServiceDiscovery} on which the Event initially occurred.
-     * @throws IllegalArgumentException if any argument is null.
-     */
-    public ServiceDiscoveryExceptionEvent(ServiceDiscovery serviceDiscovery, Exception cause) {
-        super(serviceDiscovery);
+    public ServiceDiscoveryExceptionEvent(ServiceDiscovery source, ServiceDiscovery original, Exception cause) {
+        super(source, original);
         if (cause == null) {
             throw new NullPointerException("The cause of Exception must not null");
         }
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryInitializedEvent.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryInitializedEvent.java
index 31bcc79..a688847 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryInitializedEvent.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryInitializedEvent.java
@@ -27,14 +27,7 @@ import org.apache.dubbo.registry.client.ServiceDiscovery;
  */
 public class ServiceDiscoveryInitializedEvent extends ServiceDiscoveryEvent {
 
-    /**
-     * Constructs a prototypical Event.
-     *
-     * @param serviceDiscovery The instance of {@link ServiceDiscovery} as source
-     * @throws IllegalArgumentException if source is null.
-     */
-    public ServiceDiscoveryInitializedEvent(ServiceDiscovery serviceDiscovery) {
-        super(serviceDiscovery);
+    public ServiceDiscoveryInitializedEvent(ServiceDiscovery source, ServiceDiscovery original) {
+        super(source, original);
     }
-
 }
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryInitializingEvent.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryInitializingEvent.java
index 92ef4d1..da92466 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryInitializingEvent.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryInitializingEvent.java
@@ -27,13 +27,7 @@ import org.apache.dubbo.registry.client.ServiceDiscovery;
  */
 public class ServiceDiscoveryInitializingEvent extends ServiceDiscoveryEvent {
 
-    /**
-     * Constructs a prototypical Event.
-     *
-     * @param serviceDiscovery The instance of {@link ServiceDiscovery} as source
-     * @throws IllegalArgumentException if source is null.
-     */
-    public ServiceDiscoveryInitializingEvent(ServiceDiscovery serviceDiscovery) {
-        super(serviceDiscovery);
+    public ServiceDiscoveryInitializingEvent(ServiceDiscovery source, ServiceDiscovery original) {
+        super(source, original);
     }
 }
diff --git a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/event/listener/LoggingEventListenerTest.java b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/event/listener/LoggingEventListenerTest.java
index f594a43..e1eeecf 100644
--- a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/event/listener/LoggingEventListenerTest.java
+++ b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/event/listener/LoggingEventListenerTest.java
@@ -59,10 +59,10 @@ public class LoggingEventListenerTest {
         serviceDiscovery.initialize(connectionURL);
 
         // ServiceDiscoveryStartingEvent
-        listener.onEvent(new ServiceDiscoveryInitializingEvent(serviceDiscovery));
+        listener.onEvent(new ServiceDiscoveryInitializingEvent(serviceDiscovery, serviceDiscovery));
 
         // ServiceDiscoveryStartedEvent
-        listener.onEvent(new ServiceDiscoveryInitializedEvent(serviceDiscovery));
+        listener.onEvent(new ServiceDiscoveryInitializedEvent(serviceDiscovery, serviceDiscovery));
 
         // ServiceInstancePreRegisteredEvent
         listener.onEvent(new ServiceInstancePreRegisteredEvent(serviceDiscovery, createInstance()));
@@ -80,9 +80,9 @@ public class LoggingEventListenerTest {
         listener.onEvent(new ServiceInstanceUnregisteredEvent(serviceDiscovery, createInstance()));
 
         // ServiceDiscoveryStoppingEvent
-        listener.onEvent(new ServiceDiscoveryDestroyingEvent(serviceDiscovery));
+        listener.onEvent(new ServiceDiscoveryDestroyingEvent(serviceDiscovery, serviceDiscovery));
 
         // ServiceDiscoveryStoppedEvent
-        listener.onEvent(new ServiceDiscoveryDestroyedEvent(serviceDiscovery));
+        listener.onEvent(new ServiceDiscoveryDestroyedEvent(serviceDiscovery, serviceDiscovery));
     }
 }