You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@dubbo.apache.org by li...@apache.org on 2021/11/23 03:12:16 UTC

[dubbo] 01/05: refactor

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

liujun pushed a commit to branch 3.0-metadata-refactor
in repository https://gitbox.apache.org/repos/asf/dubbo.git

commit 7a5d0a73d8cea2941983d4e4c1a36ea23bda2e4b
Author: ken.lj <ke...@gmail.com>
AuthorDate: Mon Nov 15 11:25:34 2021 +0800

    refactor
---
 .../org/apache/dubbo/config/ReferenceConfig.java   |   3 +-
 .../config/deploy/DefaultApplicationDeployer.java  |  11 +-
 .../ConfigurableMetadataServiceExporter.java       |  51 ++-
 .../ServiceInstanceHostPortCustomizer.java         |  11 +-
 .../dubbo/config/bootstrap/DubboBootstrapTest.java |   9 -
 .../ServiceInstanceHostPortCustomizerTest.java     |   9 +-
 .../dubbo/config/mock/MockServiceDiscovery.java    |   5 +
 ...ceDiscoveryRegistryRegistryServiceListener.java |   4 +-
 ...RegistryCenterDubboProtocolIntegrationTest.java |   4 +-
 ...g.apache.dubbo.registry.client.ServiceDiscovery |   1 -
 .../spring/registry/MockServiceDiscovery.java      |   5 +
 ...g.apache.dubbo.registry.client.ServiceDiscovery |   1 -
 .../dubbo-demo-native-consumer/pom.xml             |   4 -
 .../dubbo-demo-native-provider/pom.xml             |   4 -
 dubbo-dependencies-bom/pom.xml                     |   2 +-
 .../dubbo-dependencies-zookeeper/pom.xml           |   2 +-
 dubbo-distribution/dubbo-all/pom.xml               |  36 ---
 dubbo-distribution/dubbo-bom/pom.xml               |  15 -
 dubbo-distribution/dubbo-core-spi/pom.xml          |  12 -
 .../org/apache/dubbo/metadata/MetadataInfo.java    |  58 +++-
 .../org/apache/dubbo/metadata/MetadataService.java |  77 -----
 .../dubbo/metadata/WritableMetadataService.java    |  38 ---
 .../dubbo/metadata/report/MetadataReport.java      |   3 +
 .../metadata/report/MetadataReportInstance.java    |  14 +-
 .../metadata/store/nacos/NacosMetadataReport.java  |   9 +
 .../store/zookeeper/ZookeeperMetadataReport.java   |   8 +
 .../META-INF/native-image/reflect-config.json      |   3 -
 .../selector/ServiceInstanceSelector$Adaptive.java |  30 --
 .../registry/RegistryScopeModelInitializer.java    |   2 +
 .../registry/client/AbstractServiceDiscovery.java  |  81 +++--
 .../client/DefaultServiceDiscoveryFactory.java     |  46 ---
 .../dubbo/registry/client/ServiceDiscovery.java    |   9 +-
 .../registry/client/ServiceDiscoveryFactory.java   |   1 +
 .../registry/client/ServiceDiscoveryRegistry.java  |  22 +-
 .../client/ServiceDiscoveryRegistryFactory.java    |   2 +-
 .../registry/client/ServiceDiscoveryService.java}  |  19 +-
 .../registry/client/ServiceInstanceCustomizer.java |   3 +-
 .../listener/ServiceInstancesChangedListener.java  |  83 ++++-
 ...MetadataServiceURLParamsMetadataCustomizer.java |  16 +-
 .../registry/client/metadata/MetadataUtils.java    |  38 +--
 .../metadata/ProtocolPortsMetadataCustomizer.java  |   9 +-
 .../ServiceInstanceMetadataCustomizer.java         |  47 +--
 .../metadata/ServiceInstanceMetadataUtils.java     |  15 +-
 .../StandardMetadataServiceURLBuilder.java         |   4 +-
 .../client/metadata/store/MetaCacheManager.java    |   9 +-
 .../metadata/store/MetadataServiceDelegation.java  |  20 +-
 .../selector/RandomServiceInstanceSelector.java    |  47 ---
 .../client/selector/ServiceInstanceSelector.java   |  43 ---
 .../dubbo/registry/support/AbstractRegistry.java   |   2 +
 .../registry/support/AbstractRegistryFactory.java  |   4 +-
 ...g.apache.dubbo.registry.client.ServiceDiscovery |   1 -
 ...e.dubbo.registry.client.ServiceDiscoveryFactory |   1 -
 ...egistry.client.selector.ServiceInstanceSelector |   1 -
 .../registry/client/InMemoryServiceDiscovery.java  | 107 ------
 ...dataServiceURLParamsMetadataCustomizerTest.java |  29 +-
 .../ProtocolPortsMetadataCustomizerTest.java       |  40 +--
 .../ServiceInstanceMetadataCustomizerTest.java     |  25 +-
 .../metadata/ServiceInstanceMetadataUtilsTest.java | 357 ++++++++++-----------
 .../StandardMetadataServiceURLBuilderTest.java     |   5 +-
 .../client/support/MockServiceDiscovery.java       |   5 +
 .../support/ServiceOrientedRegistryTest.java       | 203 ------------
 ...g.apache.dubbo.registry.client.ServiceDiscovery |   2 -
 .../registry/multicast/MulticastRegistry.java      |   5 +
 .../multicast/MulticastRegistryFactory.java        |   2 +-
 .../multicast/MulticastServiceDiscovery.java       |   5 +
 .../MulticastServiceDiscoveryFactory.java          |   2 +-
 ...g.apache.dubbo.registry.client.ServiceDiscovery |   1 -
 .../multicast/MulticastRegistryFactoryTest.java    |   1 +
 .../multiple/MultipleServiceDiscovery.java         |   5 +
 ...g.apache.dubbo.registry.client.ServiceDiscovery |   1 -
 .../registry/nacos/NacosServiceDiscovery.java      |   9 +-
 .../nacos/NacosServiceDiscoveryFactory.java        |   5 +-
 .../nacos/util/NacosNamingServiceUtils.java        |   8 +-
 ...g.apache.dubbo.registry.client.ServiceDiscovery |   1 -
 .../nacos/util/NacosNamingServiceUtilsTest.java    |   2 +-
 .../zookeeper/ZookeeperRegistryFactory.java        |   2 -
 .../zookeeper/ZookeeperServiceDiscovery.java       |   9 +-
 .../ZookeeperServiceDiscoveryFactory.java          |   2 +-
 .../zookeeper/util/CuratorFrameworkUtils.java      |  12 +-
 ...g.apache.dubbo.registry.client.ServiceDiscovery |   1 -
 .../zookeeper/util/CuratorFrameworkUtilsTest.java  |   5 +-
 pom.xml                                            |   2 +-
 82 files changed, 600 insertions(+), 1207 deletions(-)

diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ReferenceConfig.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ReferenceConfig.java
index 11d38e1..0728645 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ReferenceConfig.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ReferenceConfig.java
@@ -278,7 +278,8 @@ public class ReferenceConfig<T> extends ReferenceConfigBase<T> {
 
     private void initServiceAppsMapping(Map<String, String> referenceParameters) {
         ServiceNameMapping serviceNameMapping = ServiceNameMapping.getDefaultExtension(getScopeModel());
-        serviceNameMapping.getServices(new ServiceConfigURL(LOCAL_PROTOCOL, LOCALHOST_VALUE, 0, interfaceName, referenceParameters));
+        URL url = new ServiceConfigURL(LOCAL_PROTOCOL, LOCALHOST_VALUE, 0, interfaceName, referenceParameters);
+        serviceNameMapping.getServices(url);
     }
 
     /**
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/deploy/DefaultApplicationDeployer.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/deploy/DefaultApplicationDeployer.java
index a9f3603..20dc429 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/deploy/DefaultApplicationDeployer.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/deploy/DefaultApplicationDeployer.java
@@ -46,7 +46,6 @@ import org.apache.dubbo.config.utils.CompositeReferenceCache;
 import org.apache.dubbo.config.utils.ConfigValidationUtils;
 import org.apache.dubbo.metadata.MetadataService;
 import org.apache.dubbo.metadata.MetadataServiceExporter;
-import org.apache.dubbo.metadata.WritableMetadataService;
 import org.apache.dubbo.metadata.report.MetadataReportFactory;
 import org.apache.dubbo.metadata.report.MetadataReportInstance;
 import org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils;
@@ -494,15 +493,9 @@ public class DefaultApplicationDeployer extends AbstractDeployer<ApplicationMode
     }
 
     /**
-     * Initialize {@link MetadataService} from {@link WritableMetadataService}'s extension
+     * Initialize {@link MetadataService}
      */
     private void initMetadataService() {
-//        startMetadataCenter();
-        this.metadataService = getExtensionLoader(WritableMetadataService.class).getDefaultExtension();
-        // support injection by super type MetadataService
-        applicationModel.getBeanFactory().registerBean(this.metadataService);
-
-        //this.metadataServiceExporter = new ConfigurableMetadataServiceExporter(metadataService);
         this.metadataServiceExporter = getExtensionLoader(MetadataServiceExporter.class).getDefaultExtension();
     }
 
@@ -742,7 +735,7 @@ public class DefaultApplicationDeployer extends AbstractDeployer<ApplicationMode
         }
         if (registered) {
             // scheduled task for updating Metadata and ServiceInstance
-            asyncMetadataFuture = executorRepository.getSharedScheduledExecutor().scheduleAtFixedRate(() -> {
+            asyncMetadataFuture = executorRepository.getSharedScheduledExecutor().scheduleWithFixedDelay(() -> {
 
                 // ignore refresh metadata on stopping
                 if (applicationModel.isDestroyed()) {
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 23606b6..dce7d23 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,8 +21,6 @@ import org.apache.dubbo.common.logger.Logger;
 import org.apache.dubbo.common.logger.LoggerFactory;
 import org.apache.dubbo.common.utils.CollectionUtils;
 import org.apache.dubbo.config.ApplicationConfig;
-import org.apache.dubbo.config.ArgumentConfig;
-import org.apache.dubbo.config.MethodConfig;
 import org.apache.dubbo.config.ProtocolConfig;
 import org.apache.dubbo.config.RegistryConfig;
 import org.apache.dubbo.config.ServiceConfig;
@@ -32,7 +30,6 @@ import org.apache.dubbo.metadata.MetadataServiceExporter;
 import org.apache.dubbo.rpc.model.ApplicationModel;
 import org.apache.dubbo.rpc.model.ScopeModelAware;
 
-import java.util.Collections;
 import java.util.List;
 import java.util.concurrent.atomic.AtomicBoolean;
 
@@ -64,14 +61,14 @@ public class ConfigurableMetadataServiceExporter implements MetadataServiceExpor
     private ApplicationModel applicationModel;
     private AtomicBoolean exported = new AtomicBoolean(false);
 
-    public ConfigurableMetadataServiceExporter() {
-    }
+    public ConfigurableMetadataServiceExporter() {}
 
     @Override
     public void setApplicationModel(ApplicationModel applicationModel) {
         this.applicationModel = applicationModel;
     }
 
+    // will be automatically injected from ScopeBeanFactory by ScopeBeanExtensionInjector
     public void setMetadataService(MetadataService metadataService) {
         this.metadataService = metadataService;
     }
@@ -92,7 +89,7 @@ public class ConfigurableMetadataServiceExporter implements MetadataServiceExpor
             serviceConfig.setRef(metadataService);
             serviceConfig.setGroup(applicationConfig.getName());
             serviceConfig.setVersion(metadataService.version());
-            serviceConfig.setMethods(generateMethodConfig());
+//            serviceConfig.setMethods(generateMethodConfig());
 
             // add to internal module, do export later
             applicationModel.getInternalModule().getConfigManager().addService(serviceConfig);
@@ -112,27 +109,27 @@ public class ConfigurableMetadataServiceExporter implements MetadataServiceExpor
         return this;
     }
 
-    /**
-     * Generate Method Config for Service Discovery Metadata <p/>
-     * <p>
-     * Make {@link MetadataService} support argument callback,
-     * used to notify {@link org.apache.dubbo.registry.client.ServiceInstance}'s
-     * metadata change event
-     *
-     * @since 3.0
-     */
-    private List<MethodConfig> generateMethodConfig() {
-        MethodConfig methodConfig = new MethodConfig();
-        methodConfig.setName("getAndListenInstanceMetadata");
-
-        ArgumentConfig argumentConfig = new ArgumentConfig();
-        argumentConfig.setIndex(1);
-        argumentConfig.setCallback(true);
-
-        methodConfig.setArguments(Collections.singletonList(argumentConfig));
-
-        return Collections.singletonList(methodConfig);
-    }
+//    /**
+//     * Generate Method Config for Service Discovery Metadata <p/>
+//     * <p>
+//     * Make {@link MetadataService} support argument callback,
+//     * used to notify {@link org.apache.dubbo.registry.client.ServiceInstance}'s
+//     * metadata change event
+//     *
+//     * @since 3.0
+//     */
+//    private List<MethodConfig> generateMethodConfig() {
+//        MethodConfig methodConfig = new MethodConfig();
+//        methodConfig.setName("getAndListenInstanceMetadata");
+//
+//        ArgumentConfig argumentConfig = new ArgumentConfig();
+//        argumentConfig.setIndex(1);
+//        argumentConfig.setCallback(true);
+//
+//        methodConfig.setArguments(Collections.singletonList(argumentConfig));
+//
+//        return Collections.singletonList(methodConfig);
+//    }
 
     @Override
     public ConfigurableMetadataServiceExporter unexport() {
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/metadata/ServiceInstanceHostPortCustomizer.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/metadata/ServiceInstanceHostPortCustomizer.java
index edccd63..fcb7813 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/metadata/ServiceInstanceHostPortCustomizer.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/metadata/ServiceInstanceHostPortCustomizer.java
@@ -20,7 +20,7 @@ import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.logger.Logger;
 import org.apache.dubbo.common.logger.LoggerFactory;
 import org.apache.dubbo.common.utils.CollectionUtils;
-import org.apache.dubbo.metadata.WritableMetadataService;
+import org.apache.dubbo.metadata.MetadataService;
 import org.apache.dubbo.registry.client.DefaultServiceInstance;
 import org.apache.dubbo.registry.client.ServiceInstance;
 import org.apache.dubbo.registry.client.ServiceInstanceCustomizer;
@@ -30,27 +30,24 @@ import java.util.Set;
 
 /**
  * The {@link ServiceInstanceCustomizer} to customize the {@link ServiceInstance#getPort() port} of service instance.
- *
- * @since 2.7.5
  */
 public class ServiceInstanceHostPortCustomizer implements ServiceInstanceCustomizer {
     private static final Logger logger = LoggerFactory.getLogger(ServiceInstanceHostPortCustomizer.class);
     
 
     @Override
-    public void customize(ServiceInstance serviceInstance) {
+    public void customize(ServiceInstance serviceInstance, ApplicationModel applicationModel) {
 
         if (serviceInstance.getPort() > 0) {
             return;
         }
 
-        WritableMetadataService writableMetadataService = WritableMetadataService.getDefaultExtension(serviceInstance.getApplicationModel());
+        MetadataService metadataService = applicationModel.getBeanFactory().getBean(MetadataService.class);
 
         String host = null;
         int port = -1;
-        Set<URL> urls = writableMetadataService.getExportedServiceURLs();
+        Set<URL> urls = metadataService.getExportedServiceURLs();
         if (CollectionUtils.isNotEmpty(urls)) {
-            ApplicationModel applicationModel = serviceInstance.getApplicationModel();
             String preferredProtocol = applicationModel.getCurrentConfig().getProtocol();
             if (preferredProtocol != null) {
                 for (URL exportedURL : urls) {
diff --git a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/bootstrap/DubboBootstrapTest.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/bootstrap/DubboBootstrapTest.java
index ccc1ed7..6f480c2 100644
--- a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/bootstrap/DubboBootstrapTest.java
+++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/bootstrap/DubboBootstrapTest.java
@@ -347,15 +347,6 @@ public class DubboBootstrapTest {
         serviceConfig.setGroup(ApplicationModel.defaultModel().getCurrentConfig().getName());
         serviceConfig.setVersion(MetadataService.VERSION);
         assertThat(exporters, hasEntry(is(serviceConfig.getUniqueServiceName() + ":" + availablePort), anything()));
-
-//        WritableMetadataService metadataService = WritableMetadataService.getDefaultExtension(ApplicationModel.defaultModel());
-//        MetadataInfo metadataInfo = metadataService.getDefaultMetadataInfo();
-//        Assertions.assertNotNull(metadataInfo);
-//        if (shouldReport) {
-//            Assertions.assertTrue(metadataInfo.hasReported());
-//        } else {
-//            Assertions.assertFalse(metadataInfo.hasReported());
-//        }
     }
 
 
diff --git a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/metadata/ServiceInstanceHostPortCustomizerTest.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/metadata/ServiceInstanceHostPortCustomizerTest.java
index 3222033..4b32934 100644
--- a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/metadata/ServiceInstanceHostPortCustomizerTest.java
+++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/metadata/ServiceInstanceHostPortCustomizerTest.java
@@ -19,7 +19,6 @@ package org.apache.dubbo.config.metadata;
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.config.ApplicationConfig;
 import org.apache.dubbo.metadata.MetadataInfo;
-import org.apache.dubbo.metadata.WritableMetadataService;
 import org.apache.dubbo.registry.client.DefaultServiceInstance;
 import org.apache.dubbo.registry.client.ServiceInstance;
 import org.apache.dubbo.rpc.model.ApplicationModel;
@@ -50,15 +49,13 @@ class ServiceInstanceHostPortCustomizerTest {
     void customizePreferredProtocol() {
         ApplicationModel applicationModel= new ApplicationModel(new FrameworkModel());
         applicationModel.getApplicationConfigManager().setApplication(new ApplicationConfig("service-preferredProtocol"));
-        
-        WritableMetadataService writableMetadataService = WritableMetadataService.getDefaultExtension(applicationModel);
-        
+
         // Trigger the fallback strategy
         DefaultServiceInstance serviceInstance1 = new DefaultServiceInstance("without-preferredProtocol", applicationModel);
         MetadataInfo metadataInfo = new MetadataInfo();
         metadataInfo.addService(URL.valueOf("tri://127.1.1.1:50052/org.apache.dubbo.demo.GreetingService"));
         serviceInstance1.setServiceMetadata(metadataInfo);
-        serviceInstanceHostPortCustomizer.customize(serviceInstance1);
+        serviceInstanceHostPortCustomizer.customize(serviceInstance1, applicationModel);
         Assertions.assertEquals("127.1.1.1", serviceInstance1.getHost());
         Assertions.assertEquals(50052, serviceInstance1.getPort());
         
@@ -69,7 +66,7 @@ class ServiceInstanceHostPortCustomizerTest {
         
         // pick the preferredProtocol
         ServiceInstance serviceInstance2 = new DefaultServiceInstance("with-preferredProtocol", applicationModel);
-        serviceInstanceHostPortCustomizer.customize(serviceInstance2);
+        serviceInstanceHostPortCustomizer.customize(serviceInstance2, applicationModel);
         Assertions.assertEquals("127.1.2.3", serviceInstance2.getHost());
         Assertions.assertEquals(20889, serviceInstance2.getPort());
     }
diff --git a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/mock/MockServiceDiscovery.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/mock/MockServiceDiscovery.java
index fcf827b..f736311 100644
--- a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/mock/MockServiceDiscovery.java
+++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/mock/MockServiceDiscovery.java
@@ -19,6 +19,7 @@ package org.apache.dubbo.config.mock;
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.registry.client.AbstractServiceDiscovery;
 import org.apache.dubbo.registry.client.ServiceInstance;
+import org.apache.dubbo.rpc.model.ApplicationModel;
 
 import java.util.HashSet;
 import java.util.Set;
@@ -26,6 +27,10 @@ import java.util.Set;
 public class MockServiceDiscovery extends AbstractServiceDiscovery {
     private URL registryURL;
 
+    public MockServiceDiscovery(ApplicationModel applicationModel) {
+        super(applicationModel);
+    }
+
     public MockServiceDiscovery(String serviceName) {
         super(serviceName);
     }
diff --git a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/integration/multiple/servicediscoveryregistry/MultipleRegistryCenterServiceDiscoveryRegistryRegistryServiceListener.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/integration/multiple/servicediscoveryregistry/MultipleRegistryCenterServiceDiscoveryRegistryRegistryServiceListener.java
index 4b5676d..3459c19 100644
--- a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/integration/multiple/servicediscoveryregistry/MultipleRegistryCenterServiceDiscoveryRegistryRegistryServiceListener.java
+++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/integration/multiple/servicediscoveryregistry/MultipleRegistryCenterServiceDiscoveryRegistryRegistryServiceListener.java
@@ -18,7 +18,7 @@ package org.apache.dubbo.integration.multiple.servicediscoveryregistry;
 
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.extension.Activate;
-import org.apache.dubbo.metadata.WritableMetadataService;
+import org.apache.dubbo.metadata.MetadataService;
 import org.apache.dubbo.registry.Registry;
 import org.apache.dubbo.registry.RegistryServiceListener;
 import org.apache.dubbo.registry.client.ServiceDiscoveryRegistry;
@@ -43,7 +43,7 @@ public class MultipleRegistryCenterServiceDiscoveryRegistryRegistryServiceListen
         serviceDiscoveryRegistryInfoWrapper.setHost(host);
         serviceDiscoveryRegistryInfoWrapper.setPort(port);
         serviceDiscoveryRegistryInfoWrapper.setServiceDiscoveryRegistry(serviceDiscoveryRegistry);
-        serviceDiscoveryRegistryInfoWrapper.setInMemoryWritableMetadataService((MetadataServiceDelegation) WritableMetadataService.getDefaultExtension(url.getScopeModel()));
+        serviceDiscoveryRegistryInfoWrapper.setInMemoryWritableMetadataService((MetadataServiceDelegation) url.getScopeModel().getBeanFactory().getBean(MetadataService.class));
         serviceDiscoveryRegistryInfoWrapper.setRegistered(true);
         return serviceDiscoveryRegistryInfoWrapper;
     }
diff --git a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/integration/single/SingleRegistryCenterDubboProtocolIntegrationTest.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/integration/single/SingleRegistryCenterDubboProtocolIntegrationTest.java
index e4e8e5a..2026553 100644
--- a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/integration/single/SingleRegistryCenterDubboProtocolIntegrationTest.java
+++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/integration/single/SingleRegistryCenterDubboProtocolIntegrationTest.java
@@ -29,7 +29,7 @@ import org.apache.dubbo.config.ServiceListener;
 import org.apache.dubbo.config.bootstrap.DubboBootstrap;
 import org.apache.dubbo.integration.IntegrationTest;
 import org.apache.dubbo.metadata.MetadataInfo;
-import org.apache.dubbo.metadata.WritableMetadataService;
+import org.apache.dubbo.metadata.MetadataService;
 import org.apache.dubbo.registry.ListenerRegistryWrapper;
 import org.apache.dubbo.registry.Registry;
 import org.apache.dubbo.registry.client.ServiceDiscoveryRegistry;
@@ -238,7 +238,7 @@ public class SingleRegistryCenterDubboProtocolIntegrationTest implements Integra
         Assertions.assertTrue(services.contains(PROVIDER_APPLICATION_NAME));
 
         // obtain InMemoryWritableMetadataService instance
-        MetadataServiceDelegation inMemoryWritableMetadataService = (MetadataServiceDelegation) WritableMetadataService.getDefaultExtension(serviceConfig.getScopeModel());
+        MetadataServiceDelegation inMemoryWritableMetadataService = (MetadataServiceDelegation) serviceConfig.getScopeModel().getBeanFactory().getBean(MetadataService.class);
         // Exported url is right or not in InMemoryWritableMetadataService
         Assertions.assertEquals(inMemoryWritableMetadataService.getExportedURLs().size(), 1);
         // MetadataInfo exists or not in InMemoryWritableMetadataService
diff --git a/dubbo-config/dubbo-config-api/src/test/resources/META-INF/services/org.apache.dubbo.registry.client.ServiceDiscovery b/dubbo-config/dubbo-config-api/src/test/resources/META-INF/services/org.apache.dubbo.registry.client.ServiceDiscovery
deleted file mode 100644
index 22ceb16..0000000
--- a/dubbo-config/dubbo-config-api/src/test/resources/META-INF/services/org.apache.dubbo.registry.client.ServiceDiscovery
+++ /dev/null
@@ -1 +0,0 @@
-mockregistry=org.apache.dubbo.config.mock.MockServiceDiscovery
\ No newline at end of file
diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/registry/MockServiceDiscovery.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/registry/MockServiceDiscovery.java
index 260b243..27c8f01 100644
--- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/registry/MockServiceDiscovery.java
+++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/registry/MockServiceDiscovery.java
@@ -19,6 +19,7 @@ package org.apache.dubbo.config.spring.registry;
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.registry.client.AbstractServiceDiscovery;
 import org.apache.dubbo.registry.client.ServiceInstance;
+import org.apache.dubbo.rpc.model.ApplicationModel;
 
 import java.util.HashSet;
 import java.util.Set;
@@ -26,6 +27,10 @@ import java.util.Set;
 public class MockServiceDiscovery extends AbstractServiceDiscovery {
     private URL registryURL;
 
+    public MockServiceDiscovery(ApplicationModel applicationModel) {
+        super(applicationModel);
+    }
+
     public MockServiceDiscovery(String serviceName) {
         super(serviceName);
     }
diff --git a/dubbo-config/dubbo-config-spring/src/test/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.client.ServiceDiscovery b/dubbo-config/dubbo-config-spring/src/test/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.client.ServiceDiscovery
deleted file mode 100644
index cea6b84..0000000
--- a/dubbo-config/dubbo-config-spring/src/test/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.client.ServiceDiscovery
+++ /dev/null
@@ -1 +0,0 @@
-mock=org.apache.dubbo.config.spring.registry.MockServiceDiscovery
\ No newline at end of file
diff --git a/dubbo-demo/dubbo-demo-native/dubbo-demo-native-consumer/pom.xml b/dubbo-demo/dubbo-demo-native/dubbo-demo-native-consumer/pom.xml
index b5e2eac..81dd095 100644
--- a/dubbo-demo/dubbo-demo-native/dubbo-demo-native-consumer/pom.xml
+++ b/dubbo-demo/dubbo-demo-native/dubbo-demo-native-consumer/pom.xml
@@ -74,10 +74,6 @@
         </dependency>
         <dependency>
             <groupId>org.apache.dubbo</groupId>
-            <artifactId>dubbo-registry-xds</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.dubbo</groupId>
             <artifactId>dubbo-filter-validation</artifactId>
         </dependency>
         <dependency>
diff --git a/dubbo-demo/dubbo-demo-native/dubbo-demo-native-provider/pom.xml b/dubbo-demo/dubbo-demo-native/dubbo-demo-native-provider/pom.xml
index bcc6d9a..1870d96 100644
--- a/dubbo-demo/dubbo-demo-native/dubbo-demo-native-provider/pom.xml
+++ b/dubbo-demo/dubbo-demo-native/dubbo-demo-native-provider/pom.xml
@@ -68,10 +68,6 @@
         </dependency>
         <dependency>
             <groupId>org.apache.dubbo</groupId>
-            <artifactId>dubbo-registry-xds</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.dubbo</groupId>
             <artifactId>dubbo-filter-validation</artifactId>
         </dependency>
         <dependency>
diff --git a/dubbo-dependencies-bom/pom.xml b/dubbo-dependencies-bom/pom.xml
index 64c6797..68a96be 100644
--- a/dubbo-dependencies-bom/pom.xml
+++ b/dubbo-dependencies-bom/pom.xml
@@ -169,7 +169,7 @@
         <mortbay_jetty_version>6.1.26</mortbay_jetty_version>
         <portlet_version>2.0</portlet_version>
         <maven_flatten_version>1.1.0</maven_flatten_version>
-        <revision>3.0.5-SNAPSHOT</revision>
+        <revision>3.0.5-metadata-SNAPSHOT</revision>
     </properties>
 
     <dependencyManagement>
diff --git a/dubbo-dependencies/dubbo-dependencies-zookeeper/pom.xml b/dubbo-dependencies/dubbo-dependencies-zookeeper/pom.xml
index 8e9acf0..0ca636e 100644
--- a/dubbo-dependencies/dubbo-dependencies-zookeeper/pom.xml
+++ b/dubbo-dependencies/dubbo-dependencies-zookeeper/pom.xml
@@ -32,7 +32,7 @@
     <packaging>pom</packaging>
 
     <properties>
-        <revision>3.0.5-SNAPSHOT</revision>
+        <revision>3.0.5-metadata-SNAPSHOT</revision>
         <maven_flatten_version>1.1.0</maven_flatten_version>
     </properties>
 
diff --git a/dubbo-distribution/dubbo-all/pom.xml b/dubbo-distribution/dubbo-all/pom.xml
index 727aca7..be7c899 100644
--- a/dubbo-distribution/dubbo-all/pom.xml
+++ b/dubbo-distribution/dubbo-all/pom.xml
@@ -173,27 +173,6 @@
         </dependency>
         <dependency>
             <groupId>org.apache.dubbo</groupId>
-            <artifactId>dubbo-registry-kubernetes</artifactId>
-            <version>${project.version}</version>
-            <scope>compile</scope>
-            <optional>true</optional>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.dubbo</groupId>
-            <artifactId>dubbo-registry-dns</artifactId>
-            <version>${project.version}</version>
-            <scope>compile</scope>
-            <optional>true</optional>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.dubbo</groupId>
-            <artifactId>dubbo-registry-xds</artifactId>
-            <version>${project.version}</version>
-            <scope>compile</scope>
-            <optional>true</optional>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.dubbo</groupId>
             <artifactId>dubbo-monitor-api</artifactId>
             <version>${project.version}</version>
             <scope>compile</scope>
@@ -433,12 +412,9 @@
                                     <include>org.apache.dubbo:dubbo-plugin</include>
                                     <include>org.apache.dubbo:dubbo-qos</include>
                                     <include>org.apache.dubbo:dubbo-registry-api</include>
-                                    <include>org.apache.dubbo:dubbo-registry-dns</include>
-                                    <include>org.apache.dubbo:dubbo-registry-kubernetes</include>
                                     <include>org.apache.dubbo:dubbo-registry-multicast</include>
                                     <include>org.apache.dubbo:dubbo-registry-multiple</include>
                                     <include>org.apache.dubbo:dubbo-registry-nacos</include>
-                                    <include>org.apache.dubbo:dubbo-registry-xds</include>
                                     <include>org.apache.dubbo:dubbo-registry-zookeeper</include>
                                     <include>org.apache.dubbo:dubbo-registry</include>
                                     <include>org.apache.dubbo:dubbo-remoting-api</include>
@@ -699,12 +675,6 @@
                                 <transformer
                                     implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                                     <resource>
-                                        META-INF/dubbo/internal/org.apache.dubbo.metadata.WritableMetadataService
-                                    </resource>
-                                </transformer>
-                                <transformer
-                                    implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
-                                    <resource>
                                         META-INF/dubbo/internal/org.apache.dubbo.metadata.annotation.processing.builder.TypeBuilder
                                     </resource>
                                 </transformer>
@@ -849,12 +819,6 @@
                                 <transformer
                                     implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                                     <resource>
-                                        META-INF/dubbo/internal/org.apache.dubbo.registry.client.selector.ServiceInstanceSelector
-                                    </resource>
-                                </transformer>
-                                <transformer
-                                    implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
-                                    <resource>
                                         META-INF/dubbo/internal/org.apache.dubbo.registry.integration.RegistryProtocolListener
                                     </resource>
                                 </transformer>
diff --git a/dubbo-distribution/dubbo-bom/pom.xml b/dubbo-distribution/dubbo-bom/pom.xml
index 821fa9e..1065927 100644
--- a/dubbo-distribution/dubbo-bom/pom.xml
+++ b/dubbo-distribution/dubbo-bom/pom.xml
@@ -155,21 +155,6 @@
             </dependency>
             <dependency>
                 <groupId>org.apache.dubbo</groupId>
-                <artifactId>dubbo-registry-xds</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.apache.dubbo</groupId>
-                <artifactId>dubbo-registry-dns</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.apache.dubbo</groupId>
-                <artifactId>dubbo-registry-kubernetes</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.apache.dubbo</groupId>
                 <artifactId>dubbo-monitor-api</artifactId>
                 <version>${project.version}</version>
             </dependency>
diff --git a/dubbo-distribution/dubbo-core-spi/pom.xml b/dubbo-distribution/dubbo-core-spi/pom.xml
index 8453537..f06ff26 100644
--- a/dubbo-distribution/dubbo-core-spi/pom.xml
+++ b/dubbo-distribution/dubbo-core-spi/pom.xml
@@ -379,12 +379,6 @@
                                 <transformer
                                     implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                                     <resource>
-                                        META-INF/dubbo/internal/org.apache.dubbo.metadata.WritableMetadataService
-                                    </resource>
-                                </transformer>
-                                <transformer
-                                    implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
-                                    <resource>
                                         META-INF/dubbo/internal/org.apache.dubbo.metadata.annotation.processing.builder.TypeBuilder
                                     </resource>
                                 </transformer>
@@ -529,12 +523,6 @@
                                 <transformer
                                     implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                                     <resource>
-                                        META-INF/dubbo/internal/org.apache.dubbo.registry.client.selector.ServiceInstanceSelector
-                                    </resource>
-                                </transformer>
-                                <transformer
-                                    implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
-                                    <resource>
                                         META-INF/dubbo/internal/org.apache.dubbo.registry.integration.RegistryProtocolListener
                                     </resource>
                                 </transformer>
diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/MetadataInfo.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/MetadataInfo.java
index 0985e3a..df06767 100644
--- a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/MetadataInfo.java
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/MetadataInfo.java
@@ -65,11 +65,13 @@ public class MetadataInfo implements Serializable {
     private Map<String, ServiceInfo> services;
 
     // used at runtime
-    private transient Map<String, String> extendParams;
+    private transient final Map<String, String> extendParams;
+    private transient final Map<String, String> instanceParams;
     protected transient AtomicBoolean updated = new AtomicBoolean(false);
     private transient ConcurrentNavigableMap<String, SortedSet<URL>> subscribedServiceURLs = new ConcurrentSkipListMap<>();
     private transient ConcurrentNavigableMap<String, SortedSet<URL>> exportedServiceURLs;
     private transient ConcurrentNavigableMap<String, String> serviceDefinitions = new ConcurrentSkipListMap<>();
+    private transient ExtensionLoader<MetadataParamsFilter> loader;
 
     public MetadataInfo() {
         this(null);
@@ -84,11 +86,18 @@ public class MetadataInfo implements Serializable {
         this.revision = revision;
         this.services = services == null ? new ConcurrentHashMap<>() : services;
         this.extendParams = new ConcurrentHashMap<>();
+        this.instanceParams = new ConcurrentHashMap<>();
     }
 
     public synchronized void addService(URL url) {
-        ServiceInfo serviceInfo = new ServiceInfo(url);
+        // fixme, pass in application mode context during initialization of MetadataInfo.
+        this.loader = url.getOrDefaultApplicationModel().getExtensionLoader(MetadataParamsFilter.class);
+        List<MetadataParamsFilter> filters = loader.getActivateExtension(url, "params-filter");
+        // generate service level metadata
+        ServiceInfo serviceInfo = new ServiceInfo(url, filters);
         this.services.put(serviceInfo.getMatchKey(), serviceInfo);
+        // extract common instance level params
+        extractInstanceParams(url, filters);
 
         if (exportedServiceURLs == null) {
             exportedServiceURLs = new ConcurrentSkipListMap<>();
@@ -115,7 +124,7 @@ public class MetadataInfo implements Serializable {
      * Reported status and metadata modification must be synchronized if used in multiple threads.
      */
     public synchronized String calAndGetRevision() {
-        if (revision != null && updated.get()) {
+        if (revision != null && !updated.get()) {
             return revision;
         }
 
@@ -156,10 +165,6 @@ public class MetadataInfo implements Serializable {
         return services;
     }
 
-    public void setServices(Map<String, ServiceInfo> services) {
-        this.services = services;
-    }
-
     public ServiceInfo getServiceInfo(String protocolServiceKey) {
         return services.get(protocolServiceKey);
     }
@@ -168,6 +173,10 @@ public class MetadataInfo implements Serializable {
         return extendParams;
     }
 
+    public Map<String, String> getInstanceParams() {
+        return instanceParams;
+    }
+
     public String getParameter(String key, String serviceKey) {
         ServiceInfo serviceInfo = services.get(serviceKey);
         if (serviceInfo == null) {
@@ -254,8 +263,34 @@ public class MetadataInfo implements Serializable {
         MetadataInfo other = (MetadataInfo)obj;
 
         return Objects.equals(app, other.getApp())
-            && ((services == null && other.getServices() == null)
-                || (services != null && services.equals(other.getServices())));
+            && ((services == null && other.services == null)
+                || (services != null && services.equals(other.services)));
+    }
+
+    private void extractInstanceParams(URL url, List<MetadataParamsFilter> filters) {
+        if (CollectionUtils.isEmpty(filters)) {
+            return;
+        }
+
+        filters.forEach(filter -> {
+            String[] included = filter.instanceParamsIncluded();
+            if (ArrayUtils.isEmpty(included)) {
+                /*
+                 * Does not put any parameter in instance if not specified.
+                 * It will bring no functional suppression as long as all params will appear in service metadata.
+                 */
+            } else {
+                for (String p : included) {
+                    String value = url.getParameter(p);
+                    if (value != null) {
+                        String oldValue = instanceParams.put(p, value);
+                        if (oldValue != null && !oldValue.equals(value)) {
+                            throw new IllegalStateException(String.format("Inconsistent instance metadata found in different services: %s, %s", oldValue, value));
+                        }
+                    }
+                }
+            }
+        });
     }
 
     @Override
@@ -306,19 +341,16 @@ public class MetadataInfo implements Serializable {
         private transient String matchKey;
 
         private transient URL url;
-        private transient ExtensionLoader<MetadataParamsFilter> loader;
 
         private final static String[] KEYS_TO_REMOVE = {MONITOR_KEY, BIND_IP_KEY, BIND_PORT_KEY, QOS_ENABLE,
             QOS_HOST, QOS_PORT, ACCEPT_FOREIGN_IP, VALIDATION_KEY, INTERFACES, PID_KEY, TIMESTAMP_KEY};
 
         public ServiceInfo() {}
 
-        public ServiceInfo(URL url) {
+        public ServiceInfo(URL url, List<MetadataParamsFilter> filters) {
             this(url.getServiceInterface(), url.getGroup(), url.getVersion(), url.getProtocol(), url.getPath(), null);
-            this.loader = url.getOrDefaultApplicationModel().getExtensionLoader(MetadataParamsFilter.class);
             this.url = url;
             Map<String, String> params = new HashMap<>();
-            List<MetadataParamsFilter> filters = loader.getActivateExtension(url, "params-filter");
             if (filters.size() == 0) {
                 params.putAll(url.getParameters());
                 for (String key : KEYS_TO_REMOVE) {
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 946322b..4606ed2 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
@@ -20,29 +20,17 @@ import org.apache.dubbo.common.URL;
 
 import java.util.Collections;
 import java.util.List;
-import java.util.Map;
 import java.util.Set;
 import java.util.SortedSet;
 import java.util.TreeSet;
-import java.util.stream.Collectors;
 import java.util.stream.Stream;
 import java.util.stream.StreamSupport;
 
 import static java.util.Collections.unmodifiableSortedSet;
-import static java.util.stream.StreamSupport.stream;
 import static org.apache.dubbo.common.URL.buildKey;
 
 /**
- * A framework interface of Dubbo Metadata Service defines the contract of Dubbo Services registration and subscription
- * 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
- * {@link #getExportedURLs()} and {@link #getSubscribedURLs()} respectively. What's more, {@link MetadataService}
- * also providers the fine-grain methods for the precise queries.
  *
- * @see WritableMetadataService
- * @since 2.7.5
  */
 public interface MetadataService {
 
@@ -186,29 +174,6 @@ public interface MetadataService {
     MetadataInfo getMetadataInfo(String revision);
 
     /**
-     * Is the {@link URL} for the {@link MetadataService} or not?
-     *
-     * @param url {@link URL url}
-     * @return
-     */
-    static boolean isMetadataServiceURL(URL url) {
-        String serviceInterface = url.getServiceInterface();
-        return SERVICE_INTERFACE_NAME.equals(serviceInterface);
-    }
-
-    /**
-     * Convert the multiple {@link URL urls} to a {@link List list} of {@link URL urls}
-     *
-     * @param urls the strings presents the {@link URL Dubbo URLs}
-     * @return non-null
-     */
-    static List<URL> toURLs(Iterable<String> urls) {
-        return stream(urls.spliterator(), false)
-                .map(URL::valueOf)
-                .collect(Collectors.toList());
-    }
-
-    /**
      * Convert the specified {@link Iterable} of {@link URL URLs} to be the {@link URL#toFullString() strings} presenting
      * the {@link URL URLs}
      *
@@ -232,48 +197,6 @@ public interface MetadataService {
         return unmodifiableSortedSet(stream.map(URL::toFullString).collect(TreeSet::new, Set::add, Set::addAll));
     }
 
-    /**
-     * Export Metadata in Service Instance of Service Discovery
-     * <p>
-     * Used for consumer to get Service Instance Metadata
-     * if Registry is unsupported with publishing metadata
-     *
-     * @param instanceMetadata {@link Map} of provider Service Instance Metadata
-     * @since 3.0
-     */
-    default void exportInstanceMetadata(String instanceMetadata) {
-        throw new UnsupportedOperationException("This operation is not supported for consumer.");
-    }
-
-    /**
-     * Get all Metadata listener from local
-     * <p>
-     * Used for consumer to get Service Instance Metadata
-     * if Registry is unsupported with publishing metadata
-     *
-     * @return {@link Map} of {@link InstanceMetadataChangedListener}
-     * @since 3.0
-     */
-    default Map<String, InstanceMetadataChangedListener> getInstanceMetadataChangedListenerMap() {
-        throw new UnsupportedOperationException("This operation is not supported for consumer.");
-    }
-
-    /**
-     * 1. Fetch Metadata in Service Instance of Service Discovery
-     * 2. Add a metadata change listener
-     * <p>
-     * Used for consumer to get Service Instance Metadata
-     * if Registry is unsupported with publishing metadata
-     *
-     * @param consumerId consumerId
-     * @param listener   {@link InstanceMetadataChangedListener} used to notify event
-     * @return {@link Map} of provider Service Instance Metadata
-     * @since 3.0
-     */
-    default String getAndListenInstanceMetadata(String consumerId, InstanceMetadataChangedListener listener) {
-        throw new UnsupportedOperationException("This operation is not supported for consumer.");
-    }
-
     List<MetadataInfo> getMetadataInfos();
 
 }
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
deleted file mode 100644
index 9c331f7..0000000
--- a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/WritableMetadataService.java
+++ /dev/null
@@ -1,38 +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.metadata;
-
-import org.apache.dubbo.common.URL;
-import org.apache.dubbo.common.extension.ExtensionScope;
-import org.apache.dubbo.common.extension.SPI;
-import org.apache.dubbo.rpc.model.ScopeModel;
-import org.apache.dubbo.rpc.model.ScopeModelUtil;
-
-/**
- * FIXME, this class is not needed anymore.
- */
-@SPI(value = "default", scope = ExtensionScope.APPLICATION)
-public interface WritableMetadataService extends MetadataService {
-
-    default URL getMetadataServiceURL() {
-        return null;
-    }
-
-    static WritableMetadataService getDefaultExtension(ScopeModel scopeModel) {
-        return ScopeModelUtil.getExtensionLoader(WritableMetadataService.class, scopeModel).getDefaultExtension();
-    }
-}
diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/MetadataReport.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/MetadataReport.java
index 0208650..9cb009b 100644
--- a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/MetadataReport.java
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/MetadataReport.java
@@ -45,6 +45,9 @@ public interface MetadataReport {
     default void publishAppMetadata(SubscriberMetadataIdentifier identifier, MetadataInfo metadataInfo) {
     }
 
+    default void unPublishAppMetadata(SubscriberMetadataIdentifier identifier, MetadataInfo metadataInfo) {
+    }
+
     default MetadataInfo getAppMetadata(SubscriberMetadataIdentifier identifier, Map<String, String> instanceMetadata) {
         return null;
     }
diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/MetadataReportInstance.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/MetadataReportInstance.java
index 937fea2..0f2d364 100644
--- a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/MetadataReportInstance.java
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/MetadataReportInstance.java
@@ -29,17 +29,27 @@ import java.util.concurrent.atomic.AtomicBoolean;
 import static org.apache.dubbo.common.constants.CommonConstants.APPLICATION_KEY;
 import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_DIRECTORY;
 import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_KEY;
+import static org.apache.dubbo.common.utils.StringUtils.isEmpty;
 import static org.apache.dubbo.metadata.report.support.Constants.METADATA_REPORT_KEY;
 
 /**
  * Repository of MetadataReport instances that can talk to remote metadata server.
  *
- * MetadataReport instances are initiated during the beginning of deployer.start() and used by components that need to interact with metadata server.
+ * MetadataReport instances are initiated during the beginning of deployer.start() and used by components that
+ * need to interact with metadata server.
+ *
+ * If multiple metadata reports and registries need to be declared, it is recommended to group each two metadata report and registry together by giving them the same id:
+ * <dubbo:registry id=demo1 address="registry://"/>
+ * <dubbo:metadata id=demo1 address="metadata://"/>
+ *
+ * <dubbo:registry id=demo2 address="registry://"/>
+ * <dubbo:metadata id=demo2 address="metadata://"/>
  */
 public class MetadataReportInstance implements Disposable {
 
     private AtomicBoolean init = new AtomicBoolean(false);
 
+    // mapping of registry id to metadata report instance, registry instances will use this mapping to find related metadata reports
     private final Map<String, MetadataReport> metadataReports = new HashMap<>();
 
     public void init(MetadataReportConfig config) {
@@ -59,7 +69,7 @@ public class MetadataReportInstance implements Disposable {
                     .build();
         }
         url = url.addParameterIfAbsent(APPLICATION_KEY, applicationModel.getCurrentConfig().getName());
-        String relatedRegistryId = config.getRegistry() == null ? DEFAULT_KEY : config.getRegistry();
+        String relatedRegistryId = isEmpty(config.getRegistry()) ? (isEmpty(config.getId()) ? DEFAULT_KEY : config.getId()) : config.getRegistry();
 //        RegistryConfig registryConfig = applicationModel.getConfigManager().getRegistry(relatedRegistryId)
 //                .orElseThrow(() -> new IllegalStateException("Registry id " + relatedRegistryId + " does not exist."));
         MetadataReport metadataReport = metadataReportFactory.getMetadataReport(url);
diff --git a/dubbo-metadata/dubbo-metadata-report-nacos/src/main/java/org/apache/dubbo/metadata/store/nacos/NacosMetadataReport.java b/dubbo-metadata/dubbo-metadata-report-nacos/src/main/java/org/apache/dubbo/metadata/store/nacos/NacosMetadataReport.java
index bfe982f..3a7f116 100644
--- a/dubbo-metadata/dubbo-metadata-report-nacos/src/main/java/org/apache/dubbo/metadata/store/nacos/NacosMetadataReport.java
+++ b/dubbo-metadata/dubbo-metadata-report-nacos/src/main/java/org/apache/dubbo/metadata/store/nacos/NacosMetadataReport.java
@@ -154,6 +154,15 @@ public class NacosMetadataReport extends AbstractMetadataReport {
     }
 
     @Override
+    public void unPublishAppMetadata(SubscriberMetadataIdentifier identifier, MetadataInfo metadataInfo) {
+        try {
+            configService.removeConfig(identifier.getApplication(), identifier.getRevision());
+        } catch (NacosException e) {
+            throw new IllegalStateException(e.getMessage(), e);
+        }
+    }
+
+    @Override
     public MetadataInfo getAppMetadata(SubscriberMetadataIdentifier identifier, Map<String, String> instanceMetadata) {
         try {
             String content = configService.getConfig(identifier.getApplication(), identifier.getRevision(), 3000L);
diff --git a/dubbo-metadata/dubbo-metadata-report-zookeeper/src/main/java/org/apache/dubbo/metadata/store/zookeeper/ZookeeperMetadataReport.java b/dubbo-metadata/dubbo-metadata-report-zookeeper/src/main/java/org/apache/dubbo/metadata/store/zookeeper/ZookeeperMetadataReport.java
index 3909227..cf28c75 100644
--- a/dubbo-metadata/dubbo-metadata-report-zookeeper/src/main/java/org/apache/dubbo/metadata/store/zookeeper/ZookeeperMetadataReport.java
+++ b/dubbo-metadata/dubbo-metadata-report-zookeeper/src/main/java/org/apache/dubbo/metadata/store/zookeeper/ZookeeperMetadataReport.java
@@ -147,6 +147,14 @@ public class ZookeeperMetadataReport extends AbstractMetadataReport {
     }
 
     @Override
+    public void unPublishAppMetadata(SubscriberMetadataIdentifier identifier, MetadataInfo metadataInfo) {
+        String path = getNodePath(identifier);
+        if (StringUtils.isNotEmpty(zkClient.getContent(path))) {
+            zkClient.delete(path);
+        }
+    }
+
+    @Override
     public MetadataInfo getAppMetadata(SubscriberMetadataIdentifier identifier, Map<String, String> instanceMetadata) {
         String content = zkClient.getContent(getNodePath(identifier));
         return gson.fromJson(content, MetadataInfo.class);
diff --git a/dubbo-native-plugin/src/main/resources/META-INF/native-image/reflect-config.json b/dubbo-native-plugin/src/main/resources/META-INF/native-image/reflect-config.json
index 9d000c1..1052e91 100644
--- a/dubbo-native-plugin/src/main/resources/META-INF/native-image/reflect-config.json
+++ b/dubbo-native-plugin/src/main/resources/META-INF/native-image/reflect-config.json
@@ -1593,9 +1593,6 @@
     ]
   },
   {
-    "name": "org.apache.dubbo.registry.client.DefaultServiceDiscoveryFactory"
-  },
-  {
     "name": "org.apache.dubbo.registry.client.DefaultServiceInstance$Endpoint",
     "allDeclaredFields": true,
     "methods": [
diff --git a/dubbo-native/src/main/java/org/apache/dubbo/registry/client/selector/ServiceInstanceSelector$Adaptive.java b/dubbo-native/src/main/java/org/apache/dubbo/registry/client/selector/ServiceInstanceSelector$Adaptive.java
deleted file mode 100644
index d3e1be0..0000000
--- a/dubbo-native/src/main/java/org/apache/dubbo/registry/client/selector/ServiceInstanceSelector$Adaptive.java
+++ /dev/null
@@ -1,30 +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.selector;
-import org.apache.dubbo.rpc.model.ScopeModel;
-import org.apache.dubbo.rpc.model.ScopeModelUtil;
-public class ServiceInstanceSelector$Adaptive implements org.apache.dubbo.registry.client.selector.ServiceInstanceSelector {
-public org.apache.dubbo.registry.client.ServiceInstance select(org.apache.dubbo.common.URL arg0, java.util.List arg1)  {
-if (arg0 == null) throw new IllegalArgumentException("url == null");
-org.apache.dubbo.common.URL url = arg0;
-String extName = url.getParameter("service-instance-selector", "random");
-if(extName == null) throw new IllegalStateException("Failed to get extension (org.apache.dubbo.registry.client.selector.ServiceInstanceSelector) name from url (" + url.toString() + ") use keys([service-instance-selector])");
-ScopeModel scopeModel = ScopeModelUtil.getOrDefault(url.getScopeModel(), org.apache.dubbo.registry.client.selector.ServiceInstanceSelector.class);
-org.apache.dubbo.registry.client.selector.ServiceInstanceSelector extension = (org.apache.dubbo.registry.client.selector.ServiceInstanceSelector)scopeModel.getExtensionLoader(org.apache.dubbo.registry.client.selector.ServiceInstanceSelector.class).getExtension(extName);
-return extension.select(arg0, arg1);
-}
-}
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/RegistryScopeModelInitializer.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/RegistryScopeModelInitializer.java
index 6be4e29..fe1973d 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/RegistryScopeModelInitializer.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/RegistryScopeModelInitializer.java
@@ -17,6 +17,7 @@
 package org.apache.dubbo.registry;
 
 import org.apache.dubbo.common.beans.factory.ScopeBeanFactory;
+import org.apache.dubbo.registry.client.metadata.store.MetadataServiceDelegation;
 import org.apache.dubbo.registry.support.RegistryManager;
 import org.apache.dubbo.rpc.model.ApplicationModel;
 import org.apache.dubbo.rpc.model.FrameworkModel;
@@ -33,6 +34,7 @@ public class RegistryScopeModelInitializer implements ScopeModelInitializer {
     public void initializeApplicationModel(ApplicationModel applicationModel) {
         ScopeBeanFactory beanFactory = applicationModel.getBeanFactory();
         beanFactory.registerBean(RegistryManager.class);
+        beanFactory.registerBean(MetadataServiceDelegation.class);
     }
 
     @Override
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/AbstractServiceDiscovery.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/AbstractServiceDiscovery.java
index e454183..812e570 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/AbstractServiceDiscovery.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/AbstractServiceDiscovery.java
@@ -24,24 +24,22 @@ import org.apache.dubbo.metadata.report.MetadataReport;
 import org.apache.dubbo.metadata.report.MetadataReportInstance;
 import org.apache.dubbo.metadata.report.identifier.SubscriberMetadataIdentifier;
 import org.apache.dubbo.registry.NotifyListener;
+import org.apache.dubbo.registry.client.metadata.MetadataUtils;
 import org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils;
+import org.apache.dubbo.registry.client.metadata.store.MetaCacheManager;
 import org.apache.dubbo.rpc.model.ApplicationModel;
-import org.apache.dubbo.rpc.model.ScopeModelAware;
 
 import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
 
 import static org.apache.dubbo.common.constants.RegistryConstants.REGISTRY_CLUSTER_KEY;
 import static org.apache.dubbo.metadata.RevisionResolver.EMPTY_REVISION;
 import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.EXPORTED_SERVICES_REVISION_PROPERTY_NAME;
-import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.customizeInstance;
 import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.setMetadataStorageType;
 
 /**
  * Each service discovery is bond to one application.
  */
-public abstract class AbstractServiceDiscovery implements ServiceDiscovery, ScopeModelAware {
+public abstract class AbstractServiceDiscovery implements ServiceDiscovery {
     private Logger logger = LoggerFactory.getLogger(AbstractServiceDiscovery.class);
     private volatile boolean isDestroy;
 
@@ -49,21 +47,19 @@ public abstract class AbstractServiceDiscovery implements ServiceDiscovery, Scop
     protected volatile ServiceInstance serviceInstance;
     protected volatile MetadataInfo metadataInfo;
     protected MetadataReport metadataReport;
+    protected MetaCacheManager metaCacheManager;
 
     private ApplicationModel applicationModel;
 
-    // fixme
-    protected Map<String, MetadataInfo> revisionToMetadata;
+    public AbstractServiceDiscovery(ApplicationModel applicationModel) {
+        this(applicationModel.getApplicationName());
+        this.applicationModel = applicationModel;
+    }
 
     public AbstractServiceDiscovery(String serviceName) {
         this.serviceName = serviceName;
         this.metadataInfo = new MetadataInfo(serviceName);
-        this.revisionToMetadata = new ConcurrentHashMap<>();
-    }
-
-    @Override
-    public void setApplicationModel(ApplicationModel applicationModel) {
-        this.applicationModel = applicationModel;
+        this.metaCacheManager = new MetaCacheManager(AbstractServiceDiscovery.class.getSimpleName());
     }
 
     @Override
@@ -73,9 +69,8 @@ public abstract class AbstractServiceDiscovery implements ServiceDiscovery, Scop
         metadataReport = applicationModel.getBeanFactory().getBean(MetadataReportInstance.class).getMetadataReport(registryCluster);
     }
 
-    public final void register() throws RuntimeException {
+    public synchronized final void register() throws RuntimeException {
         this.serviceInstance = createServiceInstance();
-        customizeInstance(this.serviceInstance);
         boolean revisionUpdated = calOrUpdateInstanceRevision();
         if (revisionUpdated) {
             reportMetadata();
@@ -84,7 +79,7 @@ public abstract class AbstractServiceDiscovery implements ServiceDiscovery, Scop
     }
 
     @Override
-    public final void update() throws RuntimeException {
+    public synchronized final void update() throws RuntimeException {
         if (this.serviceInstance == null) {
             this.serviceInstance = createServiceInstance();
         }
@@ -95,7 +90,8 @@ public abstract class AbstractServiceDiscovery implements ServiceDiscovery, Scop
     }
 
     @Override
-    public final void unregister() throws RuntimeException {
+    public synchronized final void unregister() throws RuntimeException {
+        unReportMetadata();
         doUnregister();
     }
 
@@ -110,6 +106,48 @@ public abstract class AbstractServiceDiscovery implements ServiceDiscovery, Scop
     }
 
     @Override
+    public MetadataInfo getRemoteMetadata(String revision, ServiceInstance instance) {
+        MetadataInfo metadata = metaCacheManager.get(revision);
+
+        if (metadata != null && metadata != MetadataInfo.EMPTY) {
+            // metadata loaded from cache
+            if (logger.isDebugEnabled()) {
+                logger.debug("MetadataInfo for instance " + instance.getAddress() + "?revision=" + revision
+                    + "&cluster=" + instance.getRegistryCluster() + ", " + metadata);
+            }
+            return metadata;
+        }
+
+        // try to load metadata from remote.
+        int triedTimes = 0;
+        while (triedTimes < 3) {
+            metadata = MetadataUtils.getRemoteMetadata(revision, instance, metadataReport);
+
+            if (metadata != MetadataInfo.EMPTY) {// succeeded
+                break;
+            } else {// failed
+                if (triedTimes > 0) {
+                    logger.info("Retry the " + triedTimes + " times to get metadata for instance " + instance.getAddress() + "?revision=" + revision
+                        + "&cluster=" + instance.getRegistryCluster());
+                }
+                triedTimes++;
+                try {
+                    Thread.sleep(1000);
+                } catch (InterruptedException e) {
+                }
+            }
+        }
+
+        if (metadata == MetadataInfo.EMPTY) {
+            logger.error("Failed to get metadata for instance after 3 retries, " + instance.getAddress() + "?revision=" + revision
+                + "&cluster=" + instance.getRegistryCluster());
+        } else {
+            metaCacheManager.put(revision, metadata);
+        }
+        return metadata;
+    }
+
+    @Override
     public final void destroy() throws Exception {
         isDestroy = true;
         doDestroy();
@@ -149,7 +187,7 @@ public abstract class AbstractServiceDiscovery implements ServiceDiscovery, Scop
         this.unregister();
 
         reportMetadata();
-        this.register();
+        this.doRegister(serviceInstance);
     }
 
     public abstract void doRegister(ServiceInstance serviceInstance) throws RuntimeException;
@@ -165,7 +203,7 @@ public abstract class AbstractServiceDiscovery implements ServiceDiscovery, Scop
         instance.setServiceMetadata(metadataInfo);
         String metadataType = applicationModel.getApplicationConfigManager().getApplicationOrElseThrow().getMetadataType();
         setMetadataStorageType(instance, metadataType);
-        ServiceInstanceMetadataUtils.customizeInstance(instance);
+        ServiceInstanceMetadataUtils.customizeInstance(instance, applicationModel);
         return instance;
     }
 
@@ -187,4 +225,9 @@ public abstract class AbstractServiceDiscovery implements ServiceDiscovery, Scop
         metadataReport.publishAppMetadata(identifier, metadataInfo);
     }
 
+    protected void unReportMetadata() {
+        SubscriberMetadataIdentifier identifier = new SubscriberMetadataIdentifier(serviceName, metadataInfo.calAndGetRevision());
+        metadataReport.unPublishAppMetadata(identifier, metadataInfo);
+    }
+
 }
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
deleted file mode 100644
index 7f0f1a5..0000000
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/DefaultServiceDiscoveryFactory.java
+++ /dev/null
@@ -1,46 +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;
-import org.apache.dubbo.common.extension.ExtensionLoader;
-import org.apache.dubbo.common.extension.SPI;
-
-/**
- * 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
- * @since 2.7.5
- */
-public class DefaultServiceDiscoveryFactory extends AbstractServiceDiscoveryFactory {
-
-    /**
-     * Create the {@link ServiceDiscovery} by {@link URL#getProtocol() the protocol} from {@link URL connection URL}
-     *
-     * @param registryURL
-     * @return
-     */
-    @Override
-    protected ServiceDiscovery createDiscovery(URL registryURL) {
-        String protocol = registryURL.getProtocol();
-        ExtensionLoader<ServiceDiscovery> loader = registryURL.getOrDefaultApplicationModel().getExtensionLoader(ServiceDiscovery.class);
-        return loader.getExtension(protocol);
-    }
-}
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 5652e19..182ccd0 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
@@ -17,7 +17,6 @@
 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.metadata.MetadataInfo;
@@ -33,14 +32,11 @@ import java.util.Set;
 import static java.util.Collections.unmodifiableList;
 import static java.util.Collections.unmodifiableMap;
 import static org.apache.dubbo.common.constants.CommonConstants.REGISTRY_DELAY_NOTIFICATION_KEY;
-import static org.apache.dubbo.common.extension.ExtensionScope.APPLICATION;
 
 /**
- * The common operations of Service Discovery
+ * Defines the common operations of Service Discovery, extended and loaded by ServiceDiscoveryFactory
  *
- * @since 2.7.5
  */
-@SPI(value = "zookeeper", scope = APPLICATION)
 public interface ServiceDiscovery extends RegistryService, Prioritized {
     /**
      * Initializes the {@link ServiceDiscovery}
@@ -59,7 +55,6 @@ public interface ServiceDiscovery extends RegistryService, Prioritized {
 
     boolean isDestroy();
 
-
     void register() throws RuntimeException;
 
     void update() throws RuntimeException;
@@ -188,6 +183,8 @@ public interface ServiceDiscovery extends RegistryService, Prioritized {
 
     MetadataInfo getMetadata();
 
+    MetadataInfo getRemoteMetadata(String revision, ServiceInstance instance);
+
     default URL getUrl() {
         return null;
     }
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 2168095..2332f04 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
@@ -35,6 +35,7 @@ public interface ServiceDiscoveryFactory {
      * Get the instance of {@link ServiceDiscovery}
      *
      * @param registryURL the {@link URL} to connect the registry
+     * @param model, the application model context
      * @return non-null
      */
     ServiceDiscovery getServiceDiscovery(URL registryURL);
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistry.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistry.java
index 320577b..d4e2102 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistry.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistry.java
@@ -31,12 +31,12 @@ import org.apache.dubbo.registry.client.event.listener.ServiceInstancesChangedLi
 import org.apache.dubbo.registry.client.metadata.SubscribedURLsSynthesizer;
 import org.apache.dubbo.registry.support.FailbackRegistry;
 import org.apache.dubbo.registry.support.RegistryManager;
+import org.apache.dubbo.rpc.model.ApplicationModel;
 
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
-import java.util.Objects;
 import java.util.Set;
 import java.util.TreeSet;
 import java.util.concurrent.ConcurrentHashMap;
@@ -82,11 +82,12 @@ public class ServiceDiscoveryRegistry extends FailbackRegistry {
 
     private RegistryManager registryManager;
 
-    public ServiceDiscoveryRegistry(URL registryURL) {
+    public ServiceDiscoveryRegistry(URL registryURL, ApplicationModel applicationModel) {
         super(registryURL);
         this.serviceDiscovery = createServiceDiscovery(registryURL);
         this.serviceNameMapping = ServiceNameMapping.getDefaultExtension(registryURL.getScopeModel());
-        this.registryManager = registryURL.getOrDefaultApplicationModel().getBeanFactory().getBean(RegistryManager.class);
+        this.registryManager = applicationModel.getBeanFactory().getBean(RegistryManager.class);
+        super.applicationModel = applicationModel;
     }
 
     // Currently, for test purpose
@@ -316,16 +317,6 @@ public class ServiceDiscoveryRegistry extends FailbackRegistry {
     }
 
     /**
-     * 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 ServiceDiscoveryRegistry create(URL registryURL) {
-        return supports(registryURL) ? new ServiceDiscoveryRegistry(registryURL) : null;
-    }
-
-    /**
      * Supports or not ?
      *
      * @param registryURL the {@link URL url} of registry
@@ -335,11 +326,6 @@ public class ServiceDiscoveryRegistry extends FailbackRegistry {
         return SERVICE_REGISTRY_TYPE.equalsIgnoreCase(registryURL.getParameter(REGISTRY_TYPE_KEY));
     }
 
-    private static boolean isCompatibleProtocol(String protocol, URL targetURL) {
-        return protocol == null || Objects.equals(protocol, targetURL.getParameter(PROTOCOL_KEY))
-            || Objects.equals(protocol, targetURL.getProtocol());
-    }
-
     public Map<String, ServiceInstancesChangedListener> getServiceListeners() {
         return serviceListeners;
     }
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistryFactory.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistryFactory.java
index 0a64efd..c5d5ab9 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistryFactory.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistryFactory.java
@@ -32,7 +32,7 @@ public class ServiceDiscoveryRegistryFactory extends AbstractRegistryFactory {
             String protocol = url.getParameter(REGISTRY_KEY, DEFAULT_REGISTRY);
             url = url.setProtocol(protocol).removeParameter(REGISTRY_KEY);
         }
-        return new ServiceDiscoveryRegistry(url);
+        return new ServiceDiscoveryRegistry(url, applicationModel);
     }
 
 }
diff --git a/dubbo-registry/dubbo-registry-multicast/src/main/java/org/apache/dubbo/registry/multicast/MulticastRegistryFactory.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryService.java
similarity index 66%
copy from dubbo-registry/dubbo-registry-multicast/src/main/java/org/apache/dubbo/registry/multicast/MulticastRegistryFactory.java
copy to dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryService.java
index 88e96e6..fa8341f 100644
--- a/dubbo-registry/dubbo-registry-multicast/src/main/java/org/apache/dubbo/registry/multicast/MulticastRegistryFactory.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryService.java
@@ -14,21 +14,12 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.registry.multicast;
+package org.apache.dubbo.registry.client;
 
-import org.apache.dubbo.common.URL;
-import org.apache.dubbo.registry.Registry;
-import org.apache.dubbo.registry.support.AbstractRegistryFactory;
+public interface ServiceDiscoveryService {
+    void register() throws RuntimeException;
 
-/**
- * MulticastRegistryLocator
- *
- */
-public class MulticastRegistryFactory extends AbstractRegistryFactory {
-
-    @Override
-    public Registry createRegistry(URL url) {
-        return new MulticastRegistry(url);
-    }
+    void update() throws RuntimeException;
 
+    void unregister() throws RuntimeException;
 }
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceInstanceCustomizer.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceInstanceCustomizer.java
index e91b166..811da76 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceInstanceCustomizer.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceInstanceCustomizer.java
@@ -18,6 +18,7 @@ package org.apache.dubbo.registry.client;
 
 import org.apache.dubbo.common.extension.SPI;
 import org.apache.dubbo.common.lang.Prioritized;
+import org.apache.dubbo.rpc.model.ApplicationModel;
 
 import static org.apache.dubbo.common.extension.ExtensionScope.APPLICATION;
 
@@ -35,5 +36,5 @@ public interface ServiceInstanceCustomizer extends Prioritized {
      *
      * @param serviceInstance {@link ServiceInstance the service instance}
      */
-    void customize(ServiceInstance serviceInstance);
+    void customize(ServiceInstance serviceInstance, ApplicationModel applicationModel);
 }
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/listener/ServiceInstancesChangedListener.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/listener/ServiceInstancesChangedListener.java
index 0b28109..a191826 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/listener/ServiceInstancesChangedListener.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/listener/ServiceInstancesChangedListener.java
@@ -48,6 +48,7 @@ import java.util.concurrent.ScheduledExecutorService;
 import java.util.concurrent.ScheduledFuture;
 import java.util.concurrent.Semaphore;
 import java.util.concurrent.ThreadLocalRandom;
+import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicBoolean;
 
 import static org.apache.dubbo.metadata.RevisionResolver.EMPTY_REVISION;
@@ -72,9 +73,10 @@ public class ServiceInstancesChangedListener {
     protected Map<String, Object> serviceUrls;
 
     private volatile long lastRefreshTime;
-    private Semaphore retryPermission;
+    private final Semaphore retryPermission;
     private volatile ScheduledFuture<?> retryFuture;
-    private ScheduledExecutorService scheduler;
+    private final ScheduledExecutorService scheduler;
+    private volatile boolean hasEmptyMetadata;
 
     public ServiceInstancesChangedListener(Set<String> serviceNames, ServiceDiscovery serviceDiscovery) {
         this.serviceNames = serviceNames;
@@ -94,7 +96,7 @@ public class ServiceInstancesChangedListener {
      * @param event {@link ServiceInstancesChangedEvent}
      */
     public synchronized void onEvent(ServiceInstancesChangedEvent event) {
-        if (destroyed.get() || !accept(event)) {
+        if (destroyed.get() || !accept(event) || isRetryAndExpired(event)) {
             return;
         }
 
@@ -106,7 +108,6 @@ public class ServiceInstancesChangedListener {
 
         Map<String, List<ServiceInstance>> revisionToInstances = new HashMap<>();
         Map<String, Map<String, Set<String>>> localServiceToRevisions = new HashMap<>();
-        Map<String, MetadataInfo> newRevisionToMetadata = new HashMap<>();
 
         // grouping all instances of this app(service name) by revision
         for (Map.Entry<String, List<ServiceInstance>> entry : allInstances.entrySet()) {
@@ -127,11 +128,30 @@ public class ServiceInstancesChangedListener {
         // get MetadataInfo with revision
         for (Map.Entry<String, List<ServiceInstance>> entry : revisionToInstances.entrySet()) {
             String revision = entry.getKey();
-            List<ServiceInstance> instances = entry.getValue();
-            // instances should never be empty.
-            DefaultServiceInstance instance = (DefaultServiceInstance)instances.iterator().next();
-            parseMetadata(revision, instance.getServiceMetadata(), localServiceToRevisions);
+            List<ServiceInstance> subInstances = entry.getValue();
+            ServiceInstance instance = selectInstance(subInstances);
+            MetadataInfo metadata = serviceDiscovery.getRemoteMetadata(revision, instance);
+            parseMetadata(revision, metadata, localServiceToRevisions);
+            // update metadata into each instance, in case new instance created.
+            for (ServiceInstance tmpInstance : subInstances) {
+                ((DefaultServiceInstance) tmpInstance).setServiceMetadata(metadata);
+            }
+        }
+
+        if (hasEmptyMetadata(revisionToInstances)) {// retry every 10 seconds
+            hasEmptyMetadata = true;
+            if (retryPermission.tryAcquire()) {
+                if (retryFuture != null && !retryFuture.isDone()) {
+                    // cancel last retryFuture because only one retryFuture will be canceled at destroy().
+                    retryFuture.cancel(true);
+                }
+                retryFuture = scheduler.schedule(new AddressRefreshRetryTask(retryPermission, event.getServiceName()), 10_000L, TimeUnit.MILLISECONDS);
+                logger.warn("Address refresh try task submitted.");
+            }
+            logger.error("Address refresh failed because of Metadata Server failure, wait for retry or new address refresh event.");
+            return;
         }
+        hasEmptyMetadata = false;
 
         Map<String, Map<Set<String>, Object>> protocolRevisionsToUrls = new HashMap<>();
         Map<String, Object> newServiceUrls = new HashMap<>();
@@ -224,10 +244,6 @@ public class ServiceInstancesChangedListener {
         return allInstances;
     }
 
-    public List<ServiceInstance> getInstancesOfApp(String appName) {
-        return allInstances.get(appName);
-    }
-
     /**
      * @param event {@link ServiceInstancesChangedEvent event}
      * @return If service name matches, return <code>true</code>, or <code>false</code>
@@ -236,6 +252,19 @@ public class ServiceInstancesChangedListener {
         return serviceNames.contains(event.getServiceName());
     }
 
+    protected boolean isRetryAndExpired(ServiceInstancesChangedEvent event) {
+        if (event instanceof RetryServiceInstancesChangedEvent) {
+            RetryServiceInstancesChangedEvent retryEvent = (RetryServiceInstancesChangedEvent) event;
+            logger.warn("Received address refresh retry event, " + retryEvent.getFailureRecordTime());
+            if (retryEvent.getFailureRecordTime() < lastRefreshTime && !hasEmptyMetadata) {
+                logger.warn("Ignore retry event, event time: " + retryEvent.getFailureRecordTime() + ", last refresh time: " + lastRefreshTime);
+                return true;
+            }
+            logger.warn("Retrying address notification...");
+        }
+        return false;
+    }
+
     private void refreshInstance(ServiceInstancesChangedEvent event) {
         if (event instanceof RetryServiceInstancesChangedEvent) {
             return;
@@ -247,12 +276,13 @@ public class ServiceInstancesChangedListener {
         lastRefreshTime = System.currentTimeMillis();
     }
 
-    protected boolean hasEmptyMetadata(Map<String, MetadataInfo> revisionToMetadata) {
-        if (revisionToMetadata == null) {
+    protected boolean hasEmptyMetadata(Map<String, List<ServiceInstance>> revisionToInstances) {
+        if (revisionToInstances == null) {
             return false;
         }
-        for (Map.Entry<String, MetadataInfo> entry : revisionToMetadata.entrySet()) {
-            if (entry.getValue() == MetadataInfo.EMPTY) {
+        for (Map.Entry<String, List<ServiceInstance>> entry : revisionToInstances.entrySet()) {
+            DefaultServiceInstance serviceInstance = (DefaultServiceInstance) entry.getValue().get(0);
+            if (serviceInstance == null || serviceInstance.getServiceMetadata() == MetadataInfo.EMPTY) {
                 return true;
             }
         }
@@ -358,6 +388,27 @@ public class ServiceInstancesChangedListener {
         return Objects.hash(getClass(), getServiceNames());
     }
 
+    // for test purpose
+    public List<ServiceInstance> getInstancesOfApp(String appName) {
+        return allInstances.get(appName);
+    }
+
+    protected class AddressRefreshRetryTask implements Runnable {
+        private final RetryServiceInstancesChangedEvent retryEvent;
+        private final Semaphore retryPermission;
+
+        public AddressRefreshRetryTask(Semaphore semaphore, String serviceName) {
+            this.retryEvent = new RetryServiceInstancesChangedEvent(serviceName);
+            this.retryPermission = semaphore;
+        }
+
+        @Override
+        public void run() {
+            retryPermission.release();
+            ServiceInstancesChangedListener.this.onEvent(retryEvent);
+        }
+    }
+
     protected static class NotifyListenerWithKey {
         private String serviceKey;
         private NotifyListener notifyListener;
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 71b8d8d..1576d21 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
@@ -21,7 +21,6 @@ import org.apache.dubbo.metadata.MetadataServiceExporter;
 import org.apache.dubbo.registry.client.ServiceInstance;
 import org.apache.dubbo.registry.client.ServiceInstanceCustomizer;
 import org.apache.dubbo.rpc.model.ApplicationModel;
-import org.apache.dubbo.rpc.model.ScopeModelAware;
 
 import java.util.List;
 import java.util.Map;
@@ -33,22 +32,15 @@ import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataU
 /**
  * Used to interact with non-dubbo systems, also see {@link SpringCloudMetadataServiceURLBuilder}
  */
-public class MetadataServiceURLParamsMetadataCustomizer implements ServiceInstanceCustomizer, ScopeModelAware {
-
-    private ApplicationModel applicationModel;
-
-    @Override
-    public void setApplicationModel(ApplicationModel applicationModel) {
-        this.applicationModel = applicationModel;
-    }
+public class MetadataServiceURLParamsMetadataCustomizer implements ServiceInstanceCustomizer {
 
     @Override
-    public void customize(ServiceInstance serviceInstance) {
+    public void customize(ServiceInstance serviceInstance, ApplicationModel applicationModel) {
 
         Map<String, String> metadata = serviceInstance.getMetadata();
 
         String propertyName = resolveMetadataPropertyName(serviceInstance);
-        String propertyValue = resolveMetadataPropertyValue(serviceInstance);
+        String propertyValue = resolveMetadataPropertyValue(applicationModel);
 
         if (!isBlank(propertyName) && !isBlank(propertyValue)) {
             metadata.put(propertyName, propertyValue);
@@ -59,7 +51,7 @@ public class MetadataServiceURLParamsMetadataCustomizer implements ServiceInstan
         return METADATA_SERVICE_URL_PARAMS_PROPERTY_NAME;
     }
 
-    private String resolveMetadataPropertyValue(ServiceInstance serviceInstance) {
+    private String resolveMetadataPropertyValue(ApplicationModel applicationModel) {
         MetadataServiceExporter metadataServiceExporter = applicationModel.getExtensionLoader(MetadataServiceExporter.class).getDefaultExtension();
         if (metadataServiceExporter.isExported()) {
             List<URL> metadataURLs = metadataServiceExporter.getExportedURLs();
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/MetadataUtils.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/MetadataUtils.java
index 3fbedb2..f554f17 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/MetadataUtils.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/MetadataUtils.java
@@ -135,41 +135,7 @@ public class MetadataUtils {
         return metadataServiceProxies;
     }
 
-    public static MetadataInfo getRemoteMetadata(String revision, ServiceInstance instance, Map<String, MetadataInfo> revisionToMetadata, MetadataReport metadataReport) {
-        MetadataInfo metadata = revisionToMetadata.get(revision);
-
-        if (metadata != null && metadata != MetadataInfo.EMPTY) {
-            // metadata loaded from cache
-            if (logger.isDebugEnabled()) {
-                logger.debug("MetadataInfo for instance " + instance.getAddress() + "?revision=" + revision
-                    + "&cluster=" + instance.getRegistryCluster() + ", " + metadata);
-            }
-            return metadata;
-        }
-
-        // try to load metadata from remote.
-        int triedTimes = 0;
-        while (triedTimes < 3) {
-            metadata = doGetMetadataInfo(instance, metadataReport);
-
-            if (metadata != MetadataInfo.EMPTY) {// succeeded
-                break;
-            } else {// failed
-                logger.error("Failed to get MetadataInfo for instance " + instance.getAddress() + "?revision=" + revision
-                    + "&cluster=" + instance.getRegistryCluster() + ", wait for retry.");
-                triedTimes++;
-                try {
-                    Thread.sleep(1000);
-                } catch (InterruptedException e) {
-                }
-            }
-        }
-
-        revisionToMetadata.putIfAbsent(revision, metadata);
-        return metadata;
-    }
-
-    protected static MetadataInfo doGetMetadataInfo(ServiceInstance instance, MetadataReport metadataReport) {
+    public static MetadataInfo getRemoteMetadata(String revision, ServiceInstance instance, MetadataReport metadataReport) {
         String metadataType = ServiceInstanceMetadataUtils.getMetadataStorageType(instance);
         MetadataInfo metadataInfo = null;
         try {
@@ -177,7 +143,7 @@ public class MetadataUtils {
                 logger.debug("Instance " + instance.getAddress() + " is using metadata type " + metadataType);
             }
             if (REMOTE_METADATA_STORAGE_TYPE.equals(metadataType)) {
-                getMetadata(instance, metadataReport);
+                MetadataUtils.getMetadata(instance, metadataReport);
             } else {
                 // change the instance used to communicate to avoid all requests route to the same instance
                 MetadataService metadataServiceProxy = MetadataUtils.getMetadataServiceProxy(instance);
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/ProtocolPortsMetadataCustomizer.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/ProtocolPortsMetadataCustomizer.java
index ec17ae0..96d7e23 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/ProtocolPortsMetadataCustomizer.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/ProtocolPortsMetadataCustomizer.java
@@ -16,10 +16,11 @@
  */
 package org.apache.dubbo.registry.client.metadata;
 
-import org.apache.dubbo.metadata.WritableMetadataService;
+import org.apache.dubbo.metadata.MetadataService;
 import org.apache.dubbo.registry.client.ServiceInstance;
 import org.apache.dubbo.registry.client.ServiceInstanceCustomizer;
 import org.apache.dubbo.rpc.Protocol;
+import org.apache.dubbo.rpc.model.ApplicationModel;
 
 import java.util.HashMap;
 import java.util.Map;
@@ -35,11 +36,11 @@ import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataU
 public class ProtocolPortsMetadataCustomizer implements ServiceInstanceCustomizer {
 
     @Override
-    public void customize(ServiceInstance serviceInstance) {
-        WritableMetadataService writableMetadataService = WritableMetadataService.getDefaultExtension(serviceInstance.getApplicationModel());
+    public void customize(ServiceInstance serviceInstance, ApplicationModel applicationModel) {
+        MetadataService metadataService = applicationModel.getBeanFactory().getBean(MetadataService.class);
 
         Map<String, Integer> protocols = new HashMap<>();
-        writableMetadataService.getExportedServiceURLs()
+        metadataService.getExportedServiceURLs()
                 .forEach(url -> {
                     // TODO, same protocol listen on different ports will override with each other.
                     protocols.put(url.getProtocol(), url.getPort());
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/ServiceInstanceMetadataCustomizer.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/ServiceInstanceMetadataCustomizer.java
index cfdc530..2ec8965 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/ServiceInstanceMetadataCustomizer.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/ServiceInstanceMetadataCustomizer.java
@@ -16,13 +16,9 @@
  */
 package org.apache.dubbo.registry.client.metadata;
 
-import org.apache.dubbo.common.URL;
-import org.apache.dubbo.common.extension.ExtensionLoader;
 import org.apache.dubbo.common.infra.InfraAdapter;
-import org.apache.dubbo.common.utils.ArrayUtils;
 import org.apache.dubbo.common.utils.CollectionUtils;
 import org.apache.dubbo.metadata.MetadataInfo;
-import org.apache.dubbo.metadata.MetadataParamsFilter;
 import org.apache.dubbo.registry.client.DefaultServiceInstance;
 import org.apache.dubbo.registry.client.ServiceInstance;
 import org.apache.dubbo.registry.client.ServiceInstanceCustomizer;
@@ -30,25 +26,24 @@ import org.apache.dubbo.rpc.model.ApplicationModel;
 
 import java.util.Collections;
 import java.util.HashMap;
-import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
 import static org.apache.dubbo.common.constants.CommonConstants.APPLICATION_KEY;
 
 /**
- * <p>Intercepting instance to load instance-level params from different sources before being registered to registry.</p>
+ * <p>Intercepting instance to load instance-level params from different sources before being registered into registry.</p>
  *
- * The sources can be:
+ * The sources can be one or both of the following:
  * <ul>
  *  <li>os environment</li>
  *  <li>vm options</li>
  * </ul>
  *
- * The keys left are determined by:
+ * So, finally, the keys left in order will be:
  * <ul>
  *  <li>all keys specified by sources above</li>
- *  <li>keys specified in param filters</li>
+ *  <li>keys found in metadata info</li>
  * </ul>
  *
  *
@@ -56,20 +51,13 @@ import static org.apache.dubbo.common.constants.CommonConstants.APPLICATION_KEY;
 public class ServiceInstanceMetadataCustomizer implements ServiceInstanceCustomizer {
 
     @Override
-    public void customize(ServiceInstance serviceInstance) {
-        ApplicationModel applicationModel = serviceInstance.getApplicationModel();
-        ExtensionLoader<MetadataParamsFilter> loader = applicationModel.getExtensionLoader(MetadataParamsFilter.class);
-
+    public void customize(ServiceInstance serviceInstance, ApplicationModel applicationModel) {
         MetadataInfo metadataInfo = ((DefaultServiceInstance)serviceInstance).getServiceMetadata();
         if (metadataInfo == null || CollectionUtils.isEmptyMap(metadataInfo.getServices())) {
             return;
         }
-        MetadataInfo.ServiceInfo serviceInfo = metadataInfo.getServices().values().iterator().next();
-        URL url = serviceInfo.getUrl();
-        List<MetadataParamsFilter> paramsFilters = loader.getActivateExtension(url, "params-filter");
-        Map<String, String> allParams = new HashMap<>(url.getParameters());
 
-        // load instance params users want to load.
+        // try to load instance params that do not appear in service urls
         // TODO, duplicate snippet in ApplicationConfig
         Map<String, String> extraParameters = Collections.emptyMap();
         Set<InfraAdapter> adapters = applicationModel.getExtensionLoader(InfraAdapter.class).getSupportedExtensionInstances();
@@ -81,26 +69,9 @@ public class ServiceInstanceMetadataCustomizer implements ServiceInstanceCustomi
             }
         }
 
-        if (CollectionUtils.isEmpty(paramsFilters)) {
-            serviceInstance.getMetadata().putAll(extraParameters);
-            return;
-        }
-
         serviceInstance.getMetadata().putAll(extraParameters);;
-        paramsFilters.forEach(filter -> {
-            String[] included = filter.instanceParamsIncluded();
-            if (ArrayUtils.isEmpty(included)) {
-                /*
-                 * Does not put any parameter in instance if not specified.
-                 * It has no functional impact as long as params appear in service metadata.
-                 */
-            } else {
-                for (String p : included) {
-                    if (allParams.get(p) != null) {
-                        serviceInstance.getMetadata().put(p, allParams.get(p));
-                    }
-                }
-            }
-        });
+        if (CollectionUtils.isNotEmptyMap(metadataInfo.getInstanceParams())) {
+            serviceInstance.getMetadata().putAll(metadataInfo.getInstanceParams());
+        }
     }
 }
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 6cfc2df..152bde3 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
@@ -22,7 +22,6 @@ 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.WritableMetadataService;
 import org.apache.dubbo.registry.client.DefaultServiceInstance;
 import org.apache.dubbo.registry.client.DefaultServiceInstance.Endpoint;
 import org.apache.dubbo.registry.client.ServiceDiscovery;
@@ -152,10 +151,8 @@ public class ServiceInstanceMetadataUtils {
     }
 
     /**
-     * Get the metadata's storage type is used to which {@link WritableMetadataService} instance.
-     *
-     * @param serviceInstance the specified {@link ServiceInstance}
-     * @return if not found in {@link ServiceInstance#getMetadata() metadata} of {@link ServiceInstance}, return
+     * Get the metadata storage type specified by the peer instance.
+     * @return storage type, remote or local
      */
     public static String getMetadataStorageType(ServiceInstance serviceInstance) {
         Map<String, String> metadata = serviceInstance.getMetadata();
@@ -218,8 +215,8 @@ public class ServiceInstanceMetadataUtils {
     }
 
     public static void registerMetadataAndInstance(ApplicationModel applicationModel) {
-            LOGGER.info("Start registering instance address to registry.");
-            RegistryManager registryManager = applicationModel.getBeanFactory().getBean(RegistryManager.class);
+        LOGGER.info("Start registering instance address to registry.");
+        RegistryManager registryManager = applicationModel.getBeanFactory().getBean(RegistryManager.class);
         // register service instance
         registryManager.getServiceDiscoveries().forEach(ServiceDiscovery::register);
     }
@@ -241,13 +238,13 @@ public class ServiceInstanceMetadataUtils {
         });
     }
 
-    public static void customizeInstance(ServiceInstance instance) {
+    public static void customizeInstance(ServiceInstance instance, ApplicationModel applicationModel) {
         ExtensionLoader<ServiceInstanceCustomizer> loader =
                 instance.getOrDefaultApplicationModel().getExtensionLoader(ServiceInstanceCustomizer.class);
         // FIXME, sort customizer before apply
         loader.getSupportedExtensionInstances().forEach(customizer -> {
             // customize
-            customizer.customize(instance);
+            customizer.customize(instance, applicationModel);
         });
     }
 
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/StandardMetadataServiceURLBuilder.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/StandardMetadataServiceURLBuilder.java
index d1b88f0..a0588ef 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/StandardMetadataServiceURLBuilder.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/StandardMetadataServiceURLBuilder.java
@@ -135,8 +135,8 @@ public class StandardMetadataServiceURLBuilder implements MetadataServiceURLBuil
                 .addParameter(GROUP_KEY, serviceName)
                 .addParameter(VERSION_KEY, MetadataService.VERSION);
 
-        // add ServiceInstance Metadata notify support
-        urlBuilder.addParameter("getAndListenInstanceMetadata.1.callback", true);
+//        // add ServiceInstance Metadata notify support
+//        urlBuilder.addParameter("getAndListenInstanceMetadata.1.callback", true);
 
         return urlBuilder.build();
     }
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/store/MetaCacheManager.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/store/MetaCacheManager.java
index 079c953..ddc9213 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/store/MetaCacheManager.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/store/MetaCacheManager.java
@@ -41,7 +41,6 @@ import java.util.concurrent.TimeUnit;
 public class MetaCacheManager implements ScopeModelAware, Disposable {
     private static final Logger logger = LoggerFactory.getLogger(MetaCacheManager.class);
     private static final String DEFAULT_FILE_NAME = ".metadata";
-    private static final String SUFFIX = ".dubbo.cache";
     private static final int DEFAULT_ENTRY_SIZE = 1000;
 
     private static final long INTERVAL = 60L;
@@ -55,12 +54,20 @@ public class MetaCacheManager implements ScopeModelAware, Disposable {
     }
 
     public MetaCacheManager() {
+        this("");
+    }
+
+    public MetaCacheManager(String registryName) {
         String filePath = System.getProperty("dubbo.meta.cache.filePath");
         String fileName = System.getProperty("dubbo.meta.cache.fileName");
         if (StringUtils.isEmpty(fileName)) {
             fileName = DEFAULT_FILE_NAME;
         }
 
+        if (StringUtils.isNotEmpty(registryName)) {
+            fileName = fileName + "." + registryName;
+        }
+
         String rawEntrySize = System.getProperty("dubbo.meta.cache.entrySize");
         int entrySize = StringUtils.parseInteger(rawEntrySize);
         entrySize = (entrySize == 0 ? DEFAULT_ENTRY_SIZE : entrySize);
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/store/MetadataServiceDelegation.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/store/MetadataServiceDelegation.java
index a298f17..191a60f 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/store/MetadataServiceDelegation.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/store/MetadataServiceDelegation.java
@@ -19,11 +19,10 @@ package org.apache.dubbo.registry.client.metadata.store;
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.logger.Logger;
 import org.apache.dubbo.common.logger.LoggerFactory;
+import org.apache.dubbo.common.resource.Disposable;
 import org.apache.dubbo.common.utils.StringUtils;
 import org.apache.dubbo.metadata.MetadataInfo;
 import org.apache.dubbo.metadata.MetadataService;
-import org.apache.dubbo.metadata.MetadataServiceExporter;
-import org.apache.dubbo.metadata.WritableMetadataService;
 import org.apache.dubbo.registry.client.ServiceDiscovery;
 import org.apache.dubbo.registry.support.RegistryManager;
 import org.apache.dubbo.rpc.model.ApplicationModel;
@@ -50,7 +49,7 @@ import static org.apache.dubbo.common.utils.CollectionUtils.isEmpty;
 /**
  * Implementation providing remote RPC service to facilitate the query of metadata information.
  */
-public class MetadataServiceDelegation implements WritableMetadataService, ScopeModelAware {
+public class MetadataServiceDelegation implements MetadataService, ScopeModelAware, Disposable {
     Logger logger = LoggerFactory.getLogger(getClass());
     private ApplicationModel applicationModel;
     private RegistryManager registryManager;
@@ -187,16 +186,6 @@ public class MetadataServiceDelegation implements WritableMetadataService, Scope
         return metadataInfos;
     }
 
-    @Override
-    public URL getMetadataServiceURL() {
-        MetadataServiceExporter metadataServiceExporter = applicationModel.getExtensionLoader(MetadataServiceExporter.class).getDefaultExtension();
-        if (metadataServiceExporter.isExported()) {
-            List<URL> metadataURLs = metadataServiceExporter.getExportedURLs();
-            return metadataURLs.get(0);
-        }
-        return null;
-    }
-
     private SortedSet<String> getServiceURLs(Map<String, SortedSet<URL>> exportedServiceURLs, String serviceKey,
                                              String protocol) {
 
@@ -215,6 +204,11 @@ public class MetadataServiceDelegation implements WritableMetadataService, Scope
             || protocol.equals(url.getProtocol());
     }
 
+    @Override
+    public void destroy() {
+
+    }
+
 
     static class URLComparator implements Comparator<URL> {
 
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/selector/RandomServiceInstanceSelector.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/selector/RandomServiceInstanceSelector.java
deleted file mode 100644
index b8dd7d8..0000000
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/selector/RandomServiceInstanceSelector.java
+++ /dev/null
@@ -1,47 +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.selector;
-
-import org.apache.dubbo.common.URL;
-import org.apache.dubbo.registry.client.ServiceInstance;
-
-import java.util.List;
-import java.util.concurrent.ThreadLocalRandom;
-
-/**
- * The {@link ServiceInstanceSelector} implementation based on Random algorithm
- *
- * @see ThreadLocalRandom
- * @see ServiceInstanceSelector
- * @since 2.7.5
- */
-public class RandomServiceInstanceSelector implements ServiceInstanceSelector {
-
-    @Override
-    public ServiceInstance select(URL registryURL, List<ServiceInstance> serviceInstances) {
-        int size = serviceInstances.size();
-        if (size < 1) {
-            return null;
-        }
-        int index = size == 1 ? 0 : selectIndexRandomly(size);
-        return serviceInstances.get(index);
-    }
-
-    protected int selectIndexRandomly(int size) {
-        return ThreadLocalRandom.current().nextInt(size);
-    }
-}
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/selector/ServiceInstanceSelector.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/selector/ServiceInstanceSelector.java
deleted file mode 100644
index c2f1863..0000000
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/selector/ServiceInstanceSelector.java
+++ /dev/null
@@ -1,43 +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.selector;
-
-import org.apache.dubbo.common.URL;
-import org.apache.dubbo.common.extension.Adaptive;
-import org.apache.dubbo.common.extension.SPI;
-import org.apache.dubbo.registry.client.ServiceInstance;
-
-import java.util.List;
-
-/**
- * The {@link ServiceInstance} Selector
- *
- * @since 2.7.5
- */
-@SPI("random")
-public interface ServiceInstanceSelector {
-
-    /**
-     * Select an instance of {@link ServiceInstance} by the specified {@link ServiceInstance service instances}
-     *
-     * @param registryURL      The {@link URL url} of registry
-     * @param serviceInstances the specified {@link ServiceInstance service instances}
-     * @return an instance of {@link ServiceInstance} if available, or <code>null</code>
-     */
-    @Adaptive("service-instance-selector")
-    ServiceInstance select(URL registryURL, List<ServiceInstance> serviceInstances);
-}
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/support/AbstractRegistry.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/support/AbstractRegistry.java
index 176f72b..7391fc3 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/support/AbstractRegistry.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/support/AbstractRegistry.java
@@ -27,6 +27,7 @@ import org.apache.dubbo.common.utils.StringUtils;
 import org.apache.dubbo.common.utils.UrlUtils;
 import org.apache.dubbo.registry.NotifyListener;
 import org.apache.dubbo.registry.Registry;
+import org.apache.dubbo.rpc.model.ApplicationModel;
 
 import java.io.File;
 import java.io.FileInputStream;
@@ -95,6 +96,7 @@ public abstract class AbstractRegistry implements Registry {
     private File file;
     private boolean localCacheEnabled;
     private RegistryManager registryManager;
+    protected ApplicationModel applicationModel;
 
     public AbstractRegistry(URL url) {
         setUrl(url);
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/support/AbstractRegistryFactory.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/support/AbstractRegistryFactory.java
index 72cfdd3..50889b7 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/support/AbstractRegistryFactory.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/support/AbstractRegistryFactory.java
@@ -41,11 +41,12 @@ public abstract class AbstractRegistryFactory implements RegistryFactory, ScopeM
 
     private static final Logger LOGGER = LoggerFactory.getLogger(AbstractRegistryFactory.class);
 
-
     private RegistryManager registryManager;
+    protected ApplicationModel applicationModel;
 
     @Override
     public void setApplicationModel(ApplicationModel applicationModel) {
+        this.applicationModel = applicationModel;
         this.registryManager = applicationModel.getBeanFactory().getBean(RegistryManager.class);
     }
 
@@ -118,4 +119,5 @@ public abstract class AbstractRegistryFactory implements RegistryFactory, ScopeM
 
     protected abstract Registry createRegistry(URL url);
 
+
 }
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
deleted file mode 100644
index d64d12c..0000000
--- a/dubbo-registry/dubbo-registry-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.client.ServiceDiscovery
+++ /dev/null
@@ -1 +0,0 @@
-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
deleted file mode 100644
index d30ea0c..0000000
--- a/dubbo-registry/dubbo-registry-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.client.ServiceDiscoveryFactory
+++ /dev/null
@@ -1 +0,0 @@
-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.registry.client.selector.ServiceInstanceSelector b/dubbo-registry/dubbo-registry-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.client.selector.ServiceInstanceSelector
deleted file mode 100644
index d3cca8c..0000000
--- a/dubbo-registry/dubbo-registry-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.client.selector.ServiceInstanceSelector
+++ /dev/null
@@ -1 +0,0 @@
-random=org.apache.dubbo.registry.client.selector.RandomServiceInstanceSelector
\ No newline at end of file
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
deleted file mode 100644
index 4eff847..0000000
--- a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/InMemoryServiceDiscovery.java
+++ /dev/null
@@ -1,107 +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;
-import org.apache.dubbo.common.utils.DefaultPage;
-import org.apache.dubbo.common.utils.Page;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import static java.util.Collections.emptyList;
-
-/**
- * In-Memory {@link ServiceDiscovery} implementation
- *
- * @since 2.7.5
- */
-public class InMemoryServiceDiscovery extends AbstractServiceDiscovery {
-
-    private Map<String, List<ServiceInstance>> repository = new HashMap<>();
-
-    private URL registryURL;
-
-    public InMemoryServiceDiscovery(String serviceName) {
-        super(serviceName);
-    }
-
-    @Override
-    public Set<String> getServices() {
-        return repository.keySet();
-    }
-
-    @Override
-    public Page<ServiceInstance> getInstances(String serviceName, int offset, int pageSize, boolean healthyOnly) {
-        List<ServiceInstance> instances = new ArrayList<>(repository.computeIfAbsent(serviceName, s -> new LinkedList<>()));
-        int totalSize = instances.size();
-        List<ServiceInstance> data = emptyList();
-        if (offset < totalSize) {
-            int toIndex = offset + pageSize > totalSize - 1 ? totalSize : offset + pageSize;
-            data = instances.subList(offset, toIndex);
-        }
-        if (healthyOnly) {
-            Iterator<ServiceInstance> iterator = data.iterator();
-            while (iterator.hasNext()) {
-                ServiceInstance instance = iterator.next();
-                if (!instance.isHealthy()) {
-                    iterator.remove();
-                }
-            }
-        }
-        return new DefaultPage<>(offset, pageSize, data, totalSize);
-    }
-
-    @Override
-    public URL getUrl() {
-        return registryURL;
-    }
-
-    public String toString() {
-        return "InMemoryServiceDiscovery";
-    }
-
-    @Override
-    public void doRegister(ServiceInstance serviceInstance) throws RuntimeException {
-        String serviceName = serviceInstance.getServiceName();
-        List<ServiceInstance> serviceInstances = repository.computeIfAbsent(serviceName, s -> new LinkedList<>());
-        if (!serviceInstances.contains(serviceInstance)) {
-            serviceInstances.add(serviceInstance);
-        }
-    }
-
-    @Override
-    public void doUnregister() throws RuntimeException {
-        String serviceName = serviceInstance.getServiceName();
-        List<ServiceInstance> serviceInstances = repository.computeIfAbsent(serviceName, s -> new LinkedList<>());
-        serviceInstances.remove(serviceInstance);
-    }
-
-    @Override
-    public void doInitialize(URL registryURL) throws Exception {
-        this.registryURL = registryURL;
-    }
-
-    @Override
-    public void doDestroy() {
-    }
-}
diff --git a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/metadata/MetadataServiceURLParamsMetadataCustomizerTest.java b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/metadata/MetadataServiceURLParamsMetadataCustomizerTest.java
index eb38149..f7aace9 100644
--- a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/metadata/MetadataServiceURLParamsMetadataCustomizerTest.java
+++ b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/metadata/MetadataServiceURLParamsMetadataCustomizerTest.java
@@ -18,7 +18,6 @@ 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.DefaultServiceInstance;
 import org.apache.dubbo.registry.client.metadata.store.MetadataServiceDelegation;
 import org.apache.dubbo.rpc.model.ApplicationModel;
@@ -29,7 +28,6 @@ import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
-import org.mockito.MockedStatic;
 import org.mockito.Mockito;
 
 import java.io.IOException;
@@ -43,7 +41,6 @@ import static org.apache.dubbo.common.constants.CommonConstants.TIMESTAMP_KEY;
 import static org.apache.dubbo.common.constants.CommonConstants.VERSION_KEY;
 import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.METADATA_SERVICE_URL_PARAMS_PROPERTY_NAME;
 import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
 
 public class MetadataServiceURLParamsMetadataCustomizerTest {
     private static final Gson gson = new Gson();
@@ -62,7 +59,6 @@ public class MetadataServiceURLParamsMetadataCustomizerTest {
     public void init() {
         instance = createInstance();
         metadataService = mock(MetadataServiceDelegation.class);
-        when(metadataService.getMetadataServiceURL()).thenReturn(metadataServiceURL);
     }
 
     @AfterEach
@@ -73,21 +69,18 @@ public class MetadataServiceURLParamsMetadataCustomizerTest {
     @Test
     public void test() {
         MetadataServiceURLParamsMetadataCustomizer customizer = new MetadataServiceURLParamsMetadataCustomizer();
-        try (MockedStatic<WritableMetadataService> mockMetadataService = Mockito.mockStatic(WritableMetadataService.class)) {
-            mockMetadataService.when(() -> WritableMetadataService.getDefaultExtension(ApplicationModel.defaultModel())).thenReturn(metadataService);
-            customizer.customize(instance);
+        customizer.customize(instance, ApplicationModel.defaultModel());
 
-            String val = instance.getMetadata().get(METADATA_SERVICE_URL_PARAMS_PROPERTY_NAME);
-            Assertions.assertNotNull(val);
+        String val = instance.getMetadata().get(METADATA_SERVICE_URL_PARAMS_PROPERTY_NAME);
+        Assertions.assertNotNull(val);
 
-            Map<String, String> map = gson.fromJson(val, new TypeToken<Map<String, String>>() {
-            }.getType());
-            Assertions.assertEquals(map.get(PORT_KEY), String.valueOf(metadataServiceURL.getPort()));
-            Assertions.assertEquals(map.get(PROTOCOL_KEY), metadataServiceURL.getProtocol());
-            Assertions.assertEquals(map.get(VERSION_KEY), metadataServiceURL.getVersion());
-            Assertions.assertFalse(map.containsKey(TIMESTAMP_KEY));
-            Assertions.assertFalse(map.containsKey(GROUP_KEY));
-            Assertions.assertFalse(map.containsKey(APPLICATION_KEY));
-        }
+        Map<String, String> map = gson.fromJson(val, new TypeToken<Map<String, String>>() {
+        }.getType());
+        Assertions.assertEquals(map.get(PORT_KEY), String.valueOf(metadataServiceURL.getPort()));
+        Assertions.assertEquals(map.get(PROTOCOL_KEY), metadataServiceURL.getProtocol());
+        Assertions.assertEquals(map.get(VERSION_KEY), metadataServiceURL.getVersion());
+        Assertions.assertFalse(map.containsKey(TIMESTAMP_KEY));
+        Assertions.assertFalse(map.containsKey(GROUP_KEY));
+        Assertions.assertFalse(map.containsKey(APPLICATION_KEY));
     }
 }
diff --git a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/metadata/ProtocolPortsMetadataCustomizerTest.java b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/metadata/ProtocolPortsMetadataCustomizerTest.java
index fa058f8..96ad9c1 100644
--- a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/metadata/ProtocolPortsMetadataCustomizerTest.java
+++ b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/metadata/ProtocolPortsMetadataCustomizerTest.java
@@ -17,8 +17,9 @@
 package org.apache.dubbo.registry.client.metadata;
 
 import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.beans.factory.ScopeBeanFactory;
 import org.apache.dubbo.config.ApplicationConfig;
-import org.apache.dubbo.metadata.WritableMetadataService;
+import org.apache.dubbo.metadata.MetadataService;
 import org.apache.dubbo.registry.client.DefaultServiceInstance;
 import org.apache.dubbo.registry.client.metadata.store.MetadataServiceDelegation;
 import org.apache.dubbo.rpc.model.ApplicationModel;
@@ -31,7 +32,6 @@ import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
-import org.mockito.MockedStatic;
 import org.mockito.Mockito;
 
 import java.io.IOException;
@@ -45,14 +45,15 @@ import static org.hamcrest.Matchers.hasItem;
 import static org.hamcrest.Matchers.hasProperty;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
-import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
 public class ProtocolPortsMetadataCustomizerTest {
     private static final Gson gson = new Gson();
 
     public DefaultServiceInstance instance;
-    private MetadataServiceDelegation metadataService;
+    private static MetadataServiceDelegation mockedMetadataService;
+    private static ApplicationModel mockedApplicationModel;
+    private static ScopeBeanFactory mockedBeanFactory;
 
     public static DefaultServiceInstance createInstance() {
         return new DefaultServiceInstance("A", "127.0.0.1", 20880, ApplicationModel.defaultModel());
@@ -62,6 +63,13 @@ public class ProtocolPortsMetadataCustomizerTest {
     public static void setUp() {
         ApplicationConfig applicationConfig = new ApplicationConfig("test");
         ApplicationModel.defaultModel().getApplicationConfigManager().setApplication(applicationConfig);
+
+        mockedMetadataService = Mockito.mock(MetadataServiceDelegation.class);
+
+        mockedApplicationModel = Mockito.mock(ApplicationModel.class);
+        Mockito.when(mockedApplicationModel.getBeanFactory()).thenReturn(mockedBeanFactory);
+        mockedBeanFactory = Mockito.mock(ScopeBeanFactory.class);
+        Mockito.when(mockedBeanFactory.getBean(MetadataService.class)).thenReturn(mockedMetadataService);
     }
 
     @AfterAll
@@ -72,7 +80,6 @@ public class ProtocolPortsMetadataCustomizerTest {
     @BeforeEach
     public void init() {
         instance = createInstance();
-        metadataService = mock(MetadataServiceDelegation.class);
 
         URL dubboUrl = URL.valueOf("dubbo://30.10.104.63:20880/org.apache.dubbo.demo.GreetingService?" +
             "REGISTRY_CLUSTER=registry1&anyhost=true&application=demo-provider2&delay=5000&deprecated=false&dubbo=2.0.2&dynamic=true&generic=false&group=greeting&interface=org.apache.dubbo.demo.GreetingService&metadata-type=remote&methods=hello&pid=55805&release=&revision=1.0.0&service-name-mapping=true&side=provider&timeout=5000&timestamp=1630229110058&version=1.0.0");
@@ -81,7 +88,7 @@ public class ProtocolPortsMetadataCustomizerTest {
         Set<URL> urls = new HashSet<>();
         urls.add(dubboUrl);
         urls.add(triURL);
-        when(metadataService.getExportedServiceURLs()).thenReturn(urls);
+        when(mockedMetadataService.getExportedServiceURLs()).thenReturn(urls);
     }
 
     @AfterEach
@@ -92,17 +99,14 @@ public class ProtocolPortsMetadataCustomizerTest {
     @Test
     public void test() {
         ProtocolPortsMetadataCustomizer customizer = new ProtocolPortsMetadataCustomizer();
-        try (MockedStatic<WritableMetadataService> mockMetadataService = Mockito.mockStatic(WritableMetadataService.class)) {
-            mockMetadataService.when(() -> WritableMetadataService.getDefaultExtension(ApplicationModel.defaultModel())).thenReturn(metadataService);
-            customizer.customize(instance);
-            String endpoints = instance.getMetadata().get(ENDPOINTS);
-            assertNotNull(endpoints);
-            List<DefaultServiceInstance.Endpoint> endpointList = gson.fromJson(endpoints, new TypeToken<List<DefaultServiceInstance.Endpoint>>(){}.getType());
-            assertEquals(2, endpointList.size());
-            MatcherAssert.assertThat(endpointList, hasItem(hasProperty("protocol", equalTo("dubbo"))));
-            MatcherAssert.assertThat(endpointList, hasItem(hasProperty("port", equalTo(20880))));
-            MatcherAssert.assertThat(endpointList, hasItem(hasProperty("protocol", equalTo("tri"))));
-            MatcherAssert.assertThat(endpointList, hasItem(hasProperty("port", equalTo(50332))));
-        }
+        customizer.customize(instance, ApplicationModel.defaultModel());
+        String endpoints = instance.getMetadata().get(ENDPOINTS);
+        assertNotNull(endpoints);
+        List<DefaultServiceInstance.Endpoint> endpointList = gson.fromJson(endpoints, new TypeToken<List<DefaultServiceInstance.Endpoint>>(){}.getType());
+        assertEquals(2, endpointList.size());
+        MatcherAssert.assertThat(endpointList, hasItem(hasProperty("protocol", equalTo("dubbo"))));
+        MatcherAssert.assertThat(endpointList, hasItem(hasProperty("port", equalTo(20880))));
+        MatcherAssert.assertThat(endpointList, hasItem(hasProperty("protocol", equalTo("tri"))));
+        MatcherAssert.assertThat(endpointList, hasItem(hasProperty("port", equalTo(50332))));
     }
 }
diff --git a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/metadata/ServiceInstanceMetadataCustomizerTest.java b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/metadata/ServiceInstanceMetadataCustomizerTest.java
index edaf20a..0255ea3 100644
--- a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/metadata/ServiceInstanceMetadataCustomizerTest.java
+++ b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/metadata/ServiceInstanceMetadataCustomizerTest.java
@@ -17,10 +17,11 @@
 package org.apache.dubbo.registry.client.metadata;
 
 import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.beans.factory.ScopeBeanFactory;
 import org.apache.dubbo.common.config.ConfigurationUtils;
 import org.apache.dubbo.config.ApplicationConfig;
 import org.apache.dubbo.metadata.MetadataInfo;
-import org.apache.dubbo.metadata.WritableMetadataService;
+import org.apache.dubbo.metadata.MetadataService;
 import org.apache.dubbo.registry.client.DefaultServiceInstance;
 import org.apache.dubbo.registry.client.metadata.store.MetadataServiceDelegation;
 import org.apache.dubbo.rpc.model.ApplicationModel;
@@ -42,7 +43,9 @@ import static org.mockito.Mockito.mock;
 
 public class ServiceInstanceMetadataCustomizerTest {
     public DefaultServiceInstance instance;
-    private MetadataServiceDelegation metadataService;
+    private static MetadataServiceDelegation mockedMetadataService;
+    private static ApplicationModel mockedApplicationModel;
+    private static ScopeBeanFactory mockedBeanFactory;
 
     public static DefaultServiceInstance createInstance() {
         return new DefaultServiceInstance("A", "127.0.0.1", 20880, ApplicationModel.defaultModel());
@@ -52,6 +55,13 @@ public class ServiceInstanceMetadataCustomizerTest {
     public static void setUp() {
         ApplicationConfig applicationConfig = new ApplicationConfig("test");
         ApplicationModel.defaultModel().getApplicationConfigManager().setApplication(applicationConfig);
+
+        mockedMetadataService = Mockito.mock(MetadataServiceDelegation.class);
+
+        mockedApplicationModel = Mockito.mock(ApplicationModel.class);
+        Mockito.when(mockedApplicationModel.getBeanFactory()).thenReturn(mockedBeanFactory);
+        mockedBeanFactory = Mockito.mock(ScopeBeanFactory.class);
+        Mockito.when(mockedBeanFactory.getBean(MetadataService.class)).thenReturn(mockedMetadataService);
     }
 
     @AfterAll
@@ -62,7 +72,7 @@ public class ServiceInstanceMetadataCustomizerTest {
     @BeforeEach
     public void init() {
         instance = createInstance();
-        metadataService = mock(MetadataServiceDelegation.class);
+        mockedMetadataService = mock(MetadataServiceDelegation.class);
 
         URL url = URL.valueOf("dubbo://30.10.104.63:20880/org.apache.dubbo.demo.GreetingService?" + "params-filter=-default&" +
             "REGISTRY_CLUSTER=registry1&anyhost=true&application=demo-provider2&delay=5000&deprecated=false&dubbo=2.0.2&dynamic=true&generic=false&group=greeting&interface=org.apache.dubbo.demo.GreetingService&metadata-type=remote&methods=hello&pid=55805&release=&revision=1.0.0&service-name-mapping=true&side=provider&timeout=5000&timestamp=1630229110058&version=1.0.0");
@@ -75,31 +85,28 @@ public class ServiceInstanceMetadataCustomizerTest {
     public void test() {
         ServiceInstanceMetadataCustomizer customizer = new ServiceInstanceMetadataCustomizer();
         try (MockedStatic<ConfigurationUtils> mockedUtils = Mockito.mockStatic(ConfigurationUtils.class)) {
-            try (MockedStatic<WritableMetadataService> mockMetadataService = Mockito.mockStatic(WritableMetadataService.class)) {
-                mockMetadataService.when(() -> WritableMetadataService.getDefaultExtension(ApplicationModel.defaultModel())).thenReturn(metadataService);
                 mockedUtils.when(() -> ConfigurationUtils.getProperty(ApplicationModel.defaultModel(), DUBBO_LABELS)).thenReturn("k1=v1;k2=v2");
 
                 // check parameters loaded from infra adapters.
-                customizer.customize(instance);
+                customizer.customize(instance, mockedApplicationModel);
                 assertEquals(2, instance.getMetadata().size());
                 assertEquals("v1", instance.getMetadata().get("k1"));
                 assertEquals("v2", instance.getMetadata().get("k2"));
 
                 // check filters
                 resetInstanceAndMock("excluded,-customized");
-                customizer.customize(instance);
+                customizer.customize(instance, mockedApplicationModel);
                 assertEquals(2, instance.getMetadata().size());
                 assertEquals("v1", instance.getMetadata().get("k1"));
                 assertEquals("v2", instance.getMetadata().get("k2"));
 
                 // check filters
                 resetInstanceAndMock("-excluded,customized");
-                customizer.customize(instance);
+                customizer.customize(instance, mockedApplicationModel);
                 assertEquals(3, instance.getMetadata().size());
                 assertEquals("v1", instance.getMetadata().get("k1"));
                 assertEquals("v2", instance.getMetadata().get("k2"));
                 assertEquals(PROVIDER, instance.getMetadata().get(SIDE_KEY));
-            }
         }
 
     }
diff --git a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/metadata/ServiceInstanceMetadataUtilsTest.java b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/metadata/ServiceInstanceMetadataUtilsTest.java
index 5fe23be..b736f31 100644
--- a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/metadata/ServiceInstanceMetadataUtilsTest.java
+++ b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/metadata/ServiceInstanceMetadataUtilsTest.java
@@ -14,182 +14,181 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.registry.client.metadata;
-
-import org.apache.dubbo.common.URL;
-import org.apache.dubbo.config.ApplicationConfig;
-import org.apache.dubbo.metadata.WritableMetadataService;
-import org.apache.dubbo.registry.Registry;
-import org.apache.dubbo.registry.client.DefaultServiceInstance;
-import org.apache.dubbo.registry.client.InMemoryServiceDiscovery;
-import org.apache.dubbo.registry.client.ServiceDiscovery;
-import org.apache.dubbo.registry.client.ServiceDiscoveryRegistry;
-import org.apache.dubbo.registry.support.RegistryManager;
-import org.apache.dubbo.rpc.model.ApplicationModel;
-
-import com.alibaba.fastjson.JSON;
-import com.alibaba.fastjson.JSONObject;
-import com.google.gson.Gson;
-import org.junit.jupiter.api.AfterAll;
-import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.BeforeAll;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Field;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-
-import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_METADATA_STORAGE_TYPE;
-import static org.apache.dubbo.common.constants.CommonConstants.REMOTE_METADATA_STORAGE_TYPE;
-import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.METADATA_CLUSTER_PROPERTY_NAME;
-import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.METADATA_SERVICE_URL_PARAMS_PROPERTY_NAME;
-import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.METADATA_STORAGE_TYPE_PROPERTY_NAME;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-
-/**
- * {@link ServiceInstanceMetadataUtils} Test
- *
- * @since 2.7.5
- */
-public class ServiceInstanceMetadataUtilsTest {
-
-    private static URL url = URL.valueOf("dubbo://192.168.0.102:20880/org.apache.dubbo.metadata.MetadataService?&anyhost=true&application=spring-cloud-alibaba-dubbo-provider&bind.ip=192.168.0.102&bind.port=20880&default.deprecated=false&default.dynamic=false&default.register=true&deprecated=false&dubbo=2.0.2&dynamic=false&generic=false&group=spring-cloud-alibaba-dubbo-provider&interface=org.apache.dubbo.metadata.MetadataService&methods=getAllServiceKeys,getServiceRestMetadata,getExported [...]
-    private static URL url2 = URL.valueOf("rest://192.168.0.102:20880/org.apache.dubbo.metadata.MetadataService?&anyhost=true&application=spring-cloud-alibaba-dubbo-provider&bind.ip=192.168.0.102&bind.port=20880&default.deprecated=false&default.dynamic=false&default.register=true&deprecated=false&dubbo=2.0.2&dynamic=false&generic=false&group=spring-cloud-alibaba-dubbo-provider&interface=org.apache.dubbo.metadata.MetadataService&methods=getAllServiceKeys,getServiceRestMetadata,getExported [...]
-
-    private static final String VALUE_URL = "{\"version\":\"1.0.0\",\"dubbo\":\"2.0.2\",\"release\":\"2.7.1\",\"port\":\"20880\",\"protocol\":\"dubbo\"}";
-    private static final String VALUE_URL2 = "{\"version\":\"1.0.0\",\"dubbo\":\"2.0.2\",\"release\":\"2.7.1\",\"port\":\"20880\",\"protocol\":\"rest\"}";
-
-    private DefaultServiceInstance serviceInstance;
-
-    @BeforeEach
-    public void init() {
-        serviceInstance = new DefaultServiceInstance("test", "127.0.0.1", 8080, ApplicationModel.defaultModel());
-    }
-
-    @BeforeAll
-    public static void setUp() {
-        ApplicationConfig applicationConfig = new ApplicationConfig("demo");
-        ApplicationModel.defaultModel().getApplicationConfigManager().setApplication(applicationConfig);
-    }
-
-    @AfterAll
-    public static void clearUp() {
-        ApplicationModel.reset();
-    }
-
-
-    @Test
-    public void testMetadataServiceURLParameters() {
-
-        List<URL> urls = Arrays.asList(url, url2);
-
-        urls.forEach(url -> {
-            String parameter = ServiceInstanceMetadataUtils.getMetadataServiceParameter(url);
-
-            JSONObject jsonObject = JSON.parseObject(parameter);
-
-            for (Map.Entry<String, String> param : url.getParameters().entrySet()) {
-                String value = jsonObject.getString(param.getKey());
-                if (value != null) {
-                    assertEquals(param.getValue(), value);
-                }
-            }
-
-        });
-
-        assertEquals(ServiceInstanceMetadataUtils.getMetadataServiceParameter(url), VALUE_URL);
-        assertEquals(ServiceInstanceMetadataUtils.getMetadataServiceParameter(url2), VALUE_URL2);
-    }
-
-    @Test
-    public void getMetadataServiceURLsParams() {
-        Map<String, String> urlParams = new HashMap<>();
-        urlParams.put("dubbo", "1111");
-        urlParams.put("rest", "2222");
-        serviceInstance.getMetadata().put(METADATA_SERVICE_URL_PARAMS_PROPERTY_NAME, new Gson().toJson(urlParams));
-        Map<String, String> metadataServiceURLsParams = ServiceInstanceMetadataUtils.getMetadataServiceURLsParams(serviceInstance);
-        Assertions.assertEquals(metadataServiceURLsParams.get("dubbo"), "1111");
-        Assertions.assertEquals(metadataServiceURLsParams.get("rest"), "2222");
-    }
-
-    @Test
-    public void testMetadataStorageType() {
-        Assertions.assertEquals(ServiceInstanceMetadataUtils.getMetadataStorageType(serviceInstance), DEFAULT_METADATA_STORAGE_TYPE);
-        serviceInstance.getMetadata().put(METADATA_STORAGE_TYPE_PROPERTY_NAME, REMOTE_METADATA_STORAGE_TYPE);
-        Assertions.assertEquals(ServiceInstanceMetadataUtils.getMetadataStorageType(serviceInstance), REMOTE_METADATA_STORAGE_TYPE);
-    }
-
-    @Test
-    public void getRemoteCluster() {
-        Assertions.assertNull(ServiceInstanceMetadataUtils.getRemoteCluster(serviceInstance));
-
-        serviceInstance.getMetadata().put(METADATA_CLUSTER_PROPERTY_NAME, "REGISTRY_CLUSTER_9103");
-        Assertions.assertEquals(ServiceInstanceMetadataUtils.getRemoteCluster(serviceInstance), "REGISTRY_CLUSTER_9103");
-    }
-
-    @Test
-    public void testEndpoints() {
-        Assertions.assertFalse(ServiceInstanceMetadataUtils.hasEndpoints(serviceInstance));
-
-        Map<String, Integer> endpoints = new HashMap<>();
-        endpoints.put("dubbo", 20880);
-        endpoints.put("rest", 8080);
-        ServiceInstanceMetadataUtils.setEndpoints(serviceInstance, endpoints);
-        Assertions.assertTrue(ServiceInstanceMetadataUtils.hasEndpoints(serviceInstance));
-
-        for (Map.Entry<String, Integer> entry : endpoints.entrySet()) {
-            String protocol = entry.getKey();
-            Integer port = entry.getValue();
-            DefaultServiceInstance.Endpoint endpoint = ServiceInstanceMetadataUtils.getEndpoint(serviceInstance, protocol);
-            Assertions.assertEquals(endpoint.getPort(), port);
-        }
-    }
-
-    @Test
-    public void testRegisterMetadataAndInstance() throws Exception {
-        InMemoryServiceDiscovery inMemoryServiceDiscovery = prepare();
-        ServiceInstanceMetadataUtils.registerMetadataAndInstance(ApplicationModel.defaultModel());
-
-        Assertions.assertTrue(inMemoryServiceDiscovery.getServices().contains(serviceInstance.getServiceName()));
-    }
-
-    @Test
-    public void refreshMetadataAndInstance() throws Exception {
-        InMemoryServiceDiscovery inMemoryServiceDiscovery = prepare();
-
-        Assertions.assertNull(inMemoryServiceDiscovery.getLocalInstance());
-
-        ServiceInstanceMetadataUtils.refreshMetadataAndInstance(ApplicationModel.defaultModel());
-
-        Assertions.assertEquals(inMemoryServiceDiscovery.getLocalInstance().getServiceName(), serviceInstance.getServiceName());
-        Assertions.assertEquals(inMemoryServiceDiscovery.getLocalInstance().getHost(), serviceInstance.getHost());
-        Assertions.assertEquals(inMemoryServiceDiscovery.getLocalInstance().getPort(), serviceInstance.getPort());
-        Assertions.assertEquals(inMemoryServiceDiscovery.getLocalInstance().getApplicationModel(), serviceInstance.getApplicationModel());
-    }
-
-    private InMemoryServiceDiscovery prepare() throws NoSuchMethodException, InstantiationException, IllegalAccessException, java.lang.reflect.InvocationTargetException, NoSuchFieldException {
-        WritableMetadataService writableMetadataService = WritableMetadataService.getDefaultExtension(ApplicationModel.defaultModel());
-
-        // Construct serviceDiscoveryRegistry
-        InMemoryServiceDiscovery inMemoryServiceDiscovery = new InMemoryServiceDiscovery("ServiceInstanceMetadataUtilsTest");
-        URL registryURL = URL.valueOf("registry://localhost:2181?registry=zookeeper");
-        Constructor<ServiceDiscoveryRegistry> constructor = ServiceDiscoveryRegistry.class.getDeclaredConstructor(URL.class, ServiceDiscovery.class, WritableMetadataService.class);
-        constructor.setAccessible(true);
-        ServiceDiscoveryRegistry serviceDiscoveryRegistry = constructor.newInstance(registryURL, inMemoryServiceDiscovery, writableMetadataService);
-
-        // Add serviceDiscoveryRegistry to RegisterManger
-        RegistryManager manager = ApplicationModel.defaultModel().getBeanFactory().getBean(RegistryManager.class);
-        Field field = manager.getClass().getDeclaredField("registries");
-        field.setAccessible(true);
-        Map<String, Registry> registries = new ConcurrentHashMap<>();
-        registries.put("127.0.0.1:2181", serviceDiscoveryRegistry);
-        field.set(manager, registries);
-        return inMemoryServiceDiscovery;
-    }
-
-}
+//package org.apache.dubbo.registry.client.metadata;
+//
+//import org.apache.dubbo.common.URL;
+//import org.apache.dubbo.config.ApplicationConfig;
+//import org.apache.dubbo.metadata.MetadataService;
+//import org.apache.dubbo.metadata.ServiceNameMapping;
+//import org.apache.dubbo.registry.Registry;
+//import org.apache.dubbo.registry.client.DefaultServiceInstance;
+//import org.apache.dubbo.registry.client.InMemoryServiceDiscovery;
+//import org.apache.dubbo.registry.client.ServiceDiscovery;
+//import org.apache.dubbo.registry.client.ServiceDiscoveryRegistry;
+//import org.apache.dubbo.registry.support.RegistryManager;
+//import org.apache.dubbo.rpc.model.ApplicationModel;
+//
+//import com.alibaba.fastjson.JSON;
+//import com.alibaba.fastjson.JSONObject;
+//import com.google.gson.Gson;
+//import org.junit.jupiter.api.AfterAll;
+//import org.junit.jupiter.api.Assertions;
+//import org.junit.jupiter.api.BeforeAll;
+//import org.junit.jupiter.api.BeforeEach;
+//import org.junit.jupiter.api.Test;
+//
+//import java.lang.reflect.Constructor;
+//import java.lang.reflect.Field;
+//import java.util.Arrays;
+//import java.util.HashMap;
+//import java.util.List;
+//import java.util.Map;
+//import java.util.concurrent.ConcurrentHashMap;
+//
+//import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_METADATA_STORAGE_TYPE;
+//import static org.apache.dubbo.common.constants.CommonConstants.REMOTE_METADATA_STORAGE_TYPE;
+//import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.METADATA_CLUSTER_PROPERTY_NAME;
+//import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.METADATA_SERVICE_URL_PARAMS_PROPERTY_NAME;
+//import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.METADATA_STORAGE_TYPE_PROPERTY_NAME;
+//import static org.junit.jupiter.api.Assertions.assertEquals;
+//
+///**
+// * {@link ServiceInstanceMetadataUtils} Test
+// *
+// * @since 2.7.5
+// */
+//public class ServiceInstanceMetadataUtilsTest {
+//
+//    private static URL url = URL.valueOf("dubbo://192.168.0.102:20880/org.apache.dubbo.metadata.MetadataService?&anyhost=true&application=spring-cloud-alibaba-dubbo-provider&bind.ip=192.168.0.102&bind.port=20880&default.deprecated=false&default.dynamic=false&default.register=true&deprecated=false&dubbo=2.0.2&dynamic=false&generic=false&group=spring-cloud-alibaba-dubbo-provider&interface=org.apache.dubbo.metadata.MetadataService&methods=getAllServiceKeys,getServiceRestMetadata,getExport [...]
+//    private static URL url2 = URL.valueOf("rest://192.168.0.102:20880/org.apache.dubbo.metadata.MetadataService?&anyhost=true&application=spring-cloud-alibaba-dubbo-provider&bind.ip=192.168.0.102&bind.port=20880&default.deprecated=false&default.dynamic=false&default.register=true&deprecated=false&dubbo=2.0.2&dynamic=false&generic=false&group=spring-cloud-alibaba-dubbo-provider&interface=org.apache.dubbo.metadata.MetadataService&methods=getAllServiceKeys,getServiceRestMetadata,getExport [...]
+//
+//    private static final String VALUE_URL = "{\"version\":\"1.0.0\",\"dubbo\":\"2.0.2\",\"release\":\"2.7.1\",\"port\":\"20880\",\"protocol\":\"dubbo\"}";
+//    private static final String VALUE_URL2 = "{\"version\":\"1.0.0\",\"dubbo\":\"2.0.2\",\"release\":\"2.7.1\",\"port\":\"20880\",\"protocol\":\"rest\"}";
+//
+//    private DefaultServiceInstance serviceInstance;
+//
+//    @BeforeEach
+//    public void init() {
+//        serviceInstance = new DefaultServiceInstance("test", "127.0.0.1", 8080, ApplicationModel.defaultModel());
+//    }
+//
+//    @BeforeAll
+//    public static void setUp() {
+//        ApplicationConfig applicationConfig = new ApplicationConfig("demo");
+//        ApplicationModel.defaultModel().getApplicationConfigManager().setApplication(applicationConfig);
+//    }
+//
+//    @AfterAll
+//    public static void clearUp() {
+//        ApplicationModel.reset();
+//    }
+//
+//
+//    @Test
+//    public void testMetadataServiceURLParameters() {
+//
+//        List<URL> urls = Arrays.asList(url, url2);
+//
+//        urls.forEach(url -> {
+//            String parameter = ServiceInstanceMetadataUtils.getMetadataServiceParameter(url);
+//
+//            JSONObject jsonObject = JSON.parseObject(parameter);
+//
+//            for (Map.Entry<String, String> param : url.getParameters().entrySet()) {
+//                String value = jsonObject.getString(param.getKey());
+//                if (value != null) {
+//                    assertEquals(param.getValue(), value);
+//                }
+//            }
+//
+//        });
+//
+//        assertEquals(ServiceInstanceMetadataUtils.getMetadataServiceParameter(url), VALUE_URL);
+//        assertEquals(ServiceInstanceMetadataUtils.getMetadataServiceParameter(url2), VALUE_URL2);
+//    }
+//
+//    @Test
+//    public void getMetadataServiceURLsParams() {
+//        Map<String, String> urlParams = new HashMap<>();
+//        urlParams.put("dubbo", "1111");
+//        urlParams.put("rest", "2222");
+//        serviceInstance.getMetadata().put(METADATA_SERVICE_URL_PARAMS_PROPERTY_NAME, new Gson().toJson(urlParams));
+//        Map<String, String> metadataServiceURLsParams = ServiceInstanceMetadataUtils.getMetadataServiceURLsParams(serviceInstance);
+//        Assertions.assertEquals(metadataServiceURLsParams.get("dubbo"), "1111");
+//        Assertions.assertEquals(metadataServiceURLsParams.get("rest"), "2222");
+//    }
+//
+//    @Test
+//    public void testMetadataStorageType() {
+//        Assertions.assertEquals(ServiceInstanceMetadataUtils.getMetadataStorageType(serviceInstance), DEFAULT_METADATA_STORAGE_TYPE);
+//        serviceInstance.getMetadata().put(METADATA_STORAGE_TYPE_PROPERTY_NAME, REMOTE_METADATA_STORAGE_TYPE);
+//        Assertions.assertEquals(ServiceInstanceMetadataUtils.getMetadataStorageType(serviceInstance), REMOTE_METADATA_STORAGE_TYPE);
+//    }
+//
+//    @Test
+//    public void getRemoteCluster() {
+//        Assertions.assertNull(ServiceInstanceMetadataUtils.getRemoteCluster(serviceInstance));
+//
+//        serviceInstance.getMetadata().put(METADATA_CLUSTER_PROPERTY_NAME, "REGISTRY_CLUSTER_9103");
+//        Assertions.assertEquals(ServiceInstanceMetadataUtils.getRemoteCluster(serviceInstance), "REGISTRY_CLUSTER_9103");
+//    }
+//
+//    @Test
+//    public void testEndpoints() {
+//        Assertions.assertFalse(ServiceInstanceMetadataUtils.hasEndpoints(serviceInstance));
+//
+//        Map<String, Integer> endpoints = new HashMap<>();
+//        endpoints.put("dubbo", 20880);
+//        endpoints.put("rest", 8080);
+//        ServiceInstanceMetadataUtils.setEndpoints(serviceInstance, endpoints);
+//        Assertions.assertTrue(ServiceInstanceMetadataUtils.hasEndpoints(serviceInstance));
+//
+//        for (Map.Entry<String, Integer> entry : endpoints.entrySet()) {
+//            String protocol = entry.getKey();
+//            Integer port = entry.getValue();
+//            DefaultServiceInstance.Endpoint endpoint = ServiceInstanceMetadataUtils.getEndpoint(serviceInstance, protocol);
+//            Assertions.assertEquals(endpoint.getPort(), port);
+//        }
+//    }
+//
+//    @Test
+//    public void testRegisterMetadataAndInstance() throws Exception {
+//        InMemoryServiceDiscovery inMemoryServiceDiscovery = prepare();
+//        ServiceInstanceMetadataUtils.registerMetadataAndInstance(ApplicationModel.defaultModel());
+//
+//        Assertions.assertTrue(inMemoryServiceDiscovery.getServices().contains(serviceInstance.getServiceName()));
+//    }
+//
+//    @Test
+//    public void refreshMetadataAndInstance() throws Exception {
+//        InMemoryServiceDiscovery inMemoryServiceDiscovery = prepare();
+//
+//        Assertions.assertNull(inMemoryServiceDiscovery.getLocalInstance());
+//
+//        ServiceInstanceMetadataUtils.refreshMetadataAndInstance(ApplicationModel.defaultModel());
+//
+//        Assertions.assertEquals(inMemoryServiceDiscovery.getLocalInstance().getServiceName(), serviceInstance.getServiceName());
+//        Assertions.assertEquals(inMemoryServiceDiscovery.getLocalInstance().getHost(), serviceInstance.getHost());
+//        Assertions.assertEquals(inMemoryServiceDiscovery.getLocalInstance().getPort(), serviceInstance.getPort());
+//        Assertions.assertEquals(inMemoryServiceDiscovery.getLocalInstance().getApplicationModel(), serviceInstance.getApplicationModel());
+//    }
+//
+//    private InMemoryServiceDiscovery prepare() throws NoSuchMethodException, InstantiationException, IllegalAccessException, java.lang.reflect.InvocationTargetException, NoSuchFieldException {
+//        // Construct serviceDiscoveryRegistry
+//        InMemoryServiceDiscovery inMemoryServiceDiscovery = new InMemoryServiceDiscovery("ServiceInstanceMetadataUtilsTest");
+//        URL registryURL = URL.valueOf("registry://localhost:2181?registry=zookeeper");
+//        Constructor<ServiceDiscoveryRegistry> constructor = ServiceDiscoveryRegistry.class.getDeclaredConstructor(URL.class, ServiceDiscovery.class, ServiceNameMapping.class);
+//        constructor.setAccessible(true);
+//        ServiceDiscoveryRegistry serviceDiscoveryRegistry = constructor.newInstance(registryURL, inMemoryServiceDiscovery, metadataService);
+//
+//        // Add serviceDiscoveryRegistry to RegisterManger
+//        RegistryManager manager = ApplicationModel.defaultModel().getBeanFactory().getBean(RegistryManager.class);
+//        Field field = manager.getClass().getDeclaredField("registries");
+//        field.setAccessible(true);
+//        Map<String, Registry> registries = new ConcurrentHashMap<>();
+//        registries.put("127.0.0.1:2181", serviceDiscoveryRegistry);
+//        field.set(manager, registries);
+//        return inMemoryServiceDiscovery;
+//    }
+//
+//}
diff --git a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/metadata/StandardMetadataServiceURLBuilderTest.java b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/metadata/StandardMetadataServiceURLBuilderTest.java
index 22e5832..052e123 100644
--- a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/metadata/StandardMetadataServiceURLBuilderTest.java
+++ b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/metadata/StandardMetadataServiceURLBuilderTest.java
@@ -21,14 +21,15 @@ import org.apache.dubbo.config.ApplicationConfig;
 import org.apache.dubbo.metadata.MetadataService;
 import org.apache.dubbo.registry.client.DefaultServiceInstance;
 import org.apache.dubbo.rpc.model.ApplicationModel;
+
 import org.junit.jupiter.api.AfterAll;
 import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.Test;
+
 import java.util.List;
 
 import static org.apache.dubbo.registry.client.metadata.MetadataServiceURLBuilderTest.serviceInstance;
 import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.mockito.Mockito.spy;
 
 /**
  * {@link StandardMetadataServiceURLBuilder} Test
@@ -63,7 +64,7 @@ public class StandardMetadataServiceURLBuilderTest {
         assertEquals(url.getGroup(), "test");
         assertEquals(url.getSide(), "consumer");
         assertEquals(url.getVersion(), "1.0.0");
-        assertEquals(url.getParameters().get("getAndListenInstanceMetadata.1.callback"), "true");
+//        assertEquals(url.getParameters().get("getAndListenInstanceMetadata.1.callback"), "true");
         assertEquals(url.getParameters().get("reconnect"), "false");
         assertEquals(url.getParameters().get("timeout"), "5000");
 
diff --git a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/support/MockServiceDiscovery.java b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/support/MockServiceDiscovery.java
index db0d053..f921cf5 100644
--- a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/support/MockServiceDiscovery.java
+++ b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/support/MockServiceDiscovery.java
@@ -19,10 +19,15 @@ package org.apache.dubbo.registry.client.support;
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.registry.client.AbstractServiceDiscovery;
 import org.apache.dubbo.registry.client.ServiceInstance;
+import org.apache.dubbo.rpc.model.ApplicationModel;
 
 import java.util.Set;
 
 public class MockServiceDiscovery extends AbstractServiceDiscovery {
+    public MockServiceDiscovery(ApplicationModel applicationModel) {
+        super(applicationModel);
+    }
+
     public MockServiceDiscovery(String serviceName) {
         super(serviceName);
     }
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
deleted file mode 100644
index f7da2f2..0000000
--- a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/support/ServiceOrientedRegistryTest.java
+++ /dev/null
@@ -1,203 +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.support;
-
-import org.apache.dubbo.common.URL;
-import org.apache.dubbo.common.utils.CollectionUtils;
-import org.apache.dubbo.config.ApplicationConfig;
-import org.apache.dubbo.metadata.WritableMetadataService;
-import org.apache.dubbo.registry.NotifyListener;
-import org.apache.dubbo.registry.client.ServiceDiscovery;
-import org.apache.dubbo.registry.client.ServiceDiscoveryRegistry;
-import org.apache.dubbo.rpc.model.ApplicationModel;
-import org.apache.dubbo.rpc.model.ModuleModel;
-
-import org.junit.jupiter.api.AfterAll;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.SortedSet;
-import java.util.TreeSet;
-
-import static java.util.Arrays.asList;
-import static java.util.Collections.unmodifiableSortedSet;
-import static org.apache.dubbo.common.URL.valueOf;
-import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_PROTOCOL;
-import static org.apache.dubbo.common.constants.CommonConstants.PROVIDER_SIDE;
-import static org.apache.dubbo.common.constants.RegistryConstants.REGISTRY_TYPE_KEY;
-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.rpc.Constants.ID_KEY;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertFalse;
-import static org.junit.jupiter.api.Assertions.assertNotNull;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-
-/**
- * {@link ServiceDiscoveryRegistry} Test
- *
- * @since 2.7.5
- */
-public class ServiceOrientedRegistryTest {
-
-    private static final URL registryURL = valueOf("in-memory://localhost:12345")
-            .addParameter(REGISTRY_TYPE_KEY, SERVICE_REGISTRY_TYPE)
-            .addParameter(ID_KEY, "org.apache.dubbo.config.RegistryConfig#0")
-            .addParameter(SUBSCRIBED_SERVICE_NAMES_KEY, "a, b , c,d,e ,");
-
-    private static final String SERVICE_INTERFACE = "org.apache.dubbo.metadata.MetadataService";
-
-    private static final String GROUP = "dubbo-provider";
-
-    private static final String VERSION = "1.0.0";
-
-    private static URL url = valueOf("dubbo://192.168.0.102:20880/" + SERVICE_INTERFACE +
-            "?&application=" + GROUP +
-            "&interface=" + SERVICE_INTERFACE +
-            "&group=" + GROUP +
-            "&version=" + VERSION +
-            "&methods=getAllServiceKeys,getServiceRestMetadata,getExportedURLs,getAllExportedURLs" +
-            "&side=" + PROVIDER_SIDE
-    );
-
-    private static URL url2 = url.setProtocol("rest");
-
-    private WritableMetadataService metadataService;
-
-    private ServiceDiscoveryRegistry registry;
-
-    private NotifyListener notifyListener;
-
-    @BeforeEach
-    public void init() {
-        ApplicationModel.reset();
-        ApplicationModel applicationModel = ApplicationModel.defaultModel();
-        ModuleModel scopeModel = applicationModel.getDefaultModule();
-        registryURL.setScopeModel(scopeModel);
-        registry = ServiceDiscoveryRegistry.create(registryURL);
-        metadataService = WritableMetadataService.getDefaultExtension(scopeModel);
-        notifyListener = new MyNotifyListener();
-        applicationModel.getApplicationConfigManager().setApplication(new ApplicationConfig("Test"));
-    }
-
-    @AfterAll
-    public static void clearUp() {
-        ApplicationModel.reset();
-    }
-
-    @Test
-    public void testSupports() {
-        assertTrue(ServiceDiscoveryRegistry.supports(registryURL));
-    }
-
-    @Test
-    public void testCreate() {
-        assertNotNull(registry);
-    }
-
-    @Test
-    public void testRegister() {
-
-        registry.register(url);
-
-        SortedSet<String> urls = metadataService.getExportedURLs();
-
-        assertTrue(urls.isEmpty());
-        assertEquals(toSortedSet(), metadataService.getExportedURLs(SERVICE_INTERFACE));
-        assertEquals(toSortedSet(), metadataService.getExportedURLs(SERVICE_INTERFACE, GROUP));
-
-        String serviceInterface = "com.acme.UserService";
-
-        URL newURL = url.setServiceInterface(serviceInterface).setPath(serviceInterface);
-
-        registry.register(newURL);
-
-        urls = metadataService.getExportedURLs();
-
-        assertEquals(metadataService.getExportedURLs(serviceInterface, GROUP, VERSION), toSortedSet(urls.first()));
-        assertEquals(metadataService.getExportedURLs(serviceInterface, GROUP, VERSION, DEFAULT_PROTOCOL), toSortedSet(urls.first()));
-
-    }
-
-    @Test
-    public void testUnregister() {
-
-        String serviceInterface = "com.acme.UserService";
-
-        URL newURL = url.setServiceInterface(serviceInterface).setPath(serviceInterface);
-
-        // register
-        registry.register(newURL);
-
-        SortedSet<String> urls = metadataService.getExportedURLs();
-
-        assertEquals(1, urls.size());
-        assertTrue(urls.iterator().next().contains(serviceInterface));
-        assertEquals(metadataService.getExportedURLs(serviceInterface, GROUP, VERSION), urls);
-        assertEquals(metadataService.getExportedURLs(serviceInterface, GROUP, VERSION, DEFAULT_PROTOCOL), urls);
-
-        // unregister
-        registry.unregister(newURL);
-
-        urls = metadataService.getExportedURLs();
-
-        assertEquals(toSortedSet(), urls);
-        assertTrue(CollectionUtils.isEmpty(metadataService.getExportedURLs(serviceInterface)));
-        assertTrue(CollectionUtils.isEmpty(metadataService.getExportedURLs(serviceInterface, GROUP)));
-        assertTrue(CollectionUtils.isEmpty(metadataService.getExportedURLs(serviceInterface, GROUP, VERSION)));
-        assertTrue(CollectionUtils.isEmpty(metadataService.getExportedURLs(serviceInterface, GROUP, VERSION, DEFAULT_PROTOCOL)));
-    }
-
-    @Test
-    public void testSubscribe() {
-
-        NotifyListener listener = new MyNotifyListener();
-        try {
-            registry.subscribe(url, listener);
-            ServiceDiscovery serviceDiscovery = registry.getServiceDiscovery();
-            Map<String, SortedSet<URL>> urls = serviceDiscovery.getMetadata().getSubscribedServiceURLs();
-
-            assertFalse(urls.isEmpty());
-        } finally {
-            registry.unsubscribe(url, listener);
-        }
-
-    }
-
-
-    private class MyNotifyListener implements NotifyListener {
-
-        private List<URL> cache = new LinkedList<>();
-
-        @Override
-        public void notify(List<URL> urls) {
-            cache.addAll(urls);
-        }
-
-        public List<URL> getURLs() {
-            return cache;
-        }
-    }
-
-    private static <T extends Comparable<T>> SortedSet<T> toSortedSet(T... values) {
-        return unmodifiableSortedSet(new TreeSet<>(asList(values)));
-    }
-
-}
diff --git a/dubbo-registry/dubbo-registry-api/src/test/resources/META-INF/services/org.apache.dubbo.registry.client.ServiceDiscovery b/dubbo-registry/dubbo-registry-api/src/test/resources/META-INF/services/org.apache.dubbo.registry.client.ServiceDiscovery
deleted file mode 100644
index 60edf7f..0000000
--- a/dubbo-registry/dubbo-registry-api/src/test/resources/META-INF/services/org.apache.dubbo.registry.client.ServiceDiscovery
+++ /dev/null
@@ -1,2 +0,0 @@
-in-memory=org.apache.dubbo.registry.client.InMemoryServiceDiscovery
-mock=org.apache.dubbo.registry.client.support.MockServiceDiscovery
diff --git a/dubbo-registry/dubbo-registry-multicast/src/main/java/org/apache/dubbo/registry/multicast/MulticastRegistry.java b/dubbo-registry/dubbo-registry-multicast/src/main/java/org/apache/dubbo/registry/multicast/MulticastRegistry.java
index 1c3bc50..996d7a9 100644
--- a/dubbo-registry/dubbo-registry-multicast/src/main/java/org/apache/dubbo/registry/multicast/MulticastRegistry.java
+++ b/dubbo-registry/dubbo-registry-multicast/src/main/java/org/apache/dubbo/registry/multicast/MulticastRegistry.java
@@ -27,6 +27,7 @@ import org.apache.dubbo.common.utils.NetUtils;
 import org.apache.dubbo.common.utils.UrlUtils;
 import org.apache.dubbo.registry.NotifyListener;
 import org.apache.dubbo.registry.support.FailbackRegistry;
+import org.apache.dubbo.rpc.model.ApplicationModel;
 
 import java.io.IOException;
 import java.net.DatagramPacket;
@@ -90,6 +91,10 @@ public class MulticastRegistry extends FailbackRegistry {
 
     private volatile boolean admin = false;
 
+    public MulticastRegistry(URL url, ApplicationModel applicationModel) {
+        this(url);
+    }
+
     public MulticastRegistry(URL url) {
         super(url);
         if (url.isAnyHost()) {
diff --git a/dubbo-registry/dubbo-registry-multicast/src/main/java/org/apache/dubbo/registry/multicast/MulticastRegistryFactory.java b/dubbo-registry/dubbo-registry-multicast/src/main/java/org/apache/dubbo/registry/multicast/MulticastRegistryFactory.java
index 88e96e6..de3d64e 100644
--- a/dubbo-registry/dubbo-registry-multicast/src/main/java/org/apache/dubbo/registry/multicast/MulticastRegistryFactory.java
+++ b/dubbo-registry/dubbo-registry-multicast/src/main/java/org/apache/dubbo/registry/multicast/MulticastRegistryFactory.java
@@ -28,7 +28,7 @@ public class MulticastRegistryFactory extends AbstractRegistryFactory {
 
     @Override
     public Registry createRegistry(URL url) {
-        return new MulticastRegistry(url);
+        return new MulticastRegistry(url, applicationModel);
     }
 
 }
diff --git a/dubbo-registry/dubbo-registry-multicast/src/main/java/org/apache/dubbo/registry/multicast/MulticastServiceDiscovery.java b/dubbo-registry/dubbo-registry-multicast/src/main/java/org/apache/dubbo/registry/multicast/MulticastServiceDiscovery.java
index 2c6b3db..7530201 100644
--- a/dubbo-registry/dubbo-registry-multicast/src/main/java/org/apache/dubbo/registry/multicast/MulticastServiceDiscovery.java
+++ b/dubbo-registry/dubbo-registry-multicast/src/main/java/org/apache/dubbo/registry/multicast/MulticastServiceDiscovery.java
@@ -19,6 +19,7 @@ package org.apache.dubbo.registry.multicast;
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.registry.client.AbstractServiceDiscovery;
 import org.apache.dubbo.registry.client.ServiceInstance;
+import org.apache.dubbo.rpc.model.ApplicationModel;
 
 import java.util.Collections;
 import java.util.Set;
@@ -29,6 +30,10 @@ import java.util.Set;
 public class MulticastServiceDiscovery extends AbstractServiceDiscovery {
     private URL registryURL;
 
+    public MulticastServiceDiscovery(ApplicationModel applicationModel) {
+        super(applicationModel);
+    }
+
     public MulticastServiceDiscovery(String serviceName) {
         super(serviceName);
     }
diff --git a/dubbo-registry/dubbo-registry-multicast/src/main/java/org/apache/dubbo/registry/multicast/MulticastServiceDiscoveryFactory.java b/dubbo-registry/dubbo-registry-multicast/src/main/java/org/apache/dubbo/registry/multicast/MulticastServiceDiscoveryFactory.java
index 1e8a9a4..4d3de8c 100644
--- a/dubbo-registry/dubbo-registry-multicast/src/main/java/org/apache/dubbo/registry/multicast/MulticastServiceDiscoveryFactory.java
+++ b/dubbo-registry/dubbo-registry-multicast/src/main/java/org/apache/dubbo/registry/multicast/MulticastServiceDiscoveryFactory.java
@@ -23,6 +23,6 @@ import org.apache.dubbo.registry.client.ServiceDiscovery;
 public class MulticastServiceDiscoveryFactory extends AbstractServiceDiscoveryFactory {
     @Override
     protected ServiceDiscovery createDiscovery(URL registryURL) {
-        return new MulticastServiceDiscovery(applicationModel.getApplicationName());
+        return new MulticastServiceDiscovery(applicationModel);
     }
 }
diff --git a/dubbo-registry/dubbo-registry-multicast/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.client.ServiceDiscovery b/dubbo-registry/dubbo-registry-multicast/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.client.ServiceDiscovery
deleted file mode 100644
index 091b549..0000000
--- a/dubbo-registry/dubbo-registry-multicast/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.client.ServiceDiscovery
+++ /dev/null
@@ -1 +0,0 @@
-multicast=org.apache.dubbo.registry.multicast.MulticastServiceDiscovery
\ No newline at end of file
diff --git a/dubbo-registry/dubbo-registry-multicast/src/test/java/org/apache/dubbo/registry/multicast/MulticastRegistryFactoryTest.java b/dubbo-registry/dubbo-registry-multicast/src/test/java/org/apache/dubbo/registry/multicast/MulticastRegistryFactoryTest.java
index 3999cdc..c2f5520 100644
--- a/dubbo-registry/dubbo-registry-multicast/src/test/java/org/apache/dubbo/registry/multicast/MulticastRegistryFactoryTest.java
+++ b/dubbo-registry/dubbo-registry-multicast/src/test/java/org/apache/dubbo/registry/multicast/MulticastRegistryFactoryTest.java
@@ -18,6 +18,7 @@ package org.apache.dubbo.registry.multicast;
 
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.registry.Registry;
+
 import org.junit.jupiter.api.Test;
 
 import static org.hamcrest.CoreMatchers.is;
diff --git a/dubbo-registry/dubbo-registry-multiple/src/main/java/org/apache/dubbo/registry/multiple/MultipleServiceDiscovery.java b/dubbo-registry/dubbo-registry-multiple/src/main/java/org/apache/dubbo/registry/multiple/MultipleServiceDiscovery.java
index e3a8b7e..7a36ec4 100644
--- a/dubbo-registry/dubbo-registry-multiple/src/main/java/org/apache/dubbo/registry/multiple/MultipleServiceDiscovery.java
+++ b/dubbo-registry/dubbo-registry-multiple/src/main/java/org/apache/dubbo/registry/multiple/MultipleServiceDiscovery.java
@@ -156,6 +156,11 @@ public class MultipleServiceDiscovery implements ServiceDiscovery {
     }
 
     @Override
+    public MetadataInfo getRemoteMetadata(String revision, ServiceInstance instance) {
+        throw new UnsupportedOperationException("Multiple registry implementation does not support getMetadata() method.");
+    }
+
+    @Override
     public void register(URL url) {
         serviceDiscoveries.values().forEach(serviceDiscovery -> serviceDiscovery.register(url));
     }
diff --git a/dubbo-registry/dubbo-registry-multiple/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.client.ServiceDiscovery b/dubbo-registry/dubbo-registry-multiple/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.client.ServiceDiscovery
deleted file mode 100644
index 9fc8f6d..0000000
--- a/dubbo-registry/dubbo-registry-multiple/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.client.ServiceDiscovery
+++ /dev/null
@@ -1 +0,0 @@
-multiple=org.apache.dubbo.registry.multiple.MultipleServiceDiscovery
\ No newline at end of file
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 d0483fb..1c782ac 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
@@ -26,6 +26,7 @@ import org.apache.dubbo.registry.client.ServiceInstance;
 import org.apache.dubbo.registry.client.event.ServiceInstancesChangedEvent;
 import org.apache.dubbo.registry.client.event.listener.ServiceInstancesChangedListener;
 import org.apache.dubbo.registry.nacos.util.NacosNamingServiceUtils;
+import org.apache.dubbo.rpc.model.ApplicationModel;
 
 import com.alibaba.nacos.api.common.Constants;
 import com.alibaba.nacos.api.exception.NacosException;
@@ -56,6 +57,10 @@ public class NacosServiceDiscovery extends AbstractServiceDiscovery {
 
     private URL registryURL;
 
+    public NacosServiceDiscovery(ApplicationModel applicationModel) {
+        super(applicationModel);
+    }
+
     public NacosServiceDiscovery(String serviceName) {
         super(serviceName);
     }
@@ -108,7 +113,7 @@ public class NacosServiceDiscovery extends AbstractServiceDiscovery {
     public List<ServiceInstance> getInstances(String serviceName) throws NullPointerException {
         return ThrowableFunction.execute(namingService, service ->
             service.selectInstances(serviceName, Constants.DEFAULT_GROUP, true)
-                .stream().map((i) -> NacosNamingServiceUtils.toServiceInstance(registryURL, i, revisionToMetadata, metadataReport))
+                .stream().map((i) -> NacosNamingServiceUtils.toServiceInstance(registryURL, i))
                 .collect(Collectors.toList())
         );
     }
@@ -139,7 +144,7 @@ public class NacosServiceDiscovery extends AbstractServiceDiscovery {
         String serviceName = event.getServiceName();
         List<ServiceInstance> serviceInstances = event.getInstances()
             .stream()
-            .map((i) -> NacosNamingServiceUtils.toServiceInstance(registryURL, i, revisionToMetadata, metadataReport))
+            .map((i) -> NacosNamingServiceUtils.toServiceInstance(registryURL, i))
             .collect(Collectors.toList());
         listener.onEvent(new ServiceInstancesChangedEvent(serviceName, serviceInstances));
     }
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
index ca81ac8..72bc41f 100644
--- 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
@@ -20,14 +20,11 @@ import org.apache.dubbo.common.URL;
 import org.apache.dubbo.registry.client.AbstractServiceDiscoveryFactory;
 import org.apache.dubbo.registry.client.ServiceDiscovery;
 
-/**
- *
- */
 public class NacosServiceDiscoveryFactory extends AbstractServiceDiscoveryFactory {
 
     @Override
     protected ServiceDiscovery createDiscovery(URL registryURL) {
-        return new NacosServiceDiscovery(applicationModel.getApplicationName());
+        return new NacosServiceDiscovery(applicationModel);
     }
 
 }
diff --git a/dubbo-registry/dubbo-registry-nacos/src/main/java/org/apache/dubbo/registry/nacos/util/NacosNamingServiceUtils.java b/dubbo-registry/dubbo-registry-nacos/src/main/java/org/apache/dubbo/registry/nacos/util/NacosNamingServiceUtils.java
index 6a14e7f..3fc8712 100644
--- a/dubbo-registry/dubbo-registry-nacos/src/main/java/org/apache/dubbo/registry/nacos/util/NacosNamingServiceUtils.java
+++ b/dubbo-registry/dubbo-registry-nacos/src/main/java/org/apache/dubbo/registry/nacos/util/NacosNamingServiceUtils.java
@@ -20,12 +20,8 @@ import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.logger.Logger;
 import org.apache.dubbo.common.logger.LoggerFactory;
 import org.apache.dubbo.common.utils.StringUtils;
-import org.apache.dubbo.metadata.MetadataInfo;
-import org.apache.dubbo.metadata.report.MetadataReport;
 import org.apache.dubbo.registry.client.DefaultServiceInstance;
 import org.apache.dubbo.registry.client.ServiceInstance;
-import org.apache.dubbo.registry.client.metadata.MetadataUtils;
-import org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils;
 import org.apache.dubbo.registry.nacos.NacosNamingServiceWrapper;
 import org.apache.dubbo.rpc.model.ScopeModelUtil;
 
@@ -80,7 +76,7 @@ public class NacosNamingServiceUtils {
      * @return non-null
      * @since 2.7.5
      */
-    public static ServiceInstance toServiceInstance(URL registryUrl, Instance instance, Map<String, MetadataInfo> revisionToMetadata, MetadataReport metadataReport) {
+    public static ServiceInstance toServiceInstance(URL registryUrl, Instance instance) {
         DefaultServiceInstance serviceInstance =
             new DefaultServiceInstance(
                 NamingUtils.getServiceName(instance.getServiceName()),
@@ -89,8 +85,6 @@ public class NacosNamingServiceUtils {
         serviceInstance.setMetadata(instance.getMetadata());
         serviceInstance.setEnabled(instance.isEnabled());
         serviceInstance.setHealthy(instance.isHealthy());
-        String revision = ServiceInstanceMetadataUtils.getExportedServicesRevision(serviceInstance);
-        serviceInstance.setServiceMetadata(MetadataUtils.getRemoteMetadata(revision, serviceInstance, revisionToMetadata, metadataReport));
         return serviceInstance;
     }
 
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
deleted file mode 100644
index e3819e0..0000000
--- a/dubbo-registry/dubbo-registry-nacos/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.client.ServiceDiscovery
+++ /dev/null
@@ -1 +0,0 @@
-nacos=org.apache.dubbo.registry.nacos.NacosServiceDiscovery
\ No newline at end of file
diff --git a/dubbo-registry/dubbo-registry-nacos/src/test/java/org/apache/dubbo/registry/nacos/util/NacosNamingServiceUtilsTest.java b/dubbo-registry/dubbo-registry-nacos/src/test/java/org/apache/dubbo/registry/nacos/util/NacosNamingServiceUtilsTest.java
index ba7e82d..fc82035 100644
--- a/dubbo-registry/dubbo-registry-nacos/src/test/java/org/apache/dubbo/registry/nacos/util/NacosNamingServiceUtilsTest.java
+++ b/dubbo-registry/dubbo-registry-nacos/src/test/java/org/apache/dubbo/registry/nacos/util/NacosNamingServiceUtilsTest.java
@@ -59,7 +59,7 @@ public class NacosNamingServiceUtilsTest {
         map.put("version", "2.0");
         instance.setMetadata(map);
 
-        ServiceInstance serviceInstance = NacosNamingServiceUtils.toServiceInstance(registryUrl, instance, new HashMap<>(), metadataReport);
+        ServiceInstance serviceInstance = NacosNamingServiceUtils.toServiceInstance(registryUrl, instance);
         Assertions.assertNotNull(serviceInstance);
         Assertions.assertEquals(serviceInstance.isEnabled(), Boolean.TRUE);
         Assertions.assertEquals(serviceInstance.getServiceName(), "serviceName");
diff --git a/dubbo-registry/dubbo-registry-zookeeper/src/main/java/org/apache/dubbo/registry/zookeeper/ZookeeperRegistryFactory.java b/dubbo-registry/dubbo-registry-zookeeper/src/main/java/org/apache/dubbo/registry/zookeeper/ZookeeperRegistryFactory.java
index 07858b6..b4f20df 100644
--- a/dubbo-registry/dubbo-registry-zookeeper/src/main/java/org/apache/dubbo/registry/zookeeper/ZookeeperRegistryFactory.java
+++ b/dubbo-registry/dubbo-registry-zookeeper/src/main/java/org/apache/dubbo/registry/zookeeper/ZookeeperRegistryFactory.java
@@ -30,8 +30,6 @@ public class ZookeeperRegistryFactory extends AbstractRegistryFactory {
 
     private ZookeeperTransporter zookeeperTransporter;
 
-    private ApplicationModel applicationModel;
-
     // for compatible usage
     public ZookeeperRegistryFactory() {
         this(ApplicationModel.defaultModel());
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 91e43b2..9f2ee17 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
@@ -29,6 +29,7 @@ import org.apache.dubbo.registry.client.ServiceInstance;
 import org.apache.dubbo.registry.client.event.ServiceInstancesChangedEvent;
 import org.apache.dubbo.registry.client.event.listener.ServiceInstancesChangedListener;
 import org.apache.dubbo.rpc.RpcException;
+import org.apache.dubbo.rpc.model.ApplicationModel;
 
 import org.apache.curator.framework.CuratorFramework;
 import org.apache.curator.framework.api.CuratorWatcher;
@@ -71,6 +72,10 @@ public class ZookeeperServiceDiscovery extends AbstractServiceDiscovery {
      */
     private final Map<String, ZookeeperServiceDiscoveryChangeWatcher> watcherCaches = new ConcurrentHashMap<>();
 
+    public ZookeeperServiceDiscovery(ApplicationModel applicationModel) {
+        super(applicationModel);
+    }
+
     public ZookeeperServiceDiscovery(String serviceName) {
         super(serviceName);
     }
@@ -118,7 +123,7 @@ public class ZookeeperServiceDiscovery extends AbstractServiceDiscovery {
 
     @Override
     public List<ServiceInstance> getInstances(String serviceName) throws NullPointerException {
-        return doInServiceDiscovery(s -> build(registryURL, s.queryForInstances(serviceName), revisionToMetadata, metadataReport));
+        return doInServiceDiscovery(s -> build(registryURL, s.queryForInstances(serviceName)));
     }
 
     @Override
@@ -147,7 +152,7 @@ public class ZookeeperServiceDiscovery extends AbstractServiceDiscovery {
                 for (int i = 0; i < pageSize; i++) {
                     if (iterator.hasNext()) {
                         String serviceId = iterator.next();
-                        ServiceInstance serviceInstance = build(registryURL, serviceDiscovery.queryForInstance(serviceName, serviceId), revisionToMetadata, metadataReport);
+                        ServiceInstance serviceInstance = build(registryURL, serviceDiscovery.queryForInstance(serviceName, serviceId));
                         serviceInstances.add(serviceInstance);
                     }
                 }
diff --git a/dubbo-registry/dubbo-registry-zookeeper/src/main/java/org/apache/dubbo/registry/zookeeper/ZookeeperServiceDiscoveryFactory.java b/dubbo-registry/dubbo-registry-zookeeper/src/main/java/org/apache/dubbo/registry/zookeeper/ZookeeperServiceDiscoveryFactory.java
index 00401e7..47c8fbb 100644
--- a/dubbo-registry/dubbo-registry-zookeeper/src/main/java/org/apache/dubbo/registry/zookeeper/ZookeeperServiceDiscoveryFactory.java
+++ b/dubbo-registry/dubbo-registry-zookeeper/src/main/java/org/apache/dubbo/registry/zookeeper/ZookeeperServiceDiscoveryFactory.java
@@ -24,6 +24,6 @@ public class ZookeeperServiceDiscoveryFactory extends AbstractServiceDiscoveryFa
 
     @Override
     protected ServiceDiscovery createDiscovery(URL registryURL) {
-        return new ZookeeperServiceDiscovery(applicationModel.getApplicationName());
+        return new ZookeeperServiceDiscovery(applicationModel);
     }
 }
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 0223099..97e471f 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
@@ -17,12 +17,8 @@
 package org.apache.dubbo.registry.zookeeper.util;
 
 import org.apache.dubbo.common.URL;
-import org.apache.dubbo.metadata.MetadataInfo;
-import org.apache.dubbo.metadata.report.MetadataReport;
 import org.apache.dubbo.registry.client.DefaultServiceInstance;
 import org.apache.dubbo.registry.client.ServiceInstance;
-import org.apache.dubbo.registry.client.metadata.MetadataUtils;
-import org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils;
 import org.apache.dubbo.registry.zookeeper.ZookeeperInstance;
 import org.apache.dubbo.rpc.model.ScopeModelUtil;
 
@@ -90,19 +86,17 @@ public abstract class CuratorFrameworkUtils {
 
 
     public static List<ServiceInstance> build(URL registryUrl, Collection<org.apache.curator.x.discovery.ServiceInstance<ZookeeperInstance>>
-        instances, Map<String, MetadataInfo> revisionToMetadata, MetadataReport metadataReport) {
-        return instances.stream().map((i)->build(registryUrl, i, revisionToMetadata, metadataReport)).collect(Collectors.toList());
+        instances) {
+        return instances.stream().map((i)->build(registryUrl, i)).collect(Collectors.toList());
     }
 
-    public static ServiceInstance build(URL registryUrl, org.apache.curator.x.discovery.ServiceInstance<ZookeeperInstance> instance, Map<String, MetadataInfo> revisionToMetadata, MetadataReport metadataReport) {
+    public static ServiceInstance build(URL registryUrl, org.apache.curator.x.discovery.ServiceInstance<ZookeeperInstance> instance) {
         String name = instance.getName();
         String host = instance.getAddress();
         int port = instance.getPort();
         ZookeeperInstance zookeeperInstance = instance.getPayload();
         DefaultServiceInstance serviceInstance = new DefaultServiceInstance(name, host, port, ScopeModelUtil.getApplicationModel(registryUrl.getScopeModel()));
         serviceInstance.setMetadata(zookeeperInstance.getMetadata());
-        String revision = ServiceInstanceMetadataUtils.getExportedServicesRevision(serviceInstance);
-        serviceInstance.setServiceMetadata(MetadataUtils.getRemoteMetadata(revision, serviceInstance, revisionToMetadata, metadataReport));
         return serviceInstance;
     }
 
diff --git a/dubbo-registry/dubbo-registry-zookeeper/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.client.ServiceDiscovery b/dubbo-registry/dubbo-registry-zookeeper/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.client.ServiceDiscovery
deleted file mode 100644
index 5532b31..0000000
--- a/dubbo-registry/dubbo-registry-zookeeper/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.client.ServiceDiscovery
+++ /dev/null
@@ -1 +0,0 @@
-zookeeper=org.apache.dubbo.registry.zookeeper.ZookeeperServiceDiscovery
\ No newline at end of file
diff --git a/dubbo-registry/dubbo-registry-zookeeper/src/test/java/org/apache/dubbo/registry/zookeeper/util/CuratorFrameworkUtilsTest.java b/dubbo-registry/dubbo-registry-zookeeper/src/test/java/org/apache/dubbo/registry/zookeeper/util/CuratorFrameworkUtilsTest.java
index aac245c..11bfa06 100644
--- a/dubbo-registry/dubbo-registry-zookeeper/src/test/java/org/apache/dubbo/registry/zookeeper/util/CuratorFrameworkUtilsTest.java
+++ b/dubbo-registry/dubbo-registry-zookeeper/src/test/java/org/apache/dubbo/registry/zookeeper/util/CuratorFrameworkUtilsTest.java
@@ -33,7 +33,6 @@ import org.junit.jupiter.api.Test;
 import org.mockito.Mockito;
 
 import java.util.Arrays;
-import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
@@ -106,11 +105,11 @@ class CuratorFrameworkUtilsTest {
         Assertions.assertEquals(payload.getName(), dubboServiceInstance.getServiceName());
 
         // convert {org.apache.curator.x.discovery.ServiceInstance<ZookeeperInstance>} to {org.apache.dubbo.registry.client.ServiceInstance}
-        ServiceInstance serviceInstance = CuratorFrameworkUtils.build(registryUrl, curatorServiceInstance, new HashMap<>(), metadataReport);
+        ServiceInstance serviceInstance = CuratorFrameworkUtils.build(registryUrl, curatorServiceInstance);
         Assertions.assertEquals(serviceInstance, dubboServiceInstance);
 
         // convert {Collection<org.apache.curator.x.discovery.ServiceInstance<ZookeeperInstance>>} to {List<org.apache.dubbo.registry.client.ServiceInstance>}
-        List<ServiceInstance> serviceInstances = CuratorFrameworkUtils.build(registryUrl, Arrays.asList(curatorServiceInstance), new HashMap<>(), metadataReport);
+        List<ServiceInstance> serviceInstances = CuratorFrameworkUtils.build(registryUrl, Arrays.asList(curatorServiceInstance));
         Assertions.assertNotNull(serviceInstances);
         Assertions.assertEquals(serviceInstances.get(0), dubboServiceInstance);
     }
diff --git a/pom.xml b/pom.xml
index 0a4cf60..7772e2a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -129,7 +129,7 @@
         <checkstyle_unix.skip>true</checkstyle_unix.skip>
         <rat.skip>true</rat.skip>
         <jacoco.skip>true</jacoco.skip>
-        <revision>3.0.5-SNAPSHOT</revision>
+        <revision>3.0.5-metadata-SNAPSHOT</revision>
     </properties>
 
     <modules>