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 03:11:04 UTC

[dubbo] branch cloud-native updated: [Refactor] Dubbo Cloud Native (#4844)

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 d6d0bec  [Refactor] Dubbo Cloud Native (#4844)
d6d0bec is described below

commit d6d0bec0c6733abb43f17f0a19d1d6419c81fa5b
Author: Mercy Ma <me...@gmail.com>
AuthorDate: Fri Aug 16 11:10:51 2019 +0800

    [Refactor] Dubbo Cloud Native (#4844)
    
    * 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
---
 .../org/apache/dubbo/bootstrap/DubboBootstrap.java | 165 +++++++++++++--------
 .../bootstrap/DubboServiceConsumerBootstrap.java   |   9 +-
 .../bootstrap/DubboServiceProvider2Bootstrap.java  |   9 +-
 .../file/FileSystemDynamicConfiguration.java       |   4 +
 .../dubbo/common/constants/RegistryConstants.java  |   2 +-
 .../org/apache/dubbo/common/context/Lifecycle.java |   2 +-
 .../dubbo/common/extension/ExtensionLoader.java    |  14 ++
 .../dubbo/common/function/ThrowableAction.java     |  33 +++--
 .../org/apache/dubbo/common/lang/Prioritized.java  |   3 +-
 .../org/apache/dubbo/config/DubboShutdownHook.java |   2 +-
 .../ConfigurableMetadataServiceExporter.java       |  59 ++++----
 .../dubbo/config/DubboProviderBootstrap.java       |  13 +-
 .../ConfigurableMetadataServiceExporterTest.java   |   2 +-
 .../org/apache/dubbo/metadata/MetadataService.java |   2 +-
 .../dubbo/metadata/MetadataServiceExporter.java    |  23 ++-
 .../dubbo/metadata/WritableMetadataService.java    |  28 +++-
 .../client/AbstractServiceDiscoveryFactory.java    |  16 +-
 .../client/DefaultServiceDiscoveryFactory.java     |  54 +++++++
 .../client/EventPublishingServiceDiscovery.java    | 125 +++++++++-------
 .../client/FileSystemServiceDiscovery.java         |  22 +--
 .../dubbo/registry/client/ServiceDiscovery.java    |  19 ++-
 .../registry/client/ServiceDiscoveryFactory.java   |  29 +++-
 .../ServiceDiscoveryRegistry.java}                 |  84 ++++++-----
 .../ServiceDiscoveryRegistryFactory.java}          |   6 +-
 .../ServiceDiscoveryRegistryProtocol.java}         |   4 +-
 ...nt.java => ServiceDiscoveryDestroyedEvent.java} |  17 +--
 ...t.java => ServiceDiscoveryDestroyingEvent.java} |  17 +--
 ...toppedEvent.java => ServiceDiscoveryEvent.java} |  17 ++-
 ...nt.java => ServiceDiscoveryExceptionEvent.java} |  28 ++--
 ....java => ServiceDiscoveryInitializedEvent.java} |  19 +--
 ...java => ServiceDiscoveryInitializingEvent.java} |  19 +--
 .../event/listener/LoggingEventListener.java       |  20 +--
 ...ExportedServicesRevisionMetadataCustomizer.java |  11 +-
 ...MetadataServiceURLParamsMetadataCustomizer.java |   9 +-
 .../metadata/RefreshServiceMetadataCustomizer.java |   7 +-
 .../metadata/ServiceInstanceMetadataUtils.java     |  43 ++++--
 .../SpringCloudMetadataServiceURLBuilder.java      |   4 +-
 ...bscribedServicesRevisionMetadataCustomizer.java |  11 +-
 .../org.apache.dubbo.registry.RegistryFactory      |   2 +-
 ...g.apache.dubbo.registry.client.ServiceDiscovery |   1 +
 ...e.dubbo.registry.client.ServiceDiscoveryFactory |   1 +
 .../dubbo/internal/org.apache.dubbo.rpc.Protocol   |   2 +-
 .../EventPublishingServiceDiscoveryTest.java       |  44 +++---
 .../registry/client/InMemoryServiceDiscovery.java  |   5 +-
 .../client/InMemoryServiceDiscoveryFactory.java    |  33 -----
 .../registry/client/ServiceDiscoveryTest.java      |   8 +-
 .../event/listener/LoggingEventListenerTest.java   |  23 +--
 .../support/ServiceOrientedRegistryTest.java       |  10 +-
 ....apache.dubbo.registry.client.ServiceDiscovery} |   2 +-
 .../registry/consul/ConsulServiceDiscovery.java    |  23 ++-
 .../consul/ConsulServiceDiscoveryFactory.java      |  31 ----
 ...g.apache.dubbo.registry.client.ServiceDiscovery |   1 +
 ...e.dubbo.registry.client.ServiceDiscoveryFactory |   1 -
 .../dubbo/registry/etcd/EtcdServiceDiscovery.java  |  36 ++---
 .../registry/etcd/EtcdServiceDiscoveryFactory.java |  39 -----
 ...g.apache.dubbo.registry.client.ServiceDiscovery |   1 +
 ...e.dubbo.registry.client.ServiceDiscoveryFactory |   1 -
 .../registry/nacos/NacosServiceDiscovery.java      |  16 +-
 .../nacos/NacosServiceDiscoveryFactory.java        |  36 -----
 ...g.apache.dubbo.registry.client.ServiceDiscovery |   1 +
 ...e.dubbo.registry.client.ServiceDiscoveryFactory |   1 -
 .../zookeeper/ZookeeperServiceDiscovery.java       |  34 ++---
 .../zookeeper/util/CuratorFrameworkUtils.java      |   5 -
 ....apache.dubbo.registry.client.ServiceDiscovery} |   2 +-
 ...e.dubbo.registry.client.ServiceDiscoveryFactory |   1 -
 .../zookeeper/ZookeeperServiceDiscoveryTest.java   |  10 +-
 66 files changed, 679 insertions(+), 642 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 db5963a..4ad5512 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
@@ -21,7 +21,6 @@ import org.apache.dubbo.common.config.Environment;
 import org.apache.dubbo.common.config.configcenter.DynamicConfiguration;
 import org.apache.dubbo.common.config.configcenter.wrapper.CompositeDynamicConfiguration;
 import org.apache.dubbo.common.context.Lifecycle;
-import org.apache.dubbo.common.extension.ExtensionLoader;
 import org.apache.dubbo.common.logger.Logger;
 import org.apache.dubbo.common.logger.LoggerFactory;
 import org.apache.dubbo.common.utils.CollectionUtils;
@@ -50,13 +49,14 @@ 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.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.rpc.Protocol;
-import org.apache.dubbo.rpc.ProtocolServer;
 
 import java.io.IOException;
 import java.util.ArrayList;
@@ -64,6 +64,7 @@ import java.util.Collection;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Set;
+import java.util.SortedSet;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.locks.Condition;
@@ -75,13 +76,11 @@ import static java.util.Arrays.asList;
 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.GROUP_CHAR_SEPERATOR;
-import static org.apache.dubbo.common.constants.CommonConstants.METADATA_DEFAULT;
-import static org.apache.dubbo.common.constants.CommonConstants.METADATA_KEY;
 import static org.apache.dubbo.common.constants.CommonConstants.METADATA_REMOTE;
 import static org.apache.dubbo.common.utils.StringUtils.isNotEmpty;
 import static org.apache.dubbo.config.context.ConfigManager.getInstance;
-import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.MEATADATA_STORED_TYPE_KEY;
+import static org.apache.dubbo.metadata.WritableMetadataService.getExtension;
+import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.setMetadataStorageType;
 import static org.apache.dubbo.remoting.Constants.CLIENT_KEY;
 
 /**
@@ -130,7 +129,13 @@ public class DubboBootstrap implements Lifecycle {
      */
     private volatile boolean onlyRegisterProvider = false;
 
-    private ServiceInstance serviceInstance;
+    private volatile boolean defaultMetadataStorageType = true;
+
+    private volatile ServiceInstance serviceInstance;
+
+    private volatile MetadataService metadataService;
+
+    private volatile MetadataServiceExporter metadataServiceExporter;
 
     public DubboBootstrap() {
         DubboShutdownHook.getDubboShutdownHook().register();
@@ -147,6 +152,19 @@ public class DubboBootstrap implements Lifecycle {
         return this;
     }
 
+    public boolean isOnlyRegisterProvider() {
+        return onlyRegisterProvider;
+    }
+
+    public boolean isDefaultMetadataStorageType() {
+        return defaultMetadataStorageType;
+    }
+
+    public DubboBootstrap defaultMetadataStorageType(boolean defaultMetadataStorageType) {
+        this.defaultMetadataStorageType = defaultMetadataStorageType;
+        return this;
+    }
+
     public DubboBootstrap metadataReport(MetadataReportConfig metadataReportConfig) {
         configManager.addMetadataReport(metadataReportConfig);
         return this;
@@ -161,7 +179,6 @@ public class DubboBootstrap implements Lifecycle {
         return this;
     }
 
-
     // {@link ApplicationConfig} correlative methods
 
     /**
@@ -419,6 +436,10 @@ public class DubboBootstrap implements Lifecycle {
 
             useRegistryAsConfigCenterIfNecessary();
 
+            initMetadataService();
+
+            initMetadataServiceExporter();
+
             initialized = true;
 
             if (logger.isInfoEnabled()) {
@@ -430,6 +451,24 @@ public class DubboBootstrap implements Lifecycle {
         return this;
     }
 
+    /**
+     * Initialize {@link MetadataService} from {@link WritableMetadataService}'s extension
+     */
+    private void initMetadataService() {
+        this.metadataService = getExtension(isDefaultMetadataStorageType());
+    }
+
+    /**
+     * Initialize {@link MetadataServiceExporter}
+     */
+    private void initMetadataServiceExporter() {
+        this.metadataServiceExporter = new ConfigurableMetadataServiceExporter()
+                .setApplicationConfig(getApplication())
+                .setRegistries(configManager.getRegistries())
+                .setProtocols(configManager.getProtocols())
+                .metadataService(metadataService);
+    }
+
     private void loadRemoteConfigs() {
         // registry ids to registry configs
         List<RegistryConfig> tmpRegistries = new ArrayList<>();
@@ -512,26 +551,16 @@ public class DubboBootstrap implements Lifecycle {
         }
         if (!isStarted()) {
 
+            // 1. export Dubbo Services
             exportServices();
 
-            // Not only provider register and some services are exported
-            if (!onlyRegisterProvider && !configManager.getServices().isEmpty()) {
-                /**
-                 * export {@link MetadataService}
-                 */
-                // TODO, only export to default registry?
-                ApplicationConfig applicationConfig = configManager.getApplication().orElseThrow(() -> new IllegalStateException("ApplicationConfig cannot be null"));
-                if (!METADATA_REMOTE.equals(applicationConfig.getMetadata())) {
-                    exportMetadataService(
-                            applicationConfig,
-                            configManager.getRegistries(),
-                            configManager.getProtocols()
-                    );
-                }
-                /**
-                 * Register the local {@link ServiceInstance}
-                 */
-                registerServiceInstance(applicationConfig);
+            // 2. export MetadataService
+            exportMetadataService();
+
+            // Not only provider register
+            if (!isOnlyRegisterProvider() || hasExportedServices()) {
+                //3. Register the local ServiceInstance if required
+                registerServiceInstance();
             }
 
             referServices();
@@ -545,6 +574,14 @@ public class DubboBootstrap implements Lifecycle {
         return this;
     }
 
+    private boolean hasExportedServices() {
+        return !metadataService.getExportedURLs().isEmpty();
+    }
+
+    private ApplicationConfig getApplication() {
+        return configManager.getApplication().orElseThrow(() -> new IllegalStateException("ApplicationConfig cannot be null"));
+    }
+
     /**
      * Block current thread to be await.
      *
@@ -578,6 +615,7 @@ public class DubboBootstrap implements Lifecycle {
     public DubboBootstrap stop() {
         if (isInitialized() && isStarted()) {
             unregisterServiceInstance();
+            unexportMetadataService();
             unexportServices();
             started = false;
         }
@@ -699,14 +737,17 @@ public class DubboBootstrap implements Lifecycle {
         return this;
     }
 
-    private List<URL> exportMetadataService(ApplicationConfig applicationConfig,
-                                            Collection<RegistryConfig> globalRegistryConfigs,
-                                            Collection<ProtocolConfig> globalProtocolConfigs) {
-        ConfigurableMetadataServiceExporter exporter = new ConfigurableMetadataServiceExporter();
-        exporter.setApplicationConfig(applicationConfig);
-        exporter.setRegistries(globalRegistryConfigs);
-        exporter.setProtocols(globalProtocolConfigs);
-        return exporter.export();
+    /**
+     * export {@link MetadataService} and get the exported {@link URL URLs}
+     *
+     * @return {@link MetadataServiceExporter#getExportedURLs()}
+     */
+    private List<URL> exportMetadataService() {
+        return metadataServiceExporter.export().getExportedURLs();
+    }
+
+    private void unexportMetadataService() {
+        metadataServiceExporter.unexport();
     }
 
     private void exportServices() {
@@ -724,38 +765,42 @@ public class DubboBootstrap implements Lifecycle {
         configManager.getReferences().forEach(cache::get);
     }
 
-    public boolean isOnlyRegisterProvider() {
-        return onlyRegisterProvider;
-    }
+    private void registerServiceInstance() {
 
-    private void registerServiceInstance(ApplicationConfig applicationConfig) {
-        ExtensionLoader<Protocol> loader = ExtensionLoader.getExtensionLoader(Protocol.class);
-        Set<String> protocols = loader.getLoadedExtensions();
-        if (CollectionUtils.isEmpty(protocols)) {
-            throw new IllegalStateException("There should has at least one Protocol specified.");
-        }
+        ApplicationConfig application = getApplication();
 
-        String protocol = findOneProtocolForServiceInstance(protocols);
+        String serviceName = application.getName();
 
-        Protocol protocolInstance = loader.getExtension(protocol);
+        URL exportedURL = selectMetadataServiceExportedURL();
 
-        String serviceName = applicationConfig.getName();
-        // TODO, only support exporting one server
-        ProtocolServer server = protocolInstance.getServers().get(0);
-        String[] address = server.getAddress().split(GROUP_CHAR_SEPERATOR);
-        String host = address[0];
-        int port = Integer.parseInt(address[1]);
+        String host = exportedURL.getHost();
 
-        ServiceInstance serviceInstance = initServiceInstance(
-                serviceName,
-                host,
-                port,
-                applicationConfig.getMetadata() == null ? METADATA_DEFAULT : applicationConfig.getMetadata()
-        );
+        int port = exportedURL.getPort();
+
+        ServiceInstance serviceInstance = initServiceInstance(serviceName, host, port);
 
         getServiceDiscoveries().forEach(serviceDiscovery -> serviceDiscovery.register(serviceInstance));
     }
 
+    private URL selectMetadataServiceExportedURL() {
+
+        URL selectedURL = null;
+
+        SortedSet<String> urlValues = metadataService.getExportedURLs();
+
+        for (String urlValue : urlValues) {
+            URL url = URL.valueOf(urlValue);
+            if ("rest".equals(url.getProtocol())) { // REST first
+                selectedURL = url;
+                break;
+            } else {
+                selectedURL = url; // If not found, take any one
+            }
+        }
+
+        return selectedURL;
+    }
+
     /**
      * Use rest protocol if there's one, otherwise, choose the first one available.
      *
@@ -791,9 +836,9 @@ public class DubboBootstrap implements Lifecycle {
 
     }
 
-    private ServiceInstance initServiceInstance(String serviceName, String host, int port, String metadataType) {
+    private ServiceInstance initServiceInstance(String serviceName, String host, int port) {
         this.serviceInstance = new DefaultServiceInstance(serviceName, host, port);
-        this.serviceInstance.getMetadata().put(MEATADATA_STORED_TYPE_KEY, metadataType);
+        setMetadataStorageType(serviceInstance, isDefaultMetadataStorageType());
         return this.serviceInstance;
     }
 
diff --git a/dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/DubboServiceConsumerBootstrap.java b/dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/DubboServiceConsumerBootstrap.java
index cc0e16b..bf1fe0a 100644
--- a/dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/DubboServiceConsumerBootstrap.java
+++ b/dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/DubboServiceConsumerBootstrap.java
@@ -17,16 +17,9 @@
 package org.apache.dubbo.bootstrap;
 
 import org.apache.dubbo.bootstrap.rest.UserService;
-import org.apache.dubbo.config.ApplicationConfig;
-import org.apache.dubbo.config.MetadataReportConfig;
 import org.apache.dubbo.config.ReferenceConfig;
 import org.apache.dubbo.config.context.ConfigManager;
 
-import java.util.HashMap;
-import java.util.Map;
-
-import static org.apache.dubbo.common.constants.CommonConstants.METADATA_KEY;
-
 /**
  * Dubbo Provider Bootstrap
  *
@@ -40,7 +33,7 @@ public class DubboServiceConsumerBootstrap {
                 .application("dubbo-consumer-demo")
                 // Zookeeper
                 .registry("zookeeper", builder -> builder.address("zookeeper://127.0.0.1:2181?registry.type=service&subscribed.services=dubbo-provider-demo"))
-                .metadataReport(new MetadataReportConfig("zookeeper://127.0.0.1:2181"))
+//                .metadataReport(new MetadataReportConfig("zookeeper://127.0.0.1:2181"))
                 // Nacos
 //                .registry("consul", builder -> builder.address("consul://127.0.0.1:8500?registry.type=service&subscribed.services=dubbo-provider-demo").group("namespace1"))
                 .reference("echo", builder -> builder.interfaceClass(EchoService.class).protocol("dubbo"))
diff --git a/dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/DubboServiceProvider2Bootstrap.java b/dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/DubboServiceProvider2Bootstrap.java
index ad87adb..83ea7a1 100644
--- a/dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/DubboServiceProvider2Bootstrap.java
+++ b/dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/DubboServiceProvider2Bootstrap.java
@@ -16,6 +16,9 @@
  */
 package org.apache.dubbo.bootstrap;
 
+import org.apache.dubbo.bootstrap.rest.UserService;
+import org.apache.dubbo.bootstrap.rest.UserServiceImpl;
+
 /**
  * Dubbo Provider Bootstrap
  *
@@ -31,8 +34,10 @@ public class DubboServiceProvider2Bootstrap {
                 // Nacos
 //                .registry("nacos", builder -> builder.address("nacos://127.0.0.1:8848?registry.type=service"))
 //                .registry(RegistryBuilder.newBuilder().address("etcd3://127.0.0.1:2379?registry.type=service").build())
-                .protocol(builder -> builder.port(20885).name("dubbo"))
-                .service(builder -> builder.id("test").interfaceClass(EchoService.class).ref(new EchoServiceImpl()))
+                .protocol("dubbo", builder -> builder.port(20885).name("dubbo"))
+                .protocol("rest", builder -> builder.port(9090).name("rest"))
+                .service(builder -> builder.id("echo").interfaceClass(EchoService.class).ref(new EchoServiceImpl()).protocolIds("dubbo"))
+                .service(builder -> builder.id("user").interfaceClass(UserService.class).ref(new UserServiceImpl()).protocolIds("rest"))
                 .start()
                 .await();
     }
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfiguration.java b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfiguration.java
index 3070c1f..45c2b6b 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfiguration.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfiguration.java
@@ -169,6 +169,10 @@ public class FileSystemDynamicConfiguration extends AbstractDynamicConfiguration
 
     private final Map<File, List<ConfigurationListener>> listenersRepository;
 
+    public FileSystemDynamicConfiguration() {
+        this(URL.valueOf("file:///default"));
+    }
+
     public FileSystemDynamicConfiguration(URL url) {
         this(initDirectory(url), getEncoding(url), getThreadPoolPrefixName(url), getThreadPoolSize(url),
                 getThreadPoolKeepAliveTime(url));
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/constants/RegistryConstants.java b/dubbo-common/src/main/java/org/apache/dubbo/common/constants/RegistryConstants.java
index b0d89b9..e7e604c 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/constants/RegistryConstants.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/constants/RegistryConstants.java
@@ -67,7 +67,7 @@ public interface RegistryConstants {
      */
     String SERVICE_REGISTRY_TYPE = "service";
 
-    String SERVICE_REGISTRY_PROTOCOL = "service-oriented-registry";
+    String SERVICE_REGISTRY_PROTOCOL = "service-discovery-registry";
 
     /**
      * The parameter key of the subscribed service names for Service-Oriented Registry
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/context/Lifecycle.java b/dubbo-common/src/main/java/org/apache/dubbo/common/context/Lifecycle.java
index 672ec2c..67d7b13 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/context/Lifecycle.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/context/Lifecycle.java
@@ -21,7 +21,7 @@ package org.apache.dubbo.common.context;
  *
  * @since 2.7.4
  */
-public interface Lifecycle {
+public interface Lifecycle<V> {
 
     /**
      * Initialize the component before {@link #start() start}
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionLoader.java b/dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionLoader.java
index 1cace23..4575dbb 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionLoader.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionLoader.java
@@ -354,6 +354,16 @@ public class ExtensionLoader<T> {
     }
 
     /**
+     * Get the extension by specified name if found, or {@link #getDefaultExtension() returns the default one}
+     *
+     * @param name the name of extension
+     * @return non-null
+     */
+    public T getOrDefaultExtension(String name) {
+        return containsExtension(name)  ? getExtension(name) : getDefaultExtension();
+    }
+
+    /**
      * Return default extension, return <code>null</code> if it's not configured.
      */
     public T getDefaultExtension() {
@@ -543,6 +553,10 @@ public class ExtensionLoader<T> {
         }
     }
 
+    private boolean containsExtension(String name) {
+        return getExtensionClasses().containsKey(name);
+    }
+
     private T injectExtension(T instance) {
         try {
             if (objectFactory != null) {
diff --git a/dubbo-registry/dubbo-registry-zookeeper/src/main/java/org/apache/dubbo/registry/zookeeper/ZookeeperServiceDiscoveryFactory.java b/dubbo-common/src/main/java/org/apache/dubbo/common/function/ThrowableAction.java
similarity index 59%
rename from dubbo-registry/dubbo-registry-zookeeper/src/main/java/org/apache/dubbo/registry/zookeeper/ZookeeperServiceDiscoveryFactory.java
rename to dubbo-common/src/main/java/org/apache/dubbo/common/function/ThrowableAction.java
index 4bf354d..17c96d8 100644
--- a/dubbo-registry/dubbo-registry-zookeeper/src/main/java/org/apache/dubbo/registry/zookeeper/ZookeeperServiceDiscoveryFactory.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/function/ThrowableAction.java
@@ -14,25 +14,36 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.registry.zookeeper;
+package org.apache.dubbo.common.function;
 
-import org.apache.dubbo.common.URL;
-import org.apache.dubbo.registry.client.AbstractServiceDiscoveryFactory;
-import org.apache.dubbo.registry.client.ServiceDiscovery;
-import org.apache.dubbo.registry.client.ServiceDiscoveryFactory;
+import java.util.function.Function;
 
 /**
- * The zookeeper {@link ServiceDiscoveryFactory} implementation
+ * A function interface for action with {@link Throwable}
  *
- * @see ServiceDiscoveryFactory
+ * @see Function
+ * @see Throwable
  * @since 2.7.4
  */
-public class ZookeeperServiceDiscoveryFactory extends AbstractServiceDiscoveryFactory {
+@FunctionalInterface
+public interface ThrowableAction {
 
-    @Override
-    public ServiceDiscovery createDiscovery(URL connectionURL) {
+    /**
+     * Executes the action
+     *
+     * @throws Exception if met with error
+     */
+    void execute() throws Exception;
+
+    /**
+     * Executes {@link ThrowableAction}
+     *
+     * @param action {@link ThrowableAction}
+     * @throws RuntimeException wrap {@link Exception} to {@link RuntimeException}
+     */
+    static void execute(ThrowableAction action) throws RuntimeException {
         try {
-            return new ZookeeperServiceDiscovery(connectionURL);
+            action.execute();
         } catch (Exception e) {
             throw new RuntimeException(e);
         }
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/lang/Prioritized.java b/dubbo-common/src/main/java/org/apache/dubbo/common/lang/Prioritized.java
index 98bf3f8..f416ae0 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/lang/Prioritized.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/lang/Prioritized.java
@@ -38,7 +38,7 @@ public interface Prioritized extends Comparable<Prioritized> {
             return -1;
         } else if (b2 && !b1) { // two is Prioritized, one is not
             return 1;
-        } else if (b1 && b2) {  //  one and two both Prioritized
+        } else if (b1 && b2) {  //  one and two both are Prioritized
             return ((Prioritized) one).compareTo((Prioritized) two);
         } else {                // no different
             return 0;
@@ -54,6 +54,7 @@ public interface Prioritized extends Comparable<Prioritized> {
      * The minimum priority
      */
     int MIN_PRIORITY = Integer.MAX_VALUE;
+
     /**
      * Normal Priority
      */
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/DubboShutdownHook.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/DubboShutdownHook.java
index 321649d..8172e14 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/DubboShutdownHook.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/DubboShutdownHook.java
@@ -34,7 +34,7 @@ import java.util.List;
 import java.util.concurrent.atomic.AtomicBoolean;
 
 import static java.util.Collections.sort;
-import static java.util.ServiceLoader.load;
+import static org.apache.dubbo.common.utils.DubboServiceLoader.load;
 
 /**
  * The shutdown hook thread to do the clean up stuff.
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/metadata/ConfigurableMetadataServiceExporter.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/metadata/ConfigurableMetadataServiceExporter.java
index 1e8c1f6..b5ca218 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/metadata/ConfigurableMetadataServiceExporter.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/metadata/ConfigurableMetadataServiceExporter.java
@@ -21,20 +21,18 @@ import org.apache.dubbo.common.logger.Logger;
 import org.apache.dubbo.common.logger.LoggerFactory;
 import org.apache.dubbo.config.AbstractConfig;
 import org.apache.dubbo.config.ApplicationConfig;
-import org.apache.dubbo.config.MetadataReportConfig;
 import org.apache.dubbo.config.ProtocolConfig;
 import org.apache.dubbo.config.RegistryConfig;
 import org.apache.dubbo.config.ServiceConfig;
 import org.apache.dubbo.config.context.ConfigManager;
 import org.apache.dubbo.metadata.MetadataService;
 import org.apache.dubbo.metadata.MetadataServiceExporter;
-import org.apache.dubbo.metadata.WritableMetadataService;
 
 import java.util.Collection;
 import java.util.LinkedList;
 import java.util.List;
 
-import static java.util.Collections.unmodifiableList;
+import static java.util.Collections.emptyList;
 
 /**
  * {@link MetadataServiceExporter} implementation based on {@link AbstractConfig Dubbo configurations}, the clients
@@ -43,6 +41,8 @@ import static java.util.Collections.unmodifiableList;
  * <p>
  * Typically, do not worry about their ready status, because they are initialized before
  * any {@link ServiceConfig} exports, or The Dubbo export will be failed.
+ * <p>
+ * Being aware of it's not a thread-safe implementation.
  *
  * @see MetadataServiceExporter
  * @see ServiceConfig
@@ -53,44 +53,52 @@ public class ConfigurableMetadataServiceExporter implements MetadataServiceExpor
 
     private final Logger logger = LoggerFactory.getLogger(getClass());
 
-    private volatile ServiceConfig<MetadataService> serviceConfig;
-
     private ApplicationConfig applicationConfig;
-    private MetadataReportConfig metadataReportConfig;
 
     private List<RegistryConfig> registries = new LinkedList<>();
 
     private List<ProtocolConfig> protocols = new LinkedList<>();
 
-    public void setApplicationConfig(ApplicationConfig applicationConfig) {
+    private MetadataService metadataService;
+
+    private ServiceConfig<MetadataService> serviceConfig;
+
+    public ConfigurableMetadataServiceExporter setApplicationConfig(ApplicationConfig applicationConfig) {
         this.applicationConfig = applicationConfig;
+        return this;
     }
 
-    public void setRegistries(Collection<RegistryConfig> registries) {
+    public ConfigurableMetadataServiceExporter setRegistries(Collection<RegistryConfig> registries) {
         this.registries.clear();
         this.registries.addAll(registries);
+        return this;
     }
 
-    public void setProtocols(Collection<ProtocolConfig> protocols) {
+    public ConfigurableMetadataServiceExporter setProtocols(Collection<ProtocolConfig> protocols) {
         this.protocols.clear();
-        this.protocols.addAll(protocols);
+        // TODO  only support "dubbo" protocol, add more in the future
+        protocols.stream().filter(protocolConfig -> "dubbo".equals(protocolConfig.getName()))
+                .forEach(this.protocols::add);
+        return this;
+    }
+
+    public ConfigurableMetadataServiceExporter metadataService(MetadataService metadataService) {
+        this.metadataService = metadataService;
+        return this;
     }
 
     @Override
-    public List<URL> export() {
+    public ConfigurableMetadataServiceExporter export() {
 
         if (!isExported()) {
 
-            // FIXME, if uses remote metadata center, does not need to export MetadataService locally.
-            WritableMetadataService metadataService = WritableMetadataService.getDefaultExtension();
-
             ServiceConfig<MetadataService> serviceConfig = new ServiceConfig<>();
             serviceConfig.setApplication(applicationConfig);
             serviceConfig.setRegistries(registries);
             serviceConfig.setProtocols(protocols);
             serviceConfig.setInterface(MetadataService.class);
             serviceConfig.setRef(metadataService);
-            serviceConfig.setGroup(getApplicationConfig().getName());
+            serviceConfig.setGroup(applicationConfig.getName());
             serviceConfig.setVersion(metadataService.version());
 
             // export
@@ -107,29 +115,24 @@ public class ConfigurableMetadataServiceExporter implements MetadataServiceExpor
                 logger.warn("The MetadataService has been exported : " + serviceConfig.getExportedUrls());
             }
         }
-        return serviceConfig.getExportedUrls();
+
+        return this;
     }
 
     @Override
-    public void unexport() {
+    public ConfigurableMetadataServiceExporter unexport() {
         if (isExported()) {
             serviceConfig.unexport();
         }
+        return this;
     }
 
-    private List<ProtocolConfig> getProtocols() {
-        return unmodifiableList(protocols);
-    }
-
-    private List<RegistryConfig> getRegistries() {
-        return unmodifiableList(registries);
-    }
-
-    private ApplicationConfig getApplicationConfig() {
-        return applicationConfig;
+    @Override
+    public List<URL> getExportedURLs() {
+        return serviceConfig != null ? serviceConfig.getExportedUrls() : emptyList();
     }
 
-    private boolean isExported() {
+    public boolean isExported() {
         return serviceConfig != null && serviceConfig.isExported();
     }
 }
diff --git a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/DubboProviderBootstrap.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/DubboProviderBootstrap.java
index ef8cca8..22530f8 100644
--- a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/DubboProviderBootstrap.java
+++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/DubboProviderBootstrap.java
@@ -17,7 +17,6 @@
 package org.apache.dubbo.config;
 
 import org.apache.dubbo.common.URL;
-import org.apache.dubbo.common.extension.ExtensionLoader;
 import org.apache.dubbo.common.utils.NetUtils;
 import org.apache.dubbo.config.api.DemoService;
 import org.apache.dubbo.config.metadata.ConfigurableMetadataServiceExporter;
@@ -27,14 +26,12 @@ import org.apache.dubbo.registry.client.DefaultServiceInstance;
 import org.apache.dubbo.registry.client.ServiceDiscovery;
 import org.apache.dubbo.registry.client.ServiceDiscoveryFactory;
 
-import java.io.IOException;
-
 /**
  * Dubbo Provider Bootstrap
  */
 public class DubboProviderBootstrap {
 
-    public static void main(String[] args) throws IOException {
+    public static void main(String[] args) throws Exception {
 
         ApplicationConfig application = new ApplicationConfig();
         application.setName("dubbo-provider-demo");
@@ -68,11 +65,11 @@ public class DubboProviderBootstrap {
         // 暴露 MetadataService 服务
         exporter.export();
 
-        ServiceDiscoveryFactory factory = ExtensionLoader.getExtensionLoader(ServiceDiscoveryFactory.class).getAdaptiveExtension();
+        ServiceDiscoveryFactory factory = ServiceDiscoveryFactory.getExtension(connectionURL);
 
-        ServiceDiscovery serviceDiscovery = factory.getDiscovery(connectionURL);
+        ServiceDiscovery serviceDiscovery = factory.getServiceDiscovery(connectionURL);
 
-        serviceDiscovery.start();
+        serviceDiscovery.initialize(connectionURL);
 
         DefaultServiceInstance serviceInstance = new DefaultServiceInstance(application.getName(), "127.0.0.1", protocol.getPort());
 
@@ -80,6 +77,6 @@ public class DubboProviderBootstrap {
 
         System.in.read();
 
-        serviceDiscovery.stop();
+        serviceDiscovery.destroy();
     }
 }
diff --git a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/metadata/ConfigurableMetadataServiceExporterTest.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/metadata/ConfigurableMetadataServiceExporterTest.java
index c53eb7d..1528b74 100644
--- a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/metadata/ConfigurableMetadataServiceExporterTest.java
+++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/metadata/ConfigurableMetadataServiceExporterTest.java
@@ -71,7 +71,7 @@ public class ConfigurableMetadataServiceExporterTest {
     public void testExportAndUnexport() {
         ConfigurableMetadataServiceExporter exporter = new ConfigurableMetadataServiceExporter();
         exporter.setApplicationConfig(ConfigManager.getInstance().getApplication().get());
-        List<URL> urls = exporter.export();
+        List<URL> urls = exporter.export().getExportedURLs();
 
         assertEquals(1, urls.size());
 
diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/MetadataService.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/MetadataService.java
index c4cf250..6beeba7 100644
--- a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/MetadataService.java
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/MetadataService.java
@@ -31,7 +31,7 @@ import static java.util.stream.StreamSupport.stream;
 
 /**
  * A framework interface of Dubbo Metadata Service defines the contract of Dubbo Services registartion and subscription
- * between Dubbo service providers and its consumers. The implementationwill be exported as a normal Dubbo service that
+ * between Dubbo service providers and its consumers. The implementation will be exported as a normal Dubbo service that
  * the clients would subscribe, whose version comes from the {@link #version()} method and group gets from
  * {@link #serviceName()}, that means, The different Dubbo service(application) will export the different
  * {@link MetadataService} that persists all the exported and subscribed metadata, they are present by
diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/MetadataServiceExporter.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/MetadataServiceExporter.java
index 6ba99de..108b3a7 100644
--- a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/MetadataServiceExporter.java
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/MetadataServiceExporter.java
@@ -33,12 +33,29 @@ public interface MetadataServiceExporter {
     /**
      * Exports the {@link MetadataService} as a Dubbo service
      *
-     * @return the exported {@link URL URLs}
+     * @return {@link MetadataServiceExporter itself}
      */
-    List<URL> export();
+    MetadataServiceExporter export();
 
     /**
      * Unexports the {@link MetadataService}
+     *
+     * @return {@link MetadataServiceExporter itself}
+     */
+    MetadataServiceExporter unexport();
+
+    /**
+     * Get the {@link URL URLs} that were exported
+     *
+     * @return non-null
      */
-    void unexport();
+    List<URL> getExportedURLs();
+
+    /**
+     * {@link MetadataService} is export or not
+     *
+     * @return if {@link #export()} was executed, return <code>true</code>, or <code>false</code>
+     */
+    boolean isExported();
 }
+
diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/WritableMetadataService.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/WritableMetadataService.java
index 7a8fd27..e51fa2a 100644
--- a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/WritableMetadataService.java
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/WritableMetadataService.java
@@ -34,6 +34,16 @@ import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoad
 public interface WritableMetadataService extends MetadataService {
 
     /**
+     * The default storage type value as the extension name
+     */
+    public static String DEFAULT_METADATA_STORAGE_TYPE = "default";
+
+    /**
+     * The remote storage type value as the extension name
+     */
+    public static String REMOTE_METADATA_STORAGE_TYPE = "remote";
+
+    /**
      * Gets the current Dubbo Service name
      *
      * @return non-null
@@ -64,7 +74,7 @@ public interface WritableMetadataService extends MetadataService {
      *
      * @return If success , return <code>true</code>
      */
-    default boolean refreshMetadata(String exportedRevision, String subscribedRevision){
+    default boolean refreshMetadata(String exportedRevision, String subscribedRevision) {
         return true;
     }
 
@@ -96,9 +106,21 @@ public interface WritableMetadataService extends MetadataService {
         return getExtensionLoader(WritableMetadataService.class).getDefaultExtension();
     }
 
-    static WritableMetadataService getExtension(String name) {
-        return getExtensionLoader(WritableMetadataService.class).getExtension(name);
+    /**
+     * Get the metadata's storage type
+     *
+     * @param isDefaultStorageType is default storage type or not
+     * @return non-null, {@link #DEFAULT_METADATA_STORAGE_TYPE "default"} or {@link #REMOTE_METADATA_STORAGE_TYPE "remote"}
+     */
+    public static String getMetadataStorageType(boolean isDefaultStorageType) {
+        return isDefaultStorageType ? DEFAULT_METADATA_STORAGE_TYPE : REMOTE_METADATA_STORAGE_TYPE;
     }
 
+    static WritableMetadataService getExtension(boolean isDefaultStorageType) {
+        return getExtension(getMetadataStorageType(isDefaultStorageType));
+    }
 
+    static WritableMetadataService getExtension(String name) {
+        return getExtensionLoader(WritableMetadataService.class).getOrDefaultExtension(name);
+    }
 }
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 c9c6ec0..b8d941b 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
@@ -40,12 +40,12 @@ public abstract class AbstractServiceDiscoveryFactory implements ServiceDiscover
      */
     public static void destroyAll() {
         if (logger.isInfoEnabled()) {
-            logger.info("Closing all ServiceDicovery instances: " + getDiscoveries());
+            logger.info("Closing all ServiceDiscovery instances: " + getDiscoveries());
         }
 
         for (ServiceDiscovery discovery : getDiscoveries()) {
             try {
-                discovery.stop();
+                discovery.destroy();
             } catch (Throwable e) {
                 logger.error("Error trying to close ServiceDiscovery instance.", e);
             }
@@ -54,17 +54,13 @@ public abstract class AbstractServiceDiscoveryFactory implements ServiceDiscover
     }
 
     /**
-     * @param url "zookeeper://ip:port/RegistryService?xxx"
+     * @param registryURL "zookeeper://ip:port/RegistryService?xxx"
      * @return
      */
     @Override
-    public ServiceDiscovery getDiscovery(URL url) {
-        String key = url.toServiceStringWithoutResolving();
-
-        return discoveries.computeIfAbsent(key, k -> {
-            ServiceDiscovery discovery = createDiscovery(url);
-            return new EventPublishingServiceDiscovery(discovery);
-        });
+    public ServiceDiscovery getServiceDiscovery(URL registryURL) {
+        String key = registryURL.toServiceStringWithoutResolving();
+        return discoveries.computeIfAbsent(key, k -> createDiscovery(registryURL));
     }
 
     protected abstract ServiceDiscovery createDiscovery(URL url);
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
new file mode 100644
index 0000000..0d38ace
--- /dev/null
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/DefaultServiceDiscoveryFactory.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.registry.client;
+
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.extension.ExtensionLoader;
+import org.apache.dubbo.common.extension.SPI;
+
+import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoader;
+
+/**
+ * The default {@link SPI} implementation of {@link ServiceDiscoveryFactory} to {@link #getServiceDiscovery(URL) get the
+ * instance of ServiceDiscovery} via the {@link URL#getProtocol() protocol} from the {@link URL} that will connect
+ * the infrastructure of Service registration and discovery. The {@link URL#getProtocol() protocol} will be used as the
+ * extension name by which the {@link ServiceDiscovery} instance is loaded.
+ *
+ * @see AbstractServiceDiscoveryFactory
+ * @see EventPublishingServiceDiscovery
+ * @since 2.7.4
+ */
+public class DefaultServiceDiscoveryFactory extends AbstractServiceDiscoveryFactory {
+
+    @Override
+    protected ServiceDiscovery createDiscovery(URL connectionURL) {
+        ServiceDiscovery serviceDiscovery = load(connectionURL);
+        return new EventPublishingServiceDiscovery(serviceDiscovery);
+    }
+
+    /**
+     * Load the {@link ServiceDiscovery} by {@link URL#getProtocol() the protocol} from {@link URL connection URL}
+     *
+     * @param connectionURL the {@link URL url} to connect
+     * @return non-null
+     */
+    private ServiceDiscovery load(URL connectionURL) {
+        String protocol = connectionURL.getProtocol();
+        ExtensionLoader<ServiceDiscovery> loader = getExtensionLoader(ServiceDiscovery.class);
+        return loader.getOrDefaultExtension(protocol);
+    }
+}
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 b8e6b3d..f85138f 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
@@ -16,15 +16,18 @@
  */
 package org.apache.dubbo.registry.client;
 
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.function.ThrowableAction;
 import org.apache.dubbo.common.logger.Logger;
 import org.apache.dubbo.common.logger.LoggerFactory;
 import org.apache.dubbo.common.utils.Page;
 import org.apache.dubbo.event.Event;
 import org.apache.dubbo.event.EventDispatcher;
-import org.apache.dubbo.registry.client.event.ServiceDiscoveryStartedEvent;
-import org.apache.dubbo.registry.client.event.ServiceDiscoveryStartingEvent;
-import org.apache.dubbo.registry.client.event.ServiceDiscoveryStoppedEvent;
-import org.apache.dubbo.registry.client.event.ServiceDiscoveryStoppingEvent;
+import org.apache.dubbo.registry.client.event.ServiceDiscoveryDestroyedEvent;
+import org.apache.dubbo.registry.client.event.ServiceDiscoveryDestroyingEvent;
+import org.apache.dubbo.registry.client.event.ServiceDiscoveryExceptionEvent;
+import org.apache.dubbo.registry.client.event.ServiceDiscoveryInitializedEvent;
+import org.apache.dubbo.registry.client.event.ServiceDiscoveryInitializingEvent;
 import org.apache.dubbo.registry.client.event.ServiceInstancePreRegisteredEvent;
 import org.apache.dubbo.registry.client.event.ServiceInstancePreUnregisteredEvent;
 import org.apache.dubbo.registry.client.event.ServiceInstanceRegisteredEvent;
@@ -55,14 +58,14 @@ import static java.util.Optional.of;
  * </thead>
  * <tbody>
  * <tr>
- * <td>{@link #START_ACTION start}</td>
- * <td>{@link ServiceDiscoveryStartingEvent}</td>
- * <td>{@link ServiceDiscoveryStartedEvent}</td>
+ * <td>{@link #INITIALIZE_ACTION start}</td>
+ * <td>{@link ServiceDiscoveryInitializingEvent}</td>
+ * <td>{@link ServiceDiscoveryInitializedEvent}</td>
  * </tr>
  * <tr>
- * <td>{@link #STOP_ACTION stop}</td>
- * <td>{@link ServiceDiscoveryStoppingEvent}</td>
- * <td>{@link ServiceDiscoveryStoppedEvent}</td>
+ * <td>{@link #DESTROY_ACTION stop}</td>
+ * <td>{@link ServiceDiscoveryDestroyingEvent}</td>
+ * <td>{@link ServiceDiscoveryDestroyedEvent}</td>
  * </tr>
  * </tbody>
  * </table>
@@ -96,15 +99,15 @@ import static java.util.Optional.of;
  * </ul>
  *
  * @see ServiceDiscovery
- * @see ServiceDiscoveryStartingEvent
- * @see ServiceDiscoveryStartedEvent
+ * @see ServiceDiscoveryInitializingEvent
+ * @see ServiceDiscoveryInitializedEvent
  * @see ServiceInstancePreRegisteredEvent
  * @see ServiceInstanceRegisteredEvent
- * @see ServiceDiscoveryStoppingEvent
- * @see ServiceDiscoveryStoppedEvent
+ * @see ServiceDiscoveryDestroyingEvent
+ * @see ServiceDiscoveryDestroyedEvent
  * @since 2.7.4
  */
-class EventPublishingServiceDiscovery implements ServiceDiscovery {
+final class EventPublishingServiceDiscovery implements ServiceDiscovery {
 
     /**
      * @see ServiceInstancePreRegisteredEvent
@@ -117,22 +120,22 @@ class EventPublishingServiceDiscovery implements ServiceDiscovery {
     protected static final String UNREGISTER_ACTION = "unregister";
 
     /**
-     * @see ServiceDiscoveryStartingEvent
-     * @see ServiceDiscoveryStartedEvent
+     * @see ServiceDiscoveryInitializingEvent
+     * @see ServiceDiscoveryInitializedEvent
      */
-    protected static final String START_ACTION = "start";
+    protected static final String INITIALIZE_ACTION = "initialize";
 
     /**
-     * @see ServiceDiscoveryStoppingEvent
-     * @see ServiceDiscoveryStoppedEvent
+     * @see ServiceDiscoveryDestroyingEvent
+     * @see ServiceDiscoveryDestroyedEvent
      */
-    protected static final String STOP_ACTION = "stop";
+    protected static final String DESTROY_ACTION = "destroy";
 
     protected final EventDispatcher eventDispatcher = EventDispatcher.getDefaultExtension();
 
-    protected final AtomicBoolean started = new AtomicBoolean(false);
+    protected final AtomicBoolean initialized = new AtomicBoolean(false);
 
-    protected final AtomicBoolean stopped = new AtomicBoolean(false);
+    protected final AtomicBoolean destroyed = new AtomicBoolean(false);
 
     protected final Logger logger = LoggerFactory.getLogger(getClass());
 
@@ -148,8 +151,8 @@ class EventPublishingServiceDiscovery implements ServiceDiscovery {
     @Override
     public final void register(ServiceInstance serviceInstance) throws RuntimeException {
 
-        requireStarted(REGISTER_ACTION);
-        requireNotStopped(REGISTER_ACTION);
+        assertDestroyed(REGISTER_ACTION);
+        assertInitialized(REGISTER_ACTION);
 
         executeWithEvents(
                 of(new ServiceInstancePreRegisteredEvent(serviceDiscovery, serviceInstance)),
@@ -161,8 +164,8 @@ class EventPublishingServiceDiscovery implements ServiceDiscovery {
     @Override
     public final void update(ServiceInstance serviceInstance) throws RuntimeException {
 
-        requireStarted(UPDATE_ACTION);
-        requireNotStopped(UPDATE_ACTION);
+        assertDestroyed(UPDATE_ACTION);
+        assertInitialized(UPDATE_ACTION);
 
         executeWithEvents(
                 empty(),
@@ -174,8 +177,8 @@ class EventPublishingServiceDiscovery implements ServiceDiscovery {
     @Override
     public final void unregister(ServiceInstance serviceInstance) throws RuntimeException {
 
-        requireStarted(UNREGISTER_ACTION);
-        requireNotStopped(UNREGISTER_ACTION);
+        assertDestroyed(UNREGISTER_ACTION);
+        assertInitialized(UNREGISTER_ACTION);
 
         executeWithEvents(
                 of(new ServiceInstancePreUnregisteredEvent(this, serviceInstance)),
@@ -220,11 +223,11 @@ class EventPublishingServiceDiscovery implements ServiceDiscovery {
     }
 
     @Override
-    public final void start() {
+    public void initialize(URL registryURL) {
 
-        requireNotStopped(START_ACTION);
+        assertInitialized(INITIALIZE_ACTION);
 
-        if (isStarted()) {
+        if (isInitialized()) {
             if (logger.isWarnEnabled()) {
                 logger.warn("It's ignored to start current ServiceDiscovery, because it has been started.");
             }
@@ -232,21 +235,21 @@ class EventPublishingServiceDiscovery implements ServiceDiscovery {
         }
 
         executeWithEvents(
-                of(new ServiceDiscoveryStartingEvent(serviceDiscovery)),
-                serviceDiscovery::start,
-                of(new ServiceDiscoveryStartedEvent(serviceDiscovery))
+                of(new ServiceDiscoveryInitializingEvent(serviceDiscovery)),
+                () -> serviceDiscovery.initialize(registryURL),
+                of(new ServiceDiscoveryInitializedEvent(serviceDiscovery))
         );
 
         // doesn't start -> started
-        started.compareAndSet(false, true);
+        initialized.compareAndSet(false, true);
     }
 
     @Override
-    public final void stop() {
+    public void destroy() {
 
-        requireStarted(STOP_ACTION);
+        assertDestroyed(DESTROY_ACTION);
 
-        if (isStopped()) {
+        if (isDestroyed()) {
             if (logger.isWarnEnabled()) {
                 logger.warn("It's ignored to stop current ServiceDiscovery, because it has been stopped.");
             }
@@ -254,40 +257,48 @@ class EventPublishingServiceDiscovery implements ServiceDiscovery {
         }
 
         executeWithEvents(
-                of(new ServiceDiscoveryStoppingEvent(serviceDiscovery)),
-                serviceDiscovery::stop,
-                of(new ServiceDiscoveryStoppedEvent(serviceDiscovery))
+                of(new ServiceDiscoveryDestroyingEvent(serviceDiscovery)),
+                serviceDiscovery::destroy,
+                of(new ServiceDiscoveryDestroyedEvent(serviceDiscovery))
         );
 
         // doesn't stop -> stopped
-        stopped.compareAndSet(false, true);
+        destroyed.compareAndSet(false, true);
     }
 
     protected final void executeWithEvents(Optional<? extends Event> beforeEvent,
-                                           Runnable action,
+                                           ThrowableAction action,
                                            Optional<? extends Event> afterEvent) {
-        beforeEvent.ifPresent(eventDispatcher::dispatch);
-        action.run();
-        afterEvent.ifPresent(eventDispatcher::dispatch);
+        beforeEvent.ifPresent(this::dispatchEvent);
+        try {
+            action.execute();
+        } catch (Exception e) {
+            dispatchEvent(new ServiceDiscoveryExceptionEvent(serviceDiscovery, e));
+        }
+        afterEvent.ifPresent(this::dispatchEvent);
+    }
+
+    private void dispatchEvent(Event event) {
+        eventDispatcher.dispatch(event);
     }
 
-    public final boolean isStarted() {
-        return started.get();
+    public final boolean isInitialized() {
+        return initialized.get();
     }
 
-    public final boolean isStopped() {
-        return stopped.get();
+    public final boolean isDestroyed() {
+        return destroyed.get();
     }
 
-    protected void requireStarted(String action) throws IllegalStateException {
-        if (!isStarted()) {
-            throw new IllegalStateException("The action[" + action + "] is rejected, because the ServiceDiscovery is not started yet.");
+    protected void assertDestroyed(String action) throws IllegalStateException {
+        if (!isInitialized()) {
+            throw new IllegalStateException("The action[" + action + "] is rejected, because the ServiceDiscovery is not initialized yet.");
         }
     }
 
-    protected void requireNotStopped(String action) throws IllegalStateException {
-        if (isStopped()) {
-            throw new IllegalStateException("The action[" + action + "] is rejected, because the ServiceDiscovery is stopped already.");
+    protected void assertInitialized(String action) throws IllegalStateException {
+        if (isDestroyed()) {
+            throw new IllegalStateException("The action[" + action + "] is rejected, because the ServiceDiscovery is destroyed already.");
         }
     }
 }
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/FileSystemServiceDiscovery.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/FileSystemServiceDiscovery.java
index 1dbf90d..e49d392 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/FileSystemServiceDiscovery.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/FileSystemServiceDiscovery.java
@@ -36,35 +36,21 @@ import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoad
  */
 public class FileSystemServiceDiscovery implements ServiceDiscovery, EventListener<ServiceInstancesChangedEvent> {
 
-    private final URL connectionURL;
-
     private FileSystemDynamicConfiguration dynamicConfiguration;
 
-    public FileSystemServiceDiscovery(URL connectionURL) {
-        this.connectionURL = connectionURL;
-    }
-
     @Override
     public void onEvent(ServiceInstancesChangedEvent event) {
 
     }
 
     @Override
-    public void start() {
-        if (dynamicConfiguration == null) {
-            dynamicConfiguration = createDynamicConfiguration(connectionURL);
-        }
+    public void initialize(URL registryURL) throws Exception {
+        dynamicConfiguration = createDynamicConfiguration(registryURL);
     }
 
     @Override
-    public void stop() {
-        try {
-            if (dynamicConfiguration != null) {
-                dynamicConfiguration.close();
-            }
-        } catch (Exception e) {
-            throw new RuntimeException(e);
-        }
+    public void destroy() throws Exception {
+        dynamicConfiguration.close();
     }
 
     private String getConfigKey(ServiceInstance serviceInstance) {
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscovery.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscovery.java
index 914ec95..3381d5a 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscovery.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscovery.java
@@ -16,6 +16,9 @@
  */
 package org.apache.dubbo.registry.client;
 
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.extension.SPI;
+import org.apache.dubbo.common.lang.Prioritized;
 import org.apache.dubbo.common.utils.Page;
 import org.apache.dubbo.registry.client.event.listener.ServiceInstancesChangedListener;
 
@@ -33,19 +36,25 @@ import static java.util.Collections.unmodifiableMap;
  *
  * @since 2.7.4
  */
-public interface ServiceDiscovery {
+@SPI("file")
+public interface ServiceDiscovery extends Prioritized {
 
     // ==================================== Lifecycle ==================================== //
 
     /**
-     * Starts the ServiceRegistry. This is a lifecycle method.
+     * Initializes the {@link ServiceDiscovery}
+     *
+     * @param registryURL the {@link URL url} to connect service registry
+     * @throws Exception If met with error
      */
-    void start();
+    void initialize(URL registryURL) throws Exception;
 
     /**
-     * Stops the ServiceRegistry. This is a lifecycle method.
+     * Destroy the {@link ServiceDiscovery}
+     *
+     * @throws Exception If met with error
      */
-    void stop();
+    void destroy() throws Exception;
 
     // ==================================================================================== //
 
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryFactory.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryFactory.java
index 20257f4..b9b8bb5 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryFactory.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryFactory.java
@@ -17,24 +17,37 @@
 package org.apache.dubbo.registry.client;
 
 import org.apache.dubbo.common.URL;
-import org.apache.dubbo.common.extension.Adaptive;
+import org.apache.dubbo.common.extension.ExtensionLoader;
 import org.apache.dubbo.common.extension.SPI;
 
+import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoader;
+
 /**
- * The Factory interface to create an instance of {@link ServiceDiscovery}
+ * The factory to create {@link ServiceDiscovery}
  *
  * @see ServiceDiscovery
  * @since 2.7.4
  */
-@SPI("zookeeper")
+@SPI("default")
 public interface ServiceDiscoveryFactory {
 
     /**
-     * Creates an instance of {@link ServiceDiscovery}.
+     * Get the instance of {@link ServiceDiscovery}
+     *
+     * @param registryURL the {@link URL} to connect the registry
+     * @return non-null
+     */
+    ServiceDiscovery getServiceDiscovery(URL registryURL);
+
+    /**
+     * Get the extension instance of {@link ServiceDiscoveryFactory} by {@link URL#getProtocol() the protocol}
      *
-     * @param connectionURL the  {@link URL connection url}
-     * @return an instance of {@link ServiceDiscovery}
+     * @param registryURL the {@link URL} to connect the registry
+     * @return non-null
      */
-    @Adaptive({"protocol"})
-    ServiceDiscovery getDiscovery(URL connectionURL);
+    static ServiceDiscoveryFactory getExtension(URL registryURL) {
+        String protocol = registryURL.getProtocol();
+        ExtensionLoader<ServiceDiscoveryFactory> loader = getExtensionLoader(ServiceDiscoveryFactory.class);
+        return loader.getOrDefaultExtension(protocol);
+    }
 }
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/service/ServiceOrientedRegistry.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistry.java
similarity index 87%
rename from dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/service/ServiceOrientedRegistry.java
rename to dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistry.java
index 5fdc35f..40d0a09 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/service/ServiceOrientedRegistry.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistry.java
@@ -14,21 +14,19 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.registry.service;
+package org.apache.dubbo.registry.client;
 
 import org.apache.dubbo.common.URL;
-import org.apache.dubbo.common.extension.ExtensionLoader;
 import org.apache.dubbo.common.logger.Logger;
 import org.apache.dubbo.common.logger.LoggerFactory;
 import org.apache.dubbo.common.utils.StringUtils;
 import org.apache.dubbo.metadata.MetadataService;
 import org.apache.dubbo.metadata.ServiceNameMapping;
 import org.apache.dubbo.metadata.WritableMetadataService;
+import org.apache.dubbo.metadata.store.InMemoryWritableMetadataService;
+import org.apache.dubbo.metadata.store.RemoteWritableMetadataService;
 import org.apache.dubbo.registry.NotifyListener;
 import org.apache.dubbo.registry.Registry;
-import org.apache.dubbo.registry.client.ServiceDiscovery;
-import org.apache.dubbo.registry.client.ServiceDiscoveryFactory;
-import org.apache.dubbo.registry.client.ServiceInstance;
 import org.apache.dubbo.registry.client.metadata.proxy.MetadataServiceProxyFactory;
 import org.apache.dubbo.registry.client.selector.ServiceInstanceSelector;
 import org.apache.dubbo.registry.support.FailbackRegistry;
@@ -54,7 +52,6 @@ import static java.util.stream.Stream.of;
 import static org.apache.dubbo.common.constants.CommonConstants.DUBBO_PROTOCOL;
 import static org.apache.dubbo.common.constants.CommonConstants.GROUP_KEY;
 import static org.apache.dubbo.common.constants.CommonConstants.INTERFACE_KEY;
-import static org.apache.dubbo.common.constants.CommonConstants.METADATA_DEFAULT;
 import static org.apache.dubbo.common.constants.CommonConstants.PROTOCOL_KEY;
 import static org.apache.dubbo.common.constants.CommonConstants.PROVIDER_SIDE;
 import static org.apache.dubbo.common.constants.CommonConstants.SIDE_KEY;
@@ -63,29 +60,36 @@ import static org.apache.dubbo.common.constants.RegistryConstants.REGISTRY_TYPE_
 import static org.apache.dubbo.common.constants.RegistryConstants.SERVICE_REGISTRY_TYPE;
 import static org.apache.dubbo.common.constants.RegistryConstants.SUBSCRIBED_SERVICE_NAMES_KEY;
 import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoader;
+import static org.apache.dubbo.common.function.ThrowableAction.execute;
 import static org.apache.dubbo.common.utils.CollectionUtils.isEmpty;
 import static org.apache.dubbo.common.utils.CollectionUtils.isNotEmpty;
 import static org.apache.dubbo.common.utils.StringUtils.isBlank;
 import static org.apache.dubbo.metadata.WritableMetadataService.DEFAULT_EXTENSION;
-import static org.apache.dubbo.metadata.report.support.Constants.METADATA_REPORT_KEY;
+import static org.apache.dubbo.registry.client.ServiceDiscoveryFactory.getExtension;
 import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.getExportedServicesRevision;
 import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.getMetadataServiceURLsParams;
-import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.getMetadataStoredType;
+import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.getMetadataStorageType;
 import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.getProviderHost;
 import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.getProviderPort;
 
 /**
- * Service-Oriented {@link Registry} that is dislike the traditional {@link Registry} will not communicate to
- * registry immediately instead of persisting into the metadata's repository when the Dubbo service exports.
- * The metadata repository will be used as the data source of Dubbo Metadata service that is about to export and be
- * subscribed by the consumers.
+ * {@link ServiceDiscoveryRegistry} is the service-oriented {@link Registry} and dislike the traditional one that
+ * {@link #register(URL) registers} to and {@link #subscribe(URL, NotifyListener) discoveries}
+ * the Dubbo's {@link URL urls} from the external registry. In the {@link #register(URL) registration}
+ * phase, The {@link URL urls} of Dubbo services will be {@link WritableMetadataService#exportURL(URL) exported} into
+ * {@link WritableMetadataService} that is either {@link InMemoryWritableMetadataService in-memory} or
+ * {@link RemoteWritableMetadataService remote},
+ * <p>
+ * it's decided by metadata
+ * subscribes from the remote proxy of {@link MetadataService}
+ *
  * <p>
  *
  * @see ServiceDiscovery
  * @see FailbackRegistry
  * @since 2.7.4
  */
-public class ServiceOrientedRegistry extends FailbackRegistry {
+public class ServiceDiscoveryRegistry extends FailbackRegistry {
 
     protected final Logger logger = LoggerFactory.getLogger(getClass());
 
@@ -97,20 +101,17 @@ public class ServiceOrientedRegistry extends FailbackRegistry {
 
     private final WritableMetadataService writableMetadataService;
 
-
-    public ServiceOrientedRegistry(URL registryURL) {
+    public ServiceDiscoveryRegistry(URL registryURL) {
         super(registryURL);
-        this.serviceDiscovery = buildServiceDiscovery(registryURL);
-        this.subscribedServices = buildSubscribedServices(registryURL);
+        this.serviceDiscovery = getServiceDiscovery(registryURL);
+        this.subscribedServices = getSubscribedServices(registryURL);
         this.serviceNameMapping = ServiceNameMapping.getDefaultExtension();
-
-        String metadata = registryURL.getParameter(METADATA_REPORT_KEY, METADATA_DEFAULT);
-        // FIXME
-        this.writableMetadataService = WritableMetadataService.getExtension(metadata);
+        String metadataStorageType = getMetadataStorageType(registryURL);
+        this.writableMetadataService = WritableMetadataService.getExtension(metadataStorageType);
     }
 
-    private Set<String> buildSubscribedServices(URL url) {
-        String subscribedServiceNames = url.getParameter(SUBSCRIBED_SERVICE_NAMES_KEY);
+    protected Set<String> getSubscribedServices(URL registryURL) {
+        String subscribedServiceNames = registryURL.getParameter(SUBSCRIBED_SERVICE_NAMES_KEY);
         return isBlank(subscribedServiceNames) ? emptySet() :
                 unmodifiableSet(of(subscribedServiceNames.split(","))
                         .map(String::trim)
@@ -118,17 +119,24 @@ public class ServiceOrientedRegistry extends FailbackRegistry {
                         .collect(toSet()));
     }
 
-    private ServiceDiscovery buildServiceDiscovery(URL url) {
-        ServiceDiscoveryFactory factory = ExtensionLoader.getExtensionLoader(ServiceDiscoveryFactory.class).getAdaptiveExtension();
-        ServiceDiscovery serviceDiscovery = factory.getDiscovery(url
-                .addParameter(INTERFACE_KEY, ServiceDiscovery.class.getName())
-                .removeParameter(REGISTRY_TYPE_KEY)
-        );
-        serviceDiscovery.start();
+    /**
+     * Get the {@link ServiceDiscovery} from the connection {@link URL}
+     *
+     * @param registryURL the {@link URL} to connect the registry
+     * @return non-null
+     */
+    protected ServiceDiscovery getServiceDiscovery(URL registryURL) {
+        ServiceDiscoveryFactory factory = getExtension(registryURL);
+        ServiceDiscovery serviceDiscovery = factory.getServiceDiscovery(registryURL);
+        execute(() -> {
+            serviceDiscovery.initialize(registryURL.addParameter(INTERFACE_KEY, ServiceDiscovery.class.getName())
+                    .removeParameter(REGISTRY_TYPE_KEY));
+        });
         return serviceDiscovery;
     }
 
     protected boolean shouldRegister(URL providerURL) {
+
         String side = providerURL.getParameter(SIDE_KEY);
 
         boolean should = PROVIDER_SIDE.equals(side); // Only register the Provider.
@@ -222,8 +230,10 @@ public class ServiceOrientedRegistry extends FailbackRegistry {
     @Override
     public void destroy() {
         super.destroy();
-        // stop ServiceDiscovery
-        serviceDiscovery.stop();
+        execute(() -> {
+            // stop ServiceDiscovery
+            serviceDiscovery.destroy();
+        });
     }
 
     protected void subscribeURLs(URL url, NotifyListener listener) {
@@ -429,11 +439,11 @@ public class ServiceOrientedRegistry extends FailbackRegistry {
         String version = subscribedURL.getParameter(VERSION_KEY);
         // The subscribed protocol may be null
         String protocol = subscribedURL.getParameter(PROTOCOL_KEY);
-        String metadataServiceType = getMetadataStoredType(providerInstance);
+        String metadataStorageType = getMetadataStorageType(providerInstance);
 
         try {
             MetadataService metadataService = MetadataServiceProxyFactory
-                    .getExtension(metadataServiceType == null ? DEFAULT_EXTENSION : metadataServiceType)
+                    .getExtension(metadataStorageType == null ? DEFAULT_EXTENSION : metadataStorageType)
                     .getProxy(providerInstance);
             SortedSet<String> urls = metadataService.getExportedURLs(serviceInterface, group, version, protocol);
             exportedURLs = urls.stream().map(URL::valueOf).collect(Collectors.toList());
@@ -478,13 +488,13 @@ public class ServiceOrientedRegistry extends FailbackRegistry {
     }
 
     /**
-     * Create an instance of {@link ServiceOrientedRegistry} if supported
+     * Create an instance of {@link ServiceDiscoveryRegistry} if supported
      *
      * @param registryURL the {@link URL url} of registry
      * @return <code>null</code> if not supported
      */
-    public static ServiceOrientedRegistry create(URL registryURL) {
-        return supports(registryURL) ? new ServiceOrientedRegistry(registryURL) : null;
+    public static ServiceDiscoveryRegistry create(URL registryURL) {
+        return supports(registryURL) ? new ServiceDiscoveryRegistry(registryURL) : null;
     }
 
     /**
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/service/ServiceOrientedRegistryFactory.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistryFactory.java
similarity index 89%
rename from dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/service/ServiceOrientedRegistryFactory.java
rename to dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistryFactory.java
index ea7027c..ebf3c5a 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/service/ServiceOrientedRegistryFactory.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistryFactory.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.registry.service;
+package org.apache.dubbo.registry.client;
 
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.registry.Registry;
@@ -24,7 +24,7 @@ import static org.apache.dubbo.common.constants.RegistryConstants.REGISTRY_KEY;
 import static org.apache.dubbo.common.constants.RegistryConstants.SERVICE_REGISTRY_PROTOCOL;
 import static org.apache.dubbo.registry.Constants.DEFAULT_REGISTRY;
 
-public class ServiceOrientedRegistryFactory extends AbstractRegistryFactory {
+public class ServiceDiscoveryRegistryFactory extends AbstractRegistryFactory {
 
     @Override
     protected Registry createRegistry(URL url) {
@@ -32,7 +32,7 @@ public class ServiceOrientedRegistryFactory extends AbstractRegistryFactory {
             String protocol = url.getParameter(REGISTRY_KEY, DEFAULT_REGISTRY);
             url = url.setProtocol(protocol).removeParameter(REGISTRY_KEY);
         }
-        return new ServiceOrientedRegistry(url);
+        return new ServiceDiscoveryRegistry(url);
     }
 
 }
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/service/ServiceOrientedRegistryProtocol.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistryProtocol.java
similarity index 93%
rename from dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/service/ServiceOrientedRegistryProtocol.java
rename to dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistryProtocol.java
index 733e8b8..c89c6c9 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/service/ServiceOrientedRegistryProtocol.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistryProtocol.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.registry.service;
+package org.apache.dubbo.registry.client;
 
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.registry.integration.RegistryProtocol;
@@ -25,7 +25,7 @@ import static org.apache.dubbo.common.constants.RegistryConstants.SERVICE_REGIST
 /**
  * TODO, replace RegistryProtocol completely in the future.
  */
-public class ServiceOrientedRegistryProtocol extends RegistryProtocol {
+public class ServiceDiscoveryRegistryProtocol extends RegistryProtocol {
 
     @Override
     protected URL getRegistryUrl(Invoker<?> originInvoker) {
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryStoppedEvent.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryDestroyedEvent.java
similarity index 72%
copy from dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryStoppedEvent.java
copy to dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryDestroyedEvent.java
index 406a566..2303335 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryStoppedEvent.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryDestroyedEvent.java
@@ -16,16 +16,15 @@
  */
 package org.apache.dubbo.registry.client.event;
 
-import org.apache.dubbo.event.Event;
 import org.apache.dubbo.registry.client.ServiceDiscovery;
 
 /**
- * An event raised after the {@link ServiceDiscovery Service Discovery} stopped.
+ * An event raised after the {@link ServiceDiscovery Service Discovery} destroyed.
  *
- * @see ServiceDiscovery#stop()
+ * @see ServiceDiscovery#destroy()
  * @since 2.7.4
  */
-public class ServiceDiscoveryStoppedEvent extends Event {
+public class ServiceDiscoveryDestroyedEvent extends ServiceDiscoveryEvent {
 
     /**
      * Constructs a prototypical Event.
@@ -33,16 +32,8 @@ public class ServiceDiscoveryStoppedEvent extends Event {
      * @param serviceDiscovery The instance of {@link ServiceDiscovery} as source
      * @throws IllegalArgumentException if source is null.
      */
-    public ServiceDiscoveryStoppedEvent(ServiceDiscovery serviceDiscovery) {
+    public ServiceDiscoveryDestroyedEvent(ServiceDiscovery serviceDiscovery) {
         super(serviceDiscovery);
     }
 
-    /**
-     * Get the instance of {@link ServiceDiscovery} as source
-     *
-     * @return the instance of {@link ServiceDiscovery} as source
-     */
-    public ServiceDiscovery getServiceDiscovery() {
-        return (ServiceDiscovery) getSource();
-    }
 }
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryStartingEvent.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryDestroyingEvent.java
similarity index 72%
rename from dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryStartingEvent.java
rename to dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryDestroyingEvent.java
index 9f30d67..60500ee 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryStartingEvent.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryDestroyingEvent.java
@@ -16,16 +16,15 @@
  */
 package org.apache.dubbo.registry.client.event;
 
-import org.apache.dubbo.event.Event;
 import org.apache.dubbo.registry.client.ServiceDiscovery;
 
 /**
- * An event raised when the {@link ServiceDiscovery Service Discovery} is starting.
+ * An event raised when the {@link ServiceDiscovery Service Discovery} is destroying.
  *
- * @see ServiceDiscovery#start
+ * @see ServiceDiscovery#destroy()
  * @since 2.7.4
  */
-public class ServiceDiscoveryStartingEvent extends Event {
+public class ServiceDiscoveryDestroyingEvent extends ServiceDiscoveryEvent {
 
     /**
      * Constructs a prototypical Event.
@@ -33,16 +32,8 @@ public class ServiceDiscoveryStartingEvent extends Event {
      * @param serviceDiscovery The instance of {@link ServiceDiscovery} as source
      * @throws IllegalArgumentException if source is null.
      */
-    public ServiceDiscoveryStartingEvent(ServiceDiscovery serviceDiscovery) {
+    public ServiceDiscoveryDestroyingEvent(ServiceDiscovery serviceDiscovery) {
         super(serviceDiscovery);
     }
 
-    /**
-     * Get the instance of {@link ServiceDiscovery} as source
-     *
-     * @return the instance of {@link ServiceDiscovery} as source
-     */
-    public ServiceDiscovery getServiceDiscovery() {
-        return (ServiceDiscovery) getSource();
-    }
 }
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryStoppedEvent.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryEvent.java
similarity index 70%
rename from dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryStoppedEvent.java
rename to dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryEvent.java
index 406a566..a319fd5 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryStoppedEvent.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryEvent.java
@@ -20,29 +20,30 @@ import org.apache.dubbo.event.Event;
 import org.apache.dubbo.registry.client.ServiceDiscovery;
 
 /**
- * An event raised after the {@link ServiceDiscovery Service Discovery} stopped.
+ * An abstract {@link Event} class for {@link ServiceDiscovery}
  *
- * @see ServiceDiscovery#stop()
+ * @see Event
+ * @see ServiceDiscovery
  * @since 2.7.4
  */
-public class ServiceDiscoveryStoppedEvent extends Event {
+public abstract class ServiceDiscoveryEvent extends Event {
 
     /**
      * Constructs a prototypical Event.
      *
-     * @param serviceDiscovery The instance of {@link ServiceDiscovery} as source
+     * @param serviceDiscovery The {@link ServiceDiscovery} on which the Event initially occurred.
      * @throws IllegalArgumentException if source is null.
      */
-    public ServiceDiscoveryStoppedEvent(ServiceDiscovery serviceDiscovery) {
+    public ServiceDiscoveryEvent(ServiceDiscovery serviceDiscovery) {
         super(serviceDiscovery);
     }
 
     /**
-     * Get the instance of {@link ServiceDiscovery} as source
+     * Get the {@link ServiceDiscovery} on which the Event initially occurred.
      *
-     * @return the instance of {@link ServiceDiscovery} as source
+     * @return {@link ServiceDiscovery} instance
      */
-    public ServiceDiscovery getServiceDiscovery() {
+    public final ServiceDiscovery getServiceDiscovery() {
         return (ServiceDiscovery) getSource();
     }
 }
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryStoppingEvent.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryExceptionEvent.java
similarity index 60%
copy from dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryStoppingEvent.java
copy to dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryExceptionEvent.java
index 26ea1fb..49582ab 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryStoppingEvent.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryExceptionEvent.java
@@ -16,33 +16,39 @@
  */
 package org.apache.dubbo.registry.client.event;
 
-import org.apache.dubbo.event.Event;
 import org.apache.dubbo.registry.client.ServiceDiscovery;
 
 /**
- * An event raised when the {@link ServiceDiscovery Service Discovery} is stopping.
+ * An event raised when the {@link ServiceDiscovery Service Discovery} met with some exception
  *
- * @see ServiceDiscovery#stop()
+ * @see ServiceDiscovery
+ * @see org.apache.dubbo.event.Event
  * @since 2.7.4
  */
-public class ServiceDiscoveryStoppingEvent extends Event {
+public class ServiceDiscoveryExceptionEvent extends ServiceDiscoveryEvent {
+
+    private final Exception cause;
 
     /**
      * Constructs a prototypical Event.
      *
-     * @param serviceDiscovery The instance of {@link ServiceDiscovery} as source
-     * @throws IllegalArgumentException if source is null.
+     * @param serviceDiscovery The {@link ServiceDiscovery} on which the Event initially occurred.
+     * @throws IllegalArgumentException if any argument is null.
      */
-    public ServiceDiscoveryStoppingEvent(ServiceDiscovery serviceDiscovery) {
+    public ServiceDiscoveryExceptionEvent(ServiceDiscovery serviceDiscovery, Exception cause) {
         super(serviceDiscovery);
+        if (cause == null) {
+            throw new NullPointerException("The cause of Exception must not null");
+        }
+        this.cause = cause;
     }
 
     /**
-     * Get the instance of {@link ServiceDiscovery} as source
+     * The cause of {@link Exception}
      *
-     * @return the instance of {@link ServiceDiscovery} as source
+     * @return non-nul
      */
-    public ServiceDiscovery getServiceDiscovery() {
-        return (ServiceDiscovery) getSource();
+    public Exception getCause() {
+        return cause;
     }
 }
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryStartedEvent.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryInitializedEvent.java
similarity index 72%
rename from dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryStartedEvent.java
rename to dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryInitializedEvent.java
index 08af0a6..31bcc79 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryStartedEvent.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryInitializedEvent.java
@@ -16,16 +16,16 @@
  */
 package org.apache.dubbo.registry.client.event;
 
-import org.apache.dubbo.event.Event;
+import org.apache.dubbo.common.URL;
 import org.apache.dubbo.registry.client.ServiceDiscovery;
 
 /**
- * An event raised after the {@link ServiceDiscovery Service Discovery} started
+ * An event raised after the {@link ServiceDiscovery Service Discovery} initialized
  *
- * @see ServiceDiscovery#start()
+ * @see ServiceDiscovery#initialize(URL)
  * @since 2.7.4
  */
-public class ServiceDiscoveryStartedEvent extends Event {
+public class ServiceDiscoveryInitializedEvent extends ServiceDiscoveryEvent {
 
     /**
      * Constructs a prototypical Event.
@@ -33,17 +33,8 @@ public class ServiceDiscoveryStartedEvent extends Event {
      * @param serviceDiscovery The instance of {@link ServiceDiscovery} as source
      * @throws IllegalArgumentException if source is null.
      */
-    public ServiceDiscoveryStartedEvent(ServiceDiscovery serviceDiscovery) {
+    public ServiceDiscoveryInitializedEvent(ServiceDiscovery serviceDiscovery) {
         super(serviceDiscovery);
     }
 
-    /**
-     * Get the instance of {@link ServiceDiscovery} as source
-     *
-     * @return the instance of {@link ServiceDiscovery} as source
-     */
-    public ServiceDiscovery getServiceDiscovery() {
-        return (ServiceDiscovery) getSource();
-    }
-
 }
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryStoppingEvent.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryInitializingEvent.java
similarity index 72%
rename from dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryStoppingEvent.java
rename to dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryInitializingEvent.java
index 26ea1fb..92ef4d1 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryStoppingEvent.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/ServiceDiscoveryInitializingEvent.java
@@ -16,16 +16,16 @@
  */
 package org.apache.dubbo.registry.client.event;
 
-import org.apache.dubbo.event.Event;
+import org.apache.dubbo.common.URL;
 import org.apache.dubbo.registry.client.ServiceDiscovery;
 
 /**
- * An event raised when the {@link ServiceDiscovery Service Discovery} is stopping.
+ * An event raised when the {@link ServiceDiscovery Service Discovery} is initializing.
  *
- * @see ServiceDiscovery#stop()
+ * @see ServiceDiscovery#initialize(URL)
  * @since 2.7.4
  */
-public class ServiceDiscoveryStoppingEvent extends Event {
+public class ServiceDiscoveryInitializingEvent extends ServiceDiscoveryEvent {
 
     /**
      * Constructs a prototypical Event.
@@ -33,16 +33,7 @@ public class ServiceDiscoveryStoppingEvent extends Event {
      * @param serviceDiscovery The instance of {@link ServiceDiscovery} as source
      * @throws IllegalArgumentException if source is null.
      */
-    public ServiceDiscoveryStoppingEvent(ServiceDiscovery serviceDiscovery) {
+    public ServiceDiscoveryInitializingEvent(ServiceDiscovery serviceDiscovery) {
         super(serviceDiscovery);
     }
-
-    /**
-     * Get the instance of {@link ServiceDiscovery} as source
-     *
-     * @return the instance of {@link ServiceDiscovery} as source
-     */
-    public ServiceDiscovery getServiceDiscovery() {
-        return (ServiceDiscovery) getSource();
-    }
 }
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/listener/LoggingEventListener.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/listener/LoggingEventListener.java
index ef99d6f..f2205bb 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/listener/LoggingEventListener.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/listener/LoggingEventListener.java
@@ -20,10 +20,10 @@ import org.apache.dubbo.common.logger.Logger;
 import org.apache.dubbo.common.logger.LoggerFactory;
 import org.apache.dubbo.event.Event;
 import org.apache.dubbo.event.GenericEventListener;
-import org.apache.dubbo.registry.client.event.ServiceDiscoveryStartedEvent;
-import org.apache.dubbo.registry.client.event.ServiceDiscoveryStartingEvent;
-import org.apache.dubbo.registry.client.event.ServiceDiscoveryStoppedEvent;
-import org.apache.dubbo.registry.client.event.ServiceDiscoveryStoppingEvent;
+import org.apache.dubbo.registry.client.event.ServiceDiscoveryDestroyedEvent;
+import org.apache.dubbo.registry.client.event.ServiceDiscoveryDestroyingEvent;
+import org.apache.dubbo.registry.client.event.ServiceDiscoveryInitializedEvent;
+import org.apache.dubbo.registry.client.event.ServiceDiscoveryInitializingEvent;
 import org.apache.dubbo.registry.client.event.ServiceInstancePreRegisteredEvent;
 import org.apache.dubbo.registry.client.event.ServiceInstancePreUnregisteredEvent;
 import org.apache.dubbo.registry.client.event.ServiceInstanceRegisteredEvent;
@@ -41,12 +41,12 @@ public class LoggingEventListener extends GenericEventListener {
 
     private final Logger logger = LoggerFactory.getLogger(getClass());
 
-    public void onEvent(ServiceDiscoveryStartingEvent event) {
-        info("%s is starting...", event.getServiceDiscovery());
+    public void onEvent(ServiceDiscoveryInitializingEvent event) {
+        info("%s is initializing...", event.getServiceDiscovery());
     }
 
-    public void onEvent(ServiceDiscoveryStartedEvent event) {
-        info("%s is started.", event.getServiceDiscovery());
+    public void onEvent(ServiceDiscoveryInitializedEvent event) {
+        info("%s is initialized.", event.getServiceDiscovery());
     }
 
     public void onEvent(ServiceInstancePreRegisteredEvent event) {
@@ -69,11 +69,11 @@ public class LoggingEventListener extends GenericEventListener {
         info("%s has been unregistered from %s.", event.getServiceInstance(), event.getSource());
     }
 
-    public void onEvent(ServiceDiscoveryStoppingEvent event) {
+    public void onEvent(ServiceDiscoveryDestroyingEvent event) {
         info("%s is stopping...", event.getServiceDiscovery());
     }
 
-    public void onEvent(ServiceDiscoveryStoppedEvent event) {
+    public void onEvent(ServiceDiscoveryDestroyedEvent event) {
         info("%s is stopped.", event.getServiceDiscovery());
     }
 
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/ExportedServicesRevisionMetadataCustomizer.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/ExportedServicesRevisionMetadataCustomizer.java
index 31dac6b..1045aaa 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/ExportedServicesRevisionMetadataCustomizer.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/ExportedServicesRevisionMetadataCustomizer.java
@@ -29,8 +29,9 @@ import java.util.SortedSet;
 
 import static java.lang.String.valueOf;
 import static java.util.Objects.hash;
+import static org.apache.dubbo.metadata.WritableMetadataService.getExtension;
 import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.EXPORTED_SERVICES_REVISION_KEY;
-import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.MEATADATA_STORED_TYPE_KEY;
+import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.getMetadataStorageType;
 
 /**
  * The customizer to a add the metadata that the reversion of Dubbo exported services calculates.
@@ -48,9 +49,11 @@ public class ExportedServicesRevisionMetadataCustomizer extends ServiceInstanceM
 
     @Override
     protected String buildMetadataValue(ServiceInstance serviceInstance) {
-        WritableMetadataService writableMetadataService = WritableMetadataService.getExtension(
-                serviceInstance.getMetadata().get(MEATADATA_STORED_TYPE_KEY)
-        );
+
+        String metadataStorageType = getMetadataStorageType(serviceInstance);
+
+        WritableMetadataService writableMetadataService = getExtension(metadataStorageType);
+
         SortedSet<String> exportedURLs = writableMetadataService.getExportedURLs();
         Object[] data = exportedURLs.stream()
                 .map(URL::valueOf)                       // String to URL
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/MetadataServiceURLParamsMetadataCustomizer.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/MetadataServiceURLParamsMetadataCustomizer.java
index b1baa65..8ea5a98 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/MetadataServiceURLParamsMetadataCustomizer.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/MetadataServiceURLParamsMetadataCustomizer.java
@@ -25,9 +25,10 @@ import org.apache.dubbo.registry.client.ServiceInstanceMetadataCustomizer;
 import java.util.SortedSet;
 
 import static org.apache.dubbo.metadata.MetadataService.toURLs;
-import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.MEATADATA_STORED_TYPE_KEY;
+import static org.apache.dubbo.metadata.WritableMetadataService.getExtension;
 import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.METADATA_SERVICE_URL_PARAMS_KEY;
 import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.getMetadataServiceParameter;
+import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.getMetadataStorageType;
 
 /**
  * An {@link ServiceInstanceMetadataCustomizer} to customize the {@link URL urls} of {@link MetadataService}
@@ -46,9 +47,9 @@ public class MetadataServiceURLParamsMetadataCustomizer extends ServiceInstanceM
     @Override
     public String buildMetadataValue(ServiceInstance serviceInstance) {
 
-        WritableMetadataService writableMetadataService = WritableMetadataService.getExtension(
-                serviceInstance.getMetadata().get(MEATADATA_STORED_TYPE_KEY)
-        );
+        String metadataStorageType = getMetadataStorageType(serviceInstance);
+
+        WritableMetadataService writableMetadataService = getExtension(metadataStorageType);
 
         String serviceInterface = MetadataService.class.getName();
 
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/RefreshServiceMetadataCustomizer.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/RefreshServiceMetadataCustomizer.java
index 5fd089e..3265709 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/RefreshServiceMetadataCustomizer.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/RefreshServiceMetadataCustomizer.java
@@ -4,12 +4,9 @@ import org.apache.dubbo.metadata.WritableMetadataService;
 import org.apache.dubbo.registry.client.ServiceInstance;
 import org.apache.dubbo.registry.client.ServiceInstanceCustomizer;
 
-import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_KEY;
-import static org.apache.dubbo.common.constants.CommonConstants.REVISION_KEY;
 import static org.apache.dubbo.metadata.WritableMetadataService.DEFAULT_EXTENSION;
-import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.EXPORTED_SERVICES_REVISION_KEY;
 import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.getExportedServicesRevision;
-import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.getMetadataStoredType;
+import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.getMetadataStorageType;
 import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.getSubscribedServicesRevision;
 
 /**
@@ -26,7 +23,7 @@ public class RefreshServiceMetadataCustomizer implements ServiceInstanceCustomiz
     @Override
     public void customize(ServiceInstance serviceInstance) {
         // FIXME to define the constant
-        String metadataStoredType = getMetadataStoredType(serviceInstance);
+        String metadataStoredType = getMetadataStorageType(serviceInstance);
         WritableMetadataService remoteWritableMetadataService =
                 WritableMetadataService.getExtension(metadataStoredType == null ? DEFAULT_EXTENSION : metadataStoredType);
 
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/ServiceInstanceMetadataUtils.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/ServiceInstanceMetadataUtils.java
index 329dea8..7840263 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/ServiceInstanceMetadataUtils.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/ServiceInstanceMetadataUtils.java
@@ -18,6 +18,7 @@ package org.apache.dubbo.registry.client.metadata;
 
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.metadata.MetadataService;
+import org.apache.dubbo.metadata.WritableMetadataService;
 import org.apache.dubbo.registry.client.ServiceInstance;
 
 import com.alibaba.fastjson.JSON;
@@ -30,6 +31,7 @@ import java.util.Map;
 import static java.lang.String.valueOf;
 import static java.util.Collections.emptyMap;
 import static org.apache.dubbo.common.utils.StringUtils.isBlank;
+import static org.apache.dubbo.metadata.WritableMetadataService.DEFAULT_METADATA_STORAGE_TYPE;
 import static org.apache.dubbo.registry.integration.RegistryProtocol.DEFAULT_REGISTER_PROVIDER_KEYS;
 
 /**
@@ -45,19 +47,19 @@ public class ServiceInstanceMetadataUtils {
     /**
      * The prefix of {@link MetadataService} : "dubbo.metadata-service."
      */
-    public static final String DUBBO_METADATA_SERVICE_PREFIX = "dubbo.metadata-service.";
+    public static final String METADATA_SERVICE_PREFIX = "dubbo.metadata-service.";
 
     /**
      * The key of metadata JSON of {@link MetadataService}'s {@link URL}
      */
-    public static String METADATA_SERVICE_URL_PARAMS_KEY = DUBBO_METADATA_SERVICE_PREFIX + "url-params";
+    public static String METADATA_SERVICE_URL_PARAMS_KEY = METADATA_SERVICE_PREFIX + "url-params";
 
     /**
      * The {@link URL URLs} property name of {@link MetadataService} :
      * "dubbo.metadata-service.urls", which is used to be compatible with Dubbo Spring Cloud and
      * discovery the metadata of instance
      */
-    public static final String DUBBO_METADATA_SERVICE_URLS_PROPERTY_NAME = DUBBO_METADATA_SERVICE_PREFIX + "urls";
+    public static final String METADATA_SERVICE_URLS_PROPERTY_NAME = METADATA_SERVICE_PREFIX + "urls";
 
     /**
      * The key of The revision for all exported Dubbo services.
@@ -70,9 +72,9 @@ public class ServiceInstanceMetadataUtils {
     public static String SUBSCRIBER_SERVICES_REVISION_KEY = "dubbo.subscribed-services.revision";
 
     /**
-     * The key of metadata store type.
+     * The key of metadata storage type.
      */
-    public static String MEATADATA_STORED_TYPE_KEY = "dubbo.metadata.stored-type";
+    public static String METADATA_STORAGE_TYPE_KEY = "dubbo.metadata.storage-type";
 
     /**
      * The {@link URL url's} parameter name of Dubbo Provider host
@@ -181,14 +183,37 @@ public class ServiceInstanceMetadataUtils {
     }
 
     /**
-     * The metadata is stored in the type used to which {@link org.apache.dubbo.metadata.WritableMetadataService} instance.
+     * Get metadata's storage type
+     *
+     * @param registryURL the {@link URL} to connect the registry
+     * @return if not found in {@link URL#getParameters() parameters} of {@link URL registry URL}, return
+     * {@link WritableMetadataService#DEFAULT_METADATA_STORAGE_TYPE "default"}
+     */
+    public static String getMetadataStorageType(URL registryURL) {
+        return registryURL.getParameter(METADATA_STORAGE_TYPE_KEY, DEFAULT_METADATA_STORAGE_TYPE);
+    }
+
+    /**
+     * Get the metadata's storage type is used to which {@link WritableMetadataService} instance.
      *
      * @param serviceInstance the specified {@link ServiceInstance}
-     * @return <code>null</code> if not exits
+     * @return if not found in {@link ServiceInstance#getMetadata() metadata} of {@link ServiceInstance}, return
+     * {@link WritableMetadataService#DEFAULT_METADATA_STORAGE_TYPE "default"}
+     */
+    public static String getMetadataStorageType(ServiceInstance serviceInstance) {
+        Map<String, String> metadata = serviceInstance.getMetadata();
+        return metadata.getOrDefault(METADATA_STORAGE_TYPE_KEY, DEFAULT_METADATA_STORAGE_TYPE);
+    }
+
+    /**
+     * Set the metadata storage type in specified {@link ServiceInstance service instance}
+     *
+     * @param serviceInstance      {@link ServiceInstance service instance}
+     * @param isDefaultStorageType is default storage type or not
      */
-    public static String getMetadataStoredType(ServiceInstance serviceInstance) {
+    public static void setMetadataStorageType(ServiceInstance serviceInstance, boolean isDefaultStorageType) {
         Map<String, String> metadata = serviceInstance.getMetadata();
-        return metadata.get(MEATADATA_STORED_TYPE_KEY);
+        metadata.put(METADATA_STORAGE_TYPE_KEY, WritableMetadataService.getMetadataStorageType(isDefaultStorageType));
     }
 
     private static void setProviderHostParam(Map<String, String> params, URL providerURL) {
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/SpringCloudMetadataServiceURLBuilder.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/SpringCloudMetadataServiceURLBuilder.java
index 7eb3664..efc3253 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/SpringCloudMetadataServiceURLBuilder.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/SpringCloudMetadataServiceURLBuilder.java
@@ -27,7 +27,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.stream.Collectors;
 
-import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.DUBBO_METADATA_SERVICE_URLS_PROPERTY_NAME;
+import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.METADATA_SERVICE_URLS_PROPERTY_NAME;
 
 /**
  * The {@link MetadataServiceURLBuilder} implementation for The standard Dubbo scenario
@@ -39,7 +39,7 @@ public class SpringCloudMetadataServiceURLBuilder implements MetadataServiceURLB
     @Override
     public List<URL> build(ServiceInstance serviceInstance) {
         Map<String, String> metadata = serviceInstance.getMetadata();
-        String dubboURLsJSON = metadata.get(DUBBO_METADATA_SERVICE_URLS_PROPERTY_NAME);
+        String dubboURLsJSON = metadata.get(METADATA_SERVICE_URLS_PROPERTY_NAME);
         if (StringUtils.isBlank(dubboURLsJSON)) {
             return Collections.emptyList();
         }
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/SubscribedServicesRevisionMetadataCustomizer.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/SubscribedServicesRevisionMetadataCustomizer.java
index ca89b26..c0e2c4a 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/SubscribedServicesRevisionMetadataCustomizer.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/SubscribedServicesRevisionMetadataCustomizer.java
@@ -29,8 +29,9 @@ import java.util.SortedSet;
 
 import static java.lang.String.valueOf;
 import static java.util.Objects.hash;
-import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.MEATADATA_STORED_TYPE_KEY;
+import static org.apache.dubbo.metadata.WritableMetadataService.getExtension;
 import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.SUBSCRIBER_SERVICES_REVISION_KEY;
+import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.getMetadataStorageType;
 
 /**
  * The customizer to a add the metadata that the reversion of Dubbo subscribed services calculates.
@@ -48,9 +49,11 @@ public class SubscribedServicesRevisionMetadataCustomizer extends ServiceInstanc
 
     @Override
     protected String buildMetadataValue(ServiceInstance serviceInstance) {
-        WritableMetadataService writableMetadataService = WritableMetadataService.getExtension(
-                serviceInstance.getMetadata().get(MEATADATA_STORED_TYPE_KEY)
-        );
+
+        String metadataStorageType = getMetadataStorageType(serviceInstance);
+
+        WritableMetadataService writableMetadataService = getExtension(metadataStorageType);
+
         SortedSet<String> subscribedURLs = writableMetadataService.getSubscribedURLs();
         Object[] data = subscribedURLs.stream()
                 .map(URL::valueOf)                       // String to URL
diff --git a/dubbo-registry/dubbo-registry-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.RegistryFactory b/dubbo-registry/dubbo-registry-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.RegistryFactory
index d533e06..0dc7002 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.RegistryFactory
+++ b/dubbo-registry/dubbo-registry-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.RegistryFactory
@@ -1 +1 @@
-service-oriented-registry=org.apache.dubbo.registry.service.ServiceOrientedRegistryFactory
\ No newline at end of file
+service-discovery-registry=org.apache.dubbo.registry.client.ServiceDiscoveryRegistryFactory
\ No newline at end of file
diff --git a/dubbo-registry/dubbo-registry-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.client.ServiceDiscovery b/dubbo-registry/dubbo-registry-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.client.ServiceDiscovery
new file mode 100644
index 0000000..d64d12c
--- /dev/null
+++ b/dubbo-registry/dubbo-registry-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.client.ServiceDiscovery
@@ -0,0 +1 @@
+file=org.apache.dubbo.registry.client.FileSystemServiceDiscovery
\ No newline at end of file
diff --git a/dubbo-registry/dubbo-registry-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.client.ServiceDiscoveryFactory b/dubbo-registry/dubbo-registry-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.client.ServiceDiscoveryFactory
new file mode 100644
index 0000000..d30ea0c
--- /dev/null
+++ b/dubbo-registry/dubbo-registry-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.client.ServiceDiscoveryFactory
@@ -0,0 +1 @@
+default=org.apache.dubbo.registry.client.DefaultServiceDiscoveryFactory
\ No newline at end of file
diff --git a/dubbo-registry/dubbo-registry-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.Protocol b/dubbo-registry/dubbo-registry-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.Protocol
index ed2df31..c8903b0 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.Protocol
+++ b/dubbo-registry/dubbo-registry-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.Protocol
@@ -1,2 +1,2 @@
 registry=org.apache.dubbo.registry.integration.RegistryProtocol
-service-oriented-registry=org.apache.dubbo.registry.service.ServiceOrientedRegistryProtocol
\ No newline at end of file
+service-discovery-registry=org.apache.dubbo.registry.client.ServiceDiscoveryRegistryProtocol
\ No newline at end of file
diff --git a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/EventPublishingServiceDiscoveryTest.java b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/EventPublishingServiceDiscoveryTest.java
index 5bc2729..97ccf8e 100644
--- a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/EventPublishingServiceDiscoveryTest.java
+++ b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/EventPublishingServiceDiscoveryTest.java
@@ -19,10 +19,10 @@ package org.apache.dubbo.registry.client;
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.event.EventDispatcher;
 import org.apache.dubbo.event.EventListener;
-import org.apache.dubbo.registry.client.event.ServiceDiscoveryStartedEvent;
-import org.apache.dubbo.registry.client.event.ServiceDiscoveryStartingEvent;
-import org.apache.dubbo.registry.client.event.ServiceDiscoveryStoppedEvent;
-import org.apache.dubbo.registry.client.event.ServiceDiscoveryStoppingEvent;
+import org.apache.dubbo.registry.client.event.ServiceDiscoveryDestroyedEvent;
+import org.apache.dubbo.registry.client.event.ServiceDiscoveryDestroyingEvent;
+import org.apache.dubbo.registry.client.event.ServiceDiscoveryInitializedEvent;
+import org.apache.dubbo.registry.client.event.ServiceDiscoveryInitializingEvent;
 import org.apache.dubbo.registry.client.event.ServiceInstancePreRegisteredEvent;
 import org.apache.dubbo.registry.client.event.ServiceInstanceRegisteredEvent;
 
@@ -53,7 +53,7 @@ public class EventPublishingServiceDiscoveryTest {
     private ServiceDiscoveryTest serviceDiscoveryTest;
 
     @BeforeEach
-    public void init() {
+    public void init() throws Exception {
 
         // remove all EventListeners
         eventDispatcher.removeAllEventListeners();
@@ -67,17 +67,17 @@ public class EventPublishingServiceDiscoveryTest {
         serviceDiscoveryTest.setServiceDiscovery(serviceDiscovery);
 
         // ServiceDiscoveryStartingEvent
-        eventDispatcher.addEventListener(new EventListener<ServiceDiscoveryStartingEvent>() {
+        eventDispatcher.addEventListener(new EventListener<ServiceDiscoveryInitializingEvent>() {
             @Override
-            public void onEvent(ServiceDiscoveryStartingEvent event) {
+            public void onEvent(ServiceDiscoveryInitializingEvent event) {
                 assertEquals(delegate, event.getServiceDiscovery());
             }
         });
 
         // ServiceDiscoveryStartedEvent
-        eventDispatcher.addEventListener(new EventListener<ServiceDiscoveryStartedEvent>() {
+        eventDispatcher.addEventListener(new EventListener<ServiceDiscoveryInitializedEvent>() {
             @Override
-            public void onEvent(ServiceDiscoveryStartedEvent event) {
+            public void onEvent(ServiceDiscoveryInitializedEvent event) {
                 assertEquals(delegate, event.getServiceDiscovery());
             }
         });
@@ -98,43 +98,43 @@ public class EventPublishingServiceDiscoveryTest {
             }
         });
 
-        assertFalse(serviceDiscovery.isStarted());
-        assertFalse(serviceDiscovery.isStopped());
+        assertFalse(serviceDiscovery.isInitialized());
+        assertFalse(serviceDiscovery.isDestroyed());
 
         // test start()
         serviceDiscoveryTest.init();
 
-        assertTrue(serviceDiscovery.isStarted());
-        assertFalse(serviceDiscovery.isStopped());
+        assertTrue(serviceDiscovery.isInitialized());
+        assertFalse(serviceDiscovery.isDestroyed());
     }
 
     @AfterEach
-    public void destroy() {
+    public void destroy() throws Exception {
 
         // ServiceDiscoveryStoppingEvent
-        eventDispatcher.addEventListener(new EventListener<ServiceDiscoveryStoppingEvent>() {
+        eventDispatcher.addEventListener(new EventListener<ServiceDiscoveryDestroyingEvent>() {
             @Override
-            public void onEvent(ServiceDiscoveryStoppingEvent event) {
+            public void onEvent(ServiceDiscoveryDestroyingEvent event) {
                 assertEquals(delegate, event.getServiceDiscovery());
             }
         });
 
         // ServiceDiscoveryStoppedEvent
-        eventDispatcher.addEventListener(new EventListener<ServiceDiscoveryStoppedEvent>() {
+        eventDispatcher.addEventListener(new EventListener<ServiceDiscoveryDestroyedEvent>() {
             @Override
-            public void onEvent(ServiceDiscoveryStoppedEvent event) {
+            public void onEvent(ServiceDiscoveryDestroyedEvent event) {
                 assertEquals(delegate, event.getServiceDiscovery());
             }
         });
 
-        assertTrue(serviceDiscovery.isStarted());
-        assertFalse(serviceDiscovery.isStopped());
+        assertTrue(serviceDiscovery.isInitialized());
+        assertFalse(serviceDiscovery.isDestroyed());
 
         // test stop()
         serviceDiscoveryTest.destroy();
 
-        assertTrue(serviceDiscovery.isStarted());
-        assertTrue(serviceDiscovery.isStopped());
+        assertTrue(serviceDiscovery.isInitialized());
+        assertTrue(serviceDiscovery.isDestroyed());
     }
 
     @Test
diff --git a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/InMemoryServiceDiscovery.java b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/InMemoryServiceDiscovery.java
index a8954c5..6f7c3ea 100644
--- a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/InMemoryServiceDiscovery.java
+++ b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/InMemoryServiceDiscovery.java
@@ -16,6 +16,7 @@
  */
 package org.apache.dubbo.registry.client;
 
+import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.utils.DefaultPage;
 import org.apache.dubbo.common.utils.Page;
 import org.apache.dubbo.event.EventDispatcher;
@@ -95,12 +96,12 @@ public class InMemoryServiceDiscovery implements ServiceDiscovery {
     }
 
     @Override
-    public void start() {
+    public void initialize(URL registryURL) throws Exception {
 
     }
 
     @Override
-    public void stop() {
+    public void destroy() {
     }
 
     @Override
diff --git a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/InMemoryServiceDiscoveryFactory.java b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/InMemoryServiceDiscoveryFactory.java
deleted file mode 100644
index 6264611..0000000
--- a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/InMemoryServiceDiscoveryFactory.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.dubbo.registry.client;
-
-import org.apache.dubbo.common.URL;
-
-/**
- * {@link InMemoryServiceDiscovery} Factory
- *
- * @see InMemoryServiceDiscovery
- * @since 2.7.4
- */
-public class InMemoryServiceDiscoveryFactory extends AbstractServiceDiscoveryFactory {
-
-    @Override
-    public ServiceDiscovery createDiscovery(URL connectionURL) {
-        return new InMemoryServiceDiscovery();
-    }
-}
diff --git a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/ServiceDiscoveryTest.java b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/ServiceDiscoveryTest.java
index aa60741..1d0e0d3 100644
--- a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/ServiceDiscoveryTest.java
+++ b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/ServiceDiscoveryTest.java
@@ -41,18 +41,18 @@ public class ServiceDiscoveryTest {
     private ServiceDiscovery serviceDiscovery;
 
     @BeforeEach
-    public void init() {
+    public void init() throws Exception {
         if (serviceDiscovery == null) {
             setServiceDiscovery(new InMemoryServiceDiscovery());
         }
         // test start()
-        serviceDiscovery.start();
+        serviceDiscovery.initialize(null);
     }
 
     @AfterEach
-    public void destroy() {
+    public void destroy() throws Exception {
         // test stop()
-        serviceDiscovery.stop();
+        serviceDiscovery.destroy();
     }
 
     @Test
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 ddd3aec..f594a43 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
@@ -19,10 +19,10 @@ package org.apache.dubbo.registry.client.event.listener;
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.registry.client.FileSystemServiceDiscovery;
 import org.apache.dubbo.registry.client.ServiceDiscovery;
-import org.apache.dubbo.registry.client.event.ServiceDiscoveryStartedEvent;
-import org.apache.dubbo.registry.client.event.ServiceDiscoveryStartingEvent;
-import org.apache.dubbo.registry.client.event.ServiceDiscoveryStoppedEvent;
-import org.apache.dubbo.registry.client.event.ServiceDiscoveryStoppingEvent;
+import org.apache.dubbo.registry.client.event.ServiceDiscoveryDestroyedEvent;
+import org.apache.dubbo.registry.client.event.ServiceDiscoveryDestroyingEvent;
+import org.apache.dubbo.registry.client.event.ServiceDiscoveryInitializedEvent;
+import org.apache.dubbo.registry.client.event.ServiceDiscoveryInitializingEvent;
 import org.apache.dubbo.registry.client.event.ServiceInstancePreRegisteredEvent;
 import org.apache.dubbo.registry.client.event.ServiceInstancePreUnregisteredEvent;
 import org.apache.dubbo.registry.client.event.ServiceInstanceRegisteredEvent;
@@ -50,16 +50,19 @@ public class LoggingEventListenerTest {
     }
 
     @Test
-    public void testOnEvent() {
+    public void testOnEvent() throws Exception {
 
         URL connectionURL = URL.valueOf("file:///Users/Home");
-        ServiceDiscovery serviceDiscovery = new FileSystemServiceDiscovery(connectionURL);
+
+        ServiceDiscovery serviceDiscovery = new FileSystemServiceDiscovery();
+
+        serviceDiscovery.initialize(connectionURL);
 
         // ServiceDiscoveryStartingEvent
-        listener.onEvent(new ServiceDiscoveryStartingEvent(serviceDiscovery));
+        listener.onEvent(new ServiceDiscoveryInitializingEvent(serviceDiscovery));
 
         // ServiceDiscoveryStartedEvent
-        listener.onEvent(new ServiceDiscoveryStartedEvent(serviceDiscovery));
+        listener.onEvent(new ServiceDiscoveryInitializedEvent(serviceDiscovery));
 
         // ServiceInstancePreRegisteredEvent
         listener.onEvent(new ServiceInstancePreRegisteredEvent(serviceDiscovery, createInstance()));
@@ -77,9 +80,9 @@ public class LoggingEventListenerTest {
         listener.onEvent(new ServiceInstanceUnregisteredEvent(serviceDiscovery, createInstance()));
 
         // ServiceDiscoveryStoppingEvent
-        listener.onEvent(new ServiceDiscoveryStoppingEvent(serviceDiscovery));
+        listener.onEvent(new ServiceDiscoveryDestroyingEvent(serviceDiscovery));
 
         // ServiceDiscoveryStoppedEvent
-        listener.onEvent(new ServiceDiscoveryStoppedEvent(serviceDiscovery));
+        listener.onEvent(new ServiceDiscoveryDestroyedEvent(serviceDiscovery));
     }
 }
diff --git a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/support/ServiceOrientedRegistryTest.java b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/support/ServiceOrientedRegistryTest.java
index 5d9157d..f884b9d 100644
--- a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/support/ServiceOrientedRegistryTest.java
+++ b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/support/ServiceOrientedRegistryTest.java
@@ -19,7 +19,7 @@ package org.apache.dubbo.registry.support;
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.metadata.WritableMetadataService;
 import org.apache.dubbo.registry.NotifyListener;
-import org.apache.dubbo.registry.service.ServiceOrientedRegistry;
+import org.apache.dubbo.registry.client.ServiceDiscoveryRegistry;
 
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
@@ -43,7 +43,7 @@ import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
 /**
- * {@link ServiceOrientedRegistry} Test
+ * {@link ServiceDiscoveryRegistry} Test
  *
  * @since 2.7.4
  */
@@ -72,20 +72,20 @@ public class ServiceOrientedRegistryTest {
 
     private WritableMetadataService metadataService;
 
-    private ServiceOrientedRegistry registry;
+    private ServiceDiscoveryRegistry registry;
 
     private NotifyListener notifyListener;
 
     @BeforeEach
     public void init() {
-        registry = ServiceOrientedRegistry.create(registryURL);
+        registry = ServiceDiscoveryRegistry.create(registryURL);
         metadataService = WritableMetadataService.getDefaultExtension();
         notifyListener = new MyNotifyListener();
     }
 
     @Test
     public void testSupports() {
-        assertTrue(ServiceOrientedRegistry.supports(registryURL));
+        assertTrue(ServiceDiscoveryRegistry.supports(registryURL));
     }
 
     @Test
diff --git a/dubbo-registry/dubbo-registry-api/src/test/resources/META-INF/services/org.apache.dubbo.registry.client.ServiceDiscoveryFactory b/dubbo-registry/dubbo-registry-api/src/test/resources/META-INF/services/org.apache.dubbo.registry.client.ServiceDiscovery
similarity index 86%
rename from dubbo-registry/dubbo-registry-api/src/test/resources/META-INF/services/org.apache.dubbo.registry.client.ServiceDiscoveryFactory
rename to dubbo-registry/dubbo-registry-api/src/test/resources/META-INF/services/org.apache.dubbo.registry.client.ServiceDiscovery
index 2a28074..53725cb 100644
--- a/dubbo-registry/dubbo-registry-api/src/test/resources/META-INF/services/org.apache.dubbo.registry.client.ServiceDiscoveryFactory
+++ b/dubbo-registry/dubbo-registry-api/src/test/resources/META-INF/services/org.apache.dubbo.registry.client.ServiceDiscovery
@@ -1 +1 @@
-in-memory=org.apache.dubbo.registry.client.InMemoryServiceDiscoveryFactory
\ No newline at end of file
+in-memory=org.apache.dubbo.registry.client.InMemoryServiceDiscovery
\ No newline at end of file
diff --git a/dubbo-registry/dubbo-registry-consul/src/main/java/org/apache/dubbo/registry/consul/ConsulServiceDiscovery.java b/dubbo-registry/dubbo-registry-consul/src/main/java/org/apache/dubbo/registry/consul/ConsulServiceDiscovery.java
index 503823a..22e44a1 100644
--- a/dubbo-registry/dubbo-registry-consul/src/main/java/org/apache/dubbo/registry/consul/ConsulServiceDiscovery.java
+++ b/dubbo-registry/dubbo-registry-consul/src/main/java/org/apache/dubbo/registry/consul/ConsulServiceDiscovery.java
@@ -63,6 +63,7 @@ import static org.apache.dubbo.registry.consul.AbstractConsulRegistry.WATCH_TIME
  * 2019-07-31
  */
 public class ConsulServiceDiscovery implements ServiceDiscovery, EventListener<ServiceInstancesChangedEvent> {
+
     private static final Logger logger = LoggerFactory.getLogger(ConsulServiceDiscovery.class);
 
     private ConsulClient client;
@@ -72,28 +73,24 @@ public class ConsulServiceDiscovery implements ServiceDiscovery, EventListener<S
     private long checkPassInterval;
     private URL url;
 
-    public ConsulServiceDiscovery(URL url) {
-        String host = url.getHost();
-        int port = url.getPort() != 0 ? url.getPort() : DEFAULT_PORT;
-        checkPassInterval = url.getParameter(CHECK_PASS_INTERVAL, DEFAULT_CHECK_PASS_INTERVAL);
-        client = new ConsulClient(host, port);
-        ttlScheduler = new TtlScheduler(checkPassInterval, client);
-        this.url = url;
-    }
-
     @Override
     public void onEvent(ServiceInstancesChangedEvent event) {
 
     }
 
     @Override
-    public void start() {
-
+    public void initialize(URL registryURL) throws Exception {
+        this.url = registryURL;
+        String host = url.getHost();
+        int port = url.getPort() != 0 ? url.getPort() : DEFAULT_PORT;
+        checkPassInterval = url.getParameter(CHECK_PASS_INTERVAL, DEFAULT_CHECK_PASS_INTERVAL);
+        client = new ConsulClient(host, port);
+        ttlScheduler = new TtlScheduler(checkPassInterval, client);
+        this.url = url;
     }
 
     @Override
-    public void stop() {
-
+    public void destroy() {
     }
 
     @Override
diff --git a/dubbo-registry/dubbo-registry-consul/src/main/java/org/apache/dubbo/registry/consul/ConsulServiceDiscoveryFactory.java b/dubbo-registry/dubbo-registry-consul/src/main/java/org/apache/dubbo/registry/consul/ConsulServiceDiscoveryFactory.java
deleted file mode 100644
index 95b4213..0000000
--- a/dubbo-registry/dubbo-registry-consul/src/main/java/org/apache/dubbo/registry/consul/ConsulServiceDiscoveryFactory.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.dubbo.registry.consul;
-
-import org.apache.dubbo.common.URL;
-import org.apache.dubbo.registry.client.AbstractServiceDiscoveryFactory;
-import org.apache.dubbo.registry.client.ServiceDiscovery;
-
-/**
- * 2019-07-31
- */
-public class ConsulServiceDiscoveryFactory extends AbstractServiceDiscoveryFactory {
-    @Override
-    public ServiceDiscovery createDiscovery(URL connectionURL) {
-        return new ConsulServiceDiscovery(connectionURL);
-    }
-}
diff --git a/dubbo-registry/dubbo-registry-consul/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.client.ServiceDiscovery b/dubbo-registry/dubbo-registry-consul/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.client.ServiceDiscovery
new file mode 100644
index 0000000..e46973b
--- /dev/null
+++ b/dubbo-registry/dubbo-registry-consul/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.client.ServiceDiscovery
@@ -0,0 +1 @@
+consul=org.apache.dubbo.registry.consul.ConsulServiceDiscovery
\ No newline at end of file
diff --git a/dubbo-registry/dubbo-registry-consul/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.client.ServiceDiscoveryFactory b/dubbo-registry/dubbo-registry-consul/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.client.ServiceDiscoveryFactory
deleted file mode 100644
index a0f1252..0000000
--- a/dubbo-registry/dubbo-registry-consul/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.client.ServiceDiscoveryFactory
+++ /dev/null
@@ -1 +0,0 @@
-consul=org.apache.dubbo.registry.consul.ConsulServiceDiscoveryFactory
\ No newline at end of file
diff --git a/dubbo-registry/dubbo-registry-etcd3/src/main/java/org/apache/dubbo/registry/etcd/EtcdServiceDiscovery.java b/dubbo-registry/dubbo-registry-etcd3/src/main/java/org/apache/dubbo/registry/etcd/EtcdServiceDiscovery.java
index a684c2c..b5705e9 100644
--- a/dubbo-registry/dubbo-registry-etcd3/src/main/java/org/apache/dubbo/registry/etcd/EtcdServiceDiscovery.java
+++ b/dubbo-registry/dubbo-registry-etcd3/src/main/java/org/apache/dubbo/registry/etcd/EtcdServiceDiscovery.java
@@ -17,6 +17,7 @@
 package org.apache.dubbo.registry.etcd;
 
 import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.extension.ExtensionLoader;
 import org.apache.dubbo.common.logger.Logger;
 import org.apache.dubbo.common.logger.LoggerFactory;
 import org.apache.dubbo.common.utils.ConcurrentHashSet;
@@ -57,15 +58,26 @@ public class EtcdServiceDiscovery implements ServiceDiscovery, EventListener<Ser
     private final Map<String, ChildListener> childListenerMap = new ConcurrentHashMap<>();
 
     private final ConcurrentMap<URL, ConcurrentMap<NotifyListener, ChildListener>> etcdListeners = new ConcurrentHashMap<>();
-    private final EtcdClient etcdClient;
-    private final EventDispatcher dispatcher;
+
+    private EtcdClient etcdClient;
+    private EventDispatcher dispatcher;
     private ServiceInstance serviceInstance;
 
-    public EtcdServiceDiscovery(URL url, EtcdTransporter etcdTransporter) {
-        if (url.isAnyHost()) {
-            throw new IllegalStateException("Service discovery address is invalid, actual: '" + url.getHost() + "'");
+    @Override
+    public void onEvent(ServiceInstancesChangedEvent event) {
+        registerServiceWatcher(event.getServiceName());
+    }
+
+    @Override
+    public void initialize(URL registryURL) throws Exception {
+
+        EtcdTransporter etcdTransporter = ExtensionLoader.getExtensionLoader(EtcdTransporter.class).getAdaptiveExtension();
+
+        if (registryURL.isAnyHost()) {
+            throw new IllegalStateException("Service discovery address is invalid, actual: '" + registryURL.getHost() + "'");
         }
-        etcdClient = etcdTransporter.connect(url);
+
+        etcdClient = etcdTransporter.connect(registryURL);
 
         etcdClient.addStateListener(state -> {
             if (state == StateListener.CONNECTED) {
@@ -82,17 +94,7 @@ public class EtcdServiceDiscovery implements ServiceDiscovery, EventListener<Ser
     }
 
     @Override
-    public void onEvent(ServiceInstancesChangedEvent event) {
-        registerServiceWatcher(event.getServiceName());
-    }
-
-    @Override
-    public void start() {
-
-    }
-
-    @Override
-    public void stop() {
+    public void destroy() {
 
     }
 
diff --git a/dubbo-registry/dubbo-registry-etcd3/src/main/java/org/apache/dubbo/registry/etcd/EtcdServiceDiscoveryFactory.java b/dubbo-registry/dubbo-registry-etcd3/src/main/java/org/apache/dubbo/registry/etcd/EtcdServiceDiscoveryFactory.java
deleted file mode 100644
index fb75006..0000000
--- a/dubbo-registry/dubbo-registry-etcd3/src/main/java/org/apache/dubbo/registry/etcd/EtcdServiceDiscoveryFactory.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.dubbo.registry.etcd;
-
-import org.apache.dubbo.common.URL;
-import org.apache.dubbo.registry.client.AbstractServiceDiscoveryFactory;
-import org.apache.dubbo.registry.client.ServiceDiscovery;
-import org.apache.dubbo.remoting.etcd.EtcdTransporter;
-
-/**
- * 2019-07-08
- */
-public class EtcdServiceDiscoveryFactory extends AbstractServiceDiscoveryFactory {
-
-    private EtcdTransporter etcdTransporter;
-
-    public void setEtcdTransporter(EtcdTransporter etcdTransporter) {
-        this.etcdTransporter = etcdTransporter;
-    }
-
-    @Override
-    public ServiceDiscovery createDiscovery(URL connectionURL) {
-        return new EtcdServiceDiscovery(connectionURL, etcdTransporter);
-    }
-}
diff --git a/dubbo-registry/dubbo-registry-etcd3/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.client.ServiceDiscovery b/dubbo-registry/dubbo-registry-etcd3/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.client.ServiceDiscovery
new file mode 100644
index 0000000..60f47ac
--- /dev/null
+++ b/dubbo-registry/dubbo-registry-etcd3/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.client.ServiceDiscovery
@@ -0,0 +1 @@
+etcd=org.apache.dubbo.registry.etcd.EtcdServiceDiscovery
\ No newline at end of file
diff --git a/dubbo-registry/dubbo-registry-etcd3/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.client.ServiceDiscoveryFactory b/dubbo-registry/dubbo-registry-etcd3/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.client.ServiceDiscoveryFactory
deleted file mode 100644
index ad5937a..0000000
--- a/dubbo-registry/dubbo-registry-etcd3/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.client.ServiceDiscoveryFactory
+++ /dev/null
@@ -1 +0,0 @@
-etcd3=org.apache.dubbo.registry.etcd.EtcdServiceDiscoveryFactory
diff --git a/dubbo-registry/dubbo-registry-nacos/src/main/java/org/apache/dubbo/registry/nacos/NacosServiceDiscovery.java b/dubbo-registry/dubbo-registry-nacos/src/main/java/org/apache/dubbo/registry/nacos/NacosServiceDiscovery.java
index 0db7430..8863e89 100644
--- a/dubbo-registry/dubbo-registry-nacos/src/main/java/org/apache/dubbo/registry/nacos/NacosServiceDiscovery.java
+++ b/dubbo-registry/dubbo-registry-nacos/src/main/java/org/apache/dubbo/registry/nacos/NacosServiceDiscovery.java
@@ -51,24 +51,18 @@ public class NacosServiceDiscovery implements ServiceDiscovery {
 
     private final Logger logger = LoggerFactory.getLogger(getClass());
 
-    private final URL connectionURL;
-
-    private final String group;
+    private String group;
 
     private NamingService namingService;
 
-    public NacosServiceDiscovery(URL connectionURL) {
-        this.connectionURL = connectionURL;
-        this.group = getGroup(connectionURL);
-    }
-
     @Override
-    public void start() {
-        this.namingService = createNamingService(connectionURL);
+    public void initialize(URL registryURL) throws Exception {
+        this.namingService = createNamingService(registryURL);
+        this.group = getGroup(registryURL);
     }
 
     @Override
-    public void stop() {
+    public void destroy() {
         this.namingService = null;
     }
 
diff --git a/dubbo-registry/dubbo-registry-nacos/src/main/java/org/apache/dubbo/registry/nacos/NacosServiceDiscoveryFactory.java b/dubbo-registry/dubbo-registry-nacos/src/main/java/org/apache/dubbo/registry/nacos/NacosServiceDiscoveryFactory.java
deleted file mode 100644
index e2ac08b..0000000
--- a/dubbo-registry/dubbo-registry-nacos/src/main/java/org/apache/dubbo/registry/nacos/NacosServiceDiscoveryFactory.java
+++ /dev/null
@@ -1,36 +0,0 @@
-package org.apache.dubbo.registry.nacos;/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-import org.apache.dubbo.common.URL;
-import org.apache.dubbo.registry.client.AbstractServiceDiscoveryFactory;
-import org.apache.dubbo.registry.client.ServiceDiscovery;
-import org.apache.dubbo.registry.client.ServiceDiscoveryFactory;
-
-/**
- * Nacos {@link ServiceDiscoveryFactory}
- *
- * @see ServiceDiscoveryFactory
- * @see ServiceDiscovery
- * @since 2.7.4
- */
-public class NacosServiceDiscoveryFactory extends AbstractServiceDiscoveryFactory {
-
-    @Override
-    public ServiceDiscovery createDiscovery(URL connectionURL) {
-        return new NacosServiceDiscovery(connectionURL);
-    }
-}
diff --git a/dubbo-registry/dubbo-registry-nacos/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.client.ServiceDiscovery b/dubbo-registry/dubbo-registry-nacos/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.client.ServiceDiscovery
new file mode 100644
index 0000000..e3819e0
--- /dev/null
+++ b/dubbo-registry/dubbo-registry-nacos/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.client.ServiceDiscovery
@@ -0,0 +1 @@
+nacos=org.apache.dubbo.registry.nacos.NacosServiceDiscovery
\ No newline at end of file
diff --git a/dubbo-registry/dubbo-registry-nacos/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.client.ServiceDiscoveryFactory b/dubbo-registry/dubbo-registry-nacos/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.client.ServiceDiscoveryFactory
deleted file mode 100644
index 4fc3f4a..0000000
--- a/dubbo-registry/dubbo-registry-nacos/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.client.ServiceDiscoveryFactory
+++ /dev/null
@@ -1 +0,0 @@
-nacos=org.apache.dubbo.registry.nacos.NacosServiceDiscoveryFactory
\ No newline at end of file
diff --git a/dubbo-registry/dubbo-registry-zookeeper/src/main/java/org/apache/dubbo/registry/zookeeper/ZookeeperServiceDiscovery.java b/dubbo-registry/dubbo-registry-zookeeper/src/main/java/org/apache/dubbo/registry/zookeeper/ZookeeperServiceDiscovery.java
index 9ee5dde..feac093 100644
--- a/dubbo-registry/dubbo-registry-zookeeper/src/main/java/org/apache/dubbo/registry/zookeeper/ZookeeperServiceDiscovery.java
+++ b/dubbo-registry/dubbo-registry-zookeeper/src/main/java/org/apache/dubbo/registry/zookeeper/ZookeeperServiceDiscovery.java
@@ -56,25 +56,31 @@ public class ZookeeperServiceDiscovery implements ServiceDiscovery, EventListene
 
     private final Logger logger = LoggerFactory.getLogger(getClass());
 
-    private final CuratorFramework curatorFramework;
+    private EventDispatcher dispatcher;
 
-    private final String rootPath;
+    private CuratorFramework curatorFramework;
 
-    private final org.apache.curator.x.discovery.ServiceDiscovery<ZookeeperInstance> serviceDiscovery;
+    private String rootPath;
 
-    private final EventDispatcher dispatcher;
+    private org.apache.curator.x.discovery.ServiceDiscovery<ZookeeperInstance> serviceDiscovery;
 
     /**
      * The Key is watched Zookeeper path, the value is an instance of {@link CuratorWatcher}
      */
     private final Map<String, CuratorWatcher> watcherCaches = new ConcurrentHashMap<>();
 
-    public ZookeeperServiceDiscovery(URL connectionURL) throws Exception {
-        this.curatorFramework = buildCuratorFramework(connectionURL);
-        this.rootPath = ROOT_PATH.getParameterValue(connectionURL);
-        this.serviceDiscovery = buildServiceDiscovery(curatorFramework, rootPath);
+    @Override
+    public void initialize(URL registryURL) throws Exception {
         this.dispatcher = EventDispatcher.getDefaultExtension();
         this.dispatcher.addEventListener(this);
+        this.curatorFramework = buildCuratorFramework(registryURL);
+        this.rootPath = ROOT_PATH.getParameterValue(registryURL);
+        this.serviceDiscovery = buildServiceDiscovery(curatorFramework, rootPath);
+        this.serviceDiscovery.start();
+    }
+
+    public void destroy() throws Exception {
+        serviceDiscovery.close();
     }
 
     public void register(ServiceInstance serviceInstance) throws RuntimeException {
@@ -95,18 +101,6 @@ public class ZookeeperServiceDiscovery implements ServiceDiscovery, EventListene
         });
     }
 
-    public void start() {
-        doInServiceRegistry(serviceDiscovery -> {
-            serviceDiscovery.start();
-        });
-    }
-
-    public void stop() {
-        doInServiceRegistry(serviceDiscovery -> {
-            serviceDiscovery.close();
-        });
-    }
-
     @Override
     public Set<String> getServices() {
         return doInServiceDiscovery(s -> new LinkedHashSet<>(s.queryForNames()));
diff --git a/dubbo-registry/dubbo-registry-zookeeper/src/main/java/org/apache/dubbo/registry/zookeeper/util/CuratorFrameworkUtils.java b/dubbo-registry/dubbo-registry-zookeeper/src/main/java/org/apache/dubbo/registry/zookeeper/util/CuratorFrameworkUtils.java
index 901acfc..e72b87d 100644
--- a/dubbo-registry/dubbo-registry-zookeeper/src/main/java/org/apache/dubbo/registry/zookeeper/util/CuratorFrameworkUtils.java
+++ b/dubbo-registry/dubbo-registry-zookeeper/src/main/java/org/apache/dubbo/registry/zookeeper/util/CuratorFrameworkUtils.java
@@ -20,7 +20,6 @@ import org.apache.dubbo.common.URL;
 import org.apache.dubbo.registry.client.DefaultServiceInstance;
 import org.apache.dubbo.registry.client.ServiceInstance;
 import org.apache.dubbo.registry.zookeeper.ZookeeperInstance;
-import org.apache.dubbo.registry.zookeeper.ZookeeperServiceDiscovery;
 
 import org.apache.curator.RetryPolicy;
 import org.apache.curator.framework.CuratorFramework;
@@ -49,10 +48,6 @@ import static org.apache.dubbo.registry.zookeeper.util.CuratorFrameworkParams.MA
  */
 public abstract class CuratorFrameworkUtils {
 
-    public static ZookeeperServiceDiscovery buildZookeeperServiceDiscovery(URL connectionURL) throws Exception {
-        return new ZookeeperServiceDiscovery(connectionURL);
-    }
-
     public static ServiceDiscovery<ZookeeperInstance> buildServiceDiscovery(CuratorFramework curatorFramework,
                                                                             String basePath) {
         return ServiceDiscoveryBuilder.builder(ZookeeperInstance.class)
diff --git a/dubbo-registry/dubbo-registry-zookeeper/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.client.ServiceDiscoveryFactory b/dubbo-registry/dubbo-registry-zookeeper/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.client.ServiceDiscovery
similarity index 82%
rename from dubbo-registry/dubbo-registry-zookeeper/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.client.ServiceDiscoveryFactory
rename to dubbo-registry/dubbo-registry-zookeeper/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.client.ServiceDiscovery
index 12262ad..5532b31 100644
--- a/dubbo-registry/dubbo-registry-zookeeper/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.client.ServiceDiscoveryFactory
+++ b/dubbo-registry/dubbo-registry-zookeeper/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.client.ServiceDiscovery
@@ -1 +1 @@
-zookeeper=org.apache.dubbo.registry.zookeeper.ZookeeperServiceDiscoveryFactory
\ No newline at end of file
+zookeeper=org.apache.dubbo.registry.zookeeper.ZookeeperServiceDiscovery
\ No newline at end of file
diff --git a/dubbo-registry/dubbo-registry-zookeeper/src/main/resources/META-INF/services/org.apache.dubbo.registry.client.ServiceDiscoveryFactory b/dubbo-registry/dubbo-registry-zookeeper/src/main/resources/META-INF/services/org.apache.dubbo.registry.client.ServiceDiscoveryFactory
deleted file mode 100644
index 9e2e9ec..0000000
--- a/dubbo-registry/dubbo-registry-zookeeper/src/main/resources/META-INF/services/org.apache.dubbo.registry.client.ServiceDiscoveryFactory
+++ /dev/null
@@ -1 +0,0 @@
-org.apache.dubbo.registry.zookeeper.ZookeeperServiceDiscoveryFactory
\ No newline at end of file
diff --git a/dubbo-registry/dubbo-registry-zookeeper/src/test/java/org/apache/dubbo/registry/zookeeper/ZookeeperServiceDiscoveryTest.java b/dubbo-registry/dubbo-registry-zookeeper/src/test/java/org/apache/dubbo/registry/zookeeper/ZookeeperServiceDiscoveryTest.java
index 5f14ec5..12c1a19 100644
--- a/dubbo-registry/dubbo-registry-zookeeper/src/test/java/org/apache/dubbo/registry/zookeeper/ZookeeperServiceDiscoveryTest.java
+++ b/dubbo-registry/dubbo-registry-zookeeper/src/test/java/org/apache/dubbo/registry/zookeeper/ZookeeperServiceDiscoveryTest.java
@@ -27,7 +27,6 @@ import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 
-import java.io.IOException;
 import java.util.HashMap;
 import java.util.LinkedList;
 import java.util.List;
@@ -36,7 +35,6 @@ import java.util.concurrent.CountDownLatch;
 
 import static java.util.Arrays.asList;
 import static org.apache.dubbo.common.utils.NetUtils.getAvailablePort;
-import static org.apache.dubbo.registry.zookeeper.util.CuratorFrameworkUtils.buildZookeeperServiceDiscovery;
 import static org.apache.dubbo.registry.zookeeper.util.CuratorFrameworkUtils.generateId;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertFalse;
@@ -67,13 +65,13 @@ public class ZookeeperServiceDiscoveryTest {
         zkServer.start();
 
         this.registryUrl = URL.valueOf("zookeeper://127.0.0.1:" + zkServerPort);
-        this.discovery = buildZookeeperServiceDiscovery(registryUrl);
-        this.discovery.start();
+        this.discovery = new ZookeeperServiceDiscovery();
+        this.discovery.initialize(registryUrl);
     }
 
     @AfterEach
-    public void close() throws IOException {
-        discovery.stop();
+    public void close() throws Exception {
+        discovery.destroy();
         zkServer.stop();
     }