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

[dubbo] branch cloud-native updated: unify metadata and configcenter implementations (#4360)

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

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


The following commit(s) were added to refs/heads/cloud-native by this push:
     new 5008e0f  unify metadata and configcenter implementations (#4360)
5008e0f is described below

commit 5008e0f2acd90a70590b0b9d8c40e5904d5dfcf8
Author: ken.lj <ke...@gmail.com>
AuthorDate: Wed Jun 26 17:09:21 2019 +0800

    unify metadata and configcenter implementations (#4360)
    
    * Polish apache/incubator-dubbo/#4096 : To add new module for Dubbo Event
    
    * Polish apache/incubator-dubbo#3942 : Dubbo Cloud Native: To Add Service registration and discovery abstract
    
    * Polish apache/incubator-dubbo#3946 : Dubbo Cloud Native : To Add Dubbo metadata service
    
    * Polish apache/incubator-dubbo#4093 : To add exported and unexported events for ServiceConfig
    
    * Polish apache/incubator-dubbo#3984 : Add Service registration and discovery implementation for Zookeeper
    
    * Polish apache/incubator-dubbo#4104 : To add initialized and destroyed events for ReferenceConfig
    
    * Polish apache/incubator-dubbo#3946 : Refactor Dubbo metadata service
    
    * Polish apache/incubator-dubbo#3946 : To Add MetadataServiceExporter into dubbo-config-api
    
    * Update ${project.parent.version}
    
    * Polish apache/incubator-dubbo#3946 : Refactor Dubbo metadata service
    
    * Polish apache/incubator-dubbo/#4096 : Remove the duplicated word
    
    * Polish apache/incubator-dubbo#4119 : DynamicConfiguration adds the publish and multiple get configuration methods
    
    * Polish apache/incubator-dubbo#4120 : To add DynamicConfiguration implementation for Zookeeper
    
    * Polish apache/incubator-dubbo#4121 : Add the mapping from service metadata to service name
    
    * Polish apache/incubator-dubbo/#3790 : Dependencies with no license
    
    * Polish apache/incubator-dubbo#4071 : @Reference can't match the local @Service beans
    
    * Update version to be 2.7.3
    
    * Polish apache/incubator-dubbo#3946 : Add thread-safe and performance optimization
    
    * Polish apache/incubator-dubbo#3946 : Add thread-safe and performance optimization
    
    * Polish apache/incubator-dubbo#3946 : Add thread-safe and performance optimization
    
    * Update 2.7.3
    
    * Polish apache/incubator-dubbo#4104 : To add more events for dubbo-config-api
    
    * Polish apache/incubator-dubbo#3942 : Dubbo Cloud Native: To Add Service registration and discovery abstract
    
    * Polish apache/incubator-dubbo#3984 : Add Service registration and discovery implementation for Zookeeper
    
    * Add Bootstrap
    
    * Polish GA
    
    * Polish apache/incubator-dubbo#4050 : Dubbo Cloud Native : Add a mechanism to upgrade Dubbo services smoothly
    
    * Polish apache/incubator-dubbo#4093 : To add DubboServiceDestroyedEvent
    
    * Polish apache/incubator-dubbo#4050 : Dubbo Cloud Native : Reactor
    
    * Polish apache/incubator-dubbo#3946 : Remove SPI
    
    * Polish apache/incubator-dubbo#4265 : [Feature] Dubbo Cloud Native - Add Bootstrap
    
    * Polish apache/incubator-dubbo#4265 : [Feature] Dubbo Cloud Native - Add Bootstrap
    
    * Polish apache/dubbo#4265 : Add test dependencies
    
    * Polish /apache/dubbo#3942 : Refactor implementation
    
    * Polish apache/incubator-dubbo#3984 : Refactor
    
    * Add Nacos implementation
    
    * Polish apache/incubator-dubbo#3984 : Add Nacos implementation
    
    * Polish apache/incubator-dubbo#4268 : Dubbo Event - To support Generic event type handle
    
    * Polish apache/incubator-dubbo#4268 : Update JavaDoc
    
    * Polish apache/incubator-dubbo#4268 : Add GenericEventListener implementation
    
    * add cache for MetadataServiceProxy
    
    * support multiple metadata and configcenter
    
    * unify metadata implementation
    
    * add missed files
    
    * remove duplicated files
    
    * add new SPIs and modules to dubbo-all pom.
---
 dubbo-all/pom.xml                                  |  42 +-
 dubbo-bom/pom.xml                                  |  23 +-
 dubbo-bootstrap/pom.xml                            |  13 +-
 .../org/apache/dubbo/bootstrap/DubboBootstrap.java | 429 +++++++++++++--------
 .../apache/dubbo/bootstrap/DubboBootstrapTest.java |  70 +---
 .../bootstrap/DubboServiceConsumerBootstrap.java   |  37 +-
 .../bootstrap/DubboServiceProviderBootstrap.java   |  30 +-
 dubbo-cluster/pom.xml                              |   5 -
 .../org/apache/dubbo/rpc/cluster/Directory.java    |   2 +
 .../rpc/cluster/directory/StaticDirectory.java     |   5 +
 .../dubbo/rpc/cluster/router/AbstractRouter.java   |   2 +-
 .../cluster/router/condition/config/AppRouter.java |   2 +-
 .../router/condition/config/AppRouterFactory.java  |   2 +-
 .../router/condition/config/ListenableRouter.java  |   8 +-
 .../router/condition/config/ServiceRouter.java     |   2 +-
 .../condition/config/ServiceRouterFactory.java     |   2 +-
 .../dubbo/rpc/cluster/router/tag/TagRouter.java    |  10 +-
 .../rpc/cluster/router/tag/TagRouterFactory.java   |   2 +-
 .../cluster/support/AbstractClusterInvoker.java    |   4 +
 .../org/apache/dubbo/common/bytecode/Proxy.java    |   2 +-
 .../AbstractDynamicConfigurationFactory.java       |  19 +-
 .../config}/configcenter/ConfigChangeEvent.java    |   2 +-
 .../config}/configcenter/ConfigChangeType.java     |   2 +-
 .../configcenter/ConfigurationListener.java        |   2 +-
 .../common/config}/configcenter/Constants.java     |   2 +-
 .../config}/configcenter/DynamicConfiguration.java |   2 +-
 .../configcenter/DynamicConfigurationFactory.java  |   2 +-
 .../configcenter}/nop/NopDynamicConfiguration.java |  10 +-
 .../nop/NopDynamicConfigurationFactory.java        |   6 +-
 .../wrapper/CompositeDynamicConfiguration.java     |  98 +++++
 .../dubbo/common/constants/CommonConstants.java    |   8 +
 .../org/apache/dubbo/common/utils/UrlUtils.java    |  21 +
 ...config.configcenter.DynamicConfigurationFactory |   1 +
 .../java/com/alibaba/dubbo/common/Constants.java   |   2 +-
 dubbo-config/dubbo-config-api/pom.xml              |   6 -
 .../org/apache/dubbo/config/AbstractConfig.java    |   3 -
 .../dubbo/config/AbstractInterfaceConfig.java      | 121 +-----
 .../apache/dubbo/config/AbstractServiceConfig.java |   4 +-
 .../org/apache/dubbo/config/ApplicationConfig.java |  12 +
 .../apache/dubbo/config/ConfigCenterConfig.java    |  10 +-
 .../apache/dubbo/config/MetadataReportConfig.java  |  13 +
 .../org/apache/dubbo/config/ReferenceConfig.java   |  17 +-
 .../org/apache/dubbo/config/ServiceConfig.java     |  33 +-
 .../dubbo/config/builders/ApplicationBuilder.java  |  11 +
 .../config/builders/MetadataReportBuilder.java     |   4 +
 .../dubbo/config/builders/ProtocolBuilder.java     |   4 +
 .../dubbo/config/builders/ReferenceBuilder.java    |   4 +
 .../dubbo/config/builders/RegistryBuilder.java     |   4 +
 .../dubbo/config/builders/ServiceBuilder.java      |   4 +
 .../apache/dubbo/config/context/ConfigManager.java | 165 ++++++--
 .../ConfigurableMetadataServiceExporter.java       |   4 +-
 .../config}/telnet/ShutdownTelnetHandler.java      |   2 +-
 .../org.apache.dubbo.remoting.telnet.TelnetHandler |   1 +
 .../ConfigurableMetadataServiceExporterTest.java   |   4 +-
 .../dubbo/config}/service/DemoException.java       |   2 +-
 .../apache/dubbo/config}/service/DemoService.java  |   2 +-
 .../dubbo/config}/service/DemoServiceImpl.java     |   2 +-
 .../dubbo/config}/service/GenericServiceTest.java  |   6 +-
 .../org/apache/dubbo/config}/service/User.java     |   2 +-
 .../config}/telnet/ShutdownTelnetHandlerTest.java  |   3 +-
 .../config}/validation/ValidationParameter.java    |   2 +-
 .../config}/validation/ValidationService.java      |   2 +-
 .../config}/validation/ValidationServiceImpl.java  |   2 +-
 .../dubbo/config}/validation/ValidationTest.java   |   2 +-
 .../src/main/resources/META-INF/compat/dubbo.xsd   |   5 +
 .../src/main/resources/META-INF/dubbo.xsd          |   5 +
 dubbo-configcenter/dubbo-configcenter-api/pom.xml  |  39 --
 ....dubbo.configcenter.DynamicConfigurationFactory |   1 -
 .../mock/AbstractDynamicConfigurationTest.java     |  47 ---
 .../mock/MockDynamicConfiguration.java             |  54 ---
 ....dubbo.configcenter.DynamicConfigurationFactory |   1 -
 .../dubbo-configcenter-apollo/pom.xml              |   2 +-
 .../support/apollo/ApolloDynamicConfiguration.java |  14 +-
 .../apollo/ApolloDynamicConfigurationFactory.java  |   4 +-
 ...onfig.configcenter.DynamicConfigurationFactory} |   0
 .../dubbo-configcenter-consul/pom.xml              |   2 +-
 .../consul/ConsulDynamicConfiguration.java         |  12 +-
 .../consul/ConsulDynamicConfigurationFactory.java  |   4 +-
 ...onfig.configcenter.DynamicConfigurationFactory} |   0
 dubbo-configcenter/dubbo-configcenter-etcd/pom.xml |  11 +-
 .../support/etcd/EtcdDynamicConfiguration.java     |  10 +-
 .../etcd/EtcdDynamicConfigurationFactory.java      |   4 +-
 ...onfig.configcenter.DynamicConfigurationFactory} |   0
 .../support/etcd/EtcdDynamicConfigurationTest.java |   4 +-
 .../dubbo-configcenter-nacos/pom.xml               |   2 +-
 .../support/nacos/NacosDynamicConfiguration.java   |  10 +-
 .../nacos/NacosDynamicConfigurationFactory.java    |   4 +-
 ...onfig.configcenter.DynamicConfigurationFactory} |   0
 .../nacos/NacosDynamicConfigurationTest.java       |   4 +-
 .../dubbo-configcenter-zookeeper/pom.xml           |   2 +-
 .../support/zookeeper/CacheListener.java           |   6 +-
 .../zookeeper/ZookeeperDynamicConfiguration.java   |   6 +-
 .../ZookeeperDynamicConfigurationFactory.java      |   4 +-
 ...onfig.configcenter.DynamicConfigurationFactory} |   0
 .../ZookeeperDynamicConfigurationTest.java         |   8 +-
 dubbo-configcenter/pom.xml                         |   1 -
 dubbo-container/dubbo-container-log4j/pom.xml      |   5 -
 .../dubbo-demo-api/dubbo-demo-api-consumer/pom.xml |   5 +
 .../dubbo-demo-api/dubbo-demo-api-provider/pom.xml |   5 +
 .../dubbo-metadata-definition/pom.xml              |  38 --
 ...ache.dubbo.metadata.store.MetadataReportFactory |   1 -
 .../dubbo-metadata-api}/pom.xml                    |  50 ++-
 .../DynamicConfigurationServiceNameMapping.java    |   2 +-
 .../org/apache/dubbo/metadata/MetadataService.java |  13 +-
 .../dubbo/metadata/MetadataServiceExporter.java    |   0
 .../apache/dubbo/metadata/ServiceNameMapping.java  |   0
 .../dubbo/metadata/WritableMetadataService.java}   |  18 +-
 .../definition/ServiceDefinitionBuilder.java       |   0
 .../metadata/definition/TypeDefinitionBuilder.java |   0
 .../definition/builder/ArrayTypeBuilder.java       |   0
 .../definition/builder/CollectionTypeBuilder.java  |   0
 .../definition/builder/DefaultTypeBuilder.java     |   0
 .../definition/builder/EnumTypeBuilder.java        |   0
 .../definition/builder/MapTypeBuilder.java         |   0
 .../metadata/definition/builder/TypeBuilder.java   |   0
 .../definition/model/FullServiceDefinition.java    |   0
 .../definition/model/MethodDefinition.java         |   3 +-
 .../definition/model/ServiceDefinition.java        |   3 +-
 .../metadata/definition/model/TypeDefinition.java  |   3 +-
 .../dubbo/metadata/definition/util/ClassUtils.java |   0
 .../definition/util/JaketConfigurationUtils.java   |   0
 .../dubbo/metadata/report}/MetadataReport.java     |  19 +-
 .../metadata/report}/MetadataReportFactory.java    |   2 +-
 .../report}/identifier/MetadataIdentifier.java     |  17 +-
 .../report}/support/AbstractMetadataReport.java    |  63 ++-
 .../support/AbstractMetadataReportFactory.java     |  10 +-
 .../dubbo/metadata/report}/support/Constants.java  |   2 +-
 .../store/InMemoryWritableMetadataService.java}    |  47 ++-
 .../store/RemoteWritableMetadataService.java       | 120 ++++--
 .../org.apache.dubbo.metadata.ServiceNameMapping   |   0
 ...g.apache.dubbo.metadata.WritableMetadataService |   2 +
 ...e.dubbo.metadata.definition.builder.TypeBuilder |   0
 ...DynamicConfigurationServiceNameMappingTest.java |   4 +-
 .../InMemoryWritableMetadataServiceTest.java}      |   7 +-
 .../dubbo/metadata/LocalMetadataServiceTest.java   |   6 +-
 .../dubbo/metadata/definition/MetadataTest.java    |   0
 .../dubbo/metadata/definition/MetadataUtils.java   |   0
 .../definition/ServiceDefinitionBuildderTest.java  |   0
 .../definition/common/ClassExtendsMap.java         |   0
 .../metadata/definition/common/ColorEnum.java      |   0
 .../metadata/definition/common/OuterClass.java     |   0
 .../common/ResultWithRawCollections.java           |   0
 .../metadata/definition/common/TestService.java    |   0
 .../metadata/definition/service/ComplexObject.java |   0
 .../metadata/definition/service/DemoService.java   |   0
 .../report}/identifier/MetadataIdentifierTest.java |   2 +
 .../support/AbstractMetadataReportFactoryTest.java |  37 +-
 .../support/AbstractMetadataReportTest.java        |  55 ++-
 .../metadata/store}/InterfaceNameTestService.java  |   2 +-
 .../metadata/store}/InterfaceNameTestService2.java |   2 +-
 .../store/RemoteWritableMeatadataServiceTest.java  |  39 +-
 .../dubbo/metadata/store}/RetryTestService.java    |   2 +-
 .../metadata}/test/JTestMetadataReport4Test.java   |  31 +-
 .../test/JTestMetadataReportFactory4Test.java      |   6 +-
 .../identifier/MetadataIdentifierTest.java         |   0
 .../dubbo-metadata-report-consul/pom.xml           |   2 +-
 .../store/consul/ConsulMetadataReport.java         |  31 +-
 .../store/consul/ConsulMetadataReportFactory.java  |   4 +-
 ...che.dubbo.metadata.report.MetadataReportFactory |   0
 .../dubbo-metadata-report-etcd/pom.xml             |   2 +-
 .../metadata/store/etcd/EtcdMetadataReport.java    |  31 +-
 .../store/etcd/EtcdMetadataReportFactory.java      |   4 +-
 ...che.dubbo.metadata.report.MetadataReportFactory |   0
 .../store/etcd/EtcdMetadata4TstService.java        |   0
 .../store/etcd/EtcdMetadataReportTest.java         |   2 +-
 .../dubbo-metadata-report-nacos/pom.xml            |   2 +-
 .../metadata/store/nacos/NacosMetadataReport.java  |  43 ++-
 .../store/nacos/NacosMetadataReportFactory.java    |   4 +-
 ...che.dubbo.metadata.report.MetadataReportFactory |   0
 .../store/nacos/NacosMetadata4TstService.java      |   0
 .../store/nacos/NacosMetadataReportTest.java       |   2 +-
 .../dubbo-metadata-report-redis/pom.xml            |   2 +-
 .../metadata/store/redis/RedisMetadataReport.java  |  31 +-
 .../store/redis/RedisMetadataReportFactory.java    |   4 +-
 ...che.dubbo.metadata.report.MetadataReportFactory |   0
 .../store/redis/RedisMetadata4TstService.java      |   0
 .../store/redis/RedisMetadataReportTest.java       |   4 +-
 .../dubbo-metadata-report-zookeeper/pom.xml        |   2 +-
 .../store/zookeeper/ZookeeperMetadataReport.java   |  31 +-
 .../zookeeper/ZookeeperMetadataReportFactory.java  |   4 +-
 ...che.dubbo.metadata.report.MetadataReportFactory |   0
 .../ZookeeperMetadataReport4TstService.java        |   0
 .../zookeeper/ZookeeperMetadataReportTest.java     |   2 +-
 .../dubbo-metadata-report}/pom.xml                 |   4 +-
 dubbo-metadata/pom.xml                             |  41 +-
 .../org.apache.dubbo.metadata.LocalMetadataService |   1 -
 .../java/org/apache/dubbo/qos/command/impl/Ls.java |   9 +-
 .../org/apache/dubbo/qos/command/impl/Offline.java |   8 +-
 .../org/apache/dubbo/qos/command/impl/Online.java  |   8 +-
 .../org/apache/dubbo/qos/command/impl/LsTest.java  |  17 +-
 .../apache/dubbo/qos/command/impl/OfflineTest.java |  15 +-
 .../apache/dubbo/qos/command/impl/OnlineTest.java  |  13 +-
 dubbo-registry/dubbo-registry-api/pom.xml          |  11 +-
 .../dubbo/registry/client/ServiceInstance.java     |  44 +++
 ...ExportedServicesRevisionMetadataCustomizer.java |   6 +-
 ...MetadataServiceURLParamsMetadataCustomizer.java |   6 +-
 .../proxy/DefaultMetadataServiceProxyFactory.java  |  73 ++++
 .../proxy/MetadataServiceProxyFactory.java         |  55 +++
 .../proxy/RemoteMetadataServiceProxyFactory.java   |  17 +-
 .../integration/AbstractConfiguratorListener.java  |   8 +-
 .../registry/integration/RegistryDirectory.java    |   7 +-
 .../registry/integration/RegistryProtocol.java     |  13 +-
 .../registry/support/ConsumerInvokerWrapper.java   |  88 -----
 .../registry/support/ProviderConsumerRegTable.java | 112 ------
 .../registry/support/ServiceOrientedRegistry.java  |  25 +-
 ...ient.metadata.proxy.MetadataServiceProxyFactory |   2 +
 .../support/ServiceOrientedRegistryTest.java       |   6 +-
 .../nacos/NacosServiceDiscoveryFactory.java        |   4 -
 .../apache/dubbo/rpc/model/ApplicationModel.java   |  50 ++-
 .../org/apache/dubbo/rpc/model/ConsumerModel.java  |  32 +-
 .../org/apache/dubbo/rpc/model/ProviderModel.java  |  33 +-
 .../rpc/model/invoker}/ProviderInvokerWrapper.java |   4 +-
 dubbo-rpc/dubbo-rpc-dubbo/pom.xml                  |   9 +-
 .../protocol/dubbo/telnet/InvokeTelnetHandler.java |   2 +-
 .../protocol/dubbo/telnet/ListTelnetHandler.java   |  20 +-
 .../org.apache.dubbo.remoting.telnet.TelnetHandler |   3 +-
 .../dubbo/rpc/protocol/dubbo/FutureFilterTest.java |   3 +-
 pom.xml                                            |   1 -
 218 files changed, 1797 insertions(+), 1367 deletions(-)

diff --git a/dubbo-all/pom.xml b/dubbo-all/pom.xml
index eaf1772..8b9a4c5 100644
--- a/dubbo-all/pom.xml
+++ b/dubbo-all/pom.xml
@@ -410,13 +410,6 @@
         </dependency>
         <dependency>
             <groupId>org.apache.dubbo</groupId>
-            <artifactId>dubbo-configcenter-api</artifactId>
-            <version>${project.version}</version>
-            <scope>compile</scope>
-            <optional>true</optional>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.dubbo</groupId>
             <artifactId>dubbo-configcenter-zookeeper</artifactId>
             <version>${project.version}</version>
             <scope>compile</scope>
@@ -466,7 +459,7 @@
         <!-- metadata -->
         <dependency>
             <groupId>org.apache.dubbo</groupId>
-            <artifactId>dubbo-metadata-report-api</artifactId>
+            <artifactId>dubbo-metadata-api</artifactId>
             <version>${project.version}</version>
             <scope>compile</scope>
             <optional>true</optional>
@@ -516,14 +509,6 @@
             <optional>true</optional>
         </dependency>
 
-        <dependency>
-            <groupId>org.apache.dubbo</groupId>
-            <artifactId>dubbo-metadata</artifactId>
-            <version>${project.version}</version>
-            <scope>compile</scope>
-            <optional>true</optional>
-        </dependency>
-
         <!-- Transitive dependencies -->
         <dependency>
             <groupId>org.springframework</groupId>
@@ -640,15 +625,13 @@
                                     <include>org.apache.dubbo:dubbo-serialization-protostuff</include>
                                     <include>org.apache.dubbo:dubbo-serialization-gson</include>
                                     <include>org.apache.dubbo:dubbo-serialization-googlePb</include>
-                                    <include>org.apache.dubbo:dubbo-configcenter-api</include>
                                     <include>org.apache.dubbo:dubbo-configcenter-definition</include>
                                     <include>org.apache.dubbo:dubbo-configcenter-apollo</include>
                                     <include>org.apache.dubbo:dubbo-configcenter-zookeeper</include>
                                     <include>org.apache.dubbo:dubbo-configcenter-consul</include>
                                     <include>org.apache.dubbo:dubbo-configcenter-etcd</include>
                                     <include>org.apache.dubbo:dubbo-configcenter-nacos</include>
-                                    <include>org.apache.dubbo:dubbo-metadata-report-api</include>
-                                    <include>org.apache.dubbo:dubbo-metadata-definition</include>
+                                    <include>org.apache.dubbo:dubbo-metadata-api</include>
                                     <include>org.apache.dubbo:dubbo-metadata-report-redis</include>
                                     <include>org.apache.dubbo:dubbo-metadata-report-zookeeper</include>
                                     <include>org.apache.dubbo:dubbo-metadata-report-consul</include>
@@ -656,10 +639,7 @@
                                     <include>org.apache.dubbo:dubbo-metadata-report-nacos</include>
                                     <include>org.apache.dubbo:dubbo-serialization-native-hession</include>
                                     <include>org.apache.dubbo:dubbo-rpc-native-thrift</include>
-
-                                    <!-- 2.7.3 new modules -->
                                     <include>org.apache.dubbo:dubbo-event</include>
-                                    <include>org.apache.dubbo:dubbo-metadata</include>
                                 </includes>
                             </artifactSet>
                             <transformers>
@@ -778,11 +758,11 @@
                                     </resource>
                                 </transformer>
                                 <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
-                                    <resource>META-INF/dubbo/internal/org.apache.dubbo.configcenter.DynamicConfigurationFactory
+                                    <resource>META-INF/dubbo/internal/org.apache.dubbo.common.config.configcenter.DynamicConfigurationFactory
                                     </resource>
                                 </transformer>
                                 <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
-                                    <resource>META-INF/dubbo/internal/org.apache.dubbo.metadata.store.MetadataReportFactory
+                                    <resource>META-INF/dubbo/internal/org.apache.dubbo.metadata.report.MetadataReportFactory
                                     </resource>
                                 </transformer>
                                 <!-- @since 2.7.3 -->
@@ -795,7 +775,19 @@
                                     </resource>
                                 </transformer>
                                 <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
-                                    <resource>META-INF/dubbo/internal/org.apache.dubbo.metadata.LocalMetadataService
+                                    <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.ServiceNameMapping
+                                    </resource>
+                                </transformer>
+                                <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
+                                    <resource>META-INF/dubbo/internal/org.apache.dubbo.registry.client.metadata.MetadataServiceProxyFactory
+                                    </resource>
+                                </transformer>
+                                <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
+                                    <resource>META-INF/dubbo/internal/org.apache.dubbo.registry.client.ServiceDiscoveryFactory
                                     </resource>
                                 </transformer>
                             </transformers>
diff --git a/dubbo-bom/pom.xml b/dubbo-bom/pom.xml
index 8b69673..202af02 100644
--- a/dubbo-bom/pom.xml
+++ b/dubbo-bom/pom.xml
@@ -362,6 +362,12 @@
                 <artifactId>dubbo-compatible</artifactId>
                 <version>${project.version}</version>
             </dependency>
+            <!-- metadata -->
+            <dependency>
+                <groupId>org.apache.dubbo</groupId>
+                <artifactId>dubbo-metadata-api</artifactId>
+                <version>${project.version}</version>
+            </dependency>
             <dependency>
                 <groupId>org.apache.dubbo</groupId>
                 <artifactId>dubbo-metadata-report-api</artifactId>
@@ -369,6 +375,11 @@
             </dependency>
             <dependency>
                 <groupId>org.apache.dubbo</groupId>
+                <artifactId>dubbo-metadata-definition</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.apache.dubbo</groupId>
                 <artifactId>dubbo-metadata-report-zookeeper</artifactId>
                 <version>${project.version}</version>
             </dependency>
@@ -392,11 +403,8 @@
                 <artifactId>dubbo-metadata-report-nacos</artifactId>
                 <version>${project.version}</version>
             </dependency>
-            <dependency>
-                <groupId>org.apache.dubbo</groupId>
-                <artifactId>dubbo-configcenter-api</artifactId>
-                <version>${project.version}</version>
-            </dependency>
+
+            <!-- config-center -->
             <dependency>
                 <groupId>org.apache.dubbo</groupId>
                 <artifactId>dubbo-configcenter-zookeeper</artifactId>
@@ -422,11 +430,6 @@
                 <artifactId>dubbo-configcenter-nacos</artifactId>
                 <version>${project.version}</version>
             </dependency>
-            <dependency>
-                <groupId>org.apache.dubbo</groupId>
-                <artifactId>dubbo-metadata-definition</artifactId>
-                <version>${project.version}</version>
-            </dependency>
         </dependencies>
     </dependencyManagement>
 
diff --git a/dubbo-bootstrap/pom.xml b/dubbo-bootstrap/pom.xml
index ef3cad3..17df134 100644
--- a/dubbo-bootstrap/pom.xml
+++ b/dubbo-bootstrap/pom.xml
@@ -36,6 +36,13 @@
 
         <dependency>
             <groupId>org.apache.dubbo</groupId>
+            <artifactId>dubbo-metadata-report-zookeeper</artifactId>
+            <version>${project.parent.version}</version>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.dubbo</groupId>
             <artifactId>dubbo-configcenter-zookeeper</artifactId>
             <version>${project.parent.version}</version>
             <scope>test</scope>
@@ -83,12 +90,6 @@
             <scope>test</scope>
         </dependency>
 
-        <dependency>
-            <groupId>org.apache.curator</groupId>
-            <artifactId>curator-test</artifactId>
-            <scope>test</scope>
-        </dependency>
-
     </dependencies>
 
 </project>
\ No newline at end of file
diff --git a/dubbo-bootstrap/src/main/java/org/apache/dubbo/bootstrap/DubboBootstrap.java b/dubbo-bootstrap/src/main/java/org/apache/dubbo/bootstrap/DubboBootstrap.java
index c6c2606..1273dcf 100644
--- a/dubbo-bootstrap/src/main/java/org/apache/dubbo/bootstrap/DubboBootstrap.java
+++ b/dubbo-bootstrap/src/main/java/org/apache/dubbo/bootstrap/DubboBootstrap.java
@@ -17,19 +17,32 @@
 package org.apache.dubbo.bootstrap;
 
 import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.config.Environment;
+import org.apache.dubbo.common.config.configcenter.DynamicConfiguration;
+import org.apache.dubbo.common.config.configcenter.DynamicConfigurationFactory;
+import org.apache.dubbo.common.config.configcenter.wrapper.CompositeDynamicConfiguration;
+import org.apache.dubbo.common.constants.CommonConstants;
+import org.apache.dubbo.common.extension.ExtensionLoader;
 import org.apache.dubbo.common.logger.Logger;
 import org.apache.dubbo.common.logger.LoggerFactory;
 import org.apache.dubbo.common.utils.CollectionUtils;
+import org.apache.dubbo.common.utils.StringUtils;
 import org.apache.dubbo.config.AbstractConfig;
-import org.apache.dubbo.config.AbstractInterfaceConfig;
 import org.apache.dubbo.config.ApplicationConfig;
+import org.apache.dubbo.config.ConfigCenterConfig;
+import org.apache.dubbo.config.ConsumerConfig;
+import org.apache.dubbo.config.DubboShutdownHook;
+import org.apache.dubbo.config.MetadataReportConfig;
 import org.apache.dubbo.config.ProtocolConfig;
+import org.apache.dubbo.config.ProviderConfig;
 import org.apache.dubbo.config.ReferenceConfig;
 import org.apache.dubbo.config.RegistryConfig;
 import org.apache.dubbo.config.ServiceConfig;
 import org.apache.dubbo.config.builders.AbstractBuilder;
 import org.apache.dubbo.config.builders.ApplicationBuilder;
+import org.apache.dubbo.config.builders.ConsumerBuilder;
 import org.apache.dubbo.config.builders.ProtocolBuilder;
+import org.apache.dubbo.config.builders.ProviderBuilder;
 import org.apache.dubbo.config.builders.ReferenceBuilder;
 import org.apache.dubbo.config.builders.RegistryBuilder;
 import org.apache.dubbo.config.builders.ServiceBuilder;
@@ -37,16 +50,19 @@ import org.apache.dubbo.config.context.ConfigManager;
 import org.apache.dubbo.config.metadata.ConfigurableMetadataServiceExporter;
 import org.apache.dubbo.event.EventDispatcher;
 import org.apache.dubbo.event.EventListener;
-import org.apache.dubbo.metadata.MetadataServiceExporter;
+import org.apache.dubbo.metadata.WritableMetadataService;
+import org.apache.dubbo.metadata.store.RemoteWritableMetadataService;
 import org.apache.dubbo.registry.client.DefaultServiceInstance;
 import org.apache.dubbo.registry.client.ServiceDiscovery;
 import org.apache.dubbo.registry.client.ServiceInstance;
 import org.apache.dubbo.registry.support.ServiceOrientedRegistry;
 
+import java.io.IOException;
+import java.util.ArrayList;
 import java.util.HashMap;
-import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.locks.Condition;
@@ -55,12 +71,9 @@ import java.util.concurrent.locks.ReentrantLock;
 import java.util.function.Consumer;
 import java.util.stream.Collectors;
 
-import static java.util.Collections.emptyMap;
 import static java.util.concurrent.Executors.newSingleThreadExecutor;
+import static org.apache.dubbo.common.config.ConfigurationUtils.parseProperties;
 import static org.apache.dubbo.common.constants.CommonConstants.APPLICATION_KEY;
-import static org.apache.dubbo.common.utils.StringUtils.isBlank;
-import static org.apache.dubbo.common.utils.StringUtils.split;
-import static org.apache.dubbo.common.utils.StringUtils.trim;
 import static org.apache.dubbo.registry.support.AbstractRegistryFactory.getRegistries;
 
 /**
@@ -82,8 +95,6 @@ public class DubboBootstrap {
 
     private final Logger logger = LoggerFactory.getLogger(getClass());
 
-    private final MetadataServiceExporter metadataServiceExporter = new ConfigurableMetadataServiceExporter();
-
     private final AtomicBoolean awaited = new AtomicBoolean(false);
 
     private final Lock lock = new ReentrantLock();
@@ -112,6 +123,10 @@ public class DubboBootstrap {
 
     private ApplicationBuilder applicationBuilder;
 
+    private ConsumerBuilder consumerBuilder;
+
+    private ProviderBuilder providerBuilder;
+
     private Map<String, RegistryBuilder> registryBuilders = new HashMap<>();
 
     private Map<String, ProtocolBuilder> protocolBuilders = new HashMap<>();
@@ -120,70 +135,88 @@ public class DubboBootstrap {
 
     private Map<String, ReferenceBuilder<?>> referenceBuilders = new HashMap<>();
 
-    /**
-     * The global {@link ApplicationConfig}
-     */
-    private ApplicationConfig applicationConfig;
+    public DubboBootstrap() {
+        DubboShutdownHook.getDubboShutdownHook().register();
+    }
 
     /**
-     * the global {@link RegistryConfig registries}
+     * Set only register provider or not
+     *
+     * @param onlyRegisterProvider if <code>true</code>, only register the provider and reduce the registries' load.
+     * @return {@link DubboBootstrap}
      */
-    private Map<String, RegistryConfig> registryConfigs = emptyMap();
+    public DubboBootstrap onlyRegisterProvider(boolean onlyRegisterProvider) {
+        this.onlyRegisterProvider = onlyRegisterProvider;
+        return this;
+    }
 
-    /**
-     * the global {@link RegistryConfig registries}
-     */
-    private Map<String, ProtocolConfig> protocolConfigs = emptyMap();
+    /* accept Config instance */
+    public DubboBootstrap application(ApplicationConfig applicationConfig) {
+        ConfigManager.getInstance().setApplication(applicationConfig);
+        return this;
+    }
 
-    /**
-     * the global {@link ServiceConfig services}
-     */
-    private Map<String, ServiceConfig<?>> serviceConfigs = emptyMap();
+    public DubboBootstrap configCenter(ConfigCenterConfig configCenterConfig) {
+        ConfigManager.getInstance().addConfigCenter(configCenterConfig);
+        return this;
+    }
 
-    /**
-     * the global {@link ReferenceConfig references}
-     */
-    private Map<String, ReferenceConfig<?>> referenceConfigs = new HashMap<>();
+    public DubboBootstrap configCenter(List<ConfigCenterConfig> configCenterConfigs) {
+        ConfigManager.getInstance().addConfigCenter(configCenterConfigs);
+        return this;
+    }
+
+    public DubboBootstrap metadataReport(MetadataReportConfig metadataReportConfig) {
+        ConfigManager.getInstance().addMetadataReport(metadataReportConfig);
+        return this;
+    }
 
-    public ApplicationSettings application(String name) {
-        return new ApplicationSettings(initApplicationBuilder(name), this);
+    public DubboBootstrap metadataReport(List<MetadataReportConfig> metadataReportConfigs) {
+        ConfigManager.getInstance().addMetadataReport(metadataReportConfigs);
+        return this;
     }
 
-    public RegistrySettings registry() {
-        return registry(DEFAULT_REGISTRY_ID);
+    public DubboBootstrap registry(RegistryConfig registryConfig) {
+        ConfigManager.getInstance().addRegistry(registryConfig, true);
+        return this;
     }
 
-    public RegistrySettings registry(String id) {
-        return new RegistrySettings(initRegistryBuilder(id), this);
+    public DubboBootstrap registry(List<RegistryConfig> registryConfigs) {
+        ConfigManager.getInstance().addRegistries(registryConfigs, true);
+        return this;
     }
 
-    public ProtocolSettings protocol() {
-        return protocol(DEFAULT_PROTOCOL_ID);
+    public DubboBootstrap protocol(ProtocolConfig protocolConfig) {
+        ConfigManager.getInstance().addProtocol(protocolConfig, true);
+        return this;
     }
 
-    public ProtocolSettings protocol(String id) {
-        return new ProtocolSettings(initProtocolBuilder(id), this);
+    public DubboBootstrap protocols(List<ProtocolConfig> protocolConfigs) {
+        ConfigManager.getInstance().addProtocols(protocolConfigs, true);
+        return this;
     }
 
-    public <S> ServiceSettings<S> service(String id) {
-        return new ServiceSettings(initServiceBuilder(id), this);
+    public DubboBootstrap consumer(ConsumerConfig consumerConfig) {
+        ConfigManager.getInstance().addConsumer(consumerConfig);
+        return this;
     }
 
-    public <S> ReferenceSettings<S> reference(String id) {
-        return new ReferenceSettings<>(initReferenceBuilder(id), this);
+    public DubboBootstrap provider(ProviderConfig providerConfig) {
+        ConfigManager.getInstance().addProvider(providerConfig);
+        return this;
     }
 
-    /**
-     * Set only register provider or not
-     *
-     * @param onlyRegisterProvider if <code>true</code>, only register the provider and reduce the registries' load.
-     * @return {@link DubboBootstrap}
-     */
-    public DubboBootstrap onlyRegisterProvider(boolean onlyRegisterProvider) {
-        this.onlyRegisterProvider = onlyRegisterProvider;
+    public DubboBootstrap service(ServiceConfig<?> serviceConfig) {
+        ConfigManager.getInstance().addService(serviceConfig);
         return this;
     }
 
+    public DubboBootstrap reference(ReferenceConfig<?> referenceConfig) {
+        ConfigManager.getInstance().addReference(referenceConfig);
+        return this;
+    }
+
+    /* accept builder functional interface */
     public DubboBootstrap application(String name, Consumer<ApplicationBuilder> builder) {
         initApplicationBuilder(name);
         builder.accept(applicationBuilder);
@@ -219,18 +252,31 @@ public class DubboBootstrap {
             return;
         }
 
-        initApplicationConfig();
+        buildApplicationConfig();
 
-        initRegistryConfigs();
+        buildRegistryConfigs();
 
-        initProtocolConfigs();
+        buildProtocolConfigs();
 
-        initServiceConfigs();
+        buildServiceConfigs();
 
-        initReferenceConfigs();
+        buildReferenceConfigs();
 
         clearBuilders();
 
+        startConfigCenter();
+        startMetadataReport();
+
+        loadRemoteConfigs();
+        useRegistryAsConfigCenterIfNecessary();
+
+//        checkApplication();
+//        checkProvider();
+//        chcckConsumer();
+//        checkRegistry();
+//        checkProtocol();
+//        checkMonitor();
+
         initialized = true;
 
         if (logger.isInfoEnabled()) {
@@ -238,26 +284,67 @@ public class DubboBootstrap {
         }
     }
 
-    /**
-     * Get the {@link ServiceConfig} by specified id
-     *
-     * @param id  The {@link ServiceConfig#getId() id} of {@link ServiceConfig}
-     * @param <S> the type of service interface
-     * @return <code>null</code> if not found
-     */
-    public <S> ServiceConfig<S> serviceConfig(String id) {
-        return (ServiceConfig<S>) serviceConfigs.get(id);
+    private void loadRemoteConfigs() {
+        ConfigManager configManager = ConfigManager.getInstance();
+
+        // registry ids to registry configs
+        List<RegistryConfig> tmpRegistries = new ArrayList<>();
+        Set<String> registryIds = configManager.getRegistryIds();
+        registryIds.forEach(id -> {
+            if (tmpRegistries.stream().noneMatch(reg -> reg.getId().equals(id))) {
+                tmpRegistries.add(configManager.getRegistry(id).orElseGet(() -> {
+                    RegistryConfig registryConfig = new RegistryConfig();
+                    registryConfig.setId(id);
+                    registryConfig.refresh();
+                    return registryConfig;
+                }));
+            }
+        });
+
+        configManager.addRegistries(tmpRegistries, true);
+
+        // protocol ids to protocol configs
+        List<ProtocolConfig> tmpProtocols = new ArrayList<>();
+        Set<String> protocolIds = configManager.getProtocolIds();
+        protocolIds.forEach(id -> {
+            if (tmpProtocols.stream().noneMatch(prot -> prot.getId().equals(id))) {
+                tmpProtocols.add(configManager.getProtocol(id).orElseGet(() -> {
+                    ProtocolConfig protocolConfig = new ProtocolConfig();
+                    protocolConfig.setId(id);
+                    protocolConfig.refresh();
+                    return protocolConfig;
+                }));
+            }
+        });
+
+        configManager.addProtocols(tmpProtocols, true);
     }
 
     /**
-     * Get the {@link ReferenceConfig} by specified id
-     *
-     * @param id  The {@link ReferenceConfig#getId() id} of {@link ReferenceConfig}
-     * @param <S> the type of service interface
-     * @return <code>null</code> if not found
+     * For compatibility purpose, use registry as the default config center when the registry protocol is zookeeper and
+     * there's no config center specified explicitly.
      */
-    public <S> ReferenceConfig<S> referenceConfig(String id) {
-        return (ReferenceConfig<S>) referenceConfigs.get(id);
+    private void useRegistryAsConfigCenterIfNecessary() {
+        ConfigManager configManager = ConfigManager.getInstance();
+        configManager.getDefaultRegistries().ifPresent(registryConfigs -> {
+            for (RegistryConfig registryConfig : registryConfigs) {
+                if (registryConfig != null && registryConfig.isZookeeperProtocol()) {
+                    // we use the loading status of DynamicConfiguration to decide whether ConfigCenter has been initiated.
+                    Environment.getInstance().getDynamicConfiguration().orElseGet(() -> {
+                        Set<ConfigCenterConfig> configCenters = configManager.getConfigCenters();
+                        if (CollectionUtils.isEmpty(configCenters)) {
+                            ConfigCenterConfig cc = new ConfigCenterConfig();
+                            cc.setProtocol(registryConfig.getProtocol());
+                            cc.setAddress(registryConfig.getAddress());
+                            cc.setHighestPriority(false);
+                            configManager.addConfigCenter(cc);
+                        }
+                        return null;
+                    });
+                }
+            }
+            startConfigCenter();
+        });
     }
 
     private List<ServiceDiscovery> getServiceDiscoveries() {
@@ -282,11 +369,17 @@ public class DubboBootstrap {
             exportServices();
 
             // Not only provider register and some services are exported
-            if (!onlyRegisterProvider && !serviceConfigs.isEmpty()) {
+            if (!onlyRegisterProvider && !ConfigManager.getInstance().getServiceConfigs().isEmpty()) {
                 /**
                  * export {@link MetadataService}
                  */
-                List<URL> exportedURLs = exportMetadataService(applicationConfig, registryConfigs, protocolConfigs);
+                ConfigManager configManager = ConfigManager.getInstance();
+                // TODO, only export to default registry?
+                List<URL> exportedURLs = exportMetadataService (
+                        configManager.getApplication().orElseThrow(() -> new IllegalStateException("ApplicationConfig cannot be null")),
+                        configManager.getDefaultRegistries().orElseThrow(() -> new IllegalStateException("No default RegistryConfig")),
+                        configManager.getDefaultProtocols().orElseThrow(() -> new IllegalStateException("No default ProtocolConfig"))
+                );
 
                 /**
                  * Register the local {@link ServiceInstance}
@@ -357,6 +450,7 @@ public class DubboBootstrap {
         return started;
     }
 
+    /* serve for builder apis, begin */
     private ApplicationBuilder initApplicationBuilder(String name) {
         applicationBuilder = new ApplicationBuilder().name(name);
         return applicationBuilder;
@@ -394,21 +488,76 @@ public class DubboBootstrap {
         return referenceBuilders.computeIfAbsent(id, this::createReferenceBuilder);
     }
 
-    private void initApplicationConfig() {
-        this.applicationConfig = buildApplicationConfig();
+    /* serve for builder apis, end */
+
+    private void startMetadataReport() {
+        ApplicationConfig applicationConfig = ConfigManager.getInstance().getApplication().orElseThrow(() -> new IllegalStateException("There's no ApplicationConfig specified."));
+
+        // FIXME, multiple metadata config support.
+        Set<MetadataReportConfig> metadataReportConfigs = ConfigManager.getInstance().getMetadataConfigs();
+        if (CollectionUtils.isEmpty(metadataReportConfigs)) {
+            if (CommonConstants.METADATA_REMOTE.equals(applicationConfig.getMetadata())) {
+                throw new IllegalStateException("No MetadataConfig found, you must specify the remote Metadata Center address when set 'metadata=remote'.");
+            }
+            return;
+        }
+        MetadataReportConfig metadataReportConfig = metadataReportConfigs.iterator().next();
+        if (!metadataReportConfig.isValid()) {
+            return;
+        }
+
+        RemoteWritableMetadataService remoteMetadataService =
+                (RemoteWritableMetadataService) WritableMetadataService.getExtension(applicationConfig.getMetadata());
+        remoteMetadataService.initMetadataReport(metadataReportConfig.toUrl());
     }
 
-    private void initRegistryConfigs() {
-        this.registryConfigs = buildRegistryConfigs();
+    private void startConfigCenter() {
+        Set<ConfigCenterConfig> configCenters = ConfigManager.getInstance().getConfigCenters();
+
+        if (CollectionUtils.isNotEmpty(configCenters)) {
+            CompositeDynamicConfiguration compositeDynamicConfiguration = new CompositeDynamicConfiguration();
+            for (ConfigCenterConfig configCenter : configCenters) {
+                configCenter.refresh();
+                compositeDynamicConfiguration.addConfiguration(prepareEnvironment(configCenter));
+            }
+            Environment.getInstance().setDynamicConfiguration(compositeDynamicConfiguration);
+        }
+        ConfigManager.getInstance().refreshAll();
     }
 
-    private void initProtocolConfigs() {
-        this.protocolConfigs = buildProtocolConfigs();
+    private DynamicConfiguration prepareEnvironment(ConfigCenterConfig configCenter) {
+        if (configCenter.isValid()) {
+            if (!configCenter.checkOrUpdateInited()) {
+                return null;
+            }
+            DynamicConfiguration dynamicConfiguration = getDynamicConfiguration(configCenter.toUrl());
+            String configContent = dynamicConfiguration.getConfigs(configCenter.getConfigFile(), configCenter.getGroup());
+
+            String appGroup = ConfigManager.getInstance().getApplication().orElse(new ApplicationConfig()).getName();
+            String appConfigContent = null;
+            if (StringUtils.isNotEmpty(appGroup)) {
+                appConfigContent = dynamicConfiguration.getConfigs
+                        (StringUtils.isNotEmpty(configCenter.getAppConfigFile()) ? configCenter.getAppConfigFile() : configCenter.getConfigFile(),
+                                appGroup
+                        );
+            }
+            try {
+                Environment.getInstance().setConfigCenterFirst(configCenter.isHighestPriority());
+                Environment.getInstance().updateExternalConfigurationMap(parseProperties(configContent));
+                Environment.getInstance().updateAppExternalConfigurationMap(parseProperties(appConfigContent));
+            } catch (IOException e) {
+                throw new IllegalStateException("Failed to parse configurations from Config Center.", e);
+            }
+            return dynamicConfiguration;
+        }
+        return null;
     }
 
-    private void initReferenceConfigs() {
-        this.referenceConfigs = buildReferenceConfigs();
-        this.referenceConfigs.values().forEach(this::initReferenceConfig);
+    private DynamicConfiguration getDynamicConfiguration(URL url) {
+        DynamicConfigurationFactory factory = ExtensionLoader
+                .getExtensionLoader(DynamicConfigurationFactory.class)
+                .getExtension(url.getProtocol());
+        return factory.getDynamicConfiguration(url);
     }
 
     /**
@@ -422,103 +571,49 @@ public class DubboBootstrap {
         return this;
     }
 
-    private void initServiceConfigs() {
-        this.serviceConfigs = buildServiceConfigs();
-        this.serviceConfigs.values().forEach(this::initServiceConfig);
-    }
-
     private List<URL> exportMetadataService(ApplicationConfig applicationConfig,
-                                            Map<String, RegistryConfig> globalRegistryConfigs,
-                                            Map<String, ProtocolConfig> globalProtocolConfigs) {
+                                            List<RegistryConfig> globalRegistryConfigs,
+                                            List<ProtocolConfig> globalProtocolConfigs) {
         ConfigurableMetadataServiceExporter exporter = new ConfigurableMetadataServiceExporter();
         exporter.setApplicationConfig(applicationConfig);
-        exporter.setRegistries(globalRegistryConfigs.values());
-        exporter.setProtocols(globalProtocolConfigs.values());
+        exporter.setRegistries(globalRegistryConfigs);
+        exporter.setProtocols(globalProtocolConfigs);
         return exporter.export();
     }
 
-    private ApplicationConfig buildApplicationConfig() {
-        return applicationBuilder.build();
+    private void buildApplicationConfig() {
+        ApplicationConfig applicationConfig = null;
+        if (applicationBuilder != null) {
+            applicationConfig = applicationBuilder.build();
+        }
+        ConfigManager.getInstance().setApplication(applicationConfig);
     }
 
-    private Map<String, ProtocolConfig> buildProtocolConfigs() {
-        return buildConfigs(protocolBuilders);
+    private void buildProtocolConfigs() {
+        List<ProtocolConfig> protocolConfigs = buildConfigs(protocolBuilders);
+        ConfigManager.getInstance().addProtocols(protocolConfigs, true);
     }
 
-    private Map<String, RegistryConfig> buildRegistryConfigs() {
-        return buildConfigs(registryBuilders);
+    private void buildRegistryConfigs() {
+        List<RegistryConfig> registryConfigs = buildConfigs(registryBuilders);
+        ConfigManager.getInstance().addRegistries(registryConfigs, true);
     }
 
-    private Map<String, ServiceConfig<?>> buildServiceConfigs() {
-        return buildConfigs(serviceBuilders);
+    private void buildServiceConfigs() {
+        List<ServiceConfig<?>> serviceConfigs = buildConfigs(serviceBuilders);
+        serviceConfigs.forEach(ConfigManager.getInstance()::addService);
     }
 
-    private Map<String, ReferenceConfig<?>> buildReferenceConfigs() {
-        return buildConfigs(referenceBuilders);
+    private void buildReferenceConfigs() {
+        List<ReferenceConfig<?>> referenceConfigs = buildConfigs(referenceBuilders);
+        referenceConfigs.forEach(ConfigManager.getInstance()::addReference);
     }
 
     private void exportServices() {
-        serviceConfigs.values().forEach(this::exportServiceConfig);
-    }
-
-    private void initServiceConfig(ServiceConfig<?> serviceConfig) {
-        initConfig(serviceConfig);
-        initProtocols(serviceConfig);
-    }
-
-    private void initReferenceConfig(ReferenceConfig<?> referenceConfig) {
-        initConfig(referenceConfig);
-    }
-
-    private void initConfig(AbstractInterfaceConfig config) {
-        initApplication(config);
-        initRegistries(config);
+        ConfigManager.getInstance().getServiceConfigs().forEach(this::exportServiceConfig);
     }
 
-    private void initApplication(AbstractInterfaceConfig config) {
-        if (config.getApplication() == null) {
-            config.setApplication(applicationConfig);
-        }
-    }
-
-    private void initRegistries(AbstractInterfaceConfig config) {
-        List<RegistryConfig> registries = config.getRegistries();
-        if (CollectionUtils.isEmpty(registries)) { // If no registry present
-            registries = new LinkedList<>();
-            String registerIds = config.getRegistryIds();
-            if (!isBlank(registerIds)) {
-                for (String id : split(registerIds, ',')) {
-                    RegistryConfig registryConfig = registryConfigs.get(trim(id));
-                    registries.add(registryConfig);
-                }
-            }
-            if (registries.isEmpty()) { // If empty, add all global registries
-                registries.addAll(registryConfigs.values());
-            }
-
-            config.setRegistries(registries);
-        }
-    }
-
-    private void initProtocols(ServiceConfig<?> serviceConfig) {
-        List<ProtocolConfig> protocols = serviceConfig.getProtocols();
-        if (CollectionUtils.isEmpty(protocols)) { // If no protocols present
-            protocols = new LinkedList<>();
-            String protocolIds = serviceConfig.getProtocolIds();
-            if (!isBlank(protocolIds)) {
-                for (String id : split(protocolIds, ',')) {
-                    ProtocolConfig protocol = protocolConfigs.get(trim(id));
-                    protocols.add(protocol);
-                }
-            }
-            if (protocols.isEmpty()) { // If empty, add all global protocols
-                protocols.addAll(protocolConfigs.values());
-            }
-            serviceConfig.setProtocols(protocols);
-        }
-    }
-
-    private void exportServiceConfig(ServiceConfig<?> serviceConfig) {
+    public void exportServiceConfig(ServiceConfig<?> serviceConfig) {
         serviceConfig.export();
     }
 
@@ -563,14 +658,14 @@ public class DubboBootstrap {
     }
 
     private void destroyProtocolConfigs() {
-        protocolConfigs.values().forEach(ProtocolConfig::destroy);
+        ConfigManager.getInstance().getProtocols().values().forEach(ProtocolConfig::destroy);
         if (logger.isDebugEnabled()) {
             logger.debug(NAME + "'s all ProtocolConfigs have been destroyed.");
         }
     }
 
     private void destroyReferenceConfigs() {
-        referenceConfigs.values().forEach(ReferenceConfig::destroy);
+        ConfigManager.getInstance().getReferenceConfigs().forEach(ReferenceConfig::destroy);
         if (logger.isDebugEnabled()) {
             logger.debug(NAME + "'s all ReferenceConfigs have been destroyed.");
         }
@@ -586,11 +681,7 @@ public class DubboBootstrap {
     }
 
     private void clearConfigs() {
-        this.applicationConfig = null;
-        this.registryConfigs.clear();
-        this.protocolConfigs.clear();
-        this.serviceConfigs.clear();
-        this.referenceConfigs.clear();
+        ConfigManager.getInstance().clear();
         if (logger.isDebugEnabled()) {
             logger.debug(NAME + "'s configs have been clear.");
         }
@@ -634,10 +725,10 @@ public class DubboBootstrap {
         }
     }
 
-    private static <C extends AbstractConfig, B extends AbstractBuilder> Map<String, C> buildConfigs(Map<String, B> map) {
-        Map<String, C> configs = new HashMap<>();
+    private static <C extends AbstractConfig, B extends AbstractBuilder> List<C> buildConfigs(Map<String, B> map) {
+        List<C> configs = new ArrayList<>();
         map.entrySet().forEach(entry -> {
-            configs.put(entry.getKey(), (C) entry.getValue().build());
+            configs.add((C) entry.getValue().build());
         });
         return configs;
     }
diff --git a/dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/DubboBootstrapTest.java b/dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/DubboBootstrapTest.java
index b9acd29..302980a 100644
--- a/dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/DubboBootstrapTest.java
+++ b/dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/DubboBootstrapTest.java
@@ -16,11 +16,11 @@
  */
 package org.apache.dubbo.bootstrap;
 
-import org.apache.dubbo.common.utils.NetUtils;
+import org.apache.dubbo.config.builders.ApplicationBuilder;
+import org.apache.dubbo.config.builders.ProtocolBuilder;
+import org.apache.dubbo.config.builders.RegistryBuilder;
+import org.apache.dubbo.config.builders.ServiceBuilder;
 
-import org.apache.curator.test.TestingServer;
-import org.junit.jupiter.api.AfterAll;
-import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.Test;
 
 import java.io.IOException;
@@ -32,65 +32,17 @@ import java.io.IOException;
  */
 public class DubboBootstrapTest {
 
-    private static int zkServerPort = NetUtils.getAvailablePort();
-
-    private static TestingServer zkServer;
-
-
-    @BeforeAll
-    public static void init() throws Exception {
-        zkServer = new TestingServer(zkServerPort, true);
-    }
-
-    @AfterAll
-    public static void destroy() throws IOException {
-        zkServer.stop();
-        zkServer.close();
-    }
-
     @Test
-    public void testProviderInFluentAPI() {
+    public void test() throws IOException {
 
         new DubboBootstrap()
-                .application("dubbo-provider-demo")
-                .next()
-                .registry()
-                .address("zookeeper://127.0.0.1:" + zkServerPort + "?registry-type=service")
-                .next()
-                .protocol()
-                .name("dubbo")
-                .port(-1)
-                .next()
-                .service("test")
-                .interfaceClass(EchoService.class)
-                .ref(new EchoServiceImpl())
-                .group("DEFAULT")
-                .version("1.0.0")
-                .next()
+                .application(ApplicationBuilder.newBuilder().name("dubbo-provider-demo").build())
+                .registry(RegistryBuilder.newBuilder().address("zookeeper://127.0.0.1:2181?registry-type=service&metadata=remote").build())
+                .protocol(ProtocolBuilder.newBuilder().port(-1).name("dubbo").build())
+                .service(ServiceBuilder.newBuilder().id("test").interfaceClass(EchoService.class).ref(new EchoServiceImpl()).build())
                 .start()
-                .stop();
-
-    }
+                .await();
 
-    @Test
-    public void testProviderInLambda() {
-        new DubboBootstrap()
-                .application("dubbo-provider-demo", builder -> {
-                })
-                .registry("default", builder ->
-                        builder.address("zookeeper://127.0.0.1:" + zkServerPort + "?registry-type=service")
-                )
-                .protocol("defalt", builder ->
-                        builder.name("dubbo")
-                                .port(-1)
-                )
-                .service("test", builder ->
-                        builder.interfaceClass(EchoService.class)
-                                .ref(new EchoServiceImpl())
-                                .group("DEFAULT")
-                                .version("1.0.0")
-                )
-                .start()
-                .stop();
+        System.in.read();
     }
 }
diff --git a/dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/DubboServiceConsumerBootstrap.java b/dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/DubboServiceConsumerBootstrap.java
index 800f29d..ef1efd3 100644
--- a/dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/DubboServiceConsumerBootstrap.java
+++ b/dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/DubboServiceConsumerBootstrap.java
@@ -16,10 +16,9 @@
  */
 package org.apache.dubbo.bootstrap;
 
-import org.apache.dubbo.config.ReferenceConfig;
-
-import static org.apache.dubbo.bootstrap.EchoService.GROUP;
-import static org.apache.dubbo.bootstrap.EchoService.VERSION;
+import org.apache.dubbo.config.builders.ApplicationBuilder;
+import org.apache.dubbo.config.builders.ReferenceBuilder;
+import org.apache.dubbo.config.builders.RegistryBuilder;
 
 /**
  * Dubbo Provider Bootstrap
@@ -31,28 +30,22 @@ public class DubboServiceConsumerBootstrap {
     public static void main(String[] args) throws Exception {
 
         DubboBootstrap bootstrap = new DubboBootstrap()
-                .application("dubbo-consumer-demo")
-                .next()
-                .registry()
-                .address("nacos://127.0.0.1:8848?registry-type=service&subscribed-services=dubbo-provider-demo")
-                .next()
-                .reference("ref")
-                .interfaceClass(EchoService.class)
-                .group(GROUP)
-                .version(VERSION)
-                .next()
+                .application(ApplicationBuilder.newBuilder().name("dubbo-consumer-demo").build())
+                .registry(RegistryBuilder.newBuilder().address("zookeeper://127.0.0.1:2181?registry-type=service&subscribed-services=dubbo-provider-demo&metadata=remote").build())
+                .reference(ReferenceBuilder.newBuilder().id("ref").interfaceClass(EchoService.class).build())
                 .onlyRegisterProvider(true)
                 .start()
                 .await();
 
-        ReferenceConfig<EchoService> referenceConfig = bootstrap.referenceConfig("ref");
-
-        EchoService echoService = referenceConfig.get();
-
-        for (int i = 0; i < 500; i++) {
-            Thread.sleep(2000L);
-            System.out.println(echoService.echo("Hello,World"));
-        }
+        // TODO,
+//        ReferenceConfig<EchoService> referenceConfig = ReferenceConfigCache.getCache().get(EchoService.class.getName(), EchoService.class);
+//
+//        EchoService echoService = referenceConfig.get();
+//
+//        for (int i = 0; i < 500; i++) {
+//            Thread.sleep(2000L);
+//            System.out.println(echoService.echo("Hello,World"));
+//        }
 
     }
 }
diff --git a/dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/DubboServiceProviderBootstrap.java b/dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/DubboServiceProviderBootstrap.java
index bb149ad..45ceed6 100644
--- a/dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/DubboServiceProviderBootstrap.java
+++ b/dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/DubboServiceProviderBootstrap.java
@@ -16,10 +16,13 @@
  */
 package org.apache.dubbo.bootstrap;
 
-import java.io.IOException;
+import org.apache.dubbo.config.builders.ApplicationBuilder;
+import org.apache.dubbo.config.builders.MetadataReportBuilder;
+import org.apache.dubbo.config.builders.ProtocolBuilder;
+import org.apache.dubbo.config.builders.RegistryBuilder;
+import org.apache.dubbo.config.builders.ServiceBuilder;
 
-import static org.apache.dubbo.bootstrap.EchoService.GROUP;
-import static org.apache.dubbo.bootstrap.EchoService.VERSION;
+import java.io.IOException;
 
 /**
  * Dubbo Provider Bootstrap
@@ -31,21 +34,12 @@ public class DubboServiceProviderBootstrap {
     public static void main(String[] args) throws IOException {
 
         new DubboBootstrap()
-                .application("dubbo-provider-demo")
-                .next()
-                .registry()
-                .address("nacos://127.0.0.1:8848?registry-type=service")
-                .next()
-                .protocol()
-                .name("dubbo")
-                .port(-1)
-                .next()
-                .service("test")
-                .interfaceClass(EchoService.class)
-                .ref(new EchoServiceImpl())
-                .group(GROUP)
-                .version(VERSION)
-                .next()
+                .application(ApplicationBuilder.newBuilder().name("dubbo-provider-demo").metadata("remote").build())
+                .metadataReport(MetadataReportBuilder.newBuilder().address("zookeeper://127.0.0.1:2181").build())
+//                .application(ApplicationBuilder.newBuilder().name("dubbo-provider-demo").build())
+                .registry(RegistryBuilder.newBuilder().address("zookeeper://127.0.0.1:2181?registry-type=service").build())
+                .protocol(ProtocolBuilder.newBuilder().port(-1).name("dubbo").build())
+                .service(ServiceBuilder.newBuilder().id("test").interfaceClass(EchoService.class).ref(new EchoServiceImpl()).build())
                 .start()
                 .await();
     }
diff --git a/dubbo-cluster/pom.xml b/dubbo-cluster/pom.xml
index ff59682..864e7cc 100644
--- a/dubbo-cluster/pom.xml
+++ b/dubbo-cluster/pom.xml
@@ -35,11 +35,6 @@
             <version>${project.parent.version}</version>
         </dependency>
         <dependency>
-            <groupId>org.apache.dubbo</groupId>
-            <artifactId>dubbo-configcenter-api</artifactId>
-            <version>${project.parent.version}</version>
-        </dependency>
-        <dependency>
             <groupId>org.yaml</groupId>
             <artifactId>snakeyaml</artifactId>
         </dependency>
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/Directory.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/Directory.java
index 67f0216..a03a781 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/Directory.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/Directory.java
@@ -46,4 +46,6 @@ public interface Directory<T> extends Node {
      */
     List<Invoker<T>> list(Invocation invocation) throws RpcException;
 
+    List<Invoker<T>> getAllInvokers();
+
 }
\ No newline at end of file
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/directory/StaticDirectory.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/directory/StaticDirectory.java
index c5a26a3..0595c63 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/directory/StaticDirectory.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/directory/StaticDirectory.java
@@ -62,6 +62,11 @@ public class StaticDirectory<T> extends AbstractDirectory<T> {
     }
 
     @Override
+    public List<Invoker<T>> getAllInvokers() {
+        return invokers;
+    }
+
+    @Override
     public boolean isAvailable() {
         if (isDestroyed()) {
             return false;
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/AbstractRouter.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/AbstractRouter.java
index 657ad86..b848cb1 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/AbstractRouter.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/AbstractRouter.java
@@ -17,7 +17,7 @@
 package org.apache.dubbo.rpc.cluster.router;
 
 import org.apache.dubbo.common.URL;
-import org.apache.dubbo.configcenter.DynamicConfiguration;
+import org.apache.dubbo.common.config.configcenter.DynamicConfiguration;
 import org.apache.dubbo.rpc.cluster.Router;
 
 public abstract class AbstractRouter implements Router {
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/config/AppRouter.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/config/AppRouter.java
index b334e37..852da6b 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/config/AppRouter.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/config/AppRouter.java
@@ -17,8 +17,8 @@
 package org.apache.dubbo.rpc.cluster.router.condition.config;
 
 import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.config.configcenter.DynamicConfiguration;
 import org.apache.dubbo.common.constants.CommonConstants;
-import org.apache.dubbo.configcenter.DynamicConfiguration;
 
 /**
  * Application level router, "application.condition-router"
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/config/AppRouterFactory.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/config/AppRouterFactory.java
index 066f865..067a523 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/config/AppRouterFactory.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/config/AppRouterFactory.java
@@ -17,8 +17,8 @@
 package org.apache.dubbo.rpc.cluster.router.condition.config;
 
 import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.config.configcenter.DynamicConfiguration;
 import org.apache.dubbo.common.extension.Activate;
-import org.apache.dubbo.configcenter.DynamicConfiguration;
 import org.apache.dubbo.rpc.cluster.Router;
 import org.apache.dubbo.rpc.cluster.RouterFactory;
 
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/config/ListenableRouter.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/config/ListenableRouter.java
index 564f371..5931e85 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/config/ListenableRouter.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/config/ListenableRouter.java
@@ -17,14 +17,14 @@
 package org.apache.dubbo.rpc.cluster.router.condition.config;
 
 import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.config.configcenter.ConfigChangeEvent;
+import org.apache.dubbo.common.config.configcenter.ConfigChangeType;
+import org.apache.dubbo.common.config.configcenter.ConfigurationListener;
+import org.apache.dubbo.common.config.configcenter.DynamicConfiguration;
 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.common.utils.StringUtils;
-import org.apache.dubbo.configcenter.ConfigChangeEvent;
-import org.apache.dubbo.configcenter.ConfigChangeType;
-import org.apache.dubbo.configcenter.ConfigurationListener;
-import org.apache.dubbo.configcenter.DynamicConfiguration;
 import org.apache.dubbo.rpc.Invocation;
 import org.apache.dubbo.rpc.Invoker;
 import org.apache.dubbo.rpc.RpcException;
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/config/ServiceRouter.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/config/ServiceRouter.java
index ed3748e..1bdf261 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/config/ServiceRouter.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/config/ServiceRouter.java
@@ -17,7 +17,7 @@
 package org.apache.dubbo.rpc.cluster.router.condition.config;
 
 import org.apache.dubbo.common.URL;
-import org.apache.dubbo.configcenter.DynamicConfiguration;
+import org.apache.dubbo.common.config.configcenter.DynamicConfiguration;
 
 /**
  * Service level router, "server-unique-name.condition-router"
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/config/ServiceRouterFactory.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/config/ServiceRouterFactory.java
index 18d4a1d..12911ac 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/config/ServiceRouterFactory.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/config/ServiceRouterFactory.java
@@ -17,8 +17,8 @@
 package org.apache.dubbo.rpc.cluster.router.condition.config;
 
 import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.config.configcenter.DynamicConfiguration;
 import org.apache.dubbo.common.extension.Activate;
-import org.apache.dubbo.configcenter.DynamicConfiguration;
 import org.apache.dubbo.rpc.cluster.CacheableRouterFactory;
 import org.apache.dubbo.rpc.cluster.Router;
 
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/tag/TagRouter.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/tag/TagRouter.java
index c6387fe..d33d103 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/tag/TagRouter.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/tag/TagRouter.java
@@ -17,16 +17,16 @@
 package org.apache.dubbo.rpc.cluster.router.tag;
 
 import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.config.configcenter.ConfigChangeEvent;
+import org.apache.dubbo.common.config.configcenter.ConfigChangeType;
+import org.apache.dubbo.common.config.configcenter.ConfigurationListener;
+import org.apache.dubbo.common.config.configcenter.DynamicConfiguration;
 import org.apache.dubbo.common.constants.CommonConstants;
 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.common.utils.NetUtils;
 import org.apache.dubbo.common.utils.StringUtils;
-import org.apache.dubbo.configcenter.ConfigChangeEvent;
-import org.apache.dubbo.configcenter.ConfigChangeType;
-import org.apache.dubbo.configcenter.ConfigurationListener;
-import org.apache.dubbo.configcenter.DynamicConfiguration;
 import org.apache.dubbo.rpc.Invocation;
 import org.apache.dubbo.rpc.Invoker;
 import org.apache.dubbo.rpc.RpcException;
@@ -40,8 +40,8 @@ import java.util.List;
 import java.util.function.Predicate;
 import java.util.stream.Collectors;
 
-import static org.apache.dubbo.rpc.cluster.Constants.TAG_KEY;
 import static org.apache.dubbo.rpc.Constants.FORCE_USE_TAG;
+import static org.apache.dubbo.rpc.cluster.Constants.TAG_KEY;
 
 /**
  * TagRouter, "application.tag-router"
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/tag/TagRouterFactory.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/tag/TagRouterFactory.java
index 7d3e013..0df085d 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/tag/TagRouterFactory.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/tag/TagRouterFactory.java
@@ -17,8 +17,8 @@
 package org.apache.dubbo.rpc.cluster.router.tag;
 
 import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.config.configcenter.DynamicConfiguration;
 import org.apache.dubbo.common.extension.Activate;
-import org.apache.dubbo.configcenter.DynamicConfiguration;
 import org.apache.dubbo.rpc.cluster.CacheableRouterFactory;
 import org.apache.dubbo.rpc.cluster.Router;
 
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/AbstractClusterInvoker.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/AbstractClusterInvoker.java
index db2d401..61ef955 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/AbstractClusterInvoker.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/AbstractClusterInvoker.java
@@ -94,6 +94,10 @@ public abstract class AbstractClusterInvoker<T> implements Invoker<T> {
         return directory.isAvailable();
     }
 
+    public Directory<T> getDirectory() {
+        return directory;
+    }
+
     @Override
     public void destroy() {
         if (destroyed.compareAndSet(false, true)) {
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/bytecode/Proxy.java b/dubbo-common/src/main/java/org/apache/dubbo/common/bytecode/Proxy.java
index 2da2818..cf335b4 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/bytecode/Proxy.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/bytecode/Proxy.java
@@ -155,7 +155,7 @@ public abstract class Proxy {
 
                 for (Method method : ics[i].getMethods()) {
                     String desc = ReflectUtils.getDesc(method);
-                    if (worked.contains(desc)) {
+                    if (worked.contains(desc) || Modifier.isStatic(method.getModifiers())) {
                         continue;
                     }
                     worked.add(desc);
diff --git a/dubbo-configcenter/dubbo-configcenter-api/src/main/java/org/apache/dubbo/configcenter/AbstractDynamicConfigurationFactory.java b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/AbstractDynamicConfigurationFactory.java
similarity index 70%
rename from dubbo-configcenter/dubbo-configcenter-api/src/main/java/org/apache/dubbo/configcenter/AbstractDynamicConfigurationFactory.java
rename to dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/AbstractDynamicConfigurationFactory.java
index 324f2cb..15b9145 100644
--- a/dubbo-configcenter/dubbo-configcenter-api/src/main/java/org/apache/dubbo/configcenter/AbstractDynamicConfigurationFactory.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/AbstractDynamicConfigurationFactory.java
@@ -14,27 +14,26 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.configcenter;
+package org.apache.dubbo.common.config.configcenter;
 
 import org.apache.dubbo.common.URL;
 
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_KEY;
+
 /**
  *
  */
 public abstract class AbstractDynamicConfigurationFactory implements DynamicConfigurationFactory {
 
-    private volatile DynamicConfiguration dynamicConfiguration;
+    private volatile Map<String, DynamicConfiguration> dynamicConfigurations = new ConcurrentHashMap<>();
 
     @Override
     public DynamicConfiguration getDynamicConfiguration(URL url) {
-        if (dynamicConfiguration == null) {
-            synchronized (this) {
-                if (dynamicConfiguration == null) {
-                    dynamicConfiguration = createDynamicConfiguration(url);
-                }
-            }
-        }
-        return dynamicConfiguration;
+        String key = url == null ? DEFAULT_KEY : url.getAddress();
+        return dynamicConfigurations.computeIfAbsent(key, k -> createDynamicConfiguration(url));
     }
 
     protected abstract DynamicConfiguration createDynamicConfiguration(URL url);
diff --git a/dubbo-configcenter/dubbo-configcenter-api/src/main/java/org/apache/dubbo/configcenter/ConfigChangeEvent.java b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/ConfigChangeEvent.java
similarity index 97%
rename from dubbo-configcenter/dubbo-configcenter-api/src/main/java/org/apache/dubbo/configcenter/ConfigChangeEvent.java
rename to dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/ConfigChangeEvent.java
index cdedd15..751746f 100644
--- a/dubbo-configcenter/dubbo-configcenter-api/src/main/java/org/apache/dubbo/configcenter/ConfigChangeEvent.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/ConfigChangeEvent.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.configcenter;
+package org.apache.dubbo.common.config.configcenter;
 
 /**
  * Config change event, immutable.
diff --git a/dubbo-configcenter/dubbo-configcenter-api/src/main/java/org/apache/dubbo/configcenter/ConfigChangeType.java b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/ConfigChangeType.java
similarity index 95%
rename from dubbo-configcenter/dubbo-configcenter-api/src/main/java/org/apache/dubbo/configcenter/ConfigChangeType.java
rename to dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/ConfigChangeType.java
index e810ddc..fe43a2b 100644
--- a/dubbo-configcenter/dubbo-configcenter-api/src/main/java/org/apache/dubbo/configcenter/ConfigChangeType.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/ConfigChangeType.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.configcenter;
+package org.apache.dubbo.common.config.configcenter;
 
 /**
  * Config change event type
diff --git a/dubbo-configcenter/dubbo-configcenter-api/src/main/java/org/apache/dubbo/configcenter/ConfigurationListener.java b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/ConfigurationListener.java
similarity index 95%
rename from dubbo-configcenter/dubbo-configcenter-api/src/main/java/org/apache/dubbo/configcenter/ConfigurationListener.java
rename to dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/ConfigurationListener.java
index 7c7a131..09746c5 100644
--- a/dubbo-configcenter/dubbo-configcenter-api/src/main/java/org/apache/dubbo/configcenter/ConfigurationListener.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/ConfigurationListener.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.configcenter;
+package org.apache.dubbo.common.config.configcenter;
 
 /**
  * Config listener, will get notified when the config it listens on changes.
diff --git a/dubbo-configcenter/dubbo-configcenter-api/src/main/java/org/apache/dubbo/configcenter/Constants.java b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/Constants.java
similarity index 95%
rename from dubbo-configcenter/dubbo-configcenter-api/src/main/java/org/apache/dubbo/configcenter/Constants.java
rename to dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/Constants.java
index fcf1a51..d85f86b 100644
--- a/dubbo-configcenter/dubbo-configcenter-api/src/main/java/org/apache/dubbo/configcenter/Constants.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/Constants.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.configcenter;
+package org.apache.dubbo.common.config.configcenter;
 
 public interface Constants {
     String CONFIG_CLUSTER_KEY = "config.cluster";
diff --git a/dubbo-configcenter/dubbo-configcenter-api/src/main/java/org/apache/dubbo/configcenter/DynamicConfiguration.java b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/DynamicConfiguration.java
similarity index 99%
rename from dubbo-configcenter/dubbo-configcenter-api/src/main/java/org/apache/dubbo/configcenter/DynamicConfiguration.java
rename to dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/DynamicConfiguration.java
index 804dd8b..26e831d 100644
--- a/dubbo-configcenter/dubbo-configcenter-api/src/main/java/org/apache/dubbo/configcenter/DynamicConfiguration.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/DynamicConfiguration.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.configcenter;
+package org.apache.dubbo.common.config.configcenter;
 
 import org.apache.dubbo.common.config.Configuration;
 import org.apache.dubbo.common.config.Environment;
diff --git a/dubbo-configcenter/dubbo-configcenter-api/src/main/java/org/apache/dubbo/configcenter/DynamicConfigurationFactory.java b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/DynamicConfigurationFactory.java
similarity index 95%
rename from dubbo-configcenter/dubbo-configcenter-api/src/main/java/org/apache/dubbo/configcenter/DynamicConfigurationFactory.java
rename to dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/DynamicConfigurationFactory.java
index 4e0b9b5..59c27ce 100644
--- a/dubbo-configcenter/dubbo-configcenter-api/src/main/java/org/apache/dubbo/configcenter/DynamicConfigurationFactory.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/DynamicConfigurationFactory.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.configcenter;
+package org.apache.dubbo.common.config.configcenter;
 
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.extension.SPI;
diff --git a/dubbo-configcenter/dubbo-configcenter-api/src/main/java/org/apache/dubbo/configcenter/support/nop/NopDynamicConfiguration.java b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/nop/NopDynamicConfiguration.java
similarity index 88%
rename from dubbo-configcenter/dubbo-configcenter-api/src/main/java/org/apache/dubbo/configcenter/support/nop/NopDynamicConfiguration.java
rename to dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/nop/NopDynamicConfiguration.java
index 56e1191..7637e64 100644
--- a/dubbo-configcenter/dubbo-configcenter-api/src/main/java/org/apache/dubbo/configcenter/support/nop/NopDynamicConfiguration.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/nop/NopDynamicConfiguration.java
@@ -14,11 +14,15 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.configcenter.support.nop;
+package org.apache.dubbo.common.config.configcenter.nop;
 
 import org.apache.dubbo.common.URL;
-import org.apache.dubbo.configcenter.ConfigurationListener;
-import org.apache.dubbo.configcenter.DynamicConfiguration;
+import org.apache.dubbo.common.config.configcenter.ConfigurationListener;
+import org.apache.dubbo.common.config.configcenter.DynamicConfiguration;
+
+import java.util.SortedSet;
+
+import static java.util.Collections.emptySortedSet;
 
 import java.util.SortedSet;
 
diff --git a/dubbo-configcenter/dubbo-configcenter-api/src/main/java/org/apache/dubbo/configcenter/support/nop/NopDynamicConfigurationFactory.java b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/nop/NopDynamicConfigurationFactory.java
similarity index 83%
rename from dubbo-configcenter/dubbo-configcenter-api/src/main/java/org/apache/dubbo/configcenter/support/nop/NopDynamicConfigurationFactory.java
rename to dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/nop/NopDynamicConfigurationFactory.java
index 0b6aee6..bd45e7f 100644
--- a/dubbo-configcenter/dubbo-configcenter-api/src/main/java/org/apache/dubbo/configcenter/support/nop/NopDynamicConfigurationFactory.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/nop/NopDynamicConfigurationFactory.java
@@ -14,11 +14,11 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.configcenter.support.nop;
+package org.apache.dubbo.common.config.configcenter.nop;
 
 import org.apache.dubbo.common.URL;
-import org.apache.dubbo.configcenter.AbstractDynamicConfigurationFactory;
-import org.apache.dubbo.configcenter.DynamicConfiguration;
+import org.apache.dubbo.common.config.configcenter.AbstractDynamicConfigurationFactory;
+import org.apache.dubbo.common.config.configcenter.DynamicConfiguration;
 
 /**
  *
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/wrapper/CompositeDynamicConfiguration.java b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/wrapper/CompositeDynamicConfiguration.java
new file mode 100644
index 0000000..7f98d38
--- /dev/null
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/wrapper/CompositeDynamicConfiguration.java
@@ -0,0 +1,98 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.common.config.configcenter.wrapper;
+
+import org.apache.dubbo.common.config.configcenter.ConfigurationListener;
+import org.apache.dubbo.common.config.configcenter.DynamicConfiguration;
+
+import java.util.HashSet;
+import java.util.Set;
+import java.util.SortedMap;
+import java.util.SortedSet;
+import java.util.function.Consumer;
+import java.util.function.Function;
+
+/**
+ * support multiple config center, simply iterating each underlying config center.
+ */
+public class CompositeDynamicConfiguration implements DynamicConfiguration {
+
+    public static final String NAME = "COMPOSITE";
+
+    private Set<DynamicConfiguration> configurations = new HashSet<>();
+
+    public void addConfiguration(DynamicConfiguration configuration) {
+        this.configurations.add(configuration);
+    }
+
+    @Override
+    public void addListener(String key, String group, ConfigurationListener listener) {
+        iterateListenerOperation(configuration -> configuration.addListener(key, group, listener));
+    }
+
+    @Override
+    public void removeListener(String key, String group, ConfigurationListener listener) {
+        iterateListenerOperation(configuration -> configuration.removeListener(key, group, listener));
+    }
+
+    @Override
+    public String getConfig(String key, String group, long timeout) throws IllegalStateException {
+        return (String) iterateConfigOperation(configuration -> configuration.getConfig(key, group, timeout));
+    }
+
+    @Override
+    public String getConfigs(String key, String group, long timeout) throws IllegalStateException {
+        return (String) iterateConfigOperation(configuration -> configuration.getConfigs(key, group, timeout));
+    }
+
+    @Override
+    public Object getInternalProperty(String key) {
+        return iterateConfigOperation(configuration -> configuration.getInternalProperty(key));
+    }
+
+    @Override
+    public boolean publishConfig(String key, String group, String content) throws UnsupportedOperationException {
+        return (boolean) iterateConfigOperation(configuration -> configuration.publishConfig(key, group, content));
+    }
+
+    @Override
+    public SortedSet<String> getConfigKeys(String group) throws UnsupportedOperationException {
+        return (SortedSet<String>) iterateConfigOperation(configuration -> configuration.getConfigKeys(group));
+    }
+
+    @Override
+    public SortedMap<String, String> getConfigs(String group) throws UnsupportedOperationException {
+        return (SortedMap<String, String>) iterateConfigOperation(configuration -> configuration.getConfigs(group));
+    }
+
+    private void iterateListenerOperation(Consumer<DynamicConfiguration> consumer) {
+        for (DynamicConfiguration configuration : configurations) {
+            consumer.accept(configuration);
+        }
+    }
+
+    private Object iterateConfigOperation(Function<DynamicConfiguration, Object> func) {
+        Object value = null;
+        for (DynamicConfiguration configuration : configurations) {
+            value = func.apply(configuration);
+            if (value != null) {
+                break;
+            }
+        }
+        return value;
+    }
+}
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/constants/CommonConstants.java b/dubbo-common/src/main/java/org/apache/dubbo/common/constants/CommonConstants.java
index d005ae9..c1a1357 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/constants/CommonConstants.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/constants/CommonConstants.java
@@ -151,6 +151,14 @@ public interface CommonConstants {
 
     String REVISION_KEY = "revision";
 
+    String METADATA_REVISION = "metadata.revision";
+
+    String METADATA_KEY = "metadata";
+
+    String METADATA_DEFAULT = "local";
+
+    String METADATA_REMOTE = "remote";
+
     /**
      * package version in the manifest
      */
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/UrlUtils.java b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/UrlUtils.java
index 548c48f..b4739f2 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/UrlUtils.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/UrlUtils.java
@@ -498,4 +498,25 @@ public class UrlUtils {
             return "*".equals(pattern) || pattern.equals(value);
         }
     }
+
+    /**
+     * @param serviceKey, {group}/{interfaceName}:{version}
+     * @return  [group, interfaceName, version]
+     */
+    public static String[] parseServiceKey(String serviceKey) {
+        String[] arr = new String[3];
+        int i = serviceKey.indexOf("/");
+        if (i > 0) {
+            arr[0] = serviceKey.substring(0, i);
+            serviceKey = serviceKey.substring(i + 1);
+        }
+
+        int j = serviceKey.indexOf(":");
+        if (j > 0) {
+            arr[2] = serviceKey.substring(j + 1);
+            serviceKey = serviceKey.substring(0, j);
+        }
+        arr[1] = serviceKey;
+        return arr;
+    }
 }
diff --git a/dubbo-common/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.config.configcenter.DynamicConfigurationFactory b/dubbo-common/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.config.configcenter.DynamicConfigurationFactory
new file mode 100644
index 0000000..42d6a25
--- /dev/null
+++ b/dubbo-common/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.config.configcenter.DynamicConfigurationFactory
@@ -0,0 +1 @@
+nop=org.apache.dubbo.common.config.configcenter.nop.NopDynamicConfigurationFactory
\ No newline at end of file
diff --git a/dubbo-compatible/src/main/java/com/alibaba/dubbo/common/Constants.java b/dubbo-compatible/src/main/java/com/alibaba/dubbo/common/Constants.java
index 7b489a3..f488c8d 100644
--- a/dubbo-compatible/src/main/java/com/alibaba/dubbo/common/Constants.java
+++ b/dubbo-compatible/src/main/java/com/alibaba/dubbo/common/Constants.java
@@ -36,7 +36,7 @@ public class Constants implements CommonConstants,
         org.apache.dubbo.rpc.Constants,
         org.apache.dubbo.rpc.protocol.dubbo.Constants,
         org.apache.dubbo.common.serialize.Constants,
-        org.apache.dubbo.configcenter.Constants,
+        org.apache.dubbo.common.config.configcenter.Constants,
         org.apache.dubbo.metadata.support.Constants,
         org.apache.dubbo.rpc.protocol.rest.Constants,
         org.apache.dubbo.registry.Constants {
diff --git a/dubbo-config/dubbo-config-api/pom.xml b/dubbo-config/dubbo-config-api/pom.xml
index b8f5938..896feef 100644
--- a/dubbo-config/dubbo-config-api/pom.xml
+++ b/dubbo-config/dubbo-config-api/pom.xml
@@ -66,12 +66,6 @@
             <version>${project.parent.version}</version>
         </dependency>
 
-        <dependency>
-            <groupId>org.apache.dubbo</groupId>
-            <artifactId>dubbo-metadata</artifactId>
-            <version>${project.parent.version}</version>
-        </dependency>
-
         <!-- FIXME, we shouldn't rely on these modules, even in test scope -->
         <dependency>
             <groupId>org.apache.dubbo</groupId>
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractConfig.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractConfig.java
index 2466948..4d59f91 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractConfig.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractConfig.java
@@ -114,9 +114,6 @@ public abstract class AbstractConfig implements Serializable {
         LEGACY_PROPERTIES.put("dubbo.consumer.retries", "dubbo.service.max.retry.providers");
         LEGACY_PROPERTIES.put("dubbo.consumer.check", "dubbo.service.allow.no.provider");
         LEGACY_PROPERTIES.put("dubbo.service.url", "dubbo.service.address");
-
-        // this is only for compatibility
-        DubboShutdownHook.getDubboShutdownHook().register();
     }
 
     /**
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractInterfaceConfig.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractInterfaceConfig.java
index 8130a5f..1ad15ec 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractInterfaceConfig.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractInterfaceConfig.java
@@ -19,8 +19,6 @@ package org.apache.dubbo.config;
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.URLBuilder;
 import org.apache.dubbo.common.Version;
-import org.apache.dubbo.common.config.Environment;
-import org.apache.dubbo.common.extension.ExtensionLoader;
 import org.apache.dubbo.common.utils.Assert;
 import org.apache.dubbo.common.utils.CollectionUtils;
 import org.apache.dubbo.common.utils.ConfigUtils;
@@ -30,9 +28,6 @@ import org.apache.dubbo.common.utils.StringUtils;
 import org.apache.dubbo.common.utils.UrlUtils;
 import org.apache.dubbo.config.context.ConfigManager;
 import org.apache.dubbo.config.support.Parameter;
-import org.apache.dubbo.configcenter.DynamicConfiguration;
-import org.apache.dubbo.configcenter.DynamicConfigurationFactory;
-import org.apache.dubbo.metadata.integration.MetadataReportService;
 import org.apache.dubbo.monitor.MonitorFactory;
 import org.apache.dubbo.monitor.MonitorService;
 import org.apache.dubbo.registry.RegistryService;
@@ -43,19 +38,14 @@ import org.apache.dubbo.rpc.cluster.Cluster;
 import org.apache.dubbo.rpc.model.ApplicationModel;
 import org.apache.dubbo.rpc.support.MockInvoker;
 
-import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
-import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
-import java.util.Set;
 
-import static org.apache.dubbo.common.config.ConfigurationUtils.parseProperties;
 import static org.apache.dubbo.common.constants.CommonConstants.ANYHOST_VALUE;
 import static org.apache.dubbo.common.constants.CommonConstants.CLUSTER_KEY;
-import static org.apache.dubbo.common.constants.CommonConstants.COMMA_SEPARATOR;
 import static org.apache.dubbo.common.constants.CommonConstants.COMMA_SPLIT_PATTERN;
 import static org.apache.dubbo.common.constants.CommonConstants.DUBBO_PROTOCOL;
 import static org.apache.dubbo.common.constants.CommonConstants.FILE_KEY;
@@ -73,7 +63,6 @@ import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoad
 import static org.apache.dubbo.config.Constants.DUBBO_IP_TO_REGISTRY;
 import static org.apache.dubbo.config.Constants.LAYER_KEY;
 import static org.apache.dubbo.config.Constants.LISTENER_KEY;
-import static org.apache.dubbo.config.Constants.REGISTRIES_SUFFIX;
 import static org.apache.dubbo.monitor.Constants.LOGSTAT_PROTOCOL;
 import static org.apache.dubbo.registry.Constants.REGISTER_IP_KEY;
 import static org.apache.dubbo.registry.Constants.REGISTER_KEY;
@@ -203,8 +192,6 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig {
                         "The registry config is: " + registryConfig);
             }
         }
-
-        useRegistryForConfigIfNecessary();
     }
 
     @SuppressWarnings("deprecation")
@@ -267,55 +254,6 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig {
         }
     }
 
-
-    void startConfigCenter() {
-        if (configCenter == null) {
-            ConfigManager.getInstance().getConfigCenter().ifPresent(cc -> this.configCenter = cc);
-        }
-
-        if (this.configCenter != null) {
-            // TODO there may have duplicate refresh
-            this.configCenter.refresh();
-            prepareEnvironment();
-        }
-        ConfigManager.getInstance().refreshAll();
-    }
-
-    private void prepareEnvironment() {
-        if (configCenter.isValid()) {
-            if (!configCenter.checkOrUpdateInited()) {
-                return;
-            }
-            DynamicConfiguration dynamicConfiguration = getDynamicConfiguration(configCenter.toUrl());
-            String configContent = dynamicConfiguration.getConfigs(configCenter.getConfigFile(), configCenter.getGroup());
-
-            String appGroup = application != null ? application.getName() : null;
-            String appConfigContent = null;
-            if (StringUtils.isNotEmpty(appGroup)) {
-                appConfigContent = dynamicConfiguration.getConfigs
-                        (StringUtils.isNotEmpty(configCenter.getAppConfigFile()) ? configCenter.getAppConfigFile() : configCenter.getConfigFile(),
-                         appGroup
-                        );
-            }
-            try {
-                Environment.getInstance().setConfigCenterFirst(configCenter.isHighestPriority());
-                Environment.getInstance().updateExternalConfigurationMap(parseProperties(configContent));
-                Environment.getInstance().updateAppExternalConfigurationMap(parseProperties(appConfigContent));
-            } catch (IOException e) {
-                throw new IllegalStateException("Failed to parse configurations from Config Center.", e);
-            }
-        }
-    }
-
-    private DynamicConfiguration getDynamicConfiguration(URL url) {
-        DynamicConfigurationFactory factories = ExtensionLoader
-                .getExtensionLoader(DynamicConfigurationFactory.class)
-                .getExtension(url.getProtocol());
-        DynamicConfiguration configuration = factories.getDynamicConfiguration(url);
-        Environment.getInstance().setDynamicConfiguration(configuration);
-        return configuration;
-    }
-
     /**
      *
      * Load the registry and conversion it to {@link URL}, the priority order is: system property > dubbo registry config
@@ -415,24 +353,6 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig {
         }
     }
 
-    private URL loadMetadataReporterURL() {
-        String address = metadataReportConfig.getAddress();
-        if (StringUtils.isEmpty(address)) {
-            return null;
-        }
-        Map<String, String> map = new HashMap<String, String>();
-        appendParameters(map, metadataReportConfig);
-        return UrlUtils.parseURL(address, map);
-    }
-
-    protected MetadataReportService getMetadataReportService() {
-
-        if (metadataReportConfig == null || !metadataReportConfig.isValid()) {
-            return null;
-        }
-        return MetadataReportService.instance(this::loadMetadataReporterURL);
-    }
-
     /**
      * Check whether the remote service interface and the methods meet with Dubbo's requirements.it mainly check, if the
      * methods configured in the configuration file are included in the interface of remote service
@@ -544,16 +464,6 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig {
     }
 
     private void convertRegistryIdsToRegistries() {
-        if (StringUtils.isEmpty(registryIds) && CollectionUtils.isEmpty(registries)) {
-            Set<String> configedRegistries = new HashSet<>();
-            configedRegistries.addAll(getSubProperties(Environment.getInstance().getExternalConfigurationMap(),
-                    REGISTRIES_SUFFIX));
-            configedRegistries.addAll(getSubProperties(Environment.getInstance().getAppExternalConfigurationMap(),
-                    REGISTRIES_SUFFIX));
-
-            registryIds = String.join(COMMA_SEPARATOR, configedRegistries);
-        }
-
         if (StringUtils.isEmpty(registryIds)) {
             if (CollectionUtils.isEmpty(registries)) {
                 setRegistries(
@@ -571,12 +481,7 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig {
             List<RegistryConfig> tmpRegistries = CollectionUtils.isNotEmpty(registries) ? registries : new ArrayList<>();
             Arrays.stream(ids).forEach(id -> {
                 if (tmpRegistries.stream().noneMatch(reg -> reg.getId().equals(id))) {
-                    tmpRegistries.add(ConfigManager.getInstance().getRegistry(id).orElseGet(() -> {
-                        RegistryConfig registryConfig = new RegistryConfig();
-                        registryConfig.setId(id);
-                        registryConfig.refresh();
-                        return registryConfig;
-                    }));
+                    ConfigManager.getInstance().getRegistry(id).ifPresent(tmpRegistries::add);
                 }
             });
 
@@ -610,26 +515,6 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig {
     }
 
     /**
-     * For compatibility purpose, use registry as the default config center if the registry protocol is zookeeper and
-     * there's no config center specified explicitly.
-     */
-    private void useRegistryForConfigIfNecessary() {
-        registries.stream().filter(RegistryConfig::isZookeeperProtocol).findFirst().ifPresent(rc -> {
-            // we use the loading status of DynamicConfiguration to decide whether ConfigCenter has been initiated.
-            Environment.getInstance().getDynamicConfiguration().orElseGet(() -> {
-                ConfigManager configManager = ConfigManager.getInstance();
-                ConfigCenterConfig cc = configManager.getConfigCenter().orElse(new ConfigCenterConfig());
-                cc.setProtocol(rc.getProtocol());
-                cc.setAddress(rc.getAddress());
-                cc.setHighestPriority(false);
-                setConfigCenter(cc);
-                startConfigCenter();
-                return null;
-            });
-        });
-    }
-
-    /**
      * @return local
      * @deprecated Replace to <code>getStub()</code>
      */
@@ -783,7 +668,7 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig {
 
     @SuppressWarnings({"unchecked"})
     public void setRegistries(List<? extends RegistryConfig> registries) {
-        ConfigManager.getInstance().addRegistries((List<RegistryConfig>) registries);
+        ConfigManager.getInstance().addRegistries((List<RegistryConfig>) registries, false);
         this.registries = (List<RegistryConfig>) registries;
     }
 
@@ -823,7 +708,7 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig {
     }
 
     public void setConfigCenter(ConfigCenterConfig configCenter) {
-        ConfigManager.getInstance().setConfigCenter(configCenter);
+        ConfigManager.getInstance().addConfigCenter(configCenter);
         this.configCenter = configCenter;
     }
 
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractServiceConfig.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractServiceConfig.java
index 8aff2aa..dc40e52 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractServiceConfig.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractServiceConfig.java
@@ -27,8 +27,8 @@ import java.util.List;
 
 import static org.apache.dubbo.common.constants.CommonConstants.GROUP_KEY;
 import static org.apache.dubbo.common.constants.CommonConstants.VERSION_KEY;
-import static org.apache.dubbo.rpc.Constants.SERVICE_FILTER_KEY;
 import static org.apache.dubbo.rpc.Constants.EXPORTER_LISTENER_KEY;
+import static org.apache.dubbo.rpc.Constants.SERVICE_FILTER_KEY;
 import static org.apache.dubbo.rpc.Constants.TOKEN_KEY;
 
 /**
@@ -206,7 +206,7 @@ public abstract class AbstractServiceConfig extends AbstractInterfaceConfig {
 
     @SuppressWarnings({"unchecked"})
     public void setProtocols(List<? extends ProtocolConfig> protocols) {
-        ConfigManager.getInstance().addProtocols((List<ProtocolConfig>) protocols);
+        ConfigManager.getInstance().addProtocols((List<ProtocolConfig>) protocols, false);
         this.protocols = (List<ProtocolConfig>) protocols;
     }
 
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ApplicationConfig.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ApplicationConfig.java
index 83fc6db..b33ec75 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ApplicationConfig.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ApplicationConfig.java
@@ -137,6 +137,11 @@ public class ApplicationConfig extends AbstractConfig {
      */
     private String shutwait;
 
+    /**
+     * Metadata type, local or remote, if choose remote, you need to further specify metadata center.
+     */
+    private String metadata;
+
     public ApplicationConfig() {
     }
 
@@ -374,4 +379,11 @@ public class ApplicationConfig extends AbstractConfig {
         return !StringUtils.isEmpty(name);
     }
 
+    public String getMetadata() {
+        return metadata;
+    }
+
+    public void setMetadata(String metadata) {
+        this.metadata = metadata;
+    }
 }
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ConfigCenterConfig.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ConfigCenterConfig.java
index 7caae56..fb8b2e5 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ConfigCenterConfig.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ConfigCenterConfig.java
@@ -26,17 +26,17 @@ import org.apache.dubbo.config.support.Parameter;
 import java.util.Map;
 import java.util.concurrent.atomic.AtomicBoolean;
 
+import static org.apache.dubbo.common.config.configcenter.Constants.CONFIG_CHECK_KEY;
+import static org.apache.dubbo.common.config.configcenter.Constants.CONFIG_CLUSTER_KEY;
+import static org.apache.dubbo.common.config.configcenter.Constants.CONFIG_GROUP_KEY;
+import static org.apache.dubbo.common.config.configcenter.Constants.CONFIG_NAMESPACE_KEY;
 import static org.apache.dubbo.common.constants.CommonConstants.ANYHOST_VALUE;
 import static org.apache.dubbo.common.constants.CommonConstants.PATH_KEY;
 import static org.apache.dubbo.common.constants.CommonConstants.PROTOCOL_KEY;
-import static org.apache.dubbo.configcenter.Constants.CONFIG_CHECK_KEY;
-import static org.apache.dubbo.configcenter.Constants.CONFIG_CLUSTER_KEY;
-import static org.apache.dubbo.configcenter.Constants.CONFIG_GROUP_KEY;
-import static org.apache.dubbo.configcenter.Constants.CONFIG_NAMESPACE_KEY;
-import static org.apache.dubbo.config.Constants.ZOOKEEPER_PROTOCOL;
 import static org.apache.dubbo.config.Constants.CONFIG_CONFIGFILE_KEY;
 import static org.apache.dubbo.config.Constants.CONFIG_ENABLE_KEY;
 import static org.apache.dubbo.config.Constants.CONFIG_TIMEOUT_KEY;
+import static org.apache.dubbo.config.Constants.ZOOKEEPER_PROTOCOL;
 
 /**
  * ConfigCenterConfig
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/MetadataReportConfig.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/MetadataReportConfig.java
index 5233171..30e5bcb 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/MetadataReportConfig.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/MetadataReportConfig.java
@@ -16,9 +16,12 @@
  */
 package org.apache.dubbo.config;
 
+import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.utils.StringUtils;
+import org.apache.dubbo.common.utils.UrlUtils;
 import org.apache.dubbo.config.support.Parameter;
 
+import java.util.HashMap;
 import java.util.Map;
 
 import static org.apache.dubbo.common.constants.CommonConstants.DUBBO;
@@ -83,6 +86,16 @@ public class MetadataReportConfig extends AbstractConfig {
         setAddress(address);
     }
 
+    public URL toUrl() {
+        String address = this.getAddress();
+        if (StringUtils.isEmpty(address)) {
+            return null;
+        }
+        Map<String, String> map = new HashMap<String, String>();
+        appendParameters(map, this);
+        return UrlUtils.parseURL(address, map);
+    }
+
     @Parameter(excluded = true)
     public String getAddress() {
         return address;
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 ee2e9b6..1b08ba0 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
@@ -32,7 +32,7 @@ import org.apache.dubbo.config.event.ReferenceConfigInitializedEvent;
 import org.apache.dubbo.config.support.Parameter;
 import org.apache.dubbo.event.Event;
 import org.apache.dubbo.event.EventDispatcher;
-import org.apache.dubbo.metadata.integration.MetadataReportService;
+import org.apache.dubbo.metadata.WritableMetadataService;
 import org.apache.dubbo.remoting.Constants;
 import org.apache.dubbo.rpc.Invoker;
 import org.apache.dubbo.rpc.Protocol;
@@ -66,6 +66,8 @@ import static org.apache.dubbo.common.constants.CommonConstants.CONSUMER_SIDE;
 import static org.apache.dubbo.common.constants.CommonConstants.DUBBO;
 import static org.apache.dubbo.common.constants.CommonConstants.INTERFACE_KEY;
 import static org.apache.dubbo.common.constants.CommonConstants.LOCALHOST_VALUE;
+import static org.apache.dubbo.common.constants.CommonConstants.METADATA_DEFAULT;
+import static org.apache.dubbo.common.constants.CommonConstants.METADATA_KEY;
 import static org.apache.dubbo.common.constants.CommonConstants.METHODS_KEY;
 import static org.apache.dubbo.common.constants.CommonConstants.MONITOR_KEY;
 import static org.apache.dubbo.common.constants.CommonConstants.REVISION_KEY;
@@ -228,7 +230,6 @@ public class ReferenceConfig<T> extends AbstractReferenceConfig {
             throw new IllegalStateException("<dubbo:reference interface=\"\" /> interface not allow null!");
         }
         completeCompoundConfigs();
-        startConfigCenter();
         // get consumer's global configuration
         checkDefault();
         this.refresh();
@@ -340,10 +341,11 @@ public class ReferenceConfig<T> extends AbstractReferenceConfig {
         }
         map.put(REGISTER_IP_KEY, hostToRegistry);
 
-        ref = createProxy(map);
-
         String serviceKey = URL.buildKey(interfaceName, group, version);
         ApplicationModel.initConsumerModel(serviceKey, buildConsumerModel(serviceKey, attributes));
+        ref = createProxy(map);
+        ApplicationModel.getConsumerModel(serviceKey).setProxyObject(ref);
+
         initialized = true;
 
         // dispatch a ReferenceConfigInitializedEvent since 2.7.3
@@ -441,10 +443,11 @@ public class ReferenceConfig<T> extends AbstractReferenceConfig {
          * @since 2.7.0
          * ServiceData Store
          */
-        MetadataReportService metadataReportService = null;
-        if ((metadataReportService = getMetadataReportService()) != null) {
+        String metadata = map.get(METADATA_KEY);
+        WritableMetadataService metadataService = WritableMetadataService.getExtension(metadata == null ? METADATA_DEFAULT : metadata);
+        if (metadataService != null) {
             URL consumerURL = new URL(CONSUMER_PROTOCOL, map.remove(REGISTER_IP_KEY), 0, map.get(INTERFACE_KEY), map);
-            metadataReportService.publishConsumer(consumerURL);
+            metadataService.publishServiceDefinition(consumerURL);
         }
         // create service proxy
         return (T) PROXY_FACTORY.getProxy(invoker);
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ServiceConfig.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ServiceConfig.java
index cc1138a..dc7d5a9 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ServiceConfig.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ServiceConfig.java
@@ -21,7 +21,6 @@ import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.URLBuilder;
 import org.apache.dubbo.common.Version;
 import org.apache.dubbo.common.bytecode.Wrapper;
-import org.apache.dubbo.common.config.Environment;
 import org.apache.dubbo.common.extension.ExtensionLoader;
 import org.apache.dubbo.common.utils.ClassUtils;
 import org.apache.dubbo.common.utils.CollectionUtils;
@@ -36,7 +35,7 @@ import org.apache.dubbo.config.invoker.DelegateProviderMetaDataInvoker;
 import org.apache.dubbo.config.support.Parameter;
 import org.apache.dubbo.event.Event;
 import org.apache.dubbo.event.EventDispatcher;
-import org.apache.dubbo.metadata.integration.MetadataReportService;
+import org.apache.dubbo.metadata.WritableMetadataService;
 import org.apache.dubbo.remoting.Constants;
 import org.apache.dubbo.rpc.Exporter;
 import org.apache.dubbo.rpc.Invoker;
@@ -72,6 +71,8 @@ import static org.apache.dubbo.common.constants.CommonConstants.COMMA_SPLIT_PATT
 import static org.apache.dubbo.common.constants.CommonConstants.DUBBO;
 import static org.apache.dubbo.common.constants.CommonConstants.DUBBO_IP_TO_BIND;
 import static org.apache.dubbo.common.constants.CommonConstants.LOCALHOST_VALUE;
+import static org.apache.dubbo.common.constants.CommonConstants.METADATA_DEFAULT;
+import static org.apache.dubbo.common.constants.CommonConstants.METADATA_KEY;
 import static org.apache.dubbo.common.constants.CommonConstants.METHODS_KEY;
 import static org.apache.dubbo.common.constants.CommonConstants.MONITOR_KEY;
 import static org.apache.dubbo.common.constants.CommonConstants.PATH_KEY;
@@ -87,7 +88,6 @@ import static org.apache.dubbo.config.Constants.DUBBO_IP_TO_REGISTRY;
 import static org.apache.dubbo.config.Constants.DUBBO_PORT_TO_BIND;
 import static org.apache.dubbo.config.Constants.DUBBO_PORT_TO_REGISTRY;
 import static org.apache.dubbo.config.Constants.MULTICAST;
-import static org.apache.dubbo.config.Constants.PROTOCOLS_SUFFIX;
 import static org.apache.dubbo.config.Constants.SCOPE_NONE;
 import static org.apache.dubbo.rpc.Constants.GENERIC_KEY;
 import static org.apache.dubbo.rpc.Constants.LOCAL_PROTOCOL;
@@ -301,10 +301,8 @@ public class ServiceConfig<T> extends AbstractServiceConfig {
     }
 
     public void checkAndUpdateSubConfigs() {
-        // Use default configs defined explicitly on global configs
+        // Use default configs defined explicitly on global scope
         completeCompoundConfigs();
-        // Config Center should always being started first.
-        startConfigCenter();
         checkDefault();
         checkProtocol();
         checkApplication();
@@ -635,9 +633,9 @@ public class ServiceConfig<T> extends AbstractServiceConfig {
                  * @since 2.7.0
                  * ServiceData Store
                  */
-                MetadataReportService metadataReportService = null;
-                if ((metadataReportService = getMetadataReportService()) != null) {
-                    metadataReportService.publishProvider(url);
+                WritableMetadataService metadataService = WritableMetadataService.getExtension(url.getParameter(METADATA_KEY, METADATA_DEFAULT));
+                if (metadataService != null) {
+                    metadataService.publishServiceDefinition(url);
                 }
             }
         }
@@ -882,16 +880,6 @@ public class ServiceConfig<T> extends AbstractServiceConfig {
     }
 
     private void convertProtocolIdsToProtocols() {
-        if (StringUtils.isEmpty(protocolIds) && CollectionUtils.isEmpty(protocols)) {
-            List<String> configedProtocols = new ArrayList<>();
-            configedProtocols.addAll(getSubProperties(Environment.getInstance()
-                    .getExternalConfigurationMap(), PROTOCOLS_SUFFIX));
-            configedProtocols.addAll(getSubProperties(Environment.getInstance()
-                    .getAppExternalConfigurationMap(), PROTOCOLS_SUFFIX));
-
-            protocolIds = String.join(",", configedProtocols);
-        }
-
         if (StringUtils.isEmpty(protocolIds)) {
             if (CollectionUtils.isEmpty(protocols)) {
                 setProtocols(
@@ -909,12 +897,7 @@ public class ServiceConfig<T> extends AbstractServiceConfig {
             List<ProtocolConfig> tmpProtocols = CollectionUtils.isNotEmpty(protocols) ? protocols : new ArrayList<>();
             Arrays.stream(arr).forEach(id -> {
                 if (tmpProtocols.stream().noneMatch(prot -> prot.getId().equals(id))) {
-                    tmpProtocols.add(ConfigManager.getInstance().getProtocol(id).orElseGet(() -> {
-                        ProtocolConfig protocolConfig = new ProtocolConfig();
-                        protocolConfig.setId(id);
-                        protocolConfig.refresh();
-                        return protocolConfig;
-                    }));
+                    ConfigManager.getInstance().getProtocol(id).ifPresent(tmpProtocols::add);
                 }
             });
             if (tmpProtocols.size() > arr.length) {
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/builders/ApplicationBuilder.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/builders/ApplicationBuilder.java
index 7ab59a6..f4a8047 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/builders/ApplicationBuilder.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/builders/ApplicationBuilder.java
@@ -33,6 +33,7 @@ import static org.apache.dubbo.config.Constants.PRODUCTION_ENVIRONMENT;
  */
 public class ApplicationBuilder extends AbstractBuilder<ApplicationConfig, ApplicationBuilder> {
     private String name;
+    private String metadata;
     private String version;
     private String owner;
     private String organization;
@@ -51,11 +52,20 @@ public class ApplicationBuilder extends AbstractBuilder<ApplicationConfig, Appli
     private Map<String, String> parameters;
     private String shutwait;
 
+    public static ApplicationBuilder newBuilder() {
+        return new ApplicationBuilder();
+    }
+
     public ApplicationBuilder name(String name) {
         this.name = name;
         return getThis();
     }
 
+    public ApplicationBuilder metadata(String metadata) {
+        this.metadata = metadata;
+        return getThis();
+    }
+
     public ApplicationBuilder version(String version) {
         this.version = version;
         return getThis();
@@ -167,6 +177,7 @@ public class ApplicationBuilder extends AbstractBuilder<ApplicationConfig, Appli
         super.build(config);
 
         config.setName(name);
+        config.setMetadata(metadata);
         config.setVersion(this.version);
         config.setOwner(this.owner);
         config.setOrganization(this.organization);
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/builders/MetadataReportBuilder.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/builders/MetadataReportBuilder.java
index 140ea13..62777ef 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/builders/MetadataReportBuilder.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/builders/MetadataReportBuilder.java
@@ -60,6 +60,10 @@ public class MetadataReportBuilder extends AbstractBuilder<MetadataReportConfig,
      */
     private Boolean syncReport;
 
+    public static MetadataReportBuilder newBuilder() {
+        return new MetadataReportBuilder();
+    }
+
     public MetadataReportBuilder address(String address) {
         this.address = address;
         return getThis();
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/builders/ProtocolBuilder.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/builders/ProtocolBuilder.java
index 4ddd943..70e94c3 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/builders/ProtocolBuilder.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/builders/ProtocolBuilder.java
@@ -185,6 +185,10 @@ public class ProtocolBuilder extends AbstractBuilder<ProtocolConfig, ProtocolBui
      */
     private Boolean isDefault;
 
+    public static ProtocolBuilder newBuilder() {
+        return new ProtocolBuilder();
+    }
+
     public ProtocolBuilder id(String id) {
         return super.id(id);
     }
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/builders/ReferenceBuilder.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/builders/ReferenceBuilder.java
index 52ceb94..9275476 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/builders/ReferenceBuilder.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/builders/ReferenceBuilder.java
@@ -64,6 +64,10 @@ public class ReferenceBuilder<T> extends AbstractReferenceBuilder<ReferenceConfi
      */
     private String protocol;
 
+    public static ReferenceBuilder newBuilder() {
+        return new ReferenceBuilder();
+    }
+
     public ReferenceBuilder<T> id(String id) {
         return super.id(id);
     }
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/builders/RegistryBuilder.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/builders/RegistryBuilder.java
index 616e6af..9dc9e1b 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/builders/RegistryBuilder.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/builders/RegistryBuilder.java
@@ -134,6 +134,10 @@ public class RegistryBuilder extends AbstractBuilder<RegistryConfig, RegistryBui
      */
     private String extraKeys;
 
+    public static RegistryBuilder newBuilder() {
+        return new RegistryBuilder();
+    }
+
     public RegistryBuilder id(String id) {
         return super.id(id);
     }
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/builders/ServiceBuilder.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/builders/ServiceBuilder.java
index 65cc916..9c471ce 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/builders/ServiceBuilder.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/builders/ServiceBuilder.java
@@ -68,6 +68,10 @@ public class ServiceBuilder<U> extends AbstractServiceBuilder<ServiceConfig, Ser
      */
     private String generic;
 
+    public static ServiceBuilder newBuilder() {
+        return new ServiceBuilder();
+    }
+
     public ServiceBuilder id(String id) {
         return super.id(id);
     }
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/context/ConfigManager.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/context/ConfigManager.java
index 79b097a..718d425 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/context/ConfigManager.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/context/ConfigManager.java
@@ -16,26 +16,36 @@
  */
 package org.apache.dubbo.config.context;
 
+import org.apache.dubbo.common.config.Environment;
 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.common.utils.StringUtils;
 import org.apache.dubbo.config.AbstractConfig;
 import org.apache.dubbo.config.ApplicationConfig;
 import org.apache.dubbo.config.ConfigCenterConfig;
 import org.apache.dubbo.config.ConsumerConfig;
+import org.apache.dubbo.config.MetadataReportConfig;
 import org.apache.dubbo.config.ModuleConfig;
 import org.apache.dubbo.config.MonitorConfig;
 import org.apache.dubbo.config.ProtocolConfig;
 import org.apache.dubbo.config.ProviderConfig;
+import org.apache.dubbo.config.ReferenceConfig;
 import org.apache.dubbo.config.RegistryConfig;
+import org.apache.dubbo.config.ServiceConfig;
 
 import java.util.ArrayList;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Optional;
+import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.stream.Collectors;
 
 import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_KEY;
+import static org.apache.dubbo.config.Constants.PROTOCOLS_SUFFIX;
+import static org.apache.dubbo.config.Constants.REGISTRIES_SUFFIX;
 
 /**
  * TODO
@@ -78,13 +88,23 @@ public class ConfigManager {
     private ApplicationConfig application;
     private MonitorConfig monitor;
     private ModuleConfig module;
-    private ConfigCenterConfig configCenter;
 
     private Map<String, ProtocolConfig> protocols = new ConcurrentHashMap<>();
     private Map<String, RegistryConfig> registries = new ConcurrentHashMap<>();
     private Map<String, ProviderConfig> providers = new ConcurrentHashMap<>();
     private Map<String, ConsumerConfig> consumers = new ConcurrentHashMap<>();
 
+    private List<ProtocolConfig> defaultProtocols = new ArrayList<>();
+    private List<RegistryConfig> defaultRegistries = new ArrayList<>();
+
+    private Set<ConfigCenterConfig> configCenters = new HashSet<>();
+    private Set<MetadataReportConfig> metadataConfigs = new HashSet<>();
+    private Set<String> registryIds = new HashSet<>();
+    private Set<String> protocolIds = new HashSet<>();
+
+    private List<ServiceConfig<?>> serviceConfigs = new ArrayList<>();
+    private List<ReferenceConfig<?>> referenceConfigs = new ArrayList<>();
+
     public static ConfigManager getInstance() {
         return CONFIG_MANAGER;
     }
@@ -126,14 +146,35 @@ public class ConfigManager {
         }
     }
 
-    public Optional<ConfigCenterConfig> getConfigCenter() {
-        return Optional.ofNullable(configCenter);
+    public Set<ConfigCenterConfig> getConfigCenters() {
+        return configCenters;
+    }
+
+    public void addConfigCenter(ConfigCenterConfig configCenter) {
+        if (configCenter != null && !configCenters.contains(configCenter)) {
+            this.configCenters.add(configCenter);
+        }
+    }
+
+    public void addConfigCenter(List<ConfigCenterConfig> configCenters) {
+        if (CollectionUtils.isNotEmpty(configCenters)) {
+            this.configCenters.addAll(configCenters);
+        }
+    }
+
+    public Set<MetadataReportConfig> getMetadataConfigs() {
+        return metadataConfigs;
     }
 
-    public void setConfigCenter(ConfigCenterConfig configCenter) {
-        if (configCenter != null) {
-            checkDuplicate(this.configCenter, configCenter);
-            this.configCenter = configCenter;
+    public void addMetadataReport(MetadataReportConfig metadataReportConfig) {
+        if (metadataReportConfig != null && !metadataConfigs.contains(metadataReportConfig)) {
+            this.metadataConfigs.add(metadataReportConfig);
+        }
+    }
+
+    public void addMetadataReport(List<MetadataReportConfig> metadataReportConfigs) {
+        if (CollectionUtils.isNotEmpty(metadataReportConfigs)) {
+            this.metadataConfigs.addAll(metadataReportConfigs);
         }
     }
 
@@ -200,31 +241,28 @@ public class ConfigManager {
     }
 
     public Optional<List<ProtocolConfig>> getDefaultProtocols() {
-        List<ProtocolConfig> defaults = new ArrayList<>();
-        protocols.forEach((k, v) -> {
-            if (DEFAULT_KEY.equalsIgnoreCase(k)) {
-                defaults.add(v);
-            } else if (v.isDefault() == null || v.isDefault()) {
-                defaults.add(v);
-            }
-        });
-        return Optional.of(defaults);
-    }
-
-    public void addProtocols(List<ProtocolConfig> protocolConfigs) {
+        return Optional.of(defaultProtocols);
+    }
+
+    public void addProtocols(List<ProtocolConfig> protocolConfigs, boolean canBeDefault) {
         if (protocolConfigs != null) {
-            protocolConfigs.forEach(this::addProtocol);
+            protocolConfigs.forEach(pc -> this.addProtocol(pc, canBeDefault));
         }
     }
 
-    public void addProtocol(ProtocolConfig protocolConfig) {
+    public void addProtocol(ProtocolConfig protocolConfig, boolean canBeDefault) {
         if (protocolConfig == null) {
             return;
         }
 
+        // if isDefault is not false and a ProtocolConfig is not specified being false.
+        if (canBeDefault && (protocolConfig.isDefault() == null || protocolConfig.isDefault())) {
+            this.defaultProtocols.add(protocolConfig);
+        }
+
         String key = StringUtils.isNotEmpty(protocolConfig.getId())
                 ? protocolConfig.getId()
-                : (protocolConfig.isDefault() == null || protocolConfig.isDefault()) ? DEFAULT_KEY : null;
+                : DEFAULT_KEY;
 
         if (StringUtils.isEmpty(key)) {
             throw new IllegalStateException("A ProtocolConfig should either has an id or it's the default one, " + protocolConfig);
@@ -243,31 +281,26 @@ public class ConfigManager {
     }
 
     public Optional<List<RegistryConfig>> getDefaultRegistries() {
-        List<RegistryConfig> defaults = new ArrayList<>();
-        registries.forEach((k, v) -> {
-            if (DEFAULT_KEY.equalsIgnoreCase(k)) {
-                defaults.add(v);
-            } else if (v.isDefault() == null || v.isDefault()) {
-                defaults.add(v);
-            }
-        });
-        return Optional.of(defaults);
-    }
-
-    public void addRegistries(List<RegistryConfig> registryConfigs) {
+        return Optional.of(defaultRegistries);
+    }
+
+    public void addRegistries(List<RegistryConfig> registryConfigs, boolean canBeDefault) {
         if (registryConfigs != null) {
-            registryConfigs.forEach(this::addRegistry);
+            registryConfigs.forEach(rc -> this.addRegistry(rc, canBeDefault));
         }
     }
 
-    public void addRegistry(RegistryConfig registryConfig) {
+    public void addRegistry(RegistryConfig registryConfig, boolean canBeDefault) {
         if (registryConfig == null) {
             return;
         }
 
+        if (canBeDefault && (registryConfig.isDefault() == null || registryConfig.isDefault())) {
+            this.defaultRegistries.add(registryConfig);
+        }
         String key = StringUtils.isNotEmpty(registryConfig.getId())
                 ? registryConfig.getId()
-                : (registryConfig.isDefault() == null || registryConfig.isDefault()) ? DEFAULT_KEY : null;
+                : DEFAULT_KEY;
 
         if (StringUtils.isEmpty(key)) {
             throw new IllegalStateException("A RegistryConfig should either has an id or it's the default one, " + registryConfig);
@@ -281,6 +314,51 @@ public class ConfigManager {
         }
     }
 
+    public void addProtocolIds(List<String> protocolIds) {
+        this.protocolIds.addAll(protocolIds);
+    }
+
+    public void addRegistryIds(List<String> registryIds) {
+        this.registryIds.addAll(registryIds);
+    }
+
+    public void addService(ServiceConfig<?> serviceConfig) {
+        this.serviceConfigs.add(serviceConfig);
+    }
+
+    public void addReference(ReferenceConfig<?> referenceConfig) {
+        this.referenceConfigs.add(referenceConfig);
+    }
+
+    public Set<String> getRegistryIds() {
+        Set<String> configedRegistries = new HashSet<>();
+        configedRegistries.addAll(getSubProperties(Environment.getInstance().getExternalConfigurationMap(),
+                REGISTRIES_SUFFIX));
+        configedRegistries.addAll(getSubProperties(Environment.getInstance().getAppExternalConfigurationMap(),
+                REGISTRIES_SUFFIX));
+
+        configedRegistries.addAll(registryIds);
+        return configedRegistries;
+    }
+
+    public Set<String> getProtocolIds() {
+        Set<String> configedProtocols = new HashSet<>();
+        configedProtocols.addAll(getSubProperties(Environment.getInstance()
+                .getExternalConfigurationMap(), PROTOCOLS_SUFFIX));
+        configedProtocols.addAll(getSubProperties(Environment.getInstance()
+                .getAppExternalConfigurationMap(), PROTOCOLS_SUFFIX));
+
+        configedProtocols.addAll(protocolIds);
+        return configedProtocols;
+    }
+
+    protected static Set<String> getSubProperties(Map<String, String> properties, String prefix) {
+        return properties.keySet().stream().filter(k -> k.contains(prefix)).map(k -> {
+            k = k.substring(prefix.length());
+            return k.substring(0, k.indexOf("."));
+        }).collect(Collectors.toSet());
+    }
+
     public Map<String, ProtocolConfig> getProtocols() {
         return protocols;
     }
@@ -297,6 +375,14 @@ public class ConfigManager {
         return consumers;
     }
 
+    public List<ServiceConfig<?>> getServiceConfigs() {
+        return serviceConfigs;
+    }
+
+    public List<ReferenceConfig<?>> getReferenceConfigs() {
+        return referenceConfigs;
+    }
+
     public void refreshAll() {
         // refresh all configs here,
         getApplication().ifPresent(ApplicationConfig::refresh);
@@ -319,13 +405,16 @@ public class ConfigManager {
     // For test purpose
     public void clear() {
         this.application = null;
-        this.configCenter = null;
         this.monitor = null;
         this.module = null;
         this.registries.clear();
         this.protocols.clear();
         this.providers.clear();
         this.consumers.clear();
+        this.configCenters.clear();
+        this.metadataConfigs.clear();
+        this.registryIds.clear();
+        this.protocolIds.clear();
     }
 
 }
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 ac36f9e..bf14658 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
@@ -25,9 +25,9 @@ import org.apache.dubbo.config.ProtocolConfig;
 import org.apache.dubbo.config.RegistryConfig;
 import org.apache.dubbo.config.ServiceConfig;
 import org.apache.dubbo.config.context.ConfigManager;
-import org.apache.dubbo.metadata.LocalMetadataService;
 import org.apache.dubbo.metadata.MetadataService;
 import org.apache.dubbo.metadata.MetadataServiceExporter;
+import org.apache.dubbo.metadata.WritableMetadataService;
 
 import java.util.Collection;
 import java.util.LinkedList;
@@ -79,7 +79,7 @@ public class ConfigurableMetadataServiceExporter implements MetadataServiceExpor
 
         if (!isExported()) {
 
-            LocalMetadataService metadataService = LocalMetadataService.getDefaultExtension();
+            WritableMetadataService metadataService = WritableMetadataService.getDefaultExtension();
 
             ServiceConfig<MetadataService> serviceConfig = new ServiceConfig<>();
             serviceConfig.setApplication(applicationConfig);
diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/telnet/ShutdownTelnetHandler.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/telnet/ShutdownTelnetHandler.java
similarity index 98%
rename from dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/telnet/ShutdownTelnetHandler.java
rename to dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/telnet/ShutdownTelnetHandler.java
index ff5bf07..3c24ceb 100644
--- a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/telnet/ShutdownTelnetHandler.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/telnet/ShutdownTelnetHandler.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.rpc.protocol.dubbo.telnet;
+package org.apache.dubbo.config.telnet;
 
 import org.apache.dubbo.common.extension.Activate;
 import org.apache.dubbo.common.utils.StringUtils;
diff --git a/dubbo-config/dubbo-config-api/src/main/resources/META-INF/services/org.apache.dubbo.remoting.telnet.TelnetHandler b/dubbo-config/dubbo-config-api/src/main/resources/META-INF/services/org.apache.dubbo.remoting.telnet.TelnetHandler
new file mode 100644
index 0000000..3e87526
--- /dev/null
+++ b/dubbo-config/dubbo-config-api/src/main/resources/META-INF/services/org.apache.dubbo.remoting.telnet.TelnetHandler
@@ -0,0 +1 @@
+shutdown=org.apache.dubbo.rpc.protocol.dubbo.telnet.ShutdownTelnetHandler
\ No newline at end of file
diff --git a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/metadata/ConfigurableMetadataServiceExporterTest.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/metadata/ConfigurableMetadataServiceExporterTest.java
index 66200ac..ec841a5 100644
--- a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/metadata/ConfigurableMetadataServiceExporterTest.java
+++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/metadata/ConfigurableMetadataServiceExporterTest.java
@@ -49,9 +49,9 @@ public class ConfigurableMetadataServiceExporterTest {
         configManager.setApplication(applicationConfig);
 
         // Add ProtocolConfig
-        configManager.addProtocol(protocolConfig());
+        configManager.addProtocol(protocolConfig(), true);
         // Add RegistryConfig
-        configManager.addRegistry(registryConfig());
+        configManager.addRegistry(registryConfig(), true);
     }
 
     private static ProtocolConfig protocolConfig() {
diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/service/DemoException.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/service/DemoException.java
similarity index 96%
rename from dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/service/DemoException.java
rename to dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/service/DemoException.java
index ceb187c..dc02d4e 100644
--- a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/service/DemoException.java
+++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/service/DemoException.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.dubbo.rpc.service;
+package org.apache.dubbo.config.service;
 
 /**
  * DemoException
diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/service/DemoService.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/service/DemoService.java
similarity index 96%
rename from dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/service/DemoService.java
rename to dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/service/DemoService.java
index 38ba742..cbc131a 100644
--- a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/service/DemoService.java
+++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/service/DemoService.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.dubbo.rpc.service;
+package org.apache.dubbo.config.service;
 
 import java.util.List;
 
diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/service/DemoServiceImpl.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/service/DemoServiceImpl.java
similarity index 96%
rename from dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/service/DemoServiceImpl.java
rename to dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/service/DemoServiceImpl.java
index 4ef72c3..7bd467e 100644
--- a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/service/DemoServiceImpl.java
+++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/service/DemoServiceImpl.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.dubbo.rpc.service;
+package org.apache.dubbo.config.service;
 
 import java.util.List;
 
diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/service/GenericServiceTest.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/service/GenericServiceTest.java
similarity index 99%
rename from dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/service/GenericServiceTest.java
rename to dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/service/GenericServiceTest.java
index e99c6fc..921800c 100644
--- a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/service/GenericServiceTest.java
+++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/service/GenericServiceTest.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.dubbo.rpc.service;
+package org.apache.dubbo.config.service;
 
 import org.apache.dubbo.common.beanutil.JavaBeanAccessor;
 import org.apache.dubbo.common.beanutil.JavaBeanDescriptor;
@@ -29,6 +29,8 @@ import org.apache.dubbo.config.ProtocolConfig;
 import org.apache.dubbo.config.ReferenceConfig;
 import org.apache.dubbo.config.RegistryConfig;
 import org.apache.dubbo.config.ServiceConfig;
+import org.apache.dubbo.rpc.service.GenericException;
+import org.apache.dubbo.rpc.service.GenericService;
 
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Disabled;
@@ -42,8 +44,8 @@ import java.util.List;
 import java.util.Map;
 import java.util.concurrent.atomic.AtomicReference;
 
-import static org.apache.dubbo.rpc.Constants.GENERIC_SERIALIZATION_NATIVE_JAVA;
 import static org.apache.dubbo.rpc.Constants.GENERIC_SERIALIZATION_BEAN;
+import static org.apache.dubbo.rpc.Constants.GENERIC_SERIALIZATION_NATIVE_JAVA;
 
 /**
  * GenericServiceTest
diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/service/User.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/service/User.java
similarity index 97%
rename from dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/service/User.java
rename to dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/service/User.java
index 901001b..7ba76a2 100644
--- a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/service/User.java
+++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/service/User.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.dubbo.rpc.service;
+package org.apache.dubbo.config.service;
 
 import java.io.Serializable;
 
diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/telnet/ShutdownTelnetHandlerTest.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/telnet/ShutdownTelnetHandlerTest.java
similarity index 97%
rename from dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/telnet/ShutdownTelnetHandlerTest.java
rename to dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/telnet/ShutdownTelnetHandlerTest.java
index 6dbd026..2fc4110 100644
--- a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/telnet/ShutdownTelnetHandlerTest.java
+++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/telnet/ShutdownTelnetHandlerTest.java
@@ -14,11 +14,12 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.rpc.protocol.dubbo.telnet;
+package org.apache.dubbo.config.telnet;
 
 import org.apache.dubbo.remoting.Channel;
 import org.apache.dubbo.remoting.RemotingException;
 import org.apache.dubbo.remoting.telnet.TelnetHandler;
+
 import org.junit.jupiter.api.Test;
 
 import static org.junit.jupiter.api.Assertions.assertTrue;
diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/validation/ValidationParameter.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/validation/ValidationParameter.java
similarity index 98%
rename from dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/validation/ValidationParameter.java
rename to dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/validation/ValidationParameter.java
index 77841d5..14a571d 100644
--- a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/validation/ValidationParameter.java
+++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/validation/ValidationParameter.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.dubbo.rpc.validation;
+package org.apache.dubbo.config.validation;
 
 import javax.validation.constraints.Future;
 import javax.validation.constraints.Max;
diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/validation/ValidationService.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/validation/ValidationService.java
similarity index 98%
rename from dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/validation/ValidationService.java
rename to dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/validation/ValidationService.java
index 262c996..0d15b6d 100644
--- a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/validation/ValidationService.java
+++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/validation/ValidationService.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.dubbo.rpc.validation;
+package org.apache.dubbo.config.validation;
 
 import org.apache.dubbo.validation.MethodValidated;
 
diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/validation/ValidationServiceImpl.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/validation/ValidationServiceImpl.java
similarity index 96%
rename from dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/validation/ValidationServiceImpl.java
rename to dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/validation/ValidationServiceImpl.java
index 8a621aa..783cff5 100644
--- a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/validation/ValidationServiceImpl.java
+++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/validation/ValidationServiceImpl.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.dubbo.rpc.validation;
+package org.apache.dubbo.config.validation;
 
 /**
  * ValidationServiceImpl
diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/validation/ValidationTest.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/validation/ValidationTest.java
similarity index 99%
rename from dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/validation/ValidationTest.java
rename to dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/validation/ValidationTest.java
index 691f925..04a45ea 100644
--- a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/validation/ValidationTest.java
+++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/validation/ValidationTest.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.dubbo.rpc.validation;
+package org.apache.dubbo.config.validation;
 
 import org.apache.dubbo.config.ApplicationConfig;
 import org.apache.dubbo.config.ProtocolConfig;
diff --git a/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/compat/dubbo.xsd b/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/compat/dubbo.xsd
index 756f6da..4331ea4 100644
--- a/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/compat/dubbo.xsd
+++ b/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/compat/dubbo.xsd
@@ -397,6 +397,11 @@
                 <xsd:documentation><![CDATA[ Is default. ]]></xsd:documentation>
             </xsd:annotation>
         </xsd:attribute>
+        <xsd:attribute name="metadata" type="xsd:string">
+            <xsd:annotation>
+                <xsd:documentation><![CDATA[ The metadta type: local or remote. ]]></xsd:documentation>
+            </xsd:annotation>
+        </xsd:attribute>
 
     </xsd:complexType>
 
diff --git a/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/dubbo.xsd b/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/dubbo.xsd
index 4a8cf56..f7124c8 100644
--- a/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/dubbo.xsd
+++ b/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/dubbo.xsd
@@ -392,6 +392,11 @@
                 <xsd:documentation><![CDATA[ Is default. ]]></xsd:documentation>
             </xsd:annotation>
         </xsd:attribute>
+        <xsd:attribute name="metadata" type="xsd:string">
+            <xsd:annotation>
+                <xsd:documentation><![CDATA[ The metadta type: local or remote. ]]></xsd:documentation>
+            </xsd:annotation>
+        </xsd:attribute>
     </xsd:complexType>
 
     <xsd:complexType name="moduleType">
diff --git a/dubbo-configcenter/dubbo-configcenter-api/pom.xml b/dubbo-configcenter/dubbo-configcenter-api/pom.xml
deleted file mode 100644
index bab80eb..0000000
--- a/dubbo-configcenter/dubbo-configcenter-api/pom.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-<!--
-  Licensed to the Apache Software Foundation (ASF) under one or more
-  contributor license agreements.  See the NOTICE file distributed with
-  this work for additional information regarding copyright ownership.
-  The ASF licenses this file to You under the Apache License, Version 2.0
-  (the "License"); you may not use this file except in compliance with
-  the License.  You may obtain a copy of the License at
-
-      http://www.apache.org/licenses/LICENSE-2.0
-
-  Unless required by applicable law or agreed to in writing, software
-  distributed under the License is distributed on an "AS IS" BASIS,
-  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  See the License for the specific language governing permissions and
-  limitations under the License.
-  -->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <modelVersion>4.0.0</modelVersion>
-    <parent>
-        <groupId>org.apache.dubbo</groupId>
-        <artifactId>dubbo-configcenter</artifactId>
-        <version>${revision}</version>
-    </parent>
-    <artifactId>dubbo-configcenter-api</artifactId>
-    <packaging>jar</packaging>
-    <name>${project.artifactId}</name>
-    <description>The api definition of the service config-center module</description>
-    <properties>
-        <skip_maven_deploy>false</skip_maven_deploy>
-    </properties>
-
-    <dependencies>
-        <dependency>
-            <groupId>org.apache.dubbo</groupId>
-            <artifactId>dubbo-common</artifactId>
-            <version>${project.parent.version}</version>
-        </dependency>
-    </dependencies>
-</project>
diff --git a/dubbo-configcenter/dubbo-configcenter-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.configcenter.DynamicConfigurationFactory b/dubbo-configcenter/dubbo-configcenter-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.configcenter.DynamicConfigurationFactory
deleted file mode 100644
index 51c4004..0000000
--- a/dubbo-configcenter/dubbo-configcenter-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.configcenter.DynamicConfigurationFactory
+++ /dev/null
@@ -1 +0,0 @@
-nop=org.apache.dubbo.configcenter.support.nop.NopDynamicConfigurationFactory
\ No newline at end of file
diff --git a/dubbo-configcenter/dubbo-configcenter-api/src/test/java/org/apache/dubbo/configcenter/mock/AbstractDynamicConfigurationTest.java b/dubbo-configcenter/dubbo-configcenter-api/src/test/java/org/apache/dubbo/configcenter/mock/AbstractDynamicConfigurationTest.java
deleted file mode 100644
index a5f669a..0000000
--- a/dubbo-configcenter/dubbo-configcenter-api/src/test/java/org/apache/dubbo/configcenter/mock/AbstractDynamicConfigurationTest.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.configcenter.mock;
-
-import org.apache.dubbo.common.URL;
-import org.apache.dubbo.common.extension.ExtensionLoader;
-import org.apache.dubbo.configcenter.DynamicConfiguration;
-import org.apache.dubbo.configcenter.DynamicConfigurationFactory;
-import org.apache.dubbo.configcenter.support.nop.NopDynamicConfigurationFactory;
-
-import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.Test;
-
-/**
- *
- */
-public class AbstractDynamicConfigurationTest {
-    public DynamicConfigurationFactory configurationFactory = ExtensionLoader.getExtensionLoader(DynamicConfigurationFactory.class).getExtension("mock");
-    public URL url = URL.valueOf("nop://127.0.0.1:10880/DynamicConfiguration");
-
-    @Test
-    public void testInit() {
-        DynamicConfiguration configuration1 = configurationFactory.getDynamicConfiguration(url);
-        DynamicConfiguration configuration2 = configurationFactory.getDynamicConfiguration(url);
-        Assertions.assertEquals(configuration1, configuration2);
-    }
-
-    @Test
-    public void testDefaultExtension() {
-        DynamicConfigurationFactory factory = ExtensionLoader.getExtensionLoader(DynamicConfigurationFactory.class).getDefaultExtension();
-        Assertions.assertTrue(factory instanceof NopDynamicConfigurationFactory);
-    }
-}
diff --git a/dubbo-configcenter/dubbo-configcenter-api/src/test/java/org/apache/dubbo/configcenter/mock/MockDynamicConfiguration.java b/dubbo-configcenter/dubbo-configcenter-api/src/test/java/org/apache/dubbo/configcenter/mock/MockDynamicConfiguration.java
deleted file mode 100644
index 05ce68b..0000000
--- a/dubbo-configcenter/dubbo-configcenter-api/src/test/java/org/apache/dubbo/configcenter/mock/MockDynamicConfiguration.java
+++ /dev/null
@@ -1,54 +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.configcenter.mock;
-
-import org.apache.dubbo.common.URL;
-import org.apache.dubbo.configcenter.ConfigurationListener;
-import org.apache.dubbo.configcenter.DynamicConfiguration;
-
-/**
- *
- */
-public class MockDynamicConfiguration implements DynamicConfiguration {
-    public MockDynamicConfiguration(URL url) {
-    }
-
-    @Override
-    public Object getInternalProperty(String key) {
-        return null;
-    }
-
-    @Override
-    public void addListener(String key, String group, ConfigurationListener listener) {
-
-    }
-
-    @Override
-    public void removeListener(String key, String group, ConfigurationListener listener) {
-
-    }
-
-    @Override
-    public String getConfig(String key, String group, long timeout) throws IllegalStateException {
-        return null;
-    }
-
-    @Override
-    public String getConfigs(String key, String group, long timeout) throws IllegalStateException {
-        return null;
-    }
-}
diff --git a/dubbo-configcenter/dubbo-configcenter-api/src/test/resources/META-INF/dubbo/internal/org.apache.dubbo.configcenter.DynamicConfigurationFactory b/dubbo-configcenter/dubbo-configcenter-api/src/test/resources/META-INF/dubbo/internal/org.apache.dubbo.configcenter.DynamicConfigurationFactory
deleted file mode 100644
index 211d45e..0000000
--- a/dubbo-configcenter/dubbo-configcenter-api/src/test/resources/META-INF/dubbo/internal/org.apache.dubbo.configcenter.DynamicConfigurationFactory
+++ /dev/null
@@ -1 +0,0 @@
-mock=org.apache.dubbo.configcenter.mock.MockDynamicConfigurationFactory
\ No newline at end of file
diff --git a/dubbo-configcenter/dubbo-configcenter-apollo/pom.xml b/dubbo-configcenter/dubbo-configcenter-apollo/pom.xml
index 26d2e88..6f3d8de 100644
--- a/dubbo-configcenter/dubbo-configcenter-apollo/pom.xml
+++ b/dubbo-configcenter/dubbo-configcenter-apollo/pom.xml
@@ -32,7 +32,7 @@
     <dependencies>
         <dependency>
             <groupId>org.apache.dubbo</groupId>
-            <artifactId>dubbo-configcenter-api</artifactId>
+            <artifactId>dubbo-common</artifactId>
             <version>${project.parent.version}</version>
         </dependency>
         <dependency>
diff --git a/dubbo-configcenter/dubbo-configcenter-apollo/src/main/java/org/apache/dubbo/configcenter/support/apollo/ApolloDynamicConfiguration.java b/dubbo-configcenter/dubbo-configcenter-apollo/src/main/java/org/apache/dubbo/configcenter/support/apollo/ApolloDynamicConfiguration.java
index f67c1e0..e092b71 100644
--- a/dubbo-configcenter/dubbo-configcenter-apollo/src/main/java/org/apache/dubbo/configcenter/support/apollo/ApolloDynamicConfiguration.java
+++ b/dubbo-configcenter/dubbo-configcenter-apollo/src/main/java/org/apache/dubbo/configcenter/support/apollo/ApolloDynamicConfiguration.java
@@ -17,13 +17,13 @@
 package org.apache.dubbo.configcenter.support.apollo;
 
 import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.config.configcenter.ConfigChangeEvent;
+import org.apache.dubbo.common.config.configcenter.ConfigChangeType;
+import org.apache.dubbo.common.config.configcenter.ConfigurationListener;
+import org.apache.dubbo.common.config.configcenter.DynamicConfiguration;
 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.configcenter.ConfigChangeEvent;
-import org.apache.dubbo.configcenter.ConfigChangeType;
-import org.apache.dubbo.configcenter.ConfigurationListener;
-import org.apache.dubbo.configcenter.DynamicConfiguration;
 
 import com.ctrip.framework.apollo.Config;
 import com.ctrip.framework.apollo.ConfigChangeListener;
@@ -42,12 +42,12 @@ import java.util.concurrent.ConcurrentMap;
 import java.util.concurrent.CopyOnWriteArraySet;
 import java.util.stream.Collectors;
 
+import static org.apache.dubbo.common.config.configcenter.Constants.CONFIG_CHECK_KEY;
+import static org.apache.dubbo.common.config.configcenter.Constants.CONFIG_CLUSTER_KEY;
+import static org.apache.dubbo.common.config.configcenter.Constants.CONFIG_NAMESPACE_KEY;
 import static org.apache.dubbo.common.constants.CommonConstants.ANYHOST_VALUE;
 import static org.apache.dubbo.common.constants.CommonConstants.APPLICATION_KEY;
 import static org.apache.dubbo.common.constants.CommonConstants.COMMA_SPLIT_PATTERN;
-import static org.apache.dubbo.configcenter.Constants.CONFIG_CHECK_KEY;
-import static org.apache.dubbo.configcenter.Constants.CONFIG_CLUSTER_KEY;
-import static org.apache.dubbo.configcenter.Constants.CONFIG_NAMESPACE_KEY;
 
 /**
  * Apollo implementation, https://github.com/ctripcorp/apollo
diff --git a/dubbo-configcenter/dubbo-configcenter-apollo/src/main/java/org/apache/dubbo/configcenter/support/apollo/ApolloDynamicConfigurationFactory.java b/dubbo-configcenter/dubbo-configcenter-apollo/src/main/java/org/apache/dubbo/configcenter/support/apollo/ApolloDynamicConfigurationFactory.java
index b7e877c..6a8ce30 100644
--- a/dubbo-configcenter/dubbo-configcenter-apollo/src/main/java/org/apache/dubbo/configcenter/support/apollo/ApolloDynamicConfigurationFactory.java
+++ b/dubbo-configcenter/dubbo-configcenter-apollo/src/main/java/org/apache/dubbo/configcenter/support/apollo/ApolloDynamicConfigurationFactory.java
@@ -17,8 +17,8 @@
 package org.apache.dubbo.configcenter.support.apollo;
 
 import org.apache.dubbo.common.URL;
-import org.apache.dubbo.configcenter.AbstractDynamicConfigurationFactory;
-import org.apache.dubbo.configcenter.DynamicConfiguration;
+import org.apache.dubbo.common.config.configcenter.AbstractDynamicConfigurationFactory;
+import org.apache.dubbo.common.config.configcenter.DynamicConfiguration;
 
 /**
  *
diff --git a/dubbo-configcenter/dubbo-configcenter-apollo/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.configcenter.DynamicConfigurationFactory b/dubbo-configcenter/dubbo-configcenter-apollo/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.config.configcenter.DynamicConfigurationFactory
similarity index 100%
rename from dubbo-configcenter/dubbo-configcenter-apollo/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.configcenter.DynamicConfigurationFactory
rename to dubbo-configcenter/dubbo-configcenter-apollo/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.config.configcenter.DynamicConfigurationFactory
diff --git a/dubbo-configcenter/dubbo-configcenter-consul/pom.xml b/dubbo-configcenter/dubbo-configcenter-consul/pom.xml
index 6f8b24f..830c6bd 100644
--- a/dubbo-configcenter/dubbo-configcenter-consul/pom.xml
+++ b/dubbo-configcenter/dubbo-configcenter-consul/pom.xml
@@ -29,7 +29,7 @@
     <dependencies>
         <dependency>
             <groupId>org.apache.dubbo</groupId>
-            <artifactId>dubbo-configcenter-api</artifactId>
+            <artifactId>dubbo-common</artifactId>
             <version>${project.parent.version}</version>
         </dependency>
         <dependency>
diff --git a/dubbo-configcenter/dubbo-configcenter-consul/src/main/java/org/apache/dubbo/configcenter/consul/ConsulDynamicConfiguration.java b/dubbo-configcenter/dubbo-configcenter-consul/src/main/java/org/apache/dubbo/configcenter/consul/ConsulDynamicConfiguration.java
index 2e67bbd..0303984 100644
--- a/dubbo-configcenter/dubbo-configcenter-consul/src/main/java/org/apache/dubbo/configcenter/consul/ConsulDynamicConfiguration.java
+++ b/dubbo-configcenter/dubbo-configcenter-consul/src/main/java/org/apache/dubbo/configcenter/consul/ConsulDynamicConfiguration.java
@@ -18,14 +18,14 @@
 package org.apache.dubbo.configcenter.consul;
 
 import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.config.configcenter.ConfigChangeEvent;
+import org.apache.dubbo.common.config.configcenter.ConfigChangeType;
+import org.apache.dubbo.common.config.configcenter.ConfigurationListener;
+import org.apache.dubbo.common.config.configcenter.DynamicConfiguration;
 import org.apache.dubbo.common.logger.Logger;
 import org.apache.dubbo.common.logger.LoggerFactory;
 import org.apache.dubbo.common.utils.NamedThreadFactory;
 import org.apache.dubbo.common.utils.StringUtils;
-import org.apache.dubbo.configcenter.ConfigChangeEvent;
-import org.apache.dubbo.configcenter.ConfigChangeType;
-import org.apache.dubbo.configcenter.ConfigurationListener;
-import org.apache.dubbo.configcenter.DynamicConfiguration;
 
 import com.ecwid.consul.v1.ConsulClient;
 import com.ecwid.consul.v1.QueryParams;
@@ -39,9 +39,9 @@ import java.util.concurrent.ConcurrentMap;
 import java.util.concurrent.ExecutorService;
 
 import static java.util.concurrent.Executors.newCachedThreadPool;
+import static org.apache.dubbo.common.config.configcenter.ConfigChangeType.ADDED;
+import static org.apache.dubbo.common.config.configcenter.Constants.CONFIG_NAMESPACE_KEY;
 import static org.apache.dubbo.common.constants.CommonConstants.PATH_SEPARATOR;
-import static org.apache.dubbo.configcenter.Constants.CONFIG_NAMESPACE_KEY;
-import static org.apache.dubbo.configcenter.ConfigChangeType.ADDED;
 
 /**
  * config center implementation for consul
diff --git a/dubbo-configcenter/dubbo-configcenter-consul/src/main/java/org/apache/dubbo/configcenter/consul/ConsulDynamicConfigurationFactory.java b/dubbo-configcenter/dubbo-configcenter-consul/src/main/java/org/apache/dubbo/configcenter/consul/ConsulDynamicConfigurationFactory.java
index 813b617..980a156 100644
--- a/dubbo-configcenter/dubbo-configcenter-consul/src/main/java/org/apache/dubbo/configcenter/consul/ConsulDynamicConfigurationFactory.java
+++ b/dubbo-configcenter/dubbo-configcenter-consul/src/main/java/org/apache/dubbo/configcenter/consul/ConsulDynamicConfigurationFactory.java
@@ -18,8 +18,8 @@
 package org.apache.dubbo.configcenter.consul;
 
 import org.apache.dubbo.common.URL;
-import org.apache.dubbo.configcenter.AbstractDynamicConfigurationFactory;
-import org.apache.dubbo.configcenter.DynamicConfiguration;
+import org.apache.dubbo.common.config.configcenter.AbstractDynamicConfigurationFactory;
+import org.apache.dubbo.common.config.configcenter.DynamicConfiguration;
 
 /**
  * Config center factory for consul
diff --git a/dubbo-configcenter/dubbo-configcenter-consul/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.configcenter.DynamicConfigurationFactory b/dubbo-configcenter/dubbo-configcenter-consul/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.config.configcenter.DynamicConfigurationFactory
similarity index 100%
rename from dubbo-configcenter/dubbo-configcenter-consul/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.configcenter.DynamicConfigurationFactory
rename to dubbo-configcenter/dubbo-configcenter-consul/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.config.configcenter.DynamicConfigurationFactory
diff --git a/dubbo-configcenter/dubbo-configcenter-etcd/pom.xml b/dubbo-configcenter/dubbo-configcenter-etcd/pom.xml
index 66d2dfa..76eaeb3 100644
--- a/dubbo-configcenter/dubbo-configcenter-etcd/pom.xml
+++ b/dubbo-configcenter/dubbo-configcenter-etcd/pom.xml
@@ -33,11 +33,6 @@
 
     <dependencies>
         <dependency>
-            <groupId>org.apache.dubbo</groupId>
-            <artifactId>dubbo-configcenter-api</artifactId>
-            <version>${project.parent.version}</version>
-        </dependency>
-        <dependency>
             <groupId>io.etcd</groupId>
             <artifactId>jetcd-launcher</artifactId>
             <scope>test</scope>
@@ -47,6 +42,12 @@
             <artifactId>testcontainers</artifactId>
             <scope>test</scope>
         </dependency>
+
+        <dependency>
+            <groupId>org.apache.dubbo</groupId>
+            <artifactId>dubbo-common</artifactId>
+            <version>${project.parent.version}</version>
+        </dependency>
         <dependency>
             <groupId>org.apache.dubbo</groupId>
             <artifactId>dubbo-remoting-etcd3</artifactId>
diff --git a/dubbo-configcenter/dubbo-configcenter-etcd/src/main/java/org/apache/dubbo/configcenter/support/etcd/EtcdDynamicConfiguration.java b/dubbo-configcenter/dubbo-configcenter-etcd/src/main/java/org/apache/dubbo/configcenter/support/etcd/EtcdDynamicConfiguration.java
index 10c50b6..6925f03 100644
--- a/dubbo-configcenter/dubbo-configcenter-etcd/src/main/java/org/apache/dubbo/configcenter/support/etcd/EtcdDynamicConfiguration.java
+++ b/dubbo-configcenter/dubbo-configcenter-etcd/src/main/java/org/apache/dubbo/configcenter/support/etcd/EtcdDynamicConfiguration.java
@@ -18,11 +18,11 @@
 package org.apache.dubbo.configcenter.support.etcd;
 
 import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.config.configcenter.ConfigChangeEvent;
+import org.apache.dubbo.common.config.configcenter.ConfigChangeType;
+import org.apache.dubbo.common.config.configcenter.ConfigurationListener;
+import org.apache.dubbo.common.config.configcenter.DynamicConfiguration;
 import org.apache.dubbo.common.utils.StringUtils;
-import org.apache.dubbo.configcenter.ConfigChangeEvent;
-import org.apache.dubbo.configcenter.ConfigChangeType;
-import org.apache.dubbo.configcenter.ConfigurationListener;
-import org.apache.dubbo.configcenter.DynamicConfiguration;
 import org.apache.dubbo.remoting.etcd.StateListener;
 import org.apache.dubbo.remoting.etcd.jetcd.JEtcdClient;
 
@@ -40,8 +40,8 @@ import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 
 import static java.nio.charset.StandardCharsets.UTF_8;
+import static org.apache.dubbo.common.config.configcenter.Constants.CONFIG_NAMESPACE_KEY;
 import static org.apache.dubbo.common.constants.CommonConstants.PATH_SEPARATOR;
-import static org.apache.dubbo.configcenter.Constants.CONFIG_NAMESPACE_KEY;
 
 /**
  * The etcd implementation of {@link DynamicConfiguration}
diff --git a/dubbo-configcenter/dubbo-configcenter-etcd/src/main/java/org/apache/dubbo/configcenter/support/etcd/EtcdDynamicConfigurationFactory.java b/dubbo-configcenter/dubbo-configcenter-etcd/src/main/java/org/apache/dubbo/configcenter/support/etcd/EtcdDynamicConfigurationFactory.java
index 02e91a6..269cee6 100644
--- a/dubbo-configcenter/dubbo-configcenter-etcd/src/main/java/org/apache/dubbo/configcenter/support/etcd/EtcdDynamicConfigurationFactory.java
+++ b/dubbo-configcenter/dubbo-configcenter-etcd/src/main/java/org/apache/dubbo/configcenter/support/etcd/EtcdDynamicConfigurationFactory.java
@@ -18,8 +18,8 @@
 package org.apache.dubbo.configcenter.support.etcd;
 
 import org.apache.dubbo.common.URL;
-import org.apache.dubbo.configcenter.AbstractDynamicConfigurationFactory;
-import org.apache.dubbo.configcenter.DynamicConfiguration;
+import org.apache.dubbo.common.config.configcenter.AbstractDynamicConfigurationFactory;
+import org.apache.dubbo.common.config.configcenter.DynamicConfiguration;
 
 /**
  * The etcd implementation of {@link AbstractDynamicConfigurationFactory}
diff --git a/dubbo-configcenter/dubbo-configcenter-etcd/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.configcenter.DynamicConfigurationFactory b/dubbo-configcenter/dubbo-configcenter-etcd/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.config.configcenter.DynamicConfigurationFactory
similarity index 100%
rename from dubbo-configcenter/dubbo-configcenter-etcd/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.configcenter.DynamicConfigurationFactory
rename to dubbo-configcenter/dubbo-configcenter-etcd/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.config.configcenter.DynamicConfigurationFactory
diff --git a/dubbo-configcenter/dubbo-configcenter-etcd/src/test/java/org/apache/dubbo/configcenter/support/etcd/EtcdDynamicConfigurationTest.java b/dubbo-configcenter/dubbo-configcenter-etcd/src/test/java/org/apache/dubbo/configcenter/support/etcd/EtcdDynamicConfigurationTest.java
index d56f3c4..8b4f739 100644
--- a/dubbo-configcenter/dubbo-configcenter-etcd/src/test/java/org/apache/dubbo/configcenter/support/etcd/EtcdDynamicConfigurationTest.java
+++ b/dubbo-configcenter/dubbo-configcenter-etcd/src/test/java/org/apache/dubbo/configcenter/support/etcd/EtcdDynamicConfigurationTest.java
@@ -18,8 +18,8 @@
 package org.apache.dubbo.configcenter.support.etcd;
 
 import org.apache.dubbo.common.URL;
-import org.apache.dubbo.configcenter.ConfigChangeEvent;
-import org.apache.dubbo.configcenter.ConfigurationListener;
+import org.apache.dubbo.common.config.configcenter.ConfigChangeEvent;
+import org.apache.dubbo.common.config.configcenter.ConfigurationListener;
 
 import io.etcd.jetcd.ByteSequence;
 import io.etcd.jetcd.Client;
diff --git a/dubbo-configcenter/dubbo-configcenter-nacos/pom.xml b/dubbo-configcenter/dubbo-configcenter-nacos/pom.xml
index bd5397c..68dc271 100644
--- a/dubbo-configcenter/dubbo-configcenter-nacos/pom.xml
+++ b/dubbo-configcenter/dubbo-configcenter-nacos/pom.xml
@@ -34,7 +34,7 @@
     <dependencies>
         <dependency>
             <groupId>org.apache.dubbo</groupId>
-            <artifactId>dubbo-configcenter-api</artifactId>
+            <artifactId>dubbo-common</artifactId>
             <version>${project.parent.version}</version>
         </dependency>
         <dependency>
diff --git a/dubbo-configcenter/dubbo-configcenter-nacos/src/main/java/org/apache/dubbo/configcenter/support/nacos/NacosDynamicConfiguration.java b/dubbo-configcenter/dubbo-configcenter-nacos/src/main/java/org/apache/dubbo/configcenter/support/nacos/NacosDynamicConfiguration.java
index 96bec25..8c827a3 100644
--- a/dubbo-configcenter/dubbo-configcenter-nacos/src/main/java/org/apache/dubbo/configcenter/support/nacos/NacosDynamicConfiguration.java
+++ b/dubbo-configcenter/dubbo-configcenter-nacos/src/main/java/org/apache/dubbo/configcenter/support/nacos/NacosDynamicConfiguration.java
@@ -18,13 +18,13 @@
 package org.apache.dubbo.configcenter.support.nacos;
 
 import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.config.configcenter.ConfigChangeEvent;
+import org.apache.dubbo.common.config.configcenter.ConfigChangeType;
+import org.apache.dubbo.common.config.configcenter.ConfigurationListener;
+import org.apache.dubbo.common.config.configcenter.DynamicConfiguration;
 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.configcenter.ConfigChangeEvent;
-import org.apache.dubbo.configcenter.ConfigChangeType;
-import org.apache.dubbo.configcenter.ConfigurationListener;
-import org.apache.dubbo.configcenter.DynamicConfiguration;
 
 import com.alibaba.nacos.api.NacosFactory;
 import com.alibaba.nacos.api.config.ConfigService;
@@ -46,9 +46,9 @@ import static com.alibaba.nacos.api.PropertyKeyConst.NAMESPACE;
 import static com.alibaba.nacos.api.PropertyKeyConst.SECRET_KEY;
 import static com.alibaba.nacos.api.PropertyKeyConst.SERVER_ADDR;
 import static com.alibaba.nacos.client.naming.utils.UtilAndComs.NACOS_NAMING_LOG_NAME;
+import static org.apache.dubbo.common.config.configcenter.Constants.CONFIG_NAMESPACE_KEY;
 import static org.apache.dubbo.common.constants.CommonConstants.GROUP_CHAR_SEPERATOR;
 import static org.apache.dubbo.common.constants.CommonConstants.PROPERTIES_CHAR_SEPERATOR;
-import static org.apache.dubbo.configcenter.Constants.CONFIG_NAMESPACE_KEY;
 import static org.apache.dubbo.common.constants.RemotingConstants.BACKUP_KEY;
 
 /**
diff --git a/dubbo-configcenter/dubbo-configcenter-nacos/src/main/java/org/apache/dubbo/configcenter/support/nacos/NacosDynamicConfigurationFactory.java b/dubbo-configcenter/dubbo-configcenter-nacos/src/main/java/org/apache/dubbo/configcenter/support/nacos/NacosDynamicConfigurationFactory.java
index 804e216..61c02b4 100644
--- a/dubbo-configcenter/dubbo-configcenter-nacos/src/main/java/org/apache/dubbo/configcenter/support/nacos/NacosDynamicConfigurationFactory.java
+++ b/dubbo-configcenter/dubbo-configcenter-nacos/src/main/java/org/apache/dubbo/configcenter/support/nacos/NacosDynamicConfigurationFactory.java
@@ -18,9 +18,9 @@
 package org.apache.dubbo.configcenter.support.nacos;
 
 import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.config.configcenter.AbstractDynamicConfigurationFactory;
+import org.apache.dubbo.common.config.configcenter.DynamicConfiguration;
 import org.apache.dubbo.common.constants.CommonConstants;
-import org.apache.dubbo.configcenter.AbstractDynamicConfigurationFactory;
-import org.apache.dubbo.configcenter.DynamicConfiguration;
 
 import com.alibaba.nacos.api.PropertyKeyConst;
 
diff --git a/dubbo-configcenter/dubbo-configcenter-nacos/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.configcenter.DynamicConfigurationFactory b/dubbo-configcenter/dubbo-configcenter-nacos/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.config.configcenter.DynamicConfigurationFactory
similarity index 100%
rename from dubbo-configcenter/dubbo-configcenter-nacos/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.configcenter.DynamicConfigurationFactory
rename to dubbo-configcenter/dubbo-configcenter-nacos/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.config.configcenter.DynamicConfigurationFactory
diff --git a/dubbo-configcenter/dubbo-configcenter-nacos/src/test/java/org/apache/dubbo/configcenter/support/nacos/NacosDynamicConfigurationTest.java b/dubbo-configcenter/dubbo-configcenter-nacos/src/test/java/org/apache/dubbo/configcenter/support/nacos/NacosDynamicConfigurationTest.java
index ff785b9..e48699c 100644
--- a/dubbo-configcenter/dubbo-configcenter-nacos/src/test/java/org/apache/dubbo/configcenter/support/nacos/NacosDynamicConfigurationTest.java
+++ b/dubbo-configcenter/dubbo-configcenter-nacos/src/test/java/org/apache/dubbo/configcenter/support/nacos/NacosDynamicConfigurationTest.java
@@ -18,8 +18,8 @@
 package org.apache.dubbo.configcenter.support.nacos;
 
 import org.apache.dubbo.common.URL;
-import org.apache.dubbo.configcenter.ConfigChangeEvent;
-import org.apache.dubbo.configcenter.ConfigurationListener;
+import org.apache.dubbo.common.config.configcenter.ConfigChangeEvent;
+import org.apache.dubbo.common.config.configcenter.ConfigurationListener;
 
 import org.junit.jupiter.api.AfterAll;
 import org.junit.jupiter.api.Assertions;
diff --git a/dubbo-configcenter/dubbo-configcenter-zookeeper/pom.xml b/dubbo-configcenter/dubbo-configcenter-zookeeper/pom.xml
index 9f028ce..54977b8 100644
--- a/dubbo-configcenter/dubbo-configcenter-zookeeper/pom.xml
+++ b/dubbo-configcenter/dubbo-configcenter-zookeeper/pom.xml
@@ -29,7 +29,7 @@
     <dependencies>
         <dependency>
             <groupId>org.apache.dubbo</groupId>
-            <artifactId>dubbo-configcenter-api</artifactId>
+            <artifactId>dubbo-common</artifactId>
             <version>${project.parent.version}</version>
         </dependency>
         <dependency>
diff --git a/dubbo-configcenter/dubbo-configcenter-zookeeper/src/main/java/org/apache/dubbo/configcenter/support/zookeeper/CacheListener.java b/dubbo-configcenter/dubbo-configcenter-zookeeper/src/main/java/org/apache/dubbo/configcenter/support/zookeeper/CacheListener.java
index 3eaa96b..baaaf8e 100644
--- a/dubbo-configcenter/dubbo-configcenter-zookeeper/src/main/java/org/apache/dubbo/configcenter/support/zookeeper/CacheListener.java
+++ b/dubbo-configcenter/dubbo-configcenter-zookeeper/src/main/java/org/apache/dubbo/configcenter/support/zookeeper/CacheListener.java
@@ -16,11 +16,11 @@
  */
 package org.apache.dubbo.configcenter.support.zookeeper;
 
+import org.apache.dubbo.common.config.configcenter.ConfigChangeEvent;
+import org.apache.dubbo.common.config.configcenter.ConfigChangeType;
+import org.apache.dubbo.common.config.configcenter.ConfigurationListener;
 import org.apache.dubbo.common.utils.CollectionUtils;
 import org.apache.dubbo.common.utils.StringUtils;
-import org.apache.dubbo.configcenter.ConfigChangeEvent;
-import org.apache.dubbo.configcenter.ConfigChangeType;
-import org.apache.dubbo.configcenter.ConfigurationListener;
 import org.apache.dubbo.remoting.zookeeper.DataListener;
 import org.apache.dubbo.remoting.zookeeper.EventType;
 
diff --git a/dubbo-configcenter/dubbo-configcenter-zookeeper/src/main/java/org/apache/dubbo/configcenter/support/zookeeper/ZookeeperDynamicConfiguration.java b/dubbo-configcenter/dubbo-configcenter-zookeeper/src/main/java/org/apache/dubbo/configcenter/support/zookeeper/ZookeeperDynamicConfiguration.java
index 5b034ca..8ee4581 100644
--- a/dubbo-configcenter/dubbo-configcenter-zookeeper/src/main/java/org/apache/dubbo/configcenter/support/zookeeper/ZookeeperDynamicConfiguration.java
+++ b/dubbo-configcenter/dubbo-configcenter-zookeeper/src/main/java/org/apache/dubbo/configcenter/support/zookeeper/ZookeeperDynamicConfiguration.java
@@ -17,10 +17,10 @@
 package org.apache.dubbo.configcenter.support.zookeeper;
 
 import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.config.configcenter.ConfigurationListener;
+import org.apache.dubbo.common.config.configcenter.DynamicConfiguration;
 import org.apache.dubbo.common.utils.NamedThreadFactory;
 import org.apache.dubbo.common.utils.StringUtils;
-import org.apache.dubbo.configcenter.ConfigurationListener;
-import org.apache.dubbo.configcenter.DynamicConfiguration;
 import org.apache.dubbo.remoting.zookeeper.ZookeeperClient;
 import org.apache.dubbo.remoting.zookeeper.ZookeeperTransporter;
 
@@ -36,8 +36,8 @@ import java.util.concurrent.Executors;
 
 import static java.util.Collections.emptySortedSet;
 import static java.util.Collections.unmodifiableSortedSet;
+import static org.apache.dubbo.common.config.configcenter.Constants.CONFIG_NAMESPACE_KEY;
 import static org.apache.dubbo.common.utils.CollectionUtils.isEmpty;
-import static org.apache.dubbo.configcenter.Constants.CONFIG_NAMESPACE_KEY;
 
 /**
  *
diff --git a/dubbo-configcenter/dubbo-configcenter-zookeeper/src/main/java/org/apache/dubbo/configcenter/support/zookeeper/ZookeeperDynamicConfigurationFactory.java b/dubbo-configcenter/dubbo-configcenter-zookeeper/src/main/java/org/apache/dubbo/configcenter/support/zookeeper/ZookeeperDynamicConfigurationFactory.java
index 4d78133..0eb307c 100644
--- a/dubbo-configcenter/dubbo-configcenter-zookeeper/src/main/java/org/apache/dubbo/configcenter/support/zookeeper/ZookeeperDynamicConfigurationFactory.java
+++ b/dubbo-configcenter/dubbo-configcenter-zookeeper/src/main/java/org/apache/dubbo/configcenter/support/zookeeper/ZookeeperDynamicConfigurationFactory.java
@@ -17,8 +17,8 @@
 package org.apache.dubbo.configcenter.support.zookeeper;
 
 import org.apache.dubbo.common.URL;
-import org.apache.dubbo.configcenter.AbstractDynamicConfigurationFactory;
-import org.apache.dubbo.configcenter.DynamicConfiguration;
+import org.apache.dubbo.common.config.configcenter.AbstractDynamicConfigurationFactory;
+import org.apache.dubbo.common.config.configcenter.DynamicConfiguration;
 import org.apache.dubbo.remoting.zookeeper.ZookeeperTransporter;
 
 /**
diff --git a/dubbo-configcenter/dubbo-configcenter-zookeeper/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.configcenter.DynamicConfigurationFactory b/dubbo-configcenter/dubbo-configcenter-zookeeper/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.config.configcenter.DynamicConfigurationFactory
similarity index 100%
rename from dubbo-configcenter/dubbo-configcenter-zookeeper/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.configcenter.DynamicConfigurationFactory
rename to dubbo-configcenter/dubbo-configcenter-zookeeper/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.config.configcenter.DynamicConfigurationFactory
diff --git a/dubbo-configcenter/dubbo-configcenter-zookeeper/src/test/java/org/apache/dubbo/configcenter/support/zookeeper/ZookeeperDynamicConfigurationTest.java b/dubbo-configcenter/dubbo-configcenter-zookeeper/src/test/java/org/apache/dubbo/configcenter/support/zookeeper/ZookeeperDynamicConfigurationTest.java
index df440ac..c9fb747 100644
--- a/dubbo-configcenter/dubbo-configcenter-zookeeper/src/test/java/org/apache/dubbo/configcenter/support/zookeeper/ZookeeperDynamicConfigurationTest.java
+++ b/dubbo-configcenter/dubbo-configcenter-zookeeper/src/test/java/org/apache/dubbo/configcenter/support/zookeeper/ZookeeperDynamicConfigurationTest.java
@@ -17,12 +17,12 @@
 package org.apache.dubbo.configcenter.support.zookeeper;
 
 import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.config.configcenter.ConfigChangeEvent;
+import org.apache.dubbo.common.config.configcenter.ConfigurationListener;
+import org.apache.dubbo.common.config.configcenter.DynamicConfiguration;
+import org.apache.dubbo.common.config.configcenter.DynamicConfigurationFactory;
 import org.apache.dubbo.common.extension.ExtensionLoader;
 import org.apache.dubbo.common.utils.NetUtils;
-import org.apache.dubbo.configcenter.ConfigChangeEvent;
-import org.apache.dubbo.configcenter.ConfigurationListener;
-import org.apache.dubbo.configcenter.DynamicConfiguration;
-import org.apache.dubbo.configcenter.DynamicConfigurationFactory;
 
 import org.apache.curator.framework.CuratorFramework;
 import org.apache.curator.framework.CuratorFrameworkFactory;
diff --git a/dubbo-configcenter/pom.xml b/dubbo-configcenter/pom.xml
index 0de20d3..312fc3c 100644
--- a/dubbo-configcenter/pom.xml
+++ b/dubbo-configcenter/pom.xml
@@ -30,7 +30,6 @@
     </properties>
 
     <modules>
-        <module>dubbo-configcenter-api</module>
         <module>dubbo-configcenter-zookeeper</module>
         <module>dubbo-configcenter-apollo</module>
         <module>dubbo-configcenter-consul</module>
diff --git a/dubbo-container/dubbo-container-log4j/pom.xml b/dubbo-container/dubbo-container-log4j/pom.xml
index a83b661..d4503df 100644
--- a/dubbo-container/dubbo-container-log4j/pom.xml
+++ b/dubbo-container/dubbo-container-log4j/pom.xml
@@ -34,10 +34,5 @@
             <artifactId>dubbo-container-api</artifactId>
             <version>${project.parent.version}</version>
         </dependency>
-        <dependency>
-            <groupId>org.apache.dubbo</groupId>
-            <artifactId>dubbo-configcenter-api</artifactId>
-            <version>${project.parent.version}</version>
-        </dependency>
     </dependencies>
 </project>
\ No newline at end of file
diff --git a/dubbo-demo/dubbo-demo-api/dubbo-demo-api-consumer/pom.xml b/dubbo-demo/dubbo-demo-api/dubbo-demo-api-consumer/pom.xml
index f668a85..e273e31 100644
--- a/dubbo-demo/dubbo-demo-api/dubbo-demo-api-consumer/pom.xml
+++ b/dubbo-demo/dubbo-demo-api/dubbo-demo-api-consumer/pom.xml
@@ -35,6 +35,11 @@
     <dependencies>
         <dependency>
             <groupId>org.apache.dubbo</groupId>
+            <artifactId>dubbo-config-api</artifactId>
+            <version>${project.parent.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.dubbo</groupId>
             <artifactId>dubbo-demo-interface</artifactId>
             <version>${project.parent.version}</version>
         </dependency>
diff --git a/dubbo-demo/dubbo-demo-api/dubbo-demo-api-provider/pom.xml b/dubbo-demo/dubbo-demo-api/dubbo-demo-api-provider/pom.xml
index ff5d9ce..04a2ae2 100644
--- a/dubbo-demo/dubbo-demo-api/dubbo-demo-api-provider/pom.xml
+++ b/dubbo-demo/dubbo-demo-api/dubbo-demo-api-provider/pom.xml
@@ -37,6 +37,11 @@
     <dependencies>
         <dependency>
             <groupId>org.apache.dubbo</groupId>
+            <artifactId>dubbo-config-api</artifactId>
+            <version>${project.parent.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.dubbo</groupId>
             <artifactId>dubbo-demo-interface</artifactId>
             <version>${project.parent.version}</version>
         </dependency>
diff --git a/dubbo-metadata-report/dubbo-metadata-definition/pom.xml b/dubbo-metadata-report/dubbo-metadata-definition/pom.xml
deleted file mode 100644
index 093c7e2..0000000
--- a/dubbo-metadata-report/dubbo-metadata-definition/pom.xml
+++ /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.
-  -->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-    <parent>
-        <artifactId>dubbo-metadata-report</artifactId>
-        <groupId>org.apache.dubbo</groupId>
-        <version>${revision}</version>
-    </parent>
-    <modelVersion>4.0.0</modelVersion>
-    <artifactId>dubbo-metadata-definition</artifactId>
-
-
-    <dependencies>
-        <dependency>
-            <groupId>com.google.code.gson</groupId>
-            <artifactId>gson</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.dubbo</groupId>
-            <artifactId>dubbo-common</artifactId>
-            <version>${project.parent.version}</version>
-        </dependency>
-    </dependencies>
-</project>
diff --git a/dubbo-metadata-report/dubbo-metadata-report-api/src/test/resources/META-INF/dubbo/internal/org.apache.dubbo.metadata.store.MetadataReportFactory b/dubbo-metadata-report/dubbo-metadata-report-api/src/test/resources/META-INF/dubbo/internal/org.apache.dubbo.metadata.store.MetadataReportFactory
deleted file mode 100644
index bf84023..0000000
--- a/dubbo-metadata-report/dubbo-metadata-report-api/src/test/resources/META-INF/dubbo/internal/org.apache.dubbo.metadata.store.MetadataReportFactory
+++ /dev/null
@@ -1 +0,0 @@
-JTest=org.apache.dubbo.metadata.store.test.JTestMetadataReportFactory4Test
diff --git a/dubbo-metadata-report/dubbo-metadata-report-api/pom.xml b/dubbo-metadata/dubbo-metadata-api/pom.xml
similarity index 60%
rename from dubbo-metadata-report/dubbo-metadata-report-api/pom.xml
rename to dubbo-metadata/dubbo-metadata-api/pom.xml
index b892598..3f5665a 100644
--- a/dubbo-metadata-report/dubbo-metadata-report-api/pom.xml
+++ b/dubbo-metadata/dubbo-metadata-api/pom.xml
@@ -14,57 +14,55 @@
   See the License for the specific language governing permissions and
   limitations under the License.
   -->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     <parent>
-        <artifactId>dubbo-metadata-report</artifactId>
         <groupId>org.apache.dubbo</groupId>
+        <artifactId>dubbo-metadata</artifactId>
         <version>${revision}</version>
+        <relativePath>../pom.xml</relativePath>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
-    <artifactId>dubbo-metadata-report-api</artifactId>
+    <artifactId>dubbo-metadata-api</artifactId>
     <packaging>jar</packaging>
 
-    <properties>
-        <skip_maven_deploy>false</skip_maven_deploy>
-    </properties>
+    <name>dubbo-metadata-api</name>
+    <description>The metadata module of Dubbo project</description>
+
     <dependencies>
         <dependency>
             <groupId>org.apache.dubbo</groupId>
-            <artifactId>dubbo-cluster</artifactId>
+            <artifactId>dubbo-rpc-api</artifactId>
             <version>${project.parent.version}</version>
+            <optional>true</optional>
         </dependency>
+
         <dependency>
             <groupId>org.apache.dubbo</groupId>
-            <artifactId>dubbo-common</artifactId>
+            <artifactId>dubbo-cluster</artifactId>
             <version>${project.parent.version}</version>
         </dependency>
         <dependency>
-            <groupId>org.apache.dubbo</groupId>
-            <artifactId>dubbo-container-api</artifactId>
-            <version>${project.parent.version}</version>
-            <exclusions>
-                <exclusion>
-                    <groupId>org.mortbay.jetty</groupId>
-                    <artifactId>jetty</artifactId>
-                </exclusion>
-            </exclusions>
+            <groupId>com.google.code.gson</groupId>
+            <artifactId>gson</artifactId>
         </dependency>
 
+        <!-- Test dependencies -->
         <dependency>
             <groupId>org.apache.dubbo</groupId>
-            <artifactId>dubbo-remoting-zookeeper</artifactId>
+            <artifactId>dubbo-configcenter-zookeeper</artifactId>
             <version>${project.parent.version}</version>
             <scope>test</scope>
         </dependency>
+
         <dependency>
-            <groupId>org.apache.dubbo</groupId>
-            <artifactId>dubbo-metadata-definition</artifactId>
-            <version>${project.parent.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>com.google.code.gson</groupId>
-            <artifactId>gson</artifactId>
+            <groupId>org.apache.curator</groupId>
+            <artifactId>curator-test</artifactId>
+            <scope>test</scope>
         </dependency>
+
     </dependencies>
-</project>
+
+</project>
\ No newline at end of file
diff --git a/dubbo-metadata/src/main/java/org/apache/dubbo/metadata/DynamicConfigurationServiceNameMapping.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/DynamicConfigurationServiceNameMapping.java
similarity index 98%
rename from dubbo-metadata/src/main/java/org/apache/dubbo/metadata/DynamicConfigurationServiceNameMapping.java
rename to dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/DynamicConfigurationServiceNameMapping.java
index f535a51..287ba73 100644
--- a/dubbo-metadata/src/main/java/org/apache/dubbo/metadata/DynamicConfigurationServiceNameMapping.java
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/DynamicConfigurationServiceNameMapping.java
@@ -16,9 +16,9 @@
  */
 package org.apache.dubbo.metadata;
 
+import org.apache.dubbo.common.config.configcenter.DynamicConfiguration;
 import org.apache.dubbo.common.logger.Logger;
 import org.apache.dubbo.common.logger.LoggerFactory;
-import org.apache.dubbo.configcenter.DynamicConfiguration;
 import org.apache.dubbo.rpc.model.ApplicationModel;
 
 import java.util.Collections;
diff --git a/dubbo-metadata/src/main/java/org/apache/dubbo/metadata/MetadataService.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/MetadataService.java
similarity index 95%
rename from dubbo-metadata/src/main/java/org/apache/dubbo/metadata/MetadataService.java
rename to dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/MetadataService.java
index f73d5f6..7dba967 100644
--- a/dubbo-metadata/src/main/java/org/apache/dubbo/metadata/MetadataService.java
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/MetadataService.java
@@ -32,7 +32,7 @@ import static java.util.stream.StreamSupport.stream;
  * {@link #getExportedURLs()} and {@link #getSubscribedURLs()} respectively. What's more, {@link MetadataService}
  * also providers the fine-grain methods for the precise queries.
  *
- * @see LocalMetadataService
+ * @see WritableMetadataService
  * @since 2.7.3
  */
 public interface MetadataService {
@@ -136,6 +136,17 @@ public interface MetadataService {
      */
     List<String> getExportedURLs(String serviceInterface, String group, String version, String protocol);
 
+    /**
+     * Interface definition.
+     * @return
+     */
+    String getServiceDefinition(String interfaceName, String version, String group);
+
+    /**
+     * Interface definition.
+     * @return
+     */
+    String getServiceDefinition(String serviceKey);
 
     /**
      * Convert the multiple {@link URL urls} to a {@link List list} of {@link URL urls}
diff --git a/dubbo-metadata/src/main/java/org/apache/dubbo/metadata/MetadataServiceExporter.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/MetadataServiceExporter.java
similarity index 100%
rename from dubbo-metadata/src/main/java/org/apache/dubbo/metadata/MetadataServiceExporter.java
rename to dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/MetadataServiceExporter.java
diff --git a/dubbo-metadata/src/main/java/org/apache/dubbo/metadata/ServiceNameMapping.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/ServiceNameMapping.java
similarity index 100%
rename from dubbo-metadata/src/main/java/org/apache/dubbo/metadata/ServiceNameMapping.java
rename to dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/ServiceNameMapping.java
diff --git a/dubbo-metadata/src/main/java/org/apache/dubbo/metadata/LocalMetadataService.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/WritableMetadataService.java
similarity index 79%
rename from dubbo-metadata/src/main/java/org/apache/dubbo/metadata/LocalMetadataService.java
rename to dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/WritableMetadataService.java
index 1724095..27f75a1 100644
--- a/dubbo-metadata/src/main/java/org/apache/dubbo/metadata/LocalMetadataService.java
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/WritableMetadataService.java
@@ -19,6 +19,7 @@ package org.apache.dubbo.metadata;
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.extension.ExtensionLoader;
 import org.apache.dubbo.common.extension.SPI;
+import org.apache.dubbo.metadata.store.InMemoryWritableMetadataService;
 import org.apache.dubbo.rpc.model.ApplicationModel;
 
 import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoader;
@@ -29,8 +30,8 @@ import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoad
  *
  * @since 2.7.3
  */
-@SPI("default")
-public interface LocalMetadataService extends MetadataService {
+@SPI("local")
+public interface WritableMetadataService extends MetadataService {
 
     /**
      * Gets the current Dubbo Service name
@@ -74,15 +75,20 @@ public interface LocalMetadataService extends MetadataService {
      */
     boolean unsubscribeURL(URL url);
 
+    void publishServiceDefinition(URL providerUrl);
 
     /**
-     * Get {@link ExtensionLoader#getDefaultExtension() the defautl extension} of {@link LocalMetadataService}
+     * Get {@link ExtensionLoader#getDefaultExtension() the defautl extension} of {@link WritableMetadataService}
      *
      * @return non-null
-     * @see InMemoryLocalMetadataService
+     * @see InMemoryWritableMetadataService
      */
-    public static LocalMetadataService getDefaultExtension() {
-        return getExtensionLoader(LocalMetadataService.class).getDefaultExtension();
+    static WritableMetadataService getDefaultExtension() {
+        return getExtensionLoader(WritableMetadataService.class).getDefaultExtension();
+    }
+
+    static WritableMetadataService getExtension(String name) {
+        return getExtensionLoader(WritableMetadataService.class).getExtension(name);
     }
 
 }
diff --git a/dubbo-metadata-report/dubbo-metadata-definition/src/main/java/org/apache/dubbo/metadata/definition/ServiceDefinitionBuilder.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/definition/ServiceDefinitionBuilder.java
similarity index 100%
rename from dubbo-metadata-report/dubbo-metadata-definition/src/main/java/org/apache/dubbo/metadata/definition/ServiceDefinitionBuilder.java
rename to dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/definition/ServiceDefinitionBuilder.java
diff --git a/dubbo-metadata-report/dubbo-metadata-definition/src/main/java/org/apache/dubbo/metadata/definition/TypeDefinitionBuilder.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/definition/TypeDefinitionBuilder.java
similarity index 100%
rename from dubbo-metadata-report/dubbo-metadata-definition/src/main/java/org/apache/dubbo/metadata/definition/TypeDefinitionBuilder.java
rename to dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/definition/TypeDefinitionBuilder.java
diff --git a/dubbo-metadata-report/dubbo-metadata-definition/src/main/java/org/apache/dubbo/metadata/definition/builder/ArrayTypeBuilder.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/definition/builder/ArrayTypeBuilder.java
similarity index 100%
rename from dubbo-metadata-report/dubbo-metadata-definition/src/main/java/org/apache/dubbo/metadata/definition/builder/ArrayTypeBuilder.java
rename to dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/definition/builder/ArrayTypeBuilder.java
diff --git a/dubbo-metadata-report/dubbo-metadata-definition/src/main/java/org/apache/dubbo/metadata/definition/builder/CollectionTypeBuilder.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/definition/builder/CollectionTypeBuilder.java
similarity index 100%
rename from dubbo-metadata-report/dubbo-metadata-definition/src/main/java/org/apache/dubbo/metadata/definition/builder/CollectionTypeBuilder.java
rename to dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/definition/builder/CollectionTypeBuilder.java
diff --git a/dubbo-metadata-report/dubbo-metadata-definition/src/main/java/org/apache/dubbo/metadata/definition/builder/DefaultTypeBuilder.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/definition/builder/DefaultTypeBuilder.java
similarity index 100%
rename from dubbo-metadata-report/dubbo-metadata-definition/src/main/java/org/apache/dubbo/metadata/definition/builder/DefaultTypeBuilder.java
rename to dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/definition/builder/DefaultTypeBuilder.java
diff --git a/dubbo-metadata-report/dubbo-metadata-definition/src/main/java/org/apache/dubbo/metadata/definition/builder/EnumTypeBuilder.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/definition/builder/EnumTypeBuilder.java
similarity index 100%
rename from dubbo-metadata-report/dubbo-metadata-definition/src/main/java/org/apache/dubbo/metadata/definition/builder/EnumTypeBuilder.java
rename to dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/definition/builder/EnumTypeBuilder.java
diff --git a/dubbo-metadata-report/dubbo-metadata-definition/src/main/java/org/apache/dubbo/metadata/definition/builder/MapTypeBuilder.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/definition/builder/MapTypeBuilder.java
similarity index 100%
rename from dubbo-metadata-report/dubbo-metadata-definition/src/main/java/org/apache/dubbo/metadata/definition/builder/MapTypeBuilder.java
rename to dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/definition/builder/MapTypeBuilder.java
diff --git a/dubbo-metadata-report/dubbo-metadata-definition/src/main/java/org/apache/dubbo/metadata/definition/builder/TypeBuilder.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/definition/builder/TypeBuilder.java
similarity index 100%
rename from dubbo-metadata-report/dubbo-metadata-definition/src/main/java/org/apache/dubbo/metadata/definition/builder/TypeBuilder.java
rename to dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/definition/builder/TypeBuilder.java
diff --git a/dubbo-metadata-report/dubbo-metadata-definition/src/main/java/org/apache/dubbo/metadata/definition/model/FullServiceDefinition.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/definition/model/FullServiceDefinition.java
similarity index 100%
rename from dubbo-metadata-report/dubbo-metadata-definition/src/main/java/org/apache/dubbo/metadata/definition/model/FullServiceDefinition.java
rename to dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/definition/model/FullServiceDefinition.java
diff --git a/dubbo-metadata-report/dubbo-metadata-definition/src/main/java/org/apache/dubbo/metadata/definition/model/MethodDefinition.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/definition/model/MethodDefinition.java
similarity index 97%
rename from dubbo-metadata-report/dubbo-metadata-definition/src/main/java/org/apache/dubbo/metadata/definition/model/MethodDefinition.java
rename to dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/definition/model/MethodDefinition.java
index 41ebda5..3635621 100755
--- a/dubbo-metadata-report/dubbo-metadata-definition/src/main/java/org/apache/dubbo/metadata/definition/model/MethodDefinition.java
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/definition/model/MethodDefinition.java
@@ -16,6 +16,7 @@
  */
 package org.apache.dubbo.metadata.definition.model;
 
+import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
@@ -24,7 +25,7 @@ import java.util.Objects;
 /**
  * 2015/1/27.
  */
-public class MethodDefinition {
+public class MethodDefinition implements Serializable {
 
     private String name;
     private String[] parameterTypes;
diff --git a/dubbo-metadata-report/dubbo-metadata-definition/src/main/java/org/apache/dubbo/metadata/definition/model/ServiceDefinition.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/definition/model/ServiceDefinition.java
similarity index 97%
rename from dubbo-metadata-report/dubbo-metadata-definition/src/main/java/org/apache/dubbo/metadata/definition/model/ServiceDefinition.java
rename to dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/definition/model/ServiceDefinition.java
index ebc586d..8b202df 100755
--- a/dubbo-metadata-report/dubbo-metadata-definition/src/main/java/org/apache/dubbo/metadata/definition/model/ServiceDefinition.java
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/definition/model/ServiceDefinition.java
@@ -16,6 +16,7 @@
  */
 package org.apache.dubbo.metadata.definition.model;
 
+import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Objects;
@@ -23,7 +24,7 @@ import java.util.Objects;
 /**
  * 2015/1/27.
  */
-public class ServiceDefinition {
+public class ServiceDefinition implements Serializable {
 
     private String canonicalName;
     private String codeSource;
diff --git a/dubbo-metadata-report/dubbo-metadata-definition/src/main/java/org/apache/dubbo/metadata/definition/model/TypeDefinition.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/definition/model/TypeDefinition.java
similarity index 97%
rename from dubbo-metadata-report/dubbo-metadata-definition/src/main/java/org/apache/dubbo/metadata/definition/model/TypeDefinition.java
rename to dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/definition/model/TypeDefinition.java
index bb434dc..4ae4f46 100755
--- a/dubbo-metadata-report/dubbo-metadata-definition/src/main/java/org/apache/dubbo/metadata/definition/model/TypeDefinition.java
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/definition/model/TypeDefinition.java
@@ -18,6 +18,7 @@ package org.apache.dubbo.metadata.definition.model;
 
 import com.google.gson.annotations.SerializedName;
 
+import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
@@ -27,7 +28,7 @@ import java.util.Objects;
 /**
  * 2015/1/27.
  */
-public class TypeDefinition {
+public class TypeDefinition implements Serializable {
 
     private String id;
     private String type;
diff --git a/dubbo-metadata-report/dubbo-metadata-definition/src/main/java/org/apache/dubbo/metadata/definition/util/ClassUtils.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/definition/util/ClassUtils.java
similarity index 100%
rename from dubbo-metadata-report/dubbo-metadata-definition/src/main/java/org/apache/dubbo/metadata/definition/util/ClassUtils.java
rename to dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/definition/util/ClassUtils.java
diff --git a/dubbo-metadata-report/dubbo-metadata-definition/src/main/java/org/apache/dubbo/metadata/definition/util/JaketConfigurationUtils.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/definition/util/JaketConfigurationUtils.java
similarity index 100%
rename from dubbo-metadata-report/dubbo-metadata-definition/src/main/java/org/apache/dubbo/metadata/definition/util/JaketConfigurationUtils.java
rename to dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/definition/util/JaketConfigurationUtils.java
diff --git a/dubbo-metadata-report/dubbo-metadata-report-api/src/main/java/org/apache/dubbo/metadata/store/MetadataReport.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/MetadataReport.java
similarity index 65%
rename from dubbo-metadata-report/dubbo-metadata-report-api/src/main/java/org/apache/dubbo/metadata/store/MetadataReport.java
rename to dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/MetadataReport.java
index 1afcc83..ab6f7a8 100644
--- a/dubbo-metadata-report/dubbo-metadata-report-api/src/main/java/org/apache/dubbo/metadata/store/MetadataReport.java
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/MetadataReport.java
@@ -14,20 +14,31 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.metadata.store;
+package org.apache.dubbo.metadata.report;
 
 
-import org.apache.dubbo.metadata.definition.model.FullServiceDefinition;
-import org.apache.dubbo.metadata.identifier.MetadataIdentifier;
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.metadata.definition.model.ServiceDefinition;
+import org.apache.dubbo.metadata.report.identifier.MetadataIdentifier;
 
+import java.util.List;
 import java.util.Map;
 
 /**
  */
 public interface MetadataReport {
 
-    void storeProviderMetadata(MetadataIdentifier providerMetadataIdentifier, FullServiceDefinition serviceDefinition);
+    void storeProviderMetadata(MetadataIdentifier providerMetadataIdentifier, ServiceDefinition serviceDefinition);
 
     void storeConsumerMetadata(MetadataIdentifier consumerMetadataIdentifier, Map<String, String> serviceParameterMap);
 
+    void saveMetadata(URL url);
+
+    void removeMetadata(URL url);
+
+    List<String> getExportedURLs(MetadataIdentifier metadataIdentifier);
+
+    List<String> getSubscribedURLs();
+
+    String getServiceDefinition(MetadataIdentifier consumerMetadataIdentifier);
 }
diff --git a/dubbo-metadata-report/dubbo-metadata-report-api/src/main/java/org/apache/dubbo/metadata/store/MetadataReportFactory.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/MetadataReportFactory.java
similarity index 96%
rename from dubbo-metadata-report/dubbo-metadata-report-api/src/main/java/org/apache/dubbo/metadata/store/MetadataReportFactory.java
rename to dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/MetadataReportFactory.java
index 7f42da7..1414c8b 100644
--- a/dubbo-metadata-report/dubbo-metadata-report-api/src/main/java/org/apache/dubbo/metadata/store/MetadataReportFactory.java
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/MetadataReportFactory.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.metadata.store;
+package org.apache.dubbo.metadata.report;
 
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.extension.Adaptive;
diff --git a/dubbo-metadata-report/dubbo-metadata-report-api/src/main/java/org/apache/dubbo/metadata/identifier/MetadataIdentifier.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/identifier/MetadataIdentifier.java
similarity index 82%
rename from dubbo-metadata-report/dubbo-metadata-report-api/src/main/java/org/apache/dubbo/metadata/identifier/MetadataIdentifier.java
rename to dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/identifier/MetadataIdentifier.java
index f9b7e4c..7ffa2a9 100644
--- a/dubbo-metadata-report/dubbo-metadata-report-api/src/main/java/org/apache/dubbo/metadata/identifier/MetadataIdentifier.java
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/identifier/MetadataIdentifier.java
@@ -14,9 +14,10 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.metadata.identifier;
+package org.apache.dubbo.metadata.report.identifier;
 
 import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.utils.StringUtils;
 
 import static org.apache.dubbo.common.constants.CommonConstants.ANY_VALUE;
 import static org.apache.dubbo.common.constants.CommonConstants.APPLICATION_KEY;
@@ -67,7 +68,11 @@ public class MetadataIdentifier {
     }
 
     public String getIdentifierKey() {
-        return serviceInterface + SEPARATOR + (version == null ? "" : version + SEPARATOR) + (group == null ? "" : group + SEPARATOR) + side + SEPARATOR + application;
+        return serviceInterface
+                + (version == null ? "" : (SEPARATOR + version))
+                + (group == null ? "" : (SEPARATOR + version))
+                + (side == null ? "" : (SEPARATOR + side))
+                + (getApplication() == null ? "" : (SEPARATOR + getApplication()));
     }
 
     private String getFilePathKey() {
@@ -75,8 +80,12 @@ public class MetadataIdentifier {
     }
 
     private String getFilePathKey(String pathTag) {
-        return pathTag + PATH_SEPARATOR + toServicePath() + PATH_SEPARATOR + (version == null ? "" : (version + PATH_SEPARATOR))
-                + (group == null ? "" : (group + PATH_SEPARATOR)) + side + PATH_SEPARATOR + getApplication();
+        return pathTag
+                + (StringUtils.isEmpty(toServicePath()) ? "" : (PATH_SEPARATOR + toServicePath()))
+                + (version == null ? "" : (PATH_SEPARATOR + version))
+                + (group == null ? "" : (PATH_SEPARATOR + group))
+                + (side == null ? "" : (PATH_SEPARATOR + side))
+                + (getApplication() == null ? "" : (PATH_SEPARATOR + getApplication()));
     }
 
     private String toServicePath() {
diff --git a/dubbo-metadata-report/dubbo-metadata-report-api/src/main/java/org/apache/dubbo/metadata/support/AbstractMetadataReport.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/support/AbstractMetadataReport.java
similarity index 88%
rename from dubbo-metadata-report/dubbo-metadata-report-api/src/main/java/org/apache/dubbo/metadata/support/AbstractMetadataReport.java
rename to dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/support/AbstractMetadataReport.java
index 1208508..a64c887 100644
--- a/dubbo-metadata-report/dubbo-metadata-report-api/src/main/java/org/apache/dubbo/metadata/support/AbstractMetadataReport.java
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/support/AbstractMetadataReport.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.metadata.support;
+package org.apache.dubbo.metadata.report.support;
 
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.logger.Logger;
@@ -22,8 +22,9 @@ import org.apache.dubbo.common.logger.LoggerFactory;
 import org.apache.dubbo.common.utils.ConfigUtils;
 import org.apache.dubbo.common.utils.NamedThreadFactory;
 import org.apache.dubbo.metadata.definition.model.FullServiceDefinition;
-import org.apache.dubbo.metadata.identifier.MetadataIdentifier;
-import org.apache.dubbo.metadata.store.MetadataReport;
+import org.apache.dubbo.metadata.definition.model.ServiceDefinition;
+import org.apache.dubbo.metadata.report.MetadataReport;
+import org.apache.dubbo.metadata.report.identifier.MetadataIdentifier;
 
 import com.google.gson.Gson;
 
@@ -37,6 +38,7 @@ import java.nio.channels.FileChannel;
 import java.nio.channels.FileLock;
 import java.util.Calendar;
 import java.util.Iterator;
+import java.util.List;
 import java.util.Map;
 import java.util.Properties;
 import java.util.concurrent.ConcurrentHashMap;
@@ -55,13 +57,13 @@ import static org.apache.dubbo.common.constants.CommonConstants.CONSUMER_SIDE;
 import static org.apache.dubbo.common.constants.CommonConstants.FILE_KEY;
 import static org.apache.dubbo.common.constants.CommonConstants.PROVIDER_SIDE;
 import static org.apache.dubbo.common.constants.CommonConstants.SIDE_KEY;
-import static org.apache.dubbo.metadata.support.Constants.CYCLE_REPORT_KEY;
-import static org.apache.dubbo.metadata.support.Constants.DEFAULT_METADATA_REPORT_CYCLE_REPORT;
-import static org.apache.dubbo.metadata.support.Constants.DEFAULT_METADATA_REPORT_RETRY_PERIOD;
-import static org.apache.dubbo.metadata.support.Constants.DEFAULT_METADATA_REPORT_RETRY_TIMES;
-import static org.apache.dubbo.metadata.support.Constants.RETRY_PERIOD_KEY;
-import static org.apache.dubbo.metadata.support.Constants.RETRY_TIMES_KEY;
-import static org.apache.dubbo.metadata.support.Constants.SYNC_REPORT_KEY;
+import static org.apache.dubbo.metadata.report.support.Constants.CYCLE_REPORT_KEY;
+import static org.apache.dubbo.metadata.report.support.Constants.DEFAULT_METADATA_REPORT_CYCLE_REPORT;
+import static org.apache.dubbo.metadata.report.support.Constants.DEFAULT_METADATA_REPORT_RETRY_PERIOD;
+import static org.apache.dubbo.metadata.report.support.Constants.DEFAULT_METADATA_REPORT_RETRY_TIMES;
+import static org.apache.dubbo.metadata.report.support.Constants.RETRY_PERIOD_KEY;
+import static org.apache.dubbo.metadata.report.support.Constants.RETRY_TIMES_KEY;
+import static org.apache.dubbo.metadata.report.support.Constants.SYNC_REPORT_KEY;
 
 /**
  *
@@ -225,7 +227,7 @@ public abstract class AbstractMetadataReport implements MetadataReport {
     }
 
     @Override
-    public void storeProviderMetadata(MetadataIdentifier providerMetadataIdentifier, FullServiceDefinition serviceDefinition) {
+    public void storeProviderMetadata(MetadataIdentifier providerMetadataIdentifier, ServiceDefinition serviceDefinition) {
         if (syncReport) {
             storeProviderMetadataTask(providerMetadataIdentifier, serviceDefinition);
         } else {
@@ -233,7 +235,7 @@ public abstract class AbstractMetadataReport implements MetadataReport {
         }
     }
 
-    private void storeProviderMetadataTask(MetadataIdentifier providerMetadataIdentifier, FullServiceDefinition serviceDefinition) {
+    private void storeProviderMetadataTask(MetadataIdentifier providerMetadataIdentifier, ServiceDefinition serviceDefinition) {
         try {
             if (logger.isInfoEnabled()) {
                 logger.info("store provider metadata. Identifier : " + providerMetadataIdentifier + "; definition: " + serviceDefinition);
@@ -281,6 +283,35 @@ public abstract class AbstractMetadataReport implements MetadataReport {
         }
     }
 
+    @Override
+    public void saveMetadata(URL url) {
+        if (syncReport) {
+            doSaveMetadata(url);
+        } else {
+            reportCacheExecutor.execute(() -> doSaveMetadata(url));
+        }
+    }
+
+    @Override
+    public void removeMetadata(URL url) {
+        if (syncReport) {
+            doRemoveMetadata(url);
+        } else {
+            reportCacheExecutor.execute(() -> doRemoveMetadata(url));
+        }
+    }
+
+    @Override
+    public List<String> getExportedURLs(MetadataIdentifier metadataIdentifier) {
+        // TODO, fallback to local cache
+        return doGetExportedURLs();
+    }
+
+    @Override
+    public List<String> getSubscribedURLs() {
+        // TODO, fallback to local cache
+        return doGetSubscribedURLs();
+    }
 
     String getProtocol(URL url) {
         String protocol = url.getParameter(SIDE_KEY);
@@ -391,4 +422,12 @@ public abstract class AbstractMetadataReport implements MetadataReport {
 
     protected abstract void doStoreConsumerMetadata(MetadataIdentifier consumerMetadataIdentifier, String serviceParameterString);
 
+    protected abstract void doSaveMetadata(URL url);
+
+    protected abstract void doRemoveMetadata(URL url);
+
+    protected abstract List<String> doGetExportedURLs();
+
+    protected abstract List<String> doGetSubscribedURLs();
+
 }
diff --git a/dubbo-metadata-report/dubbo-metadata-report-api/src/main/java/org/apache/dubbo/metadata/support/AbstractMetadataReportFactory.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/support/AbstractMetadataReportFactory.java
similarity index 87%
rename from dubbo-metadata-report/dubbo-metadata-report-api/src/main/java/org/apache/dubbo/metadata/support/AbstractMetadataReportFactory.java
rename to dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/support/AbstractMetadataReportFactory.java
index fd4895c..9776e8c 100644
--- a/dubbo-metadata-report/dubbo-metadata-report-api/src/main/java/org/apache/dubbo/metadata/support/AbstractMetadataReportFactory.java
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/support/AbstractMetadataReportFactory.java
@@ -14,11 +14,11 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.metadata.support;
+package org.apache.dubbo.metadata.report.support;
 
 import org.apache.dubbo.common.URL;
-import org.apache.dubbo.metadata.store.MetadataReport;
-import org.apache.dubbo.metadata.store.MetadataReportFactory;
+import org.apache.dubbo.metadata.report.MetadataReport;
+import org.apache.dubbo.metadata.report.MetadataReportFactory;
 
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
@@ -31,7 +31,7 @@ public abstract class AbstractMetadataReportFactory implements MetadataReportFac
     // The lock for the acquisition process of the registry
     private static final ReentrantLock LOCK = new ReentrantLock();
 
-    // Registry Collection Map<RegistryAddress, Registry>
+    // Registry Collection Map<metadataAddress, MetadataReport>
     private static final Map<String, MetadataReport> SERVICE_STORE_MAP = new ConcurrentHashMap<String, MetadataReport>();
 
     @Override
@@ -39,7 +39,7 @@ public abstract class AbstractMetadataReportFactory implements MetadataReportFac
         url = url.setPath(MetadataReport.class.getName())
                 .removeParameters(EXPORT_KEY, REFER_KEY);
         String key = url.toServiceString();
-        // Lock the registry access process to ensure a single instance of the registry
+        // Lock the metadata access process to ensure a single instance of the metadata instance
         LOCK.lock();
         try {
             MetadataReport metadataReport = SERVICE_STORE_MAP.get(key);
diff --git a/dubbo-metadata-report/dubbo-metadata-report-api/src/main/java/org/apache/dubbo/metadata/support/Constants.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/support/Constants.java
similarity index 96%
rename from dubbo-metadata-report/dubbo-metadata-report-api/src/main/java/org/apache/dubbo/metadata/support/Constants.java
rename to dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/support/Constants.java
index 3d74b2b..8cee825 100644
--- a/dubbo-metadata-report/dubbo-metadata-report-api/src/main/java/org/apache/dubbo/metadata/support/Constants.java
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/support/Constants.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.dubbo.metadata.support;
+package org.apache.dubbo.metadata.report.support;
 
 public interface Constants {
     String METADATA_REPORT_KEY = "metadata";
diff --git a/dubbo-metadata/src/main/java/org/apache/dubbo/metadata/InMemoryLocalMetadataService.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/store/InMemoryWritableMetadataService.java
similarity index 76%
rename from dubbo-metadata/src/main/java/org/apache/dubbo/metadata/InMemoryLocalMetadataService.java
rename to dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/store/InMemoryWritableMetadataService.java
index 947a9fb..4177903 100644
--- a/dubbo-metadata/src/main/java/org/apache/dubbo/metadata/InMemoryLocalMetadataService.java
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/store/InMemoryWritableMetadataService.java
@@ -14,11 +14,18 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.metadata;
+package org.apache.dubbo.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.utils.StringUtils;
+import org.apache.dubbo.metadata.MetadataService;
+import org.apache.dubbo.metadata.WritableMetadataService;
+import org.apache.dubbo.metadata.definition.ServiceDefinitionBuilder;
+import org.apache.dubbo.metadata.definition.model.ServiceDefinition;
+
+import com.google.gson.Gson;
 
 import java.util.Collection;
 import java.util.LinkedList;
@@ -34,18 +41,19 @@ import java.util.stream.Collectors;
 import static java.util.Collections.emptyList;
 import static java.util.Collections.unmodifiableList;
 import static org.apache.dubbo.common.URL.buildKey;
+import static org.apache.dubbo.common.constants.CommonConstants.INTERFACE_KEY;
 import static org.apache.dubbo.common.constants.CommonConstants.PROTOCOL_KEY;
 import static org.apache.dubbo.common.utils.CollectionUtils.isEmpty;
 
 /**
- * The {@link LocalMetadataService} implementation stores the metadata of Dubbo services in memory locally when they
+ * The {@link WritableMetadataService} implementation stores the metadata of Dubbo services in memory locally when they
  * exported.
  *
  * @see MetadataService
- * @see LocalMetadataService
+ * @see WritableMetadataService
  * @since 2.7.3
  */
-public class InMemoryLocalMetadataService implements LocalMetadataService {
+public class InMemoryWritableMetadataService implements WritableMetadataService {
 
     /**
      * The class name of {@link MetadataService}
@@ -75,6 +83,8 @@ public class InMemoryLocalMetadataService implements LocalMetadataService {
      */
     private final ConcurrentMap<String, List<URL>> subscribedServiceURLs = new ConcurrentHashMap<>();
 
+    private final ConcurrentHashMap<String, String> serviceDefinitions = new ConcurrentHashMap<>();
+
     // ==================================================================================== //
 
     @Override
@@ -117,6 +127,35 @@ public class InMemoryLocalMetadataService implements LocalMetadataService {
         return removeURL(subscribedServiceURLs, url);
     }
 
+    @Override
+    public void publishServiceDefinition(URL providerUrl) {
+        try {
+            String interfaceName = providerUrl.getParameter(INTERFACE_KEY);
+            if (StringUtils.isNotEmpty(interfaceName)) {
+                Class interfaceClass = Class.forName(interfaceName);
+                ServiceDefinition serviceDefinition = ServiceDefinitionBuilder.build(interfaceClass);
+                Gson gson = new Gson();
+                String data = gson.toJson(serviceDefinition);
+                serviceDefinitions.put(providerUrl.getServiceKey(), data);
+                return;
+            }
+            logger.error("publishProvider interfaceName is empty . providerUrl: " + providerUrl.toFullString());
+        } catch (ClassNotFoundException e) {
+            //ignore error
+            logger.error("publishProvider getServiceDescriptor error. providerUrl: " + providerUrl.toFullString(), e);
+        }
+    }
+
+    @Override
+    public String getServiceDefinition(String interfaceName, String version, String group) {
+        return serviceDefinitions.get(URL.buildKey(interfaceName, group, version));
+    }
+
+    @Override
+    public String getServiceDefinition(String serviceKey) {
+        return serviceDefinitions.get(serviceKey);
+    }
+
     private boolean addURL(Map<String, List<URL>> serviceURLs, URL url) {
         return executeMutually(() -> {
             List<URL> urls = serviceURLs.computeIfAbsent(url.getServiceKey(), s -> new LinkedList());
diff --git a/dubbo-metadata-report/dubbo-metadata-report-api/src/main/java/org/apache/dubbo/metadata/integration/MetadataReportService.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/store/RemoteWritableMetadataService.java
similarity index 55%
rename from dubbo-metadata-report/dubbo-metadata-report-api/src/main/java/org/apache/dubbo/metadata/integration/MetadataReportService.java
rename to dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/store/RemoteWritableMetadataService.java
index 06d39b6..c52f5c8 100644
--- a/dubbo-metadata-report/dubbo-metadata-report-api/src/main/java/org/apache/dubbo/metadata/integration/MetadataReportService.java
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/store/RemoteWritableMetadataService.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.metadata.integration;
+package org.apache.dubbo.metadata.store;
 
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.URLBuilder;
@@ -22,15 +22,19 @@ import org.apache.dubbo.common.extension.ExtensionLoader;
 import org.apache.dubbo.common.logger.Logger;
 import org.apache.dubbo.common.logger.LoggerFactory;
 import org.apache.dubbo.common.utils.StringUtils;
+import org.apache.dubbo.common.utils.UrlUtils;
+import org.apache.dubbo.metadata.WritableMetadataService;
 import org.apache.dubbo.metadata.definition.ServiceDefinitionBuilder;
 import org.apache.dubbo.metadata.definition.model.FullServiceDefinition;
-import org.apache.dubbo.metadata.identifier.MetadataIdentifier;
-import org.apache.dubbo.metadata.store.MetadataReport;
-import org.apache.dubbo.metadata.store.MetadataReportFactory;
+import org.apache.dubbo.metadata.definition.model.ServiceDefinition;
+import org.apache.dubbo.metadata.report.MetadataReport;
+import org.apache.dubbo.metadata.report.MetadataReportFactory;
+import org.apache.dubbo.metadata.report.identifier.MetadataIdentifier;
 import org.apache.dubbo.remoting.Constants;
 import org.apache.dubbo.rpc.RpcException;
 
-import java.util.function.Supplier;
+import java.util.List;
+import java.util.function.Consumer;
 
 import static org.apache.dubbo.common.constants.CommonConstants.APPLICATION_KEY;
 import static org.apache.dubbo.common.constants.CommonConstants.CONSUMER_SIDE;
@@ -41,23 +45,21 @@ import static org.apache.dubbo.common.constants.CommonConstants.PID_KEY;
 import static org.apache.dubbo.common.constants.CommonConstants.PROVIDER_SIDE;
 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.metadata.support.Constants.METADATA_REPORT_KEY;
+import static org.apache.dubbo.metadata.report.support.Constants.METADATA_REPORT_KEY;
 
 /**
  * @since 2.7.0
  */
-public class MetadataReportService {
+public class RemoteWritableMetadataService implements WritableMetadataService {
 
     protected final Logger logger = LoggerFactory.getLogger(getClass());
 
-    private static volatile MetadataReportService metadataReportService;
-    private static Object lock = new Object();
-
     private MetadataReportFactory metadataReportFactory = ExtensionLoader.getExtensionLoader(MetadataReportFactory.class).getAdaptiveExtension();
-    MetadataReport metadataReport;
-    URL metadataReportUrl;
+    private MetadataReport metadataReport;
+
+    public RemoteWritableMetadataService() {}
 
-    MetadataReportService(URL metadataReportURL) {
+    public void initMetadataReport(URL metadataReportURL) {
         if (METADATA_REPORT_KEY.equals(metadataReportURL.getProtocol())) {
             String protocol = metadataReportURL.getParameter(METADATA_REPORT_KEY, DEFAULT_DIRECTORY);
             metadataReportURL = URLBuilder.from(metadataReportURL)
@@ -65,27 +67,36 @@ public class MetadataReportService {
                     .removeParameter(METADATA_REPORT_KEY)
                     .build();
         }
-        this.metadataReportUrl = metadataReportURL;
-        metadataReport = metadataReportFactory.getMetadataReport(this.metadataReportUrl);
-
+        metadataReport = metadataReportFactory.getMetadataReport(metadataReportURL);
     }
 
+    public MetadataReport getMetadataReport() {
+        return metadataReport;
+    }
 
-    public static MetadataReportService instance(Supplier<URL> metadataReportUrl) {
-        if (metadataReportService == null) {
-            synchronized (lock) {
-                if (metadataReportService == null) {
-                    URL metadataReportURLTmp = metadataReportUrl.get();
-                    if (metadataReportURLTmp == null) {
-                        return null;
-                    }
-                    metadataReportService = new MetadataReportService(metadataReportURLTmp);
-                }
+    @Override
+    public void publishServiceDefinition(URL providerUrl) {
+        try {
+            String interfaceName = providerUrl.getParameter(INTERFACE_KEY);
+            if (StringUtils.isNotEmpty(interfaceName)) {
+                Class interfaceClass = Class.forName(interfaceName);
+                ServiceDefinition serviceDefinition = ServiceDefinitionBuilder.build(interfaceClass);
+                metadataReport.storeProviderMetadata(new MetadataIdentifier(providerUrl.getServiceInterface(),
+                        providerUrl.getParameter(VERSION_KEY), providerUrl.getParameter(GROUP_KEY),
+                        null, null), serviceDefinition);
+                return;
             }
+            logger.error("publishProvider interfaceName is empty . providerUrl: " + providerUrl.toFullString());
+        } catch (ClassNotFoundException e) {
+            //ignore error
+            logger.error("publishProvider getServiceDescriptor error. providerUrl: " + providerUrl.toFullString(), e);
         }
-        return metadataReportService;
+
+        // backward compatibility
+        publishProvider(providerUrl);
     }
 
+    @Deprecated
     public void publishProvider(URL providerUrl) throws RpcException {
         //first add into the list
         // remove the individul param
@@ -108,6 +119,7 @@ public class MetadataReportService {
         }
     }
 
+    @Deprecated
     public void publishConsumer(URL consumerURL) throws RpcException {
         consumerURL = consumerURL.removeParameters(PID_KEY, TIMESTAMP_KEY, Constants.BIND_IP_KEY, Constants.BIND_PORT_KEY, TIMESTAMP_KEY);
         metadataReport.storeConsumerMetadata(new MetadataIdentifier(consumerURL.getServiceInterface(),
@@ -115,4 +127,58 @@ public class MetadataReportService {
                 consumerURL.getParameter(APPLICATION_KEY)), consumerURL.getParameters());
     }
 
+    @Override
+    public boolean exportURL(URL url) {
+        return throwableAction(metadataReport::saveMetadata, url);
+    }
+
+    @Override
+    public boolean unexportURL(URL url) {
+        return throwableAction(metadataReport::removeMetadata, url);
+    }
+
+    @Override
+    public boolean subscribeURL(URL url) {
+        return throwableAction(metadataReport::saveMetadata, url);
+    }
+
+    @Override
+    public boolean unsubscribeURL(URL url) {
+        return throwableAction(metadataReport::removeMetadata, url);
+    }
+
+    @Override
+    public List<String> getSubscribedURLs() {
+        return metadataReport.getSubscribedURLs();
+    }
+
+    // TODO, protocol should be used
+    @Override
+    public List<String> getExportedURLs(String serviceInterface, String group, String version, String protocol) {
+        return metadataReport.getExportedURLs(new MetadataIdentifier(serviceInterface, group, version, null, null));
+    }
+
+    @Override
+    public String getServiceDefinition(String interfaceName, String version, String group) {
+        return metadataReport.getServiceDefinition(new MetadataIdentifier(interfaceName,
+                version, group, null, null));
+    }
+
+    @Override
+    public String getServiceDefinition(String serviceKey) {
+        String[] services = UrlUtils.parseServiceKey(serviceKey);
+        return metadataReport.getServiceDefinition(new MetadataIdentifier(services[1],
+                services[0], services[2], null, null));
+    }
+
+    private boolean throwableAction(Consumer<URL> consumer, URL url) {
+        try {
+            consumer.accept(url);
+        } catch (Exception e) {
+            logger.error("Failed to remove url metadata to remote center, url is: " + url);
+            return false;
+        }
+        return true;
+    }
+
 }
diff --git a/dubbo-metadata/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.metadata.ServiceNameMapping b/dubbo-metadata/dubbo-metadata-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.metadata.ServiceNameMapping
similarity index 100%
rename from dubbo-metadata/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.metadata.ServiceNameMapping
rename to dubbo-metadata/dubbo-metadata-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.metadata.ServiceNameMapping
diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.metadata.WritableMetadataService b/dubbo-metadata/dubbo-metadata-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.metadata.WritableMetadataService
new file mode 100644
index 0000000..26bc942
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.metadata.WritableMetadataService
@@ -0,0 +1,2 @@
+local=org.apache.dubbo.metadata.store.InMemoryWritableMetadataService
+remote=org.apache.dubbo.metadata.store.RemoteWritableMetadataService
\ No newline at end of file
diff --git a/dubbo-metadata-report/dubbo-metadata-definition/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.metadata.definition.builder.TypeBuilder b/dubbo-metadata/dubbo-metadata-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.metadata.definition.builder.TypeBuilder
similarity index 100%
rename from dubbo-metadata-report/dubbo-metadata-definition/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.metadata.definition.builder.TypeBuilder
rename to dubbo-metadata/dubbo-metadata-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.metadata.definition.builder.TypeBuilder
diff --git a/dubbo-metadata/src/test/java/org/apache/dubbo/metadata/DynamicConfigurationServiceNameMappingTest.java b/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/DynamicConfigurationServiceNameMappingTest.java
similarity index 96%
rename from dubbo-metadata/src/test/java/org/apache/dubbo/metadata/DynamicConfigurationServiceNameMappingTest.java
rename to dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/DynamicConfigurationServiceNameMappingTest.java
index 95e7a16..4fa9617 100644
--- a/dubbo-metadata/src/test/java/org/apache/dubbo/metadata/DynamicConfigurationServiceNameMappingTest.java
+++ b/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/DynamicConfigurationServiceNameMappingTest.java
@@ -18,9 +18,9 @@ package org.apache.dubbo.metadata;
 
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.config.Environment;
+import org.apache.dubbo.common.config.configcenter.DynamicConfiguration;
+import org.apache.dubbo.common.config.configcenter.DynamicConfigurationFactory;
 import org.apache.dubbo.common.utils.NetUtils;
-import org.apache.dubbo.configcenter.DynamicConfiguration;
-import org.apache.dubbo.configcenter.DynamicConfigurationFactory;
 import org.apache.dubbo.rpc.model.ApplicationModel;
 
 import org.apache.curator.framework.CuratorFramework;
diff --git a/dubbo-metadata/src/test/java/org/apache/dubbo/metadata/InMemoryLocalMetadataServiceTest.java b/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/InMemoryWritableMetadataServiceTest.java
similarity index 95%
rename from dubbo-metadata/src/test/java/org/apache/dubbo/metadata/InMemoryLocalMetadataServiceTest.java
rename to dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/InMemoryWritableMetadataServiceTest.java
index 406e4ae..8ffbd4c 100644
--- a/dubbo-metadata/src/test/java/org/apache/dubbo/metadata/InMemoryLocalMetadataServiceTest.java
+++ b/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/InMemoryWritableMetadataServiceTest.java
@@ -17,6 +17,7 @@
 package org.apache.dubbo.metadata;
 
 import org.apache.dubbo.common.URL;
+import org.apache.dubbo.metadata.store.InMemoryWritableMetadataService;
 import org.apache.dubbo.rpc.model.ApplicationModel;
 
 import org.junit.jupiter.api.BeforeAll;
@@ -34,13 +35,13 @@ import static org.junit.jupiter.api.Assertions.assertFalse;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
 /**
- * {@link InMemoryLocalMetadataService} Test
+ * {@link InMemoryWritableMetadataService} Test
  *
  * @since 2.7.3
  */
-public class InMemoryLocalMetadataServiceTest {
+public class InMemoryWritableMetadataServiceTest {
 
-    private LocalMetadataService metadataService = new InMemoryLocalMetadataService();
+    private WritableMetadataService metadataService = new InMemoryWritableMetadataService();
 
     private static final String TEST_SERVICE = "org.apache.dubbo.test.TestService";
 
diff --git a/dubbo-metadata/src/test/java/org/apache/dubbo/metadata/LocalMetadataServiceTest.java b/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/LocalMetadataServiceTest.java
similarity index 82%
rename from dubbo-metadata/src/test/java/org/apache/dubbo/metadata/LocalMetadataServiceTest.java
rename to dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/LocalMetadataServiceTest.java
index 508a959..e34ed13 100644
--- a/dubbo-metadata/src/test/java/org/apache/dubbo/metadata/LocalMetadataServiceTest.java
+++ b/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/LocalMetadataServiceTest.java
@@ -16,12 +16,14 @@
  */
 package org.apache.dubbo.metadata;
 
+import org.apache.dubbo.metadata.store.InMemoryWritableMetadataService;
+
 import org.junit.jupiter.api.Test;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
 
 /**
- * {@link LocalMetadataService} Test
+ * {@link WritableMetadataService} Test
  *
  * @since 2.7.3
  */
@@ -29,6 +31,6 @@ public class LocalMetadataServiceTest {
 
     @Test
     public void testDefaultExtension() {
-        assertEquals(InMemoryLocalMetadataService.class, LocalMetadataService.getDefaultExtension().getClass());
+        assertEquals(InMemoryWritableMetadataService.class, WritableMetadataService.getDefaultExtension().getClass());
     }
 }
diff --git a/dubbo-metadata-report/dubbo-metadata-definition/src/test/java/org/apache/dubbo/metadata/definition/MetadataTest.java b/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/definition/MetadataTest.java
similarity index 100%
rename from dubbo-metadata-report/dubbo-metadata-definition/src/test/java/org/apache/dubbo/metadata/definition/MetadataTest.java
rename to dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/definition/MetadataTest.java
diff --git a/dubbo-metadata-report/dubbo-metadata-definition/src/test/java/org/apache/dubbo/metadata/definition/MetadataUtils.java b/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/definition/MetadataUtils.java
similarity index 100%
rename from dubbo-metadata-report/dubbo-metadata-definition/src/test/java/org/apache/dubbo/metadata/definition/MetadataUtils.java
rename to dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/definition/MetadataUtils.java
diff --git a/dubbo-metadata-report/dubbo-metadata-definition/src/test/java/org/apache/dubbo/metadata/definition/ServiceDefinitionBuildderTest.java b/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/definition/ServiceDefinitionBuildderTest.java
similarity index 100%
rename from dubbo-metadata-report/dubbo-metadata-definition/src/test/java/org/apache/dubbo/metadata/definition/ServiceDefinitionBuildderTest.java
rename to dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/definition/ServiceDefinitionBuildderTest.java
diff --git a/dubbo-metadata-report/dubbo-metadata-definition/src/test/java/org/apache/dubbo/metadata/definition/common/ClassExtendsMap.java b/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/definition/common/ClassExtendsMap.java
similarity index 100%
rename from dubbo-metadata-report/dubbo-metadata-definition/src/test/java/org/apache/dubbo/metadata/definition/common/ClassExtendsMap.java
rename to dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/definition/common/ClassExtendsMap.java
diff --git a/dubbo-metadata-report/dubbo-metadata-definition/src/test/java/org/apache/dubbo/metadata/definition/common/ColorEnum.java b/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/definition/common/ColorEnum.java
similarity index 100%
rename from dubbo-metadata-report/dubbo-metadata-definition/src/test/java/org/apache/dubbo/metadata/definition/common/ColorEnum.java
rename to dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/definition/common/ColorEnum.java
diff --git a/dubbo-metadata-report/dubbo-metadata-definition/src/test/java/org/apache/dubbo/metadata/definition/common/OuterClass.java b/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/definition/common/OuterClass.java
similarity index 100%
rename from dubbo-metadata-report/dubbo-metadata-definition/src/test/java/org/apache/dubbo/metadata/definition/common/OuterClass.java
rename to dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/definition/common/OuterClass.java
diff --git a/dubbo-metadata-report/dubbo-metadata-definition/src/test/java/org/apache/dubbo/metadata/definition/common/ResultWithRawCollections.java b/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/definition/common/ResultWithRawCollections.java
similarity index 100%
rename from dubbo-metadata-report/dubbo-metadata-definition/src/test/java/org/apache/dubbo/metadata/definition/common/ResultWithRawCollections.java
rename to dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/definition/common/ResultWithRawCollections.java
diff --git a/dubbo-metadata-report/dubbo-metadata-definition/src/test/java/org/apache/dubbo/metadata/definition/common/TestService.java b/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/definition/common/TestService.java
similarity index 100%
rename from dubbo-metadata-report/dubbo-metadata-definition/src/test/java/org/apache/dubbo/metadata/definition/common/TestService.java
rename to dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/definition/common/TestService.java
diff --git a/dubbo-metadata-report/dubbo-metadata-definition/src/test/java/org/apache/dubbo/metadata/definition/service/ComplexObject.java b/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/definition/service/ComplexObject.java
similarity index 100%
rename from dubbo-metadata-report/dubbo-metadata-definition/src/test/java/org/apache/dubbo/metadata/definition/service/ComplexObject.java
rename to dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/definition/service/ComplexObject.java
diff --git a/dubbo-metadata-report/dubbo-metadata-definition/src/test/java/org/apache/dubbo/metadata/definition/service/DemoService.java b/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/definition/service/DemoService.java
similarity index 100%
rename from dubbo-metadata-report/dubbo-metadata-definition/src/test/java/org/apache/dubbo/metadata/definition/service/DemoService.java
rename to dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/definition/service/DemoService.java
diff --git a/dubbo-metadata-report/dubbo-metadata-report-api/src/test/java/org/apache/dubbo/metadata/identifier/MetadataIdentifierTest.java b/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/report/identifier/MetadataIdentifierTest.java
similarity index 97%
copy from dubbo-metadata-report/dubbo-metadata-report-api/src/test/java/org/apache/dubbo/metadata/identifier/MetadataIdentifierTest.java
copy to dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/report/identifier/MetadataIdentifierTest.java
index c660a34..c85ee48 100644
--- a/dubbo-metadata-report/dubbo-metadata-report-api/src/test/java/org/apache/dubbo/metadata/identifier/MetadataIdentifierTest.java
+++ b/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/report/identifier/MetadataIdentifierTest.java
@@ -16,6 +16,8 @@
  */
 package org.apache.dubbo.metadata.identifier;
 
+import org.apache.dubbo.metadata.report.identifier.MetadataIdentifier;
+
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 
diff --git a/dubbo-metadata-report/dubbo-metadata-report-api/src/test/java/org/apache/dubbo/metadata/support/AbstractMetadataReportFactoryTest.java b/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/report/support/AbstractMetadataReportFactoryTest.java
similarity index 80%
rename from dubbo-metadata-report/dubbo-metadata-report-api/src/test/java/org/apache/dubbo/metadata/support/AbstractMetadataReportFactoryTest.java
rename to dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/report/support/AbstractMetadataReportFactoryTest.java
index 62bcbe8..1dfc4e7 100644
--- a/dubbo-metadata-report/dubbo-metadata-report-api/src/test/java/org/apache/dubbo/metadata/support/AbstractMetadataReportFactoryTest.java
+++ b/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/report/support/AbstractMetadataReportFactoryTest.java
@@ -14,19 +14,19 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.metadata.support;
+package org.apache.dubbo.metadata.report.support;
 
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.utils.NetUtils;
-import org.apache.dubbo.metadata.definition.model.FullServiceDefinition;
-import org.apache.dubbo.metadata.identifier.MetadataIdentifier;
-import org.apache.dubbo.metadata.store.MetadataReport;
+import org.apache.dubbo.metadata.definition.model.ServiceDefinition;
+import org.apache.dubbo.metadata.report.MetadataReport;
+import org.apache.dubbo.metadata.report.identifier.MetadataIdentifier;
 
 import com.alibaba.fastjson.JSON;
-
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 
+import java.util.List;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 
@@ -41,11 +41,36 @@ public class AbstractMetadataReportFactoryTest {
             return new MetadataReport() {
 
                 @Override
-                public void storeProviderMetadata(MetadataIdentifier providerMetadataIdentifier, FullServiceDefinition serviceDefinition) {
+                public void storeProviderMetadata(MetadataIdentifier providerMetadataIdentifier, ServiceDefinition serviceDefinition) {
                     store.put(providerMetadataIdentifier.getIdentifierKey(), JSON.toJSONString(serviceDefinition));
                 }
 
                 @Override
+                public void saveMetadata(URL url) {
+
+                }
+
+                @Override
+                public void removeMetadata(URL url) {
+
+                }
+
+                @Override
+                public List<String> getExportedURLs(MetadataIdentifier metadataIdentifier) {
+                    return null;
+                }
+
+                @Override
+                public List<String> getSubscribedURLs() {
+                    return null;
+                }
+
+                @Override
+                public String getServiceDefinition(MetadataIdentifier consumerMetadataIdentifier) {
+                    return null;
+                }
+
+                @Override
                 public void storeConsumerMetadata(MetadataIdentifier consumerMetadataIdentifier, Map serviceParameterMap) {
                     store.put(consumerMetadataIdentifier.getIdentifierKey(), JSON.toJSONString(serviceParameterMap));
                 }
diff --git a/dubbo-metadata-report/dubbo-metadata-report-api/src/test/java/org/apache/dubbo/metadata/support/AbstractMetadataReportTest.java b/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/report/support/AbstractMetadataReportTest.java
similarity index 87%
rename from dubbo-metadata-report/dubbo-metadata-report-api/src/test/java/org/apache/dubbo/metadata/support/AbstractMetadataReportTest.java
rename to dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/report/support/AbstractMetadataReportTest.java
index d74c790..0faf717 100644
--- a/dubbo-metadata-report/dubbo-metadata-report-api/src/test/java/org/apache/dubbo/metadata/support/AbstractMetadataReportTest.java
+++ b/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/report/support/AbstractMetadataReportTest.java
@@ -14,13 +14,13 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.metadata.support;
+package org.apache.dubbo.metadata.report.support;
 
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.utils.NetUtils;
 import org.apache.dubbo.metadata.definition.ServiceDefinitionBuilder;
 import org.apache.dubbo.metadata.definition.model.FullServiceDefinition;
-import org.apache.dubbo.metadata.identifier.MetadataIdentifier;
+import org.apache.dubbo.metadata.report.identifier.MetadataIdentifier;
 
 import com.google.gson.Gson;
 import org.junit.jupiter.api.Assertions;
@@ -30,6 +30,7 @@ import org.junit.jupiter.api.Test;
 import java.util.Calendar;
 import java.util.Collections;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 
@@ -287,6 +288,31 @@ public class AbstractMetadataReportTest {
         protected void doStoreConsumerMetadata(MetadataIdentifier consumerMetadataIdentifier, String serviceParameterString) {
             store.put(consumerMetadataIdentifier.getUniqueKey(MetadataIdentifier.KeyTypeEnum.UNIQUE_KEY), serviceParameterString);
         }
+
+        @Override
+        protected void doSaveMetadata(URL url) {
+            throw new UnsupportedOperationException("This extension does not support working as a remote metadata center.");
+        }
+
+        @Override
+        protected void doRemoveMetadata(URL url) {
+            throw new UnsupportedOperationException("This extension does not support working as a remote metadata center.");
+        }
+
+        @Override
+        protected List<String> doGetExportedURLs() {
+            throw new UnsupportedOperationException("This extension does not support working as a remote metadata center.");
+        }
+
+        @Override
+        protected List<String> doGetSubscribedURLs() {
+            throw new UnsupportedOperationException("This extension does not support working as a remote metadata center.");
+        }
+
+        @Override
+        public String getServiceDefinition(MetadataIdentifier consumerMetadataIdentifier) {
+            throw new UnsupportedOperationException("This extension does not support working as a remote metadata center.");
+        }
     }
 
     private static class RetryMetadataReport extends AbstractMetadataReport {
@@ -319,6 +345,31 @@ public class AbstractMetadataReportTest {
             store.put(consumerMetadataIdentifier.getUniqueKey(MetadataIdentifier.KeyTypeEnum.UNIQUE_KEY), serviceParameterString);
         }
 
+        @Override
+        protected void doSaveMetadata(URL url) {
+            throw new UnsupportedOperationException("This extension does not support working as a remote metadata center.");
+        }
+
+        @Override
+        protected void doRemoveMetadata(URL url) {
+            throw new UnsupportedOperationException("This extension does not support working as a remote metadata center.");
+        }
+
+        @Override
+        protected List<String> doGetExportedURLs() {
+            throw new UnsupportedOperationException("This extension does not support working as a remote metadata center.");
+        }
+
+        @Override
+        protected List<String> doGetSubscribedURLs() {
+            throw new UnsupportedOperationException("This extension does not support working as a remote metadata center.");
+        }
+
+        @Override
+        public String getServiceDefinition(MetadataIdentifier consumerMetadataIdentifier) {
+            throw new UnsupportedOperationException("This extension does not support working as a remote metadata center.");
+        }
+
     }
 
 
diff --git a/dubbo-metadata-report/dubbo-metadata-report-api/src/test/java/org/apache/dubbo/metadata/integration/InterfaceNameTestService.java b/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/store/InterfaceNameTestService.java
similarity index 95%
rename from dubbo-metadata-report/dubbo-metadata-report-api/src/test/java/org/apache/dubbo/metadata/integration/InterfaceNameTestService.java
rename to dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/store/InterfaceNameTestService.java
index 3622062..e45fc38 100644
--- a/dubbo-metadata-report/dubbo-metadata-report-api/src/test/java/org/apache/dubbo/metadata/integration/InterfaceNameTestService.java
+++ b/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/store/InterfaceNameTestService.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.metadata.integration;
+package org.apache.dubbo.metadata.store;
 
 /**
  * 2018/9/19
diff --git a/dubbo-metadata-report/dubbo-metadata-report-api/src/test/java/org/apache/dubbo/metadata/integration/InterfaceNameTestService2.java b/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/store/InterfaceNameTestService2.java
similarity index 95%
rename from dubbo-metadata-report/dubbo-metadata-report-api/src/test/java/org/apache/dubbo/metadata/integration/InterfaceNameTestService2.java
rename to dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/store/InterfaceNameTestService2.java
index 1c27f91..938efc2 100644
--- a/dubbo-metadata-report/dubbo-metadata-report-api/src/test/java/org/apache/dubbo/metadata/integration/InterfaceNameTestService2.java
+++ b/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/store/InterfaceNameTestService2.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.metadata.integration;
+package org.apache.dubbo.metadata.store;
 
 /**
  * 2018/9/19
diff --git a/dubbo-metadata-report/dubbo-metadata-report-api/src/test/java/org/apache/dubbo/metadata/integration/MetadataReportServiceTest.java b/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/store/RemoteWritableMeatadataServiceTest.java
similarity index 77%
rename from dubbo-metadata-report/dubbo-metadata-report-api/src/test/java/org/apache/dubbo/metadata/integration/MetadataReportServiceTest.java
rename to dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/store/RemoteWritableMeatadataServiceTest.java
index d6ec491..64867a0 100644
--- a/dubbo-metadata-report/dubbo-metadata-report-api/src/test/java/org/apache/dubbo/metadata/integration/MetadataReportServiceTest.java
+++ b/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/store/RemoteWritableMeatadataServiceTest.java
@@ -14,12 +14,13 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.metadata.integration;
+package org.apache.dubbo.metadata.store;
 
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.utils.NetUtils;
+import org.apache.dubbo.metadata.WritableMetadataService;
 import org.apache.dubbo.metadata.definition.model.FullServiceDefinition;
-import org.apache.dubbo.metadata.store.test.JTestMetadataReport4Test;
+import org.apache.dubbo.metadata.test.JTestMetadataReport4Test;
 
 import com.google.gson.Gson;
 import org.junit.jupiter.api.Assertions;
@@ -27,31 +28,27 @@ import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 
 import java.util.Map;
-import java.util.function.Supplier;
+
+import static org.apache.dubbo.common.constants.CommonConstants.METADATA_REMOTE;
 
 /**
  * 2018/9/14
  */
-public class MetadataReportServiceTest {
+public class RemoteWritableMeatadataServiceTest {
     URL url = URL.valueOf("JTest://" + NetUtils.getLocalAddress().getHostName() + ":4444/org.apache.dubbo.TestService?version=1.0.0&application=vic");
-    MetadataReportService metadataReportService1;
+    RemoteWritableMetadataService metadataReportService1;
 
     @BeforeEach
     public void before() {
-        metadataReportService1 = MetadataReportService.instance(() -> url);
+        metadataReportService1 = (RemoteWritableMetadataService) WritableMetadataService.getExtension(METADATA_REMOTE);
+        metadataReportService1.initMetadataReport(url);
     }
 
     @Test
     public void testInstance() {
 
-        MetadataReportService metadataReportService2 = MetadataReportService.instance(new Supplier<URL>() {
-            @Override
-            public URL get() {
-                return url;
-            }
-        });
+        RemoteWritableMetadataService metadataReportService2 = (RemoteWritableMetadataService) WritableMetadataService.getExtension(METADATA_REMOTE);
         Assertions.assertSame(metadataReportService1, metadataReportService2);
-        Assertions.assertEquals(metadataReportService1.metadataReportUrl, url);
     }
 
     @Test
@@ -61,9 +58,9 @@ public class MetadataReportServiceTest {
         URL publishUrl = URL.valueOf("dubbo://" + NetUtils.getLocalAddress().getHostName() + ":4444/org.apache.dubbo.TestService?version=1.0.0&application=vicpubprovder&side=provider");
         metadataReportService1.publishProvider(publishUrl);
 
-        Assertions.assertTrue(metadataReportService1.metadataReport instanceof JTestMetadataReport4Test);
+        Assertions.assertTrue(metadataReportService1.getMetadataReport() instanceof JTestMetadataReport4Test);
 
-        JTestMetadataReport4Test jTestMetadataReport4Test = (JTestMetadataReport4Test) metadataReportService1.metadataReport;
+        JTestMetadataReport4Test jTestMetadataReport4Test = (JTestMetadataReport4Test) metadataReportService1.getMetadataReport();
         Assertions.assertTrue(!jTestMetadataReport4Test.store.containsKey(JTestMetadataReport4Test.getProviderKey(publishUrl)));
 
     }
@@ -74,9 +71,9 @@ public class MetadataReportServiceTest {
         URL publishUrl = URL.valueOf("dubbo://" + NetUtils.getLocalAddress().getHostName() + ":4444/org.apache.dubbo.TestService?version=1.0.0&application=vicpu&interface=ccc&side=provider");
         metadataReportService1.publishProvider(publishUrl);
 
-        Assertions.assertTrue(metadataReportService1.metadataReport instanceof JTestMetadataReport4Test);
+        Assertions.assertTrue(metadataReportService1.getMetadataReport() instanceof JTestMetadataReport4Test);
 
-        JTestMetadataReport4Test jTestMetadataReport4Test = (JTestMetadataReport4Test) metadataReportService1.metadataReport;
+        JTestMetadataReport4Test jTestMetadataReport4Test = (JTestMetadataReport4Test) metadataReportService1.getMetadataReport();
         Assertions.assertTrue(!jTestMetadataReport4Test.store.containsKey(JTestMetadataReport4Test.getProviderKey(publishUrl)));
 
     }
@@ -88,9 +85,9 @@ public class MetadataReportServiceTest {
         metadataReportService1.publishProvider(publishUrl);
         Thread.sleep(300);
 
-        Assertions.assertTrue(metadataReportService1.metadataReport instanceof JTestMetadataReport4Test);
+        Assertions.assertTrue(metadataReportService1.getMetadataReport() instanceof JTestMetadataReport4Test);
 
-        JTestMetadataReport4Test jTestMetadataReport4Test = (JTestMetadataReport4Test) metadataReportService1.metadataReport;
+        JTestMetadataReport4Test jTestMetadataReport4Test = (JTestMetadataReport4Test) metadataReportService1.getMetadataReport();
         Assertions.assertTrue(jTestMetadataReport4Test.store.containsKey(JTestMetadataReport4Test.getProviderKey(publishUrl)));
 
         String value = jTestMetadataReport4Test.store.get(JTestMetadataReport4Test.getProviderKey(publishUrl));
@@ -108,9 +105,9 @@ public class MetadataReportServiceTest {
         metadataReportService1.publishConsumer(publishUrl);
         Thread.sleep(300);
 
-        Assertions.assertTrue(metadataReportService1.metadataReport instanceof JTestMetadataReport4Test);
+        Assertions.assertTrue(metadataReportService1.getMetadataReport() instanceof JTestMetadataReport4Test);
 
-        JTestMetadataReport4Test jTestMetadataReport4Test = (JTestMetadataReport4Test) metadataReportService1.metadataReport;
+        JTestMetadataReport4Test jTestMetadataReport4Test = (JTestMetadataReport4Test) metadataReportService1.getMetadataReport();
         Assertions.assertTrue(jTestMetadataReport4Test.store.containsKey(JTestMetadataReport4Test.getConsumerKey(publishUrl)));
 
         String value = jTestMetadataReport4Test.store.get(JTestMetadataReport4Test.getConsumerKey(publishUrl));
diff --git a/dubbo-metadata-report/dubbo-metadata-report-api/src/test/java/org/apache/dubbo/metadata/integration/RetryTestService.java b/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/store/RetryTestService.java
similarity index 95%
rename from dubbo-metadata-report/dubbo-metadata-report-api/src/test/java/org/apache/dubbo/metadata/integration/RetryTestService.java
rename to dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/store/RetryTestService.java
index 43f0bbd..9133d25 100644
--- a/dubbo-metadata-report/dubbo-metadata-report-api/src/test/java/org/apache/dubbo/metadata/integration/RetryTestService.java
+++ b/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/store/RetryTestService.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.metadata.integration;
+package org.apache.dubbo.metadata.store;
 
 /**
  * 2018/10/26
diff --git a/dubbo-metadata-report/dubbo-metadata-report-api/src/test/java/org/apache/dubbo/metadata/store/test/JTestMetadataReport4Test.java b/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/test/JTestMetadataReport4Test.java
similarity index 69%
rename from dubbo-metadata-report/dubbo-metadata-report-api/src/test/java/org/apache/dubbo/metadata/store/test/JTestMetadataReport4Test.java
rename to dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/test/JTestMetadataReport4Test.java
index e01a71a..603a27f 100644
--- a/dubbo-metadata-report/dubbo-metadata-report-api/src/test/java/org/apache/dubbo/metadata/store/test/JTestMetadataReport4Test.java
+++ b/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/test/JTestMetadataReport4Test.java
@@ -14,14 +14,15 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.metadata.store.test;
+package org.apache.dubbo.metadata.test;
 
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.logger.Logger;
 import org.apache.dubbo.common.logger.LoggerFactory;
-import org.apache.dubbo.metadata.identifier.MetadataIdentifier;
-import org.apache.dubbo.metadata.support.AbstractMetadataReport;
+import org.apache.dubbo.metadata.report.identifier.MetadataIdentifier;
+import org.apache.dubbo.metadata.report.support.AbstractMetadataReport;
 
+import java.util.List;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 
@@ -58,6 +59,26 @@ public class JTestMetadataReport4Test extends AbstractMetadataReport {
         store.put(consumerMetadataIdentifier.getUniqueKey(MetadataIdentifier.KeyTypeEnum.UNIQUE_KEY), serviceParameterString);
     }
 
+    @Override
+    protected void doSaveMetadata(URL url) {
+        throw new UnsupportedOperationException("This extension does not support working as a remote metadata center.");
+    }
+
+    @Override
+    protected void doRemoveMetadata(URL url) {
+        throw new UnsupportedOperationException("This extension does not support working as a remote metadata center.");
+    }
+
+    @Override
+    protected List<String> doGetExportedURLs() {
+        throw new UnsupportedOperationException("This extension does not support working as a remote metadata center.");
+    }
+
+    @Override
+    protected List<String> doGetSubscribedURLs() {
+        throw new UnsupportedOperationException("This extension does not support working as a remote metadata center.");
+    }
+
     public static String getProviderKey(URL url) {
         return new MetadataIdentifier(url).getUniqueKey(MetadataIdentifier.KeyTypeEnum.UNIQUE_KEY);
     }
@@ -66,4 +87,8 @@ public class JTestMetadataReport4Test extends AbstractMetadataReport {
         return new MetadataIdentifier(url).getUniqueKey(MetadataIdentifier.KeyTypeEnum.UNIQUE_KEY);
     }
 
+    @Override
+    public String getServiceDefinition(MetadataIdentifier consumerMetadataIdentifier) {
+        return null;
+    }
 }
diff --git a/dubbo-metadata-report/dubbo-metadata-report-api/src/test/java/org/apache/dubbo/metadata/store/test/JTestMetadataReportFactory4Test.java b/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/test/JTestMetadataReportFactory4Test.java
similarity index 86%
rename from dubbo-metadata-report/dubbo-metadata-report-api/src/test/java/org/apache/dubbo/metadata/store/test/JTestMetadataReportFactory4Test.java
rename to dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/test/JTestMetadataReportFactory4Test.java
index 4e50a07..6e26408 100644
--- a/dubbo-metadata-report/dubbo-metadata-report-api/src/test/java/org/apache/dubbo/metadata/store/test/JTestMetadataReportFactory4Test.java
+++ b/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/test/JTestMetadataReportFactory4Test.java
@@ -14,11 +14,11 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.metadata.store.test;
+package org.apache.dubbo.metadata.test;
 
 import org.apache.dubbo.common.URL;
-import org.apache.dubbo.metadata.store.MetadataReport;
-import org.apache.dubbo.metadata.support.AbstractMetadataReportFactory;
+import org.apache.dubbo.metadata.report.MetadataReport;
+import org.apache.dubbo.metadata.report.support.AbstractMetadataReportFactory;
 
 /**
  * ZookeeperRegistryFactory.
diff --git a/dubbo-metadata-report/dubbo-metadata-report-api/src/test/java/org/apache/dubbo/metadata/identifier/MetadataIdentifierTest.java b/dubbo-metadata/dubbo-metadata-report/dubbo-metadata-report-api/src/test/java/org/apache/dubbo/metadata/identifier/MetadataIdentifierTest.java
similarity index 100%
rename from dubbo-metadata-report/dubbo-metadata-report-api/src/test/java/org/apache/dubbo/metadata/identifier/MetadataIdentifierTest.java
rename to dubbo-metadata/dubbo-metadata-report/dubbo-metadata-report-api/src/test/java/org/apache/dubbo/metadata/identifier/MetadataIdentifierTest.java
diff --git a/dubbo-metadata-report/dubbo-metadata-report-consul/pom.xml b/dubbo-metadata/dubbo-metadata-report/dubbo-metadata-report-consul/pom.xml
similarity index 96%
rename from dubbo-metadata-report/dubbo-metadata-report-consul/pom.xml
rename to dubbo-metadata/dubbo-metadata-report/dubbo-metadata-report-consul/pom.xml
index ad3eb49..fdf0527 100644
--- a/dubbo-metadata-report/dubbo-metadata-report-consul/pom.xml
+++ b/dubbo-metadata/dubbo-metadata-report/dubbo-metadata-report-consul/pom.xml
@@ -29,7 +29,7 @@
     <dependencies>
         <dependency>
             <groupId>org.apache.dubbo</groupId>
-            <artifactId>dubbo-metadata-report-api</artifactId>
+            <artifactId>dubbo-metadata-api</artifactId>
             <version>${project.parent.version}</version>
         </dependency>
         <dependency>
diff --git a/dubbo-metadata-report/dubbo-metadata-report-consul/src/main/java/org/apache/dubbo/metadata/store/consul/ConsulMetadataReport.java b/dubbo-metadata/dubbo-metadata-report/dubbo-metadata-report-consul/src/main/java/org/apache/dubbo/metadata/store/consul/ConsulMetadataReport.java
similarity index 68%
rename from dubbo-metadata-report/dubbo-metadata-report-consul/src/main/java/org/apache/dubbo/metadata/store/consul/ConsulMetadataReport.java
rename to dubbo-metadata/dubbo-metadata-report/dubbo-metadata-report-consul/src/main/java/org/apache/dubbo/metadata/store/consul/ConsulMetadataReport.java
index 42a2f60..89227e5 100644
--- a/dubbo-metadata-report/dubbo-metadata-report-consul/src/main/java/org/apache/dubbo/metadata/store/consul/ConsulMetadataReport.java
+++ b/dubbo-metadata/dubbo-metadata-report/dubbo-metadata-report-consul/src/main/java/org/apache/dubbo/metadata/store/consul/ConsulMetadataReport.java
@@ -20,12 +20,14 @@ package org.apache.dubbo.metadata.store.consul;
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.logger.Logger;
 import org.apache.dubbo.common.logger.LoggerFactory;
-import org.apache.dubbo.metadata.identifier.MetadataIdentifier;
-import org.apache.dubbo.metadata.support.AbstractMetadataReport;
+import org.apache.dubbo.metadata.report.identifier.MetadataIdentifier;
+import org.apache.dubbo.metadata.report.support.AbstractMetadataReport;
 import org.apache.dubbo.rpc.RpcException;
 
 import com.ecwid.consul.v1.ConsulClient;
 
+import java.util.List;
+
 /**
  * metadata report impl for consul
  */
@@ -53,6 +55,26 @@ public class ConsulMetadataReport extends AbstractMetadataReport {
         this.storeMetadata(consumerMetadataIdentifier, value);
     }
 
+    @Override
+    protected void doSaveMetadata(URL url) {
+        throw new UnsupportedOperationException("This extension does not support working as a remote metadata center.");
+    }
+
+    @Override
+    protected void doRemoveMetadata(URL url) {
+        throw new UnsupportedOperationException("This extension does not support working as a remote metadata center.");
+    }
+
+    @Override
+    protected List<String> doGetExportedURLs() {
+        throw new UnsupportedOperationException("This extension does not support working as a remote metadata center.");
+    }
+
+    @Override
+    protected List<String> doGetSubscribedURLs() {
+        throw new UnsupportedOperationException("This extension does not support working as a remote metadata center.");
+    }
+
     private void storeMetadata(MetadataIdentifier identifier, String v) {
         try {
             client.setKVValue(identifier.getUniqueKey(MetadataIdentifier.KeyTypeEnum.UNIQUE_KEY), v);
@@ -61,4 +83,9 @@ public class ConsulMetadataReport extends AbstractMetadataReport {
             throw new RpcException("Failed to put " + identifier + " to consul " + v + ", cause: " + t.getMessage(), t);
         }
     }
+
+    @Override
+    public String getServiceDefinition(MetadataIdentifier consumerMetadataIdentifier) {
+        throw new UnsupportedOperationException("This extension does not support working as a remote metadata center.");
+    }
 }
diff --git a/dubbo-metadata-report/dubbo-metadata-report-consul/src/main/java/org/apache/dubbo/metadata/store/consul/ConsulMetadataReportFactory.java b/dubbo-metadata/dubbo-metadata-report/dubbo-metadata-report-consul/src/main/java/org/apache/dubbo/metadata/store/consul/ConsulMetadataReportFactory.java
similarity index 89%
rename from dubbo-metadata-report/dubbo-metadata-report-consul/src/main/java/org/apache/dubbo/metadata/store/consul/ConsulMetadataReportFactory.java
rename to dubbo-metadata/dubbo-metadata-report/dubbo-metadata-report-consul/src/main/java/org/apache/dubbo/metadata/store/consul/ConsulMetadataReportFactory.java
index 66d7b5e..1d1f5bb 100644
--- a/dubbo-metadata-report/dubbo-metadata-report-consul/src/main/java/org/apache/dubbo/metadata/store/consul/ConsulMetadataReportFactory.java
+++ b/dubbo-metadata/dubbo-metadata-report/dubbo-metadata-report-consul/src/main/java/org/apache/dubbo/metadata/store/consul/ConsulMetadataReportFactory.java
@@ -18,8 +18,8 @@
 package org.apache.dubbo.metadata.store.consul;
 
 import org.apache.dubbo.common.URL;
-import org.apache.dubbo.metadata.store.MetadataReport;
-import org.apache.dubbo.metadata.support.AbstractMetadataReportFactory;
+import org.apache.dubbo.metadata.report.MetadataReport;
+import org.apache.dubbo.metadata.report.support.AbstractMetadataReportFactory;
 
 /**
  * metadata report factory impl for consul
diff --git a/dubbo-metadata-report/dubbo-metadata-report-consul/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.metadata.store.MetadataReportFactory b/dubbo-metadata/dubbo-metadata-report/dubbo-metadata-report-consul/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.metadata.report.MetadataReportFactory
similarity index 100%
rename from dubbo-metadata-report/dubbo-metadata-report-consul/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.metadata.store.MetadataReportFactory
rename to dubbo-metadata/dubbo-metadata-report/dubbo-metadata-report-consul/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.metadata.report.MetadataReportFactory
diff --git a/dubbo-metadata-report/dubbo-metadata-report-etcd/pom.xml b/dubbo-metadata/dubbo-metadata-report/dubbo-metadata-report-etcd/pom.xml
similarity index 96%
rename from dubbo-metadata-report/dubbo-metadata-report-etcd/pom.xml
rename to dubbo-metadata/dubbo-metadata-report/dubbo-metadata-report-etcd/pom.xml
index 45a1413..56e4a38 100644
--- a/dubbo-metadata-report/dubbo-metadata-report-etcd/pom.xml
+++ b/dubbo-metadata/dubbo-metadata-report/dubbo-metadata-report-etcd/pom.xml
@@ -31,7 +31,7 @@
     <dependencies>
         <dependency>
             <groupId>org.apache.dubbo</groupId>
-            <artifactId>dubbo-metadata-report-api</artifactId>
+            <artifactId>dubbo-metadata-api</artifactId>
             <version>${project.parent.version}</version>
         </dependency>
         <dependency>
diff --git a/dubbo-metadata-report/dubbo-metadata-report-etcd/src/main/java/org/apache/dubbo/metadata/store/etcd/EtcdMetadataReport.java b/dubbo-metadata/dubbo-metadata-report/dubbo-metadata-report-etcd/src/main/java/org/apache/dubbo/metadata/store/etcd/EtcdMetadataReport.java
similarity index 76%
rename from dubbo-metadata-report/dubbo-metadata-report-etcd/src/main/java/org/apache/dubbo/metadata/store/etcd/EtcdMetadataReport.java
rename to dubbo-metadata/dubbo-metadata-report/dubbo-metadata-report-etcd/src/main/java/org/apache/dubbo/metadata/store/etcd/EtcdMetadataReport.java
index 5ee9506..d01e02d 100644
--- a/dubbo-metadata-report/dubbo-metadata-report-etcd/src/main/java/org/apache/dubbo/metadata/store/etcd/EtcdMetadataReport.java
+++ b/dubbo-metadata/dubbo-metadata-report/dubbo-metadata-report-etcd/src/main/java/org/apache/dubbo/metadata/store/etcd/EtcdMetadataReport.java
@@ -36,10 +36,12 @@ package org.apache.dubbo.metadata.store.etcd;
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.logger.Logger;
 import org.apache.dubbo.common.logger.LoggerFactory;
-import org.apache.dubbo.metadata.identifier.MetadataIdentifier;
-import org.apache.dubbo.metadata.support.AbstractMetadataReport;
+import org.apache.dubbo.metadata.report.identifier.MetadataIdentifier;
+import org.apache.dubbo.metadata.report.support.AbstractMetadataReport;
 import org.apache.dubbo.remoting.etcd.jetcd.JEtcdClient;
 
+import java.util.List;
+
 import static org.apache.dubbo.common.constants.CommonConstants.GROUP_KEY;
 import static org.apache.dubbo.common.constants.CommonConstants.PATH_SEPARATOR;
 
@@ -80,6 +82,31 @@ public class EtcdMetadataReport extends AbstractMetadataReport {
         storeMetadata(consumerMetadataIdentifier, value);
     }
 
+    @Override
+    protected void doSaveMetadata(URL url) {
+        throw new UnsupportedOperationException("This extension does not support working as a remote metadata center.");
+    }
+
+    @Override
+    protected void doRemoveMetadata(URL url) {
+        throw new UnsupportedOperationException("This extension does not support working as a remote metadata center.");
+    }
+
+    @Override
+    protected List<String> doGetExportedURLs() {
+        throw new UnsupportedOperationException("This extension does not support working as a remote metadata center.");
+    }
+
+    @Override
+    protected List<String> doGetSubscribedURLs() {
+        throw new UnsupportedOperationException("This extension does not support working as a remote metadata center.");
+    }
+
+    @Override
+    public String getServiceDefinition(MetadataIdentifier consumerMetadataIdentifier) {
+        throw new UnsupportedOperationException("This extension does not support working as a remote metadata center.");
+    }
+
     private void storeMetadata(MetadataIdentifier identifier, String v) {
         String key = getNodeKey(identifier);
         if (!etcdClient.put(key, v)) {
diff --git a/dubbo-metadata-report/dubbo-metadata-report-etcd/src/main/java/org/apache/dubbo/metadata/store/etcd/EtcdMetadataReportFactory.java b/dubbo-metadata/dubbo-metadata-report/dubbo-metadata-report-etcd/src/main/java/org/apache/dubbo/metadata/store/etcd/EtcdMetadataReportFactory.java
similarity index 93%
rename from dubbo-metadata-report/dubbo-metadata-report-etcd/src/main/java/org/apache/dubbo/metadata/store/etcd/EtcdMetadataReportFactory.java
rename to dubbo-metadata/dubbo-metadata-report/dubbo-metadata-report-etcd/src/main/java/org/apache/dubbo/metadata/store/etcd/EtcdMetadataReportFactory.java
index f0572b6..3bb9e92 100644
--- a/dubbo-metadata-report/dubbo-metadata-report-etcd/src/main/java/org/apache/dubbo/metadata/store/etcd/EtcdMetadataReportFactory.java
+++ b/dubbo-metadata/dubbo-metadata-report/dubbo-metadata-report-etcd/src/main/java/org/apache/dubbo/metadata/store/etcd/EtcdMetadataReportFactory.java
@@ -34,8 +34,8 @@
 package org.apache.dubbo.metadata.store.etcd;
 
 import org.apache.dubbo.common.URL;
-import org.apache.dubbo.metadata.store.MetadataReport;
-import org.apache.dubbo.metadata.support.AbstractMetadataReportFactory;
+import org.apache.dubbo.metadata.report.MetadataReport;
+import org.apache.dubbo.metadata.report.support.AbstractMetadataReportFactory;
 
 /**
  * MetadataReportFactory to create an Etcd based {@link MetadataReport}.
diff --git a/dubbo-metadata-report/dubbo-metadata-report-etcd/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.metadata.store.MetadataReportFactory b/dubbo-metadata/dubbo-metadata-report/dubbo-metadata-report-etcd/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.metadata.report.MetadataReportFactory
similarity index 100%
rename from dubbo-metadata-report/dubbo-metadata-report-etcd/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.metadata.store.MetadataReportFactory
rename to dubbo-metadata/dubbo-metadata-report/dubbo-metadata-report-etcd/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.metadata.report.MetadataReportFactory
diff --git a/dubbo-metadata-report/dubbo-metadata-report-etcd/src/test/java/org/apache/dubbo/metadata/store/etcd/EtcdMetadata4TstService.java b/dubbo-metadata/dubbo-metadata-report/dubbo-metadata-report-etcd/src/test/java/org/apache/dubbo/metadata/store/etcd/EtcdMetadata4TstService.java
similarity index 100%
rename from dubbo-metadata-report/dubbo-metadata-report-etcd/src/test/java/org/apache/dubbo/metadata/store/etcd/EtcdMetadata4TstService.java
rename to dubbo-metadata/dubbo-metadata-report/dubbo-metadata-report-etcd/src/test/java/org/apache/dubbo/metadata/store/etcd/EtcdMetadata4TstService.java
diff --git a/dubbo-metadata-report/dubbo-metadata-report-etcd/src/test/java/org/apache/dubbo/metadata/store/etcd/EtcdMetadataReportTest.java b/dubbo-metadata/dubbo-metadata-report/dubbo-metadata-report-etcd/src/test/java/org/apache/dubbo/metadata/store/etcd/EtcdMetadataReportTest.java
similarity index 98%
rename from dubbo-metadata-report/dubbo-metadata-report-etcd/src/test/java/org/apache/dubbo/metadata/store/etcd/EtcdMetadataReportTest.java
rename to dubbo-metadata/dubbo-metadata-report/dubbo-metadata-report-etcd/src/test/java/org/apache/dubbo/metadata/store/etcd/EtcdMetadataReportTest.java
index 770b058..6ae18ca 100644
--- a/dubbo-metadata-report/dubbo-metadata-report-etcd/src/test/java/org/apache/dubbo/metadata/store/etcd/EtcdMetadataReportTest.java
+++ b/dubbo-metadata/dubbo-metadata-report/dubbo-metadata-report-etcd/src/test/java/org/apache/dubbo/metadata/store/etcd/EtcdMetadataReportTest.java
@@ -21,7 +21,7 @@ import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.utils.NetUtils;
 import org.apache.dubbo.metadata.definition.ServiceDefinitionBuilder;
 import org.apache.dubbo.metadata.definition.model.FullServiceDefinition;
-import org.apache.dubbo.metadata.identifier.MetadataIdentifier;
+import org.apache.dubbo.metadata.report.identifier.MetadataIdentifier;
 
 import com.google.gson.Gson;
 import io.etcd.jetcd.ByteSequence;
diff --git a/dubbo-metadata-report/dubbo-metadata-report-nacos/pom.xml b/dubbo-metadata/dubbo-metadata-report/dubbo-metadata-report-nacos/pom.xml
similarity index 96%
rename from dubbo-metadata-report/dubbo-metadata-report-nacos/pom.xml
rename to dubbo-metadata/dubbo-metadata-report/dubbo-metadata-report-nacos/pom.xml
index d324d5c..95fcf15 100644
--- a/dubbo-metadata-report/dubbo-metadata-report-nacos/pom.xml
+++ b/dubbo-metadata/dubbo-metadata-report/dubbo-metadata-report-nacos/pom.xml
@@ -29,7 +29,7 @@
     <dependencies>
         <dependency>
             <groupId>org.apache.dubbo</groupId>
-            <artifactId>dubbo-metadata-report-api</artifactId>
+            <artifactId>dubbo-metadata-api</artifactId>
             <version>${project.parent.version}</version>
         </dependency>
         <dependency>
diff --git a/dubbo-metadata-report/dubbo-metadata-report-nacos/src/main/java/org/apache/dubbo/metadata/store/nacos/NacosMetadataReport.java b/dubbo-metadata/dubbo-metadata-report/dubbo-metadata-report-nacos/src/main/java/org/apache/dubbo/metadata/store/nacos/NacosMetadataReport.java
similarity index 81%
rename from dubbo-metadata-report/dubbo-metadata-report-nacos/src/main/java/org/apache/dubbo/metadata/store/nacos/NacosMetadataReport.java
rename to dubbo-metadata/dubbo-metadata-report/dubbo-metadata-report-nacos/src/main/java/org/apache/dubbo/metadata/store/nacos/NacosMetadataReport.java
index 03bdeb8..846bc74 100644
--- a/dubbo-metadata-report/dubbo-metadata-report-nacos/src/main/java/org/apache/dubbo/metadata/store/nacos/NacosMetadataReport.java
+++ b/dubbo-metadata/dubbo-metadata-report/dubbo-metadata-report-nacos/src/main/java/org/apache/dubbo/metadata/store/nacos/NacosMetadataReport.java
@@ -17,25 +17,27 @@
 
 package org.apache.dubbo.metadata.store.nacos;
 
-import com.alibaba.nacos.api.NacosFactory;
-import com.alibaba.nacos.api.config.ConfigService;
-import com.alibaba.nacos.api.exception.NacosException;
 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.identifier.MetadataIdentifier;
-import org.apache.dubbo.metadata.support.AbstractMetadataReport;
+import org.apache.dubbo.metadata.report.identifier.MetadataIdentifier;
+import org.apache.dubbo.metadata.report.support.AbstractMetadataReport;
 import org.apache.dubbo.rpc.RpcException;
 
+import com.alibaba.nacos.api.NacosFactory;
+import com.alibaba.nacos.api.config.ConfigService;
+import com.alibaba.nacos.api.exception.NacosException;
+
+import java.util.List;
 import java.util.Properties;
 
-import static com.alibaba.nacos.api.PropertyKeyConst.SERVER_ADDR;
-import static com.alibaba.nacos.api.PropertyKeyConst.SECRET_KEY;
 import static com.alibaba.nacos.api.PropertyKeyConst.ACCESS_KEY;
+import static com.alibaba.nacos.api.PropertyKeyConst.CLUSTER_NAME;
 import static com.alibaba.nacos.api.PropertyKeyConst.ENDPOINT;
 import static com.alibaba.nacos.api.PropertyKeyConst.NAMESPACE;
-import static com.alibaba.nacos.api.PropertyKeyConst.CLUSTER_NAME;
+import static com.alibaba.nacos.api.PropertyKeyConst.SECRET_KEY;
+import static com.alibaba.nacos.api.PropertyKeyConst.SERVER_ADDR;
 import static com.alibaba.nacos.client.naming.utils.UtilAndComs.NACOS_NAMING_LOG_NAME;
 import static org.apache.dubbo.common.constants.RemotingConstants.BACKUP_KEY;
 
@@ -111,6 +113,31 @@ public class NacosMetadataReport extends AbstractMetadataReport {
         this.storeMetadata(consumerMetadataIdentifier, value);
     }
 
+    @Override
+    protected void doSaveMetadata(URL url) {
+        throw new UnsupportedOperationException("This extension does not support working as a remote metadata center.");
+    }
+
+    @Override
+    protected void doRemoveMetadata(URL url) {
+        throw new UnsupportedOperationException("This extension does not support working as a remote metadata center.");
+    }
+
+    @Override
+    protected List<String> doGetExportedURLs() {
+        throw new UnsupportedOperationException("This extension does not support working as a remote metadata center.");
+    }
+
+    @Override
+    protected List<String> doGetSubscribedURLs() {
+        throw new UnsupportedOperationException("This extension does not support working as a remote metadata center.");
+    }
+
+    @Override
+    public String getServiceDefinition(MetadataIdentifier consumerMetadataIdentifier) {
+        throw new UnsupportedOperationException("This extension does not support working as a remote metadata center.");
+    }
+
     private void storeMetadata(MetadataIdentifier identifier, String value) {
         try {
             boolean publishResult = configService.publishConfig(identifier.getUniqueKey(MetadataIdentifier.KeyTypeEnum.UNIQUE_KEY), identifier.getGroup(), value);
diff --git a/dubbo-metadata-report/dubbo-metadata-report-nacos/src/main/java/org/apache/dubbo/metadata/store/nacos/NacosMetadataReportFactory.java b/dubbo-metadata/dubbo-metadata-report/dubbo-metadata-report-nacos/src/main/java/org/apache/dubbo/metadata/store/nacos/NacosMetadataReportFactory.java
similarity index 89%
rename from dubbo-metadata-report/dubbo-metadata-report-nacos/src/main/java/org/apache/dubbo/metadata/store/nacos/NacosMetadataReportFactory.java
rename to dubbo-metadata/dubbo-metadata-report/dubbo-metadata-report-nacos/src/main/java/org/apache/dubbo/metadata/store/nacos/NacosMetadataReportFactory.java
index b882042..2cff74c 100644
--- a/dubbo-metadata-report/dubbo-metadata-report-nacos/src/main/java/org/apache/dubbo/metadata/store/nacos/NacosMetadataReportFactory.java
+++ b/dubbo-metadata/dubbo-metadata-report/dubbo-metadata-report-nacos/src/main/java/org/apache/dubbo/metadata/store/nacos/NacosMetadataReportFactory.java
@@ -18,8 +18,8 @@
 package org.apache.dubbo.metadata.store.nacos;
 
 import org.apache.dubbo.common.URL;
-import org.apache.dubbo.metadata.store.MetadataReport;
-import org.apache.dubbo.metadata.support.AbstractMetadataReportFactory;
+import org.apache.dubbo.metadata.report.MetadataReport;
+import org.apache.dubbo.metadata.report.support.AbstractMetadataReportFactory;
 
 /**
  * metadata report factory impl for nacos
diff --git a/dubbo-metadata-report/dubbo-metadata-report-nacos/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.metadata.store.MetadataReportFactory b/dubbo-metadata/dubbo-metadata-report/dubbo-metadata-report-nacos/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.metadata.report.MetadataReportFactory
similarity index 100%
rename from dubbo-metadata-report/dubbo-metadata-report-nacos/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.metadata.store.MetadataReportFactory
rename to dubbo-metadata/dubbo-metadata-report/dubbo-metadata-report-nacos/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.metadata.report.MetadataReportFactory
diff --git a/dubbo-metadata-report/dubbo-metadata-report-nacos/src/test/java/org/apache/dubbo/metadata/store/nacos/NacosMetadata4TstService.java b/dubbo-metadata/dubbo-metadata-report/dubbo-metadata-report-nacos/src/test/java/org/apache/dubbo/metadata/store/nacos/NacosMetadata4TstService.java
similarity index 100%
rename from dubbo-metadata-report/dubbo-metadata-report-nacos/src/test/java/org/apache/dubbo/metadata/store/nacos/NacosMetadata4TstService.java
rename to dubbo-metadata/dubbo-metadata-report/dubbo-metadata-report-nacos/src/test/java/org/apache/dubbo/metadata/store/nacos/NacosMetadata4TstService.java
diff --git a/dubbo-metadata-report/dubbo-metadata-report-nacos/src/test/java/org/apache/dubbo/metadata/store/nacos/NacosMetadataReportTest.java b/dubbo-metadata/dubbo-metadata-report/dubbo-metadata-report-nacos/src/test/java/org/apache/dubbo/metadata/store/nacos/NacosMetadataReportTest.java
similarity index 98%
rename from dubbo-metadata-report/dubbo-metadata-report-nacos/src/test/java/org/apache/dubbo/metadata/store/nacos/NacosMetadataReportTest.java
rename to dubbo-metadata/dubbo-metadata-report/dubbo-metadata-report-nacos/src/test/java/org/apache/dubbo/metadata/store/nacos/NacosMetadataReportTest.java
index 07d6f8b..909244c 100644
--- a/dubbo-metadata-report/dubbo-metadata-report-nacos/src/test/java/org/apache/dubbo/metadata/store/nacos/NacosMetadataReportTest.java
+++ b/dubbo-metadata/dubbo-metadata-report/dubbo-metadata-report-nacos/src/test/java/org/apache/dubbo/metadata/store/nacos/NacosMetadataReportTest.java
@@ -20,7 +20,7 @@ import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.utils.NetUtils;
 import org.apache.dubbo.metadata.definition.ServiceDefinitionBuilder;
 import org.apache.dubbo.metadata.definition.model.FullServiceDefinition;
-import org.apache.dubbo.metadata.identifier.MetadataIdentifier;
+import org.apache.dubbo.metadata.report.identifier.MetadataIdentifier;
 
 import com.alibaba.nacos.api.config.ConfigService;
 import com.google.gson.Gson;
diff --git a/dubbo-metadata-report/dubbo-metadata-report-redis/pom.xml b/dubbo-metadata/dubbo-metadata-report/dubbo-metadata-report-redis/pom.xml
similarity index 97%
rename from dubbo-metadata-report/dubbo-metadata-report-redis/pom.xml
rename to dubbo-metadata/dubbo-metadata-report/dubbo-metadata-report-redis/pom.xml
index 419c77f..da07d27 100644
--- a/dubbo-metadata-report/dubbo-metadata-report-redis/pom.xml
+++ b/dubbo-metadata/dubbo-metadata-report/dubbo-metadata-report-redis/pom.xml
@@ -30,7 +30,7 @@
     <dependencies>
         <dependency>
             <groupId>org.apache.dubbo</groupId>
-            <artifactId>dubbo-metadata-report-api</artifactId>
+            <artifactId>dubbo-metadata-api</artifactId>
             <version>${project.parent.version}</version>
         </dependency>
         <dependency>
diff --git a/dubbo-metadata-report/dubbo-metadata-report-redis/src/main/java/org/apache/dubbo/metadata/store/redis/RedisMetadataReport.java b/dubbo-metadata/dubbo-metadata-report/dubbo-metadata-report-redis/src/main/java/org/apache/dubbo/metadata/store/redis/RedisMetadataReport.java
similarity index 84%
rename from dubbo-metadata-report/dubbo-metadata-report-redis/src/main/java/org/apache/dubbo/metadata/store/redis/RedisMetadataReport.java
rename to dubbo-metadata/dubbo-metadata-report/dubbo-metadata-report-redis/src/main/java/org/apache/dubbo/metadata/store/redis/RedisMetadataReport.java
index 6f38104..bc2b2eb 100644
--- a/dubbo-metadata-report/dubbo-metadata-report-redis/src/main/java/org/apache/dubbo/metadata/store/redis/RedisMetadataReport.java
+++ b/dubbo-metadata/dubbo-metadata-report/dubbo-metadata-report-redis/src/main/java/org/apache/dubbo/metadata/store/redis/RedisMetadataReport.java
@@ -19,8 +19,8 @@ package org.apache.dubbo.metadata.store.redis;
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.logger.Logger;
 import org.apache.dubbo.common.logger.LoggerFactory;
-import org.apache.dubbo.metadata.identifier.MetadataIdentifier;
-import org.apache.dubbo.metadata.support.AbstractMetadataReport;
+import org.apache.dubbo.metadata.report.identifier.MetadataIdentifier;
+import org.apache.dubbo.metadata.report.support.AbstractMetadataReport;
 import org.apache.dubbo.rpc.RpcException;
 
 import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
@@ -37,7 +37,7 @@ import java.util.Set;
 import static org.apache.dubbo.common.constants.CommonConstants.CLUSTER_KEY;
 import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_TIMEOUT;
 import static org.apache.dubbo.common.constants.CommonConstants.TIMEOUT_KEY;
-import static org.apache.dubbo.metadata.identifier.MetadataIdentifier.META_DATA_STORE_TAG;
+import static org.apache.dubbo.metadata.report.identifier.MetadataIdentifier.META_DATA_STORE_TAG;
 
 /**
  * RedisMetadataReport
@@ -76,6 +76,31 @@ public class RedisMetadataReport extends AbstractMetadataReport {
         this.storeMetadata(consumerMetadataIdentifier, value);
     }
 
+    @Override
+    protected void doSaveMetadata(URL url) {
+
+    }
+
+    @Override
+    protected void doRemoveMetadata(URL url) {
+
+    }
+
+    @Override
+    protected List<String> doGetExportedURLs() {
+        return null;
+    }
+
+    @Override
+    protected List<String> doGetSubscribedURLs() {
+        return null;
+    }
+
+    @Override
+    public String getServiceDefinition(MetadataIdentifier consumerMetadataIdentifier) {
+        throw new UnsupportedOperationException("This extension does not support working as a remote metadata center.");
+    }
+
     private void storeMetadata(MetadataIdentifier metadataIdentifier, String v) {
         if (pool != null) {
             storeMetadataStandalone(metadataIdentifier, v);
diff --git a/dubbo-metadata-report/dubbo-metadata-report-redis/src/main/java/org/apache/dubbo/metadata/store/redis/RedisMetadataReportFactory.java b/dubbo-metadata/dubbo-metadata-report/dubbo-metadata-report-redis/src/main/java/org/apache/dubbo/metadata/store/redis/RedisMetadataReportFactory.java
similarity index 89%
rename from dubbo-metadata-report/dubbo-metadata-report-redis/src/main/java/org/apache/dubbo/metadata/store/redis/RedisMetadataReportFactory.java
rename to dubbo-metadata/dubbo-metadata-report/dubbo-metadata-report-redis/src/main/java/org/apache/dubbo/metadata/store/redis/RedisMetadataReportFactory.java
index b507dbe..bd08877 100644
--- a/dubbo-metadata-report/dubbo-metadata-report-redis/src/main/java/org/apache/dubbo/metadata/store/redis/RedisMetadataReportFactory.java
+++ b/dubbo-metadata/dubbo-metadata-report/dubbo-metadata-report-redis/src/main/java/org/apache/dubbo/metadata/store/redis/RedisMetadataReportFactory.java
@@ -17,8 +17,8 @@
 package org.apache.dubbo.metadata.store.redis;
 
 import org.apache.dubbo.common.URL;
-import org.apache.dubbo.metadata.store.MetadataReport;
-import org.apache.dubbo.metadata.support.AbstractMetadataReportFactory;
+import org.apache.dubbo.metadata.report.MetadataReport;
+import org.apache.dubbo.metadata.report.support.AbstractMetadataReportFactory;
 
 /**
  * RedisMetadataReportFactory.
diff --git a/dubbo-metadata-report/dubbo-metadata-report-redis/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.metadata.store.MetadataReportFactory b/dubbo-metadata/dubbo-metadata-report/dubbo-metadata-report-redis/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.metadata.report.MetadataReportFactory
similarity index 100%
rename from dubbo-metadata-report/dubbo-metadata-report-redis/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.metadata.store.MetadataReportFactory
rename to dubbo-metadata/dubbo-metadata-report/dubbo-metadata-report-redis/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.metadata.report.MetadataReportFactory
diff --git a/dubbo-metadata-report/dubbo-metadata-report-redis/src/test/java/org/apache/dubbo/metadata/store/redis/RedisMetadata4TstService.java b/dubbo-metadata/dubbo-metadata-report/dubbo-metadata-report-redis/src/test/java/org/apache/dubbo/metadata/store/redis/RedisMetadata4TstService.java
similarity index 100%
rename from dubbo-metadata-report/dubbo-metadata-report-redis/src/test/java/org/apache/dubbo/metadata/store/redis/RedisMetadata4TstService.java
rename to dubbo-metadata/dubbo-metadata-report/dubbo-metadata-report-redis/src/test/java/org/apache/dubbo/metadata/store/redis/RedisMetadata4TstService.java
diff --git a/dubbo-metadata-report/dubbo-metadata-report-redis/src/test/java/org/apache/dubbo/metadata/store/redis/RedisMetadataReportTest.java b/dubbo-metadata/dubbo-metadata-report/dubbo-metadata-report-redis/src/test/java/org/apache/dubbo/metadata/store/redis/RedisMetadataReportTest.java
similarity index 98%
rename from dubbo-metadata-report/dubbo-metadata-report-redis/src/test/java/org/apache/dubbo/metadata/store/redis/RedisMetadataReportTest.java
rename to dubbo-metadata/dubbo-metadata-report/dubbo-metadata-report-redis/src/test/java/org/apache/dubbo/metadata/store/redis/RedisMetadataReportTest.java
index 63a2a39..88105e2 100644
--- a/dubbo-metadata-report/dubbo-metadata-report-redis/src/test/java/org/apache/dubbo/metadata/store/redis/RedisMetadataReportTest.java
+++ b/dubbo-metadata/dubbo-metadata-report/dubbo-metadata-report-redis/src/test/java/org/apache/dubbo/metadata/store/redis/RedisMetadataReportTest.java
@@ -20,7 +20,7 @@ import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.utils.NetUtils;
 import org.apache.dubbo.metadata.definition.ServiceDefinitionBuilder;
 import org.apache.dubbo.metadata.definition.model.FullServiceDefinition;
-import org.apache.dubbo.metadata.identifier.MetadataIdentifier;
+import org.apache.dubbo.metadata.report.identifier.MetadataIdentifier;
 import org.apache.dubbo.rpc.RpcException;
 
 import com.google.gson.Gson;
@@ -40,7 +40,7 @@ import java.util.Map;
 
 import static org.apache.dubbo.common.constants.CommonConstants.CONSUMER_SIDE;
 import static org.apache.dubbo.common.constants.CommonConstants.PROVIDER_SIDE;
-import static org.apache.dubbo.metadata.support.Constants.SYNC_REPORT_KEY;
+import static org.apache.dubbo.metadata.report.support.Constants.SYNC_REPORT_KEY;
 
 /**
  * 2018/10/9
diff --git a/dubbo-metadata-report/dubbo-metadata-report-zookeeper/pom.xml b/dubbo-metadata/dubbo-metadata-report/dubbo-metadata-report-zookeeper/pom.xml
similarity index 96%
rename from dubbo-metadata-report/dubbo-metadata-report-zookeeper/pom.xml
rename to dubbo-metadata/dubbo-metadata-report/dubbo-metadata-report-zookeeper/pom.xml
index a276f83..b84bd10 100644
--- a/dubbo-metadata-report/dubbo-metadata-report-zookeeper/pom.xml
+++ b/dubbo-metadata/dubbo-metadata-report/dubbo-metadata-report-zookeeper/pom.xml
@@ -27,7 +27,7 @@
     <dependencies>
         <dependency>
             <groupId>org.apache.dubbo</groupId>
-            <artifactId>dubbo-metadata-report-api</artifactId>
+            <artifactId>dubbo-metadata-api</artifactId>
             <version>${project.parent.version}</version>
         </dependency>
         <dependency>
diff --git a/dubbo-metadata-report/dubbo-metadata-report-zookeeper/src/main/java/org/apache/dubbo/metadata/store/zookeeper/ZookeeperMetadataReport.java b/dubbo-metadata/dubbo-metadata-report/dubbo-metadata-report-zookeeper/src/main/java/org/apache/dubbo/metadata/store/zookeeper/ZookeeperMetadataReport.java
similarity index 78%
rename from dubbo-metadata-report/dubbo-metadata-report-zookeeper/src/main/java/org/apache/dubbo/metadata/store/zookeeper/ZookeeperMetadataReport.java
rename to dubbo-metadata/dubbo-metadata-report/dubbo-metadata-report-zookeeper/src/main/java/org/apache/dubbo/metadata/store/zookeeper/ZookeeperMetadataReport.java
index 66353f6..5649933 100644
--- a/dubbo-metadata-report/dubbo-metadata-report-zookeeper/src/main/java/org/apache/dubbo/metadata/store/zookeeper/ZookeeperMetadataReport.java
+++ b/dubbo-metadata/dubbo-metadata-report/dubbo-metadata-report-zookeeper/src/main/java/org/apache/dubbo/metadata/store/zookeeper/ZookeeperMetadataReport.java
@@ -19,11 +19,13 @@ package org.apache.dubbo.metadata.store.zookeeper;
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.logger.Logger;
 import org.apache.dubbo.common.logger.LoggerFactory;
-import org.apache.dubbo.metadata.identifier.MetadataIdentifier;
-import org.apache.dubbo.metadata.support.AbstractMetadataReport;
+import org.apache.dubbo.metadata.report.identifier.MetadataIdentifier;
+import org.apache.dubbo.metadata.report.support.AbstractMetadataReport;
 import org.apache.dubbo.remoting.zookeeper.ZookeeperClient;
 import org.apache.dubbo.remoting.zookeeper.ZookeeperTransporter;
 
+import java.util.List;
+
 import static org.apache.dubbo.common.constants.CommonConstants.GROUP_KEY;
 import static org.apache.dubbo.common.constants.CommonConstants.PATH_SEPARATOR;
 
@@ -68,6 +70,31 @@ public class ZookeeperMetadataReport extends AbstractMetadataReport {
         storeMetadata(consumerMetadataIdentifier, value);
     }
 
+    @Override
+    protected void doSaveMetadata(URL url) {
+//        zkClient.create(, URL.encode(url.toFullString()));
+    }
+
+    @Override
+    protected void doRemoveMetadata(URL url) {
+
+    }
+
+    @Override
+    protected List<String> doGetExportedURLs() {
+        return null;
+    }
+
+    @Override
+    protected List<String> doGetSubscribedURLs() {
+        return null;
+    }
+
+    @Override
+    public String getServiceDefinition(MetadataIdentifier consumerMetadataIdentifier) {
+        throw new UnsupportedOperationException("This extension does not support working as a remote metadata center.");
+    }
+
     private void storeMetadata(MetadataIdentifier metadataIdentifier, String v) {
         zkClient.create(getNodePath(metadataIdentifier), v, false);
     }
diff --git a/dubbo-metadata-report/dubbo-metadata-report-zookeeper/src/main/java/org/apache/dubbo/metadata/store/zookeeper/ZookeeperMetadataReportFactory.java b/dubbo-metadata/dubbo-metadata-report/dubbo-metadata-report-zookeeper/src/main/java/org/apache/dubbo/metadata/store/zookeeper/ZookeeperMetadataReportFactory.java
similarity index 91%
rename from dubbo-metadata-report/dubbo-metadata-report-zookeeper/src/main/java/org/apache/dubbo/metadata/store/zookeeper/ZookeeperMetadataReportFactory.java
rename to dubbo-metadata/dubbo-metadata-report/dubbo-metadata-report-zookeeper/src/main/java/org/apache/dubbo/metadata/store/zookeeper/ZookeeperMetadataReportFactory.java
index cf26d4a..0ffed8d 100644
--- a/dubbo-metadata-report/dubbo-metadata-report-zookeeper/src/main/java/org/apache/dubbo/metadata/store/zookeeper/ZookeeperMetadataReportFactory.java
+++ b/dubbo-metadata/dubbo-metadata-report/dubbo-metadata-report-zookeeper/src/main/java/org/apache/dubbo/metadata/store/zookeeper/ZookeeperMetadataReportFactory.java
@@ -17,8 +17,8 @@
 package org.apache.dubbo.metadata.store.zookeeper;
 
 import org.apache.dubbo.common.URL;
-import org.apache.dubbo.metadata.store.MetadataReport;
-import org.apache.dubbo.metadata.support.AbstractMetadataReportFactory;
+import org.apache.dubbo.metadata.report.MetadataReport;
+import org.apache.dubbo.metadata.report.support.AbstractMetadataReportFactory;
 import org.apache.dubbo.remoting.zookeeper.ZookeeperTransporter;
 
 /**
diff --git a/dubbo-metadata-report/dubbo-metadata-report-zookeeper/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.metadata.store.MetadataReportFactory b/dubbo-metadata/dubbo-metadata-report/dubbo-metadata-report-zookeeper/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.metadata.report.MetadataReportFactory
similarity index 100%
rename from dubbo-metadata-report/dubbo-metadata-report-zookeeper/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.metadata.store.MetadataReportFactory
rename to dubbo-metadata/dubbo-metadata-report/dubbo-metadata-report-zookeeper/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.metadata.report.MetadataReportFactory
diff --git a/dubbo-metadata-report/dubbo-metadata-report-zookeeper/src/test/java/org/apache/dubbo/metadata/store/zookeeper/ZookeeperMetadataReport4TstService.java b/dubbo-metadata/dubbo-metadata-report/dubbo-metadata-report-zookeeper/src/test/java/org/apache/dubbo/metadata/store/zookeeper/ZookeeperMetadataReport4TstService.java
similarity index 100%
rename from dubbo-metadata-report/dubbo-metadata-report-zookeeper/src/test/java/org/apache/dubbo/metadata/store/zookeeper/ZookeeperMetadataReport4TstService.java
rename to dubbo-metadata/dubbo-metadata-report/dubbo-metadata-report-zookeeper/src/test/java/org/apache/dubbo/metadata/store/zookeeper/ZookeeperMetadataReport4TstService.java
diff --git a/dubbo-metadata-report/dubbo-metadata-report-zookeeper/src/test/java/org/apache/dubbo/metadata/store/zookeeper/ZookeeperMetadataReportTest.java b/dubbo-metadata/dubbo-metadata-report/dubbo-metadata-report-zookeeper/src/test/java/org/apache/dubbo/metadata/store/zookeeper/ZookeeperMetadataReportTest.java
similarity index 99%
rename from dubbo-metadata-report/dubbo-metadata-report-zookeeper/src/test/java/org/apache/dubbo/metadata/store/zookeeper/ZookeeperMetadataReportTest.java
rename to dubbo-metadata/dubbo-metadata-report/dubbo-metadata-report-zookeeper/src/test/java/org/apache/dubbo/metadata/store/zookeeper/ZookeeperMetadataReportTest.java
index 799a1bb..55912f0 100644
--- a/dubbo-metadata-report/dubbo-metadata-report-zookeeper/src/test/java/org/apache/dubbo/metadata/store/zookeeper/ZookeeperMetadataReportTest.java
+++ b/dubbo-metadata/dubbo-metadata-report/dubbo-metadata-report-zookeeper/src/test/java/org/apache/dubbo/metadata/store/zookeeper/ZookeeperMetadataReportTest.java
@@ -20,7 +20,7 @@ import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.utils.NetUtils;
 import org.apache.dubbo.metadata.definition.ServiceDefinitionBuilder;
 import org.apache.dubbo.metadata.definition.model.FullServiceDefinition;
-import org.apache.dubbo.metadata.identifier.MetadataIdentifier;
+import org.apache.dubbo.metadata.report.identifier.MetadataIdentifier;
 import org.apache.dubbo.remoting.zookeeper.curator.CuratorZookeeperTransporter;
 
 import com.google.gson.Gson;
diff --git a/dubbo-metadata-report/pom.xml b/dubbo-metadata/dubbo-metadata-report/pom.xml
similarity index 91%
rename from dubbo-metadata-report/pom.xml
rename to dubbo-metadata/dubbo-metadata-report/pom.xml
index 5e0fb1a..3c2fa60 100644
--- a/dubbo-metadata-report/pom.xml
+++ b/dubbo-metadata/dubbo-metadata-report/pom.xml
@@ -16,7 +16,7 @@
   -->
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     <parent>
-        <artifactId>dubbo-parent</artifactId>
+        <artifactId>dubbo-metadata</artifactId>
         <groupId>org.apache.dubbo</groupId>
         <version>${revision}</version>
     </parent>
@@ -25,10 +25,8 @@
     <artifactId>dubbo-metadata-report</artifactId>
     <packaging>pom</packaging>
     <modules>
-        <module>dubbo-metadata-report-api</module>
         <module>dubbo-metadata-report-zookeeper</module>
         <module>dubbo-metadata-report-redis</module>
-        <module>dubbo-metadata-definition</module>
         <module>dubbo-metadata-report-consul</module>
         <module>dubbo-metadata-report-etcd</module>
         <module>dubbo-metadata-report-nacos</module>
diff --git a/dubbo-metadata/pom.xml b/dubbo-metadata/pom.xml
index 9a690ae..2115c45 100644
--- a/dubbo-metadata/pom.xml
+++ b/dubbo-metadata/pom.xml
@@ -26,41 +26,10 @@
     <modelVersion>4.0.0</modelVersion>
 
     <artifactId>dubbo-metadata</artifactId>
-    <packaging>jar</packaging>
-
-    <name>dubbo-metadata</name>
-    <description>The metadata module of Dubbo project</description>
-
-    <dependencies>
-
-        <dependency>
-            <groupId>org.apache.dubbo</groupId>
-            <artifactId>dubbo-config-api</artifactId>
-            <version>${project.parent.version}</version>
-            <optional>true</optional>
-        </dependency>
-
-        <dependency>
-            <groupId>org.apache.dubbo</groupId>
-            <artifactId>dubbo-rpc-api</artifactId>
-            <version>${project.parent.version}</version>
-            <optional>true</optional>
-        </dependency>
-
-        <!-- Test dependencies -->
-        <dependency>
-            <groupId>org.apache.dubbo</groupId>
-            <artifactId>dubbo-configcenter-zookeeper</artifactId>
-            <version>${project.parent.version}</version>
-            <scope>test</scope>
-        </dependency>
-
-        <dependency>
-            <groupId>org.apache.curator</groupId>
-            <artifactId>curator-test</artifactId>
-            <scope>test</scope>
-        </dependency>
-
-    </dependencies>
+    <packaging>pom</packaging>
+    <modules>
+        <module>dubbo-metadata-api</module>
+        <module>dubbo-metadata-report</module>
+    </modules>
 
 </project>
\ No newline at end of file
diff --git a/dubbo-metadata/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.metadata.LocalMetadataService b/dubbo-metadata/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.metadata.LocalMetadataService
deleted file mode 100644
index 2af06fd..0000000
--- a/dubbo-metadata/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.metadata.LocalMetadataService
+++ /dev/null
@@ -1 +0,0 @@
-default=org.apache.dubbo.metadata.InMemoryLocalMetadataService
\ No newline at end of file
diff --git a/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/command/impl/Ls.java b/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/command/impl/Ls.java
index 469a40a..cf0dc68 100644
--- a/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/command/impl/Ls.java
+++ b/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/command/impl/Ls.java
@@ -20,15 +20,13 @@ import org.apache.dubbo.qos.command.BaseCommand;
 import org.apache.dubbo.qos.command.CommandContext;
 import org.apache.dubbo.qos.command.annotation.Cmd;
 import org.apache.dubbo.qos.textui.TTable;
+import org.apache.dubbo.rpc.cluster.support.AbstractClusterInvoker;
 import org.apache.dubbo.rpc.model.ApplicationModel;
 import org.apache.dubbo.rpc.model.ConsumerModel;
 import org.apache.dubbo.rpc.model.ProviderModel;
 
 import java.util.Collection;
 
-import static org.apache.dubbo.registry.support.ProviderConsumerRegTable.getConsumerAddressNum;
-import static org.apache.dubbo.registry.support.ProviderConsumerRegTable.isRegistered;
-
 @Cmd(name = "ls", summary = "ls service", example = {
         "ls"
 })
@@ -57,7 +55,7 @@ public class Ls implements BaseCommand {
 
         //Content
         for (ProviderModel providerModel : providerModelList) {
-            tTable.addRow(providerModel.getServiceName(), isRegistered(providerModel.getServiceName()) ? "Y" : "N");
+            tTable.addRow(providerModel.getServiceKey(), ApplicationModel.isRegistered(providerModel.getServiceKey()) ? "Y" : "N");
         }
         stringBuilder.append(tTable.rendering());
 
@@ -80,7 +78,8 @@ public class Ls implements BaseCommand {
         //Content
         //TODO to calculate consumerAddressNum
         for (ConsumerModel consumerModel : consumerModelList) {
-            tTable.addRow(consumerModel.getServiceName(), getConsumerAddressNum(consumerModel.getServiceName()));
+            AbstractClusterInvoker clusterInvoker = (AbstractClusterInvoker) consumerModel.getInvoker();
+            tTable.addRow(consumerModel.getServiceKey(), clusterInvoker.getDirectory().getAllInvokers().size());
         }
 
         stringBuilder.append(tTable.rendering());
diff --git a/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/command/impl/Offline.java b/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/command/impl/Offline.java
index 79c41f3..fcbf548 100644
--- a/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/command/impl/Offline.java
+++ b/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/command/impl/Offline.java
@@ -24,13 +24,11 @@ import org.apache.dubbo.qos.command.CommandContext;
 import org.apache.dubbo.qos.command.annotation.Cmd;
 import org.apache.dubbo.registry.Registry;
 import org.apache.dubbo.registry.RegistryFactory;
-import org.apache.dubbo.registry.support.ProviderConsumerRegTable;
-import org.apache.dubbo.registry.support.ProviderInvokerWrapper;
 import org.apache.dubbo.rpc.model.ApplicationModel;
 import org.apache.dubbo.rpc.model.ProviderModel;
+import org.apache.dubbo.rpc.model.invoker.ProviderInvokerWrapper;
 
 import java.util.Collection;
-import java.util.Set;
 
 @Cmd(name = "offline", summary = "offline dubbo", example = {
         "offline dubbo",
@@ -51,9 +49,9 @@ public class Offline implements BaseCommand {
 
         Collection<ProviderModel> providerModelList = ApplicationModel.allProviderModels();
         for (ProviderModel providerModel : providerModelList) {
-            if (providerModel.getServiceName().matches(servicePattern)) {
+            if (providerModel.getServiceKey().matches(servicePattern)) {
                 hasService = true;
-                Set<ProviderInvokerWrapper> providerInvokerWrapperSet = ProviderConsumerRegTable.getProviderInvoker(providerModel.getServiceName());
+                Collection<ProviderInvokerWrapper> providerInvokerWrapperSet = ApplicationModel.getProviderInvokers(providerModel.getServiceKey());
                 for (ProviderInvokerWrapper providerInvokerWrapper : providerInvokerWrapperSet) {
                     if (!providerInvokerWrapper.isReg()) {
                         continue;
diff --git a/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/command/impl/Online.java b/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/command/impl/Online.java
index 30ba14b..ae3d17f 100644
--- a/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/command/impl/Online.java
+++ b/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/command/impl/Online.java
@@ -25,13 +25,11 @@ import org.apache.dubbo.qos.command.CommandContext;
 import org.apache.dubbo.qos.command.annotation.Cmd;
 import org.apache.dubbo.registry.Registry;
 import org.apache.dubbo.registry.RegistryFactory;
-import org.apache.dubbo.registry.support.ProviderConsumerRegTable;
-import org.apache.dubbo.registry.support.ProviderInvokerWrapper;
 import org.apache.dubbo.rpc.model.ApplicationModel;
 import org.apache.dubbo.rpc.model.ProviderModel;
+import org.apache.dubbo.rpc.model.invoker.ProviderInvokerWrapper;
 
 import java.util.Collection;
-import java.util.Set;
 
 @Cmd(name = "online", summary = "online dubbo", example = {
         "online dubbo",
@@ -53,9 +51,9 @@ public class Online implements BaseCommand {
 
         Collection<ProviderModel> providerModelList = ApplicationModel.allProviderModels();
         for (ProviderModel providerModel : providerModelList) {
-            if (providerModel.getServiceName().matches(servicePattern)) {
+            if (providerModel.getServiceKey().matches(servicePattern)) {
                 hasService = true;
-                Set<ProviderInvokerWrapper> providerInvokerWrapperSet = ProviderConsumerRegTable.getProviderInvoker(providerModel.getServiceName());
+                Collection<ProviderInvokerWrapper> providerInvokerWrapperSet = ApplicationModel.getProviderInvokers(providerModel.getServiceKey());
                 for (ProviderInvokerWrapper providerInvokerWrapper : providerInvokerWrapperSet) {
                     if (providerInvokerWrapper.isReg()) {
                         continue;
diff --git a/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/command/impl/LsTest.java b/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/command/impl/LsTest.java
index c82e2d5..bef3088 100644
--- a/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/command/impl/LsTest.java
+++ b/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/command/impl/LsTest.java
@@ -19,20 +19,19 @@ package org.apache.dubbo.qos.command.impl;
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.qos.command.CommandContext;
 import org.apache.dubbo.registry.integration.RegistryDirectory;
-import org.apache.dubbo.registry.support.ProviderConsumerRegTable;
-import org.apache.dubbo.registry.support.ProviderInvokerWrapper;
 import org.apache.dubbo.rpc.Invoker;
 import org.apache.dubbo.rpc.model.ApplicationModel;
 import org.apache.dubbo.rpc.model.ConsumerModel;
 import org.apache.dubbo.rpc.model.ProviderModel;
+import org.apache.dubbo.rpc.model.invoker.ProviderInvokerWrapper;
+
 import org.junit.jupiter.api.Test;
 import org.mockito.Mockito;
 
 import java.util.Map;
 
-import static org.apache.dubbo.registry.support.ProviderConsumerRegTable.getProviderInvoker;
-import static org.hamcrest.Matchers.containsString;
 import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.containsString;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
@@ -40,9 +39,9 @@ public class LsTest {
     @Test
     public void testExecute() throws Exception {
         ConsumerModel consumerModel = mock(ConsumerModel.class);
-        when(consumerModel.getServiceName()).thenReturn("org.apache.dubbo.FooService");
+        when(consumerModel.getServiceKey()).thenReturn("org.apache.dubbo.FooService");
         ProviderModel providerModel = mock(ProviderModel.class);
-        when(providerModel.getServiceName()).thenReturn("org.apache.dubbo.BarService");
+        when(providerModel.getServiceKey()).thenReturn("org.apache.dubbo.BarService");
         ApplicationModel.initConsumerModel("org.apache.dubbo.FooService", consumerModel);
         ApplicationModel.initProviderModel("org.apache.dubbo.BarService", providerModel);
 
@@ -53,8 +52,8 @@ public class LsTest {
         when(providerUrl.getServiceKey()).thenReturn("org.apache.dubbo.BarService");
         when(providerUrl.toFullString()).thenReturn("dubbo://localhost:8888/org.apache.dubbo.BarService");
         when(providerInvoker.getUrl()).thenReturn(providerUrl);
-        ProviderConsumerRegTable.registerProvider(providerInvoker, registryUrl, providerUrl);
-        for (ProviderInvokerWrapper wrapper : getProviderInvoker("org.apache.dubbo.BarService")) {
+        ApplicationModel.registerProviderInvoker(providerInvoker, registryUrl, providerUrl);
+        for (ProviderInvokerWrapper wrapper : ApplicationModel.getProviderInvokers("org.apache.dubbo.BarService")) {
             wrapper.setReg(true);
         }
 
@@ -67,7 +66,7 @@ public class LsTest {
         Map invokers = Mockito.mock(Map.class);
         when(invokers.size()).thenReturn(100);
         when(directory.getUrlInvokerMap()).thenReturn(invokers);
-        ProviderConsumerRegTable.registerConsumer(consumerInvoker, registryUrl, consumerUrl, directory);
+        ApplicationModel.registerConsumerInvoker(consumerInvoker, consumerUrl.getServiceKey());
 
         Ls ls = new Ls();
         String output = ls.execute(mock(CommandContext.class), null);
diff --git a/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/command/impl/OfflineTest.java b/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/command/impl/OfflineTest.java
index f498d5a..8d27d12 100644
--- a/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/command/impl/OfflineTest.java
+++ b/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/command/impl/OfflineTest.java
@@ -19,18 +19,17 @@ package org.apache.dubbo.qos.command.impl;
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.qos.command.CommandContext;
 import org.apache.dubbo.registry.Registry;
-import org.apache.dubbo.registry.support.ProviderConsumerRegTable;
-import org.apache.dubbo.registry.support.ProviderInvokerWrapper;
 import org.apache.dubbo.rpc.Invoker;
 import org.apache.dubbo.rpc.model.ApplicationModel;
 import org.apache.dubbo.rpc.model.ProviderModel;
+import org.apache.dubbo.rpc.model.invoker.ProviderInvokerWrapper;
+
 import org.junit.jupiter.api.Test;
 import org.mockito.Mockito;
 
-import static org.apache.dubbo.registry.support.ProviderConsumerRegTable.getProviderInvoker;
+import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.Matchers.containsString;
 import static org.hamcrest.core.Is.is;
-import static org.hamcrest.MatcherAssert.assertThat;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
@@ -38,7 +37,7 @@ public class OfflineTest {
     @Test
     public void testExecute() throws Exception {
         ProviderModel providerModel = mock(ProviderModel.class);
-        when(providerModel.getServiceName()).thenReturn("org.apache.dubbo.BarService");
+        when(providerModel.getServiceKey()).thenReturn("org.apache.dubbo.BarService");
         ApplicationModel.initProviderModel("org.apache.dubbo.BarService", providerModel);
 
         Invoker providerInvoker = mock(Invoker.class);
@@ -48,8 +47,8 @@ public class OfflineTest {
         when(providerUrl.getServiceKey()).thenReturn("org.apache.dubbo.BarService");
         when(providerUrl.toFullString()).thenReturn("dubbo://localhost:8888/org.apache.dubbo.BarService");
         when(providerInvoker.getUrl()).thenReturn(providerUrl);
-        ProviderConsumerRegTable.registerProvider(providerInvoker, registryUrl, providerUrl);
-        for (ProviderInvokerWrapper wrapper : getProviderInvoker("org.apache.dubbo.BarService")) {
+        ApplicationModel.registerProviderInvoker(providerInvoker, registryUrl, providerUrl);
+        for (ProviderInvokerWrapper wrapper : ApplicationModel.getProviderInvokers("org.apache.dubbo.BarService")) {
             wrapper.setReg(true);
         }
 
@@ -60,7 +59,7 @@ public class OfflineTest {
         String output = offline.execute(mock(CommandContext.class), new String[]{"org.apache.dubbo.BarService"});
         assertThat(output, containsString("OK"));
         Mockito.verify(registry).unregister(providerUrl);
-        for (ProviderInvokerWrapper wrapper : getProviderInvoker("org.apache.dubbo.BarService")) {
+        for (ProviderInvokerWrapper wrapper : ApplicationModel.getProviderInvokers("org.apache.dubbo.BarService")) {
             assertThat(wrapper.isReg(), is(false));
         }
 
diff --git a/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/command/impl/OnlineTest.java b/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/command/impl/OnlineTest.java
index 71132c0..7474b68 100644
--- a/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/command/impl/OnlineTest.java
+++ b/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/command/impl/OnlineTest.java
@@ -19,16 +19,15 @@ package org.apache.dubbo.qos.command.impl;
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.qos.command.CommandContext;
 import org.apache.dubbo.registry.Registry;
-import org.apache.dubbo.registry.support.ProviderConsumerRegTable;
-import org.apache.dubbo.registry.support.ProviderInvokerWrapper;
 import org.apache.dubbo.rpc.Invoker;
 import org.apache.dubbo.rpc.model.ApplicationModel;
 import org.apache.dubbo.rpc.model.ProviderModel;
+import org.apache.dubbo.rpc.model.invoker.ProviderInvokerWrapper;
+
 import org.junit.jupiter.api.Test;
 
-import static org.apache.dubbo.registry.support.ProviderConsumerRegTable.getProviderInvoker;
-import static org.hamcrest.Matchers.equalTo;
 import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.equalTo;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
@@ -37,7 +36,7 @@ public class OnlineTest {
     @Test
     public void testExecute() throws Exception {
         ProviderModel providerModel = mock(ProviderModel.class);
-        when(providerModel.getServiceName()).thenReturn("org.apache.dubbo.BarService");
+        when(providerModel.getServiceKey()).thenReturn("org.apache.dubbo.BarService");
         ApplicationModel.initProviderModel("org.apache.dubbo.BarService", providerModel);
 
         Invoker providerInvoker = mock(Invoker.class);
@@ -47,7 +46,7 @@ public class OnlineTest {
         when(providerUrl.getServiceKey()).thenReturn("org.apache.dubbo.BarService");
         when(providerUrl.toFullString()).thenReturn("dubbo://localhost:8888/org.apache.dubbo.BarService");
         when(providerInvoker.getUrl()).thenReturn(providerUrl);
-        ProviderConsumerRegTable.registerProvider(providerInvoker, registryUrl, providerUrl);
+        ApplicationModel.registerProviderInvoker(providerInvoker, registryUrl, providerUrl);
 
         Registry registry = mock(Registry.class);
         TestRegistryFactory.registry = registry;
@@ -55,7 +54,7 @@ public class OnlineTest {
         Online online = new Online();
         String output = online.execute(mock(CommandContext.class), new String[]{"org.apache.dubbo.BarService"});
         assertThat(output, equalTo("OK"));
-        for (ProviderInvokerWrapper wrapper : getProviderInvoker("org.apache.dubbo.BarService")) {
+        for (ProviderInvokerWrapper wrapper : ApplicationModel.getProviderInvokers("org.apache.dubbo.BarService")) {
             assertTrue(wrapper.isReg());
         }
     }
diff --git a/dubbo-registry/dubbo-registry-api/pom.xml b/dubbo-registry/dubbo-registry-api/pom.xml
index 44eb895..7ae8b75 100644
--- a/dubbo-registry/dubbo-registry-api/pom.xml
+++ b/dubbo-registry/dubbo-registry-api/pom.xml
@@ -32,12 +32,12 @@
     <dependencies>
         <dependency>
             <groupId>org.apache.dubbo</groupId>
-            <artifactId>dubbo-cluster</artifactId>
+            <artifactId>dubbo-common</artifactId>
             <version>${project.parent.version}</version>
         </dependency>
         <dependency>
             <groupId>org.apache.dubbo</groupId>
-            <artifactId>dubbo-configcenter-api</artifactId>
+            <artifactId>dubbo-cluster</artifactId>
             <version>${project.parent.version}</version>
         </dependency>
         <dependency>
@@ -64,7 +64,12 @@
 
         <dependency>
             <groupId>org.apache.dubbo</groupId>
-            <artifactId>dubbo-metadata</artifactId>
+            <artifactId>dubbo-metadata-api</artifactId>
+            <version>${project.parent.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.dubbo</groupId>
+            <artifactId>dubbo-metadata-report-api</artifactId>
             <version>${project.parent.version}</version>
         </dependency>
 
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceInstance.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceInstance.java
index bcdcfd2..cd501e6 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceInstance.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceInstance.java
@@ -16,8 +16,19 @@
  */
 package org.apache.dubbo.registry.client;
 
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.URLBuilder;
+import org.apache.dubbo.metadata.MetadataService;
+
+import java.util.ArrayList;
+import java.util.List;
 import java.util.Map;
 
+import static java.lang.String.valueOf;
+import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.getMetadataServiceURLsParams;
+import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.getProviderHost;
+import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.getProviderPort;
+
 /**
  * The model class of an instance of a service, which is used for service registration and discovery.
  * <p>
@@ -91,4 +102,37 @@ public interface ServiceInstance {
      * @return if equals , return <code>true</code>, or <code>false</code>
      */
     boolean equals(Object another);
+
+    /**
+     * Build the {@link URL urls} from {@link ServiceInstance#getMetadata() the metadata} of {@link ServiceInstance}
+     *
+     * @param serviceInstance {@link ServiceInstance}
+     * @return the not-null {@link List}
+     */
+    static List<URL> toUrls(ServiceInstance serviceInstance) {
+
+        Map<String, Map<String, Object>> paramsMap = getMetadataServiceURLsParams(serviceInstance);
+
+        List<URL> urls = new ArrayList<>(paramsMap.size());
+
+        for (Map.Entry<String, Map<String, Object>> entry : paramsMap.entrySet()) {
+
+            URLBuilder urlBuilder = new URLBuilder();
+            String protocol = entry.getKey();
+            Map<String, Object> urlParams = entry.getValue();
+            String host = getProviderHost(urlParams);
+            Integer port = getProviderPort(urlParams);
+            urlBuilder.setHost(host)
+                    .setPort(port)
+                    .setProtocol(protocol)
+                    .setPath(MetadataService.class.getName());
+
+            // add parameters
+            entry.getValue().forEach((name, value) -> urlBuilder.addParameter(name, valueOf(value)));
+
+            urls.add(urlBuilder.build());
+        }
+
+        return urls;
+    }
 }
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/ExportedServicesRevisionMetadataCustomizer.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/ExportedServicesRevisionMetadataCustomizer.java
index 5c1cc8e..5679723 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/ExportedServicesRevisionMetadataCustomizer.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/ExportedServicesRevisionMetadataCustomizer.java
@@ -18,8 +18,8 @@ package org.apache.dubbo.registry.client.metadata;
 
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.compiler.support.ClassUtils;
-import org.apache.dubbo.metadata.LocalMetadataService;
 import org.apache.dubbo.metadata.MetadataService;
+import org.apache.dubbo.metadata.WritableMetadataService;
 import org.apache.dubbo.registry.client.ServiceInstance;
 import org.apache.dubbo.registry.client.ServiceInstanceMetadataCustomizer;
 
@@ -47,8 +47,8 @@ public class ExportedServicesRevisionMetadataCustomizer extends ServiceInstanceM
 
     @Override
     protected String buildMetadataValue(ServiceInstance serviceInstance) {
-        LocalMetadataService localMetadataService = LocalMetadataService.getDefaultExtension();
-        List<String> exportedURLs = localMetadataService.getExportedURLs();
+        WritableMetadataService writableMetadataService = WritableMetadataService.getDefaultExtension();
+        List<String> exportedURLs = writableMetadataService.getExportedURLs();
         Object[] data = exportedURLs.stream()
                 .map(URL::valueOf)                       // String to URL
                 .map(URL::getServiceInterface)           // get the service interface
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 97ba53c..b41873d 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
@@ -17,8 +17,8 @@
 package org.apache.dubbo.registry.client.metadata;
 
 import org.apache.dubbo.common.URL;
-import org.apache.dubbo.metadata.LocalMetadataService;
 import org.apache.dubbo.metadata.MetadataService;
+import org.apache.dubbo.metadata.WritableMetadataService;
 import org.apache.dubbo.registry.client.ServiceInstance;
 import org.apache.dubbo.registry.client.ServiceInstanceMetadataCustomizer;
 
@@ -45,7 +45,7 @@ public class MetadataServiceURLParamsMetadataCustomizer extends ServiceInstanceM
     @Override
     public String buildMetadataValue(ServiceInstance serviceInstance) {
 
-        LocalMetadataService localMetadataService = LocalMetadataService.getDefaultExtension();
+        WritableMetadataService writableMetadataService = WritableMetadataService.getDefaultExtension();
 
         String serviceInterface = MetadataService.class.getName();
 
@@ -53,7 +53,7 @@ public class MetadataServiceURLParamsMetadataCustomizer extends ServiceInstanceM
 
         String version = MetadataService.VERSION;
 
-        List<String> urls = localMetadataService.getExportedURLs(serviceInterface, group, version);
+        List<String> urls = writableMetadataService.getExportedURLs(serviceInterface, group, version);
 
         return getMetadataServiceParameter(toURLs(urls));
     }
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/proxy/DefaultMetadataServiceProxyFactory.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/proxy/DefaultMetadataServiceProxyFactory.java
new file mode 100644
index 0000000..58dca64
--- /dev/null
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/proxy/DefaultMetadataServiceProxyFactory.java
@@ -0,0 +1,73 @@
+/*
+ * 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.metadata.proxy;
+
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.extension.ExtensionLoader;
+import org.apache.dubbo.metadata.MetadataService;
+import org.apache.dubbo.registry.client.ServiceInstance;
+import org.apache.dubbo.rpc.Invoker;
+import org.apache.dubbo.rpc.Protocol;
+import org.apache.dubbo.rpc.ProxyFactory;
+import org.apache.dubbo.rpc.cluster.Cluster;
+import org.apache.dubbo.rpc.cluster.directory.StaticDirectory;
+import org.apache.dubbo.rpc.cluster.support.AvailableCluster;
+
+import java.lang.reflect.Proxy;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+/**
+ * The factory of {@link MetadataService}'s {@link Proxy}
+ *
+ * @since 2.7.3
+ */
+public class DefaultMetadataServiceProxyFactory implements MetadataServiceProxyFactory {
+
+    private final Map<String, MetadataService> proxys = new HashMap<>();
+
+    private ProxyFactory proxyFactory;
+
+    private Protocol protocol;
+
+    private Cluster cluster = ExtensionLoader.getExtensionLoader(Cluster.class).getExtension(AvailableCluster.NAME);
+
+    public void setProtocol(Protocol protocol) {
+        this.protocol = protocol;
+    }
+
+    public void setProxyFactory(ProxyFactory proxyFactory) {
+        this.proxyFactory = proxyFactory;
+    }
+
+    @Override
+    public MetadataService getProxy(ServiceInstance serviceInstance) {
+        return proxys.computeIfAbsent(serviceInstance.getId(), id -> createProxy(serviceInstance));
+    }
+
+    protected MetadataService createProxy(ServiceInstance serviceInstance) {
+        List<URL> urls = ServiceInstance.toUrls(serviceInstance);
+        List<Invoker<MetadataService>> invokers = urls.stream()
+                .map(url -> protocol.refer(MetadataService.class, url))
+                .collect(Collectors.toList());
+
+        Invoker<MetadataService> invoker = cluster.join(new StaticDirectory<>(invokers));
+        return proxyFactory.getProxy(invoker);
+    }
+}
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/proxy/MetadataServiceProxyFactory.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/proxy/MetadataServiceProxyFactory.java
new file mode 100644
index 0000000..9ec31df
--- /dev/null
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/proxy/MetadataServiceProxyFactory.java
@@ -0,0 +1,55 @@
+/*
+ * 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.metadata.proxy;
+
+import org.apache.dubbo.common.extension.SPI;
+import org.apache.dubbo.metadata.MetadataService;
+import org.apache.dubbo.registry.client.ServiceInstance;
+
+import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoader;
+
+/**
+ * A factory to create a {@link MetadataService} proxy
+ *
+ * @see ServiceInstance
+ * @see MetadataService
+ * @since 2.7.3
+ */
+@SPI("local")
+public interface MetadataServiceProxyFactory {
+
+    /**
+     * Create a {@link MetadataService} proxy via the specified {@link ServiceInstance}
+     *
+     * @param serviceInstance the instance of {@link ServiceInstance}
+     * @return non-null
+     */
+    MetadataService getProxy(ServiceInstance serviceInstance);
+
+    /**
+     * Get the default extension of {@link MetadataServiceProxyFactory}
+     *
+     * @return non-null
+     */
+    static MetadataServiceProxyFactory getDefaultExtension() {
+        return getExtensionLoader(MetadataServiceProxyFactory.class).getDefaultExtension();
+    }
+
+    static MetadataServiceProxyFactory getExtension(String name) {
+        return getExtensionLoader(MetadataServiceProxyFactory.class).getExtension(name);
+    }
+}
diff --git a/dubbo-configcenter/dubbo-configcenter-api/src/test/java/org/apache/dubbo/configcenter/mock/MockDynamicConfigurationFactory.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/proxy/RemoteMetadataServiceProxyFactory.java
similarity index 61%
rename from dubbo-configcenter/dubbo-configcenter-api/src/test/java/org/apache/dubbo/configcenter/mock/MockDynamicConfigurationFactory.java
rename to dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/proxy/RemoteMetadataServiceProxyFactory.java
index 13482b7..3544294 100644
--- a/dubbo-configcenter/dubbo-configcenter-api/src/test/java/org/apache/dubbo/configcenter/mock/MockDynamicConfigurationFactory.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/proxy/RemoteMetadataServiceProxyFactory.java
@@ -14,19 +14,22 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.configcenter.mock;
+package org.apache.dubbo.registry.client.metadata.proxy;
 
-import org.apache.dubbo.common.URL;
-import org.apache.dubbo.configcenter.AbstractDynamicConfigurationFactory;
-import org.apache.dubbo.configcenter.DynamicConfiguration;
+import org.apache.dubbo.metadata.MetadataService;
+import org.apache.dubbo.metadata.WritableMetadataService;
+import org.apache.dubbo.registry.client.ServiceInstance;
+
+import static org.apache.dubbo.common.constants.CommonConstants.METADATA_REMOTE;
 
 /**
  *
  */
-public class MockDynamicConfigurationFactory extends AbstractDynamicConfigurationFactory {
+public class RemoteMetadataServiceProxyFactory implements MetadataServiceProxyFactory {
 
     @Override
-    protected DynamicConfiguration createDynamicConfiguration(URL url) {
-        return new MockDynamicConfiguration(url);
+    public MetadataService getProxy(ServiceInstance serviceInstance) {
+        return WritableMetadataService.getExtension(METADATA_REMOTE);
     }
+
 }
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/AbstractConfiguratorListener.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/AbstractConfiguratorListener.java
index 5258d24..7a135a7 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/AbstractConfiguratorListener.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/AbstractConfiguratorListener.java
@@ -16,14 +16,14 @@
  */
 package org.apache.dubbo.registry.integration;
 
+import org.apache.dubbo.common.config.configcenter.ConfigChangeEvent;
+import org.apache.dubbo.common.config.configcenter.ConfigChangeType;
+import org.apache.dubbo.common.config.configcenter.ConfigurationListener;
+import org.apache.dubbo.common.config.configcenter.DynamicConfiguration;
 import org.apache.dubbo.common.constants.CommonConstants;
 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.configcenter.ConfigChangeEvent;
-import org.apache.dubbo.configcenter.ConfigChangeType;
-import org.apache.dubbo.configcenter.ConfigurationListener;
-import org.apache.dubbo.configcenter.DynamicConfiguration;
 import org.apache.dubbo.rpc.cluster.Configurator;
 import org.apache.dubbo.rpc.cluster.configurator.parser.ConfigParser;
 
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryDirectory.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryDirectory.java
index 2f3a835..20759a5 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryDirectory.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryDirectory.java
@@ -19,6 +19,7 @@ package org.apache.dubbo.registry.integration;
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.URLBuilder;
 import org.apache.dubbo.common.Version;
+import org.apache.dubbo.common.config.configcenter.DynamicConfiguration;
 import org.apache.dubbo.common.extension.ExtensionLoader;
 import org.apache.dubbo.common.logger.Logger;
 import org.apache.dubbo.common.logger.LoggerFactory;
@@ -27,7 +28,6 @@ import org.apache.dubbo.common.utils.CollectionUtils;
 import org.apache.dubbo.common.utils.NetUtils;
 import org.apache.dubbo.common.utils.StringUtils;
 import org.apache.dubbo.common.utils.UrlUtils;
-import org.apache.dubbo.configcenter.DynamicConfiguration;
 import org.apache.dubbo.registry.NotifyListener;
 import org.apache.dubbo.registry.Registry;
 import org.apache.dubbo.remoting.Constants;
@@ -605,6 +605,11 @@ public class RegistryDirectory<T> extends AbstractDirectory<T> implements Notify
     }
 
     @Override
+    public List<Invoker<T>> getAllInvokers() {
+        return invokers;
+    }
+
+    @Override
     public URL getUrl() {
         return this.overrideDirectoryUrl;
     }
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryProtocol.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryProtocol.java
index 9afa7ab..a394388 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryProtocol.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryProtocol.java
@@ -19,6 +19,7 @@ package org.apache.dubbo.registry.integration;
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.URLBuilder;
 import org.apache.dubbo.common.config.ConfigurationUtils;
+import org.apache.dubbo.common.config.configcenter.DynamicConfiguration;
 import org.apache.dubbo.common.extension.ExtensionLoader;
 import org.apache.dubbo.common.logger.Logger;
 import org.apache.dubbo.common.logger.LoggerFactory;
@@ -26,13 +27,10 @@ import org.apache.dubbo.common.utils.CollectionUtils;
 import org.apache.dubbo.common.utils.NamedThreadFactory;
 import org.apache.dubbo.common.utils.StringUtils;
 import org.apache.dubbo.common.utils.UrlUtils;
-import org.apache.dubbo.configcenter.DynamicConfiguration;
 import org.apache.dubbo.registry.NotifyListener;
 import org.apache.dubbo.registry.Registry;
 import org.apache.dubbo.registry.RegistryFactory;
 import org.apache.dubbo.registry.RegistryService;
-import org.apache.dubbo.registry.support.ProviderConsumerRegTable;
-import org.apache.dubbo.registry.support.ProviderInvokerWrapper;
 import org.apache.dubbo.rpc.Exporter;
 import org.apache.dubbo.rpc.Invoker;
 import org.apache.dubbo.rpc.Protocol;
@@ -41,6 +39,7 @@ import org.apache.dubbo.rpc.RpcException;
 import org.apache.dubbo.rpc.cluster.Cluster;
 import org.apache.dubbo.rpc.cluster.Configurator;
 import org.apache.dubbo.rpc.model.ApplicationModel;
+import org.apache.dubbo.rpc.model.invoker.ProviderInvokerWrapper;
 import org.apache.dubbo.rpc.protocol.InvokerWrapper;
 
 import java.util.ArrayList;
@@ -211,7 +210,7 @@ public class RegistryProtocol implements Protocol {
         // url to registry
         final Registry registry = getRegistry(originInvoker);
         final URL registeredProviderUrl = getRegisteredProviderUrl(providerUrl, registryUrl);
-        ProviderInvokerWrapper<T> providerInvokerWrapper = ProviderConsumerRegTable.registerProvider(originInvoker,
+        ProviderInvokerWrapper<T> providerInvokerWrapper = ApplicationModel.registerProviderInvoker(originInvoker,
                 registryUrl, registeredProviderUrl);
         //to judge if we need to delay publish
         boolean register = registeredProviderUrl.getParameter("register", true);
@@ -254,8 +253,8 @@ public class RegistryProtocol implements Protocol {
         final URL registeredProviderUrl = getRegisteredProviderUrl(newInvokerUrl, registryUrl);
 
         //decide if we need to re-publish
-        ProviderInvokerWrapper<T> providerInvokerWrapper = ProviderConsumerRegTable.getProviderWrapper(registeredProviderUrl, originInvoker);
-        ProviderInvokerWrapper<T> newProviderInvokerWrapper = ProviderConsumerRegTable.registerProvider(originInvoker, registryUrl, registeredProviderUrl);
+        ProviderInvokerWrapper<T> providerInvokerWrapper = ApplicationModel.getProviderInvoker(registeredProviderUrl.getServiceKey(), originInvoker);
+        ProviderInvokerWrapper<T> newProviderInvokerWrapper = ApplicationModel.registerProviderInvoker(originInvoker, registryUrl, registeredProviderUrl);
         /**
          * Only if the new url going to Registry is different with the previous one should we do unregister and register.
          */
@@ -412,7 +411,7 @@ public class RegistryProtocol implements Protocol {
                 PROVIDERS_CATEGORY + "," + CONFIGURATORS_CATEGORY + "," + ROUTERS_CATEGORY));
 
         Invoker invoker = cluster.join(directory);
-        ProviderConsumerRegTable.registerConsumer(invoker, url, subscribeUrl, directory);
+        ApplicationModel.registerConsumerInvoker(invoker, subscribeUrl.getServiceKey());
         return invoker;
     }
 
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/support/ConsumerInvokerWrapper.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/support/ConsumerInvokerWrapper.java
deleted file mode 100644
index 141634d..0000000
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/support/ConsumerInvokerWrapper.java
+++ /dev/null
@@ -1,88 +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.registry.integration.RegistryDirectory;
-import org.apache.dubbo.rpc.Invocation;
-import org.apache.dubbo.rpc.Invoker;
-import org.apache.dubbo.rpc.Result;
-import org.apache.dubbo.rpc.RpcException;
-
-/**
- * @date 2017/11/23
- */
-public class ConsumerInvokerWrapper<T> implements Invoker {
-    private Invoker<T> invoker;
-    private URL originUrl;
-    private URL registryUrl;
-    private URL consumerUrl;
-    private RegistryDirectory registryDirectory;
-
-    public ConsumerInvokerWrapper(Invoker<T> invoker, URL registryUrl, URL consumerUrl, RegistryDirectory registryDirectory) {
-        this.invoker = invoker;
-        this.originUrl = URL.valueOf(invoker.getUrl().toFullString());
-        this.registryUrl = URL.valueOf(registryUrl.toFullString());
-        this.consumerUrl = consumerUrl;
-        this.registryDirectory = registryDirectory;
-    }
-
-    @Override
-    public Class<T> getInterface() {
-        return invoker.getInterface();
-    }
-
-    @Override
-    public URL getUrl() {
-        return invoker.getUrl();
-    }
-
-    @Override
-    public boolean isAvailable() {
-        return invoker.isAvailable();
-    }
-
-    @Override
-    public Result invoke(Invocation invocation) throws RpcException {
-        return invoker.invoke(invocation);
-    }
-
-    @Override
-    public void destroy() {
-        invoker.destroy();
-    }
-
-    public URL getOriginUrl() {
-        return originUrl;
-    }
-
-    public URL getRegistryUrl() {
-        return registryUrl;
-    }
-
-    public Invoker<T> getInvoker() {
-        return invoker;
-    }
-
-    public URL getConsumerUrl() {
-        return consumerUrl;
-    }
-
-    public RegistryDirectory getRegistryDirectory() {
-        return registryDirectory;
-    }
-}
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/support/ProviderConsumerRegTable.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/support/ProviderConsumerRegTable.java
deleted file mode 100644
index 9af3988..0000000
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/support/ProviderConsumerRegTable.java
+++ /dev/null
@@ -1,112 +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.ConcurrentHashSet;
-import org.apache.dubbo.registry.integration.RegistryDirectory;
-import org.apache.dubbo.rpc.Invoker;
-
-import java.util.Collections;
-import java.util.Map;
-import java.util.Objects;
-import java.util.HashSet;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-
-/**
- * @date 2017/11/23
- */
-public class ProviderConsumerRegTable {
-    public static ConcurrentHashMap<String, ConcurrentMap<Invoker, ProviderInvokerWrapper>> providerInvokers = new ConcurrentHashMap<>();
-    public static ConcurrentHashMap<String, Set<ConsumerInvokerWrapper>> consumerInvokers = new ConcurrentHashMap<>();
-
-    public static <T> ProviderInvokerWrapper<T> registerProvider(Invoker<T> invoker, URL registryUrl, URL providerUrl) {
-        ProviderInvokerWrapper<T> wrapperInvoker = new ProviderInvokerWrapper<>(invoker, registryUrl, providerUrl);
-        String serviceUniqueName = providerUrl.getServiceKey();
-        ConcurrentMap<Invoker, ProviderInvokerWrapper> invokers = providerInvokers.get(serviceUniqueName);
-        if (invokers == null) {
-            providerInvokers.putIfAbsent(serviceUniqueName, new ConcurrentHashMap<>());
-            invokers = providerInvokers.get(serviceUniqueName);
-        }
-        invokers.put(invoker, wrapperInvoker);
-        return wrapperInvoker;
-    }
-
-    /*public static ProviderInvokerWrapper removeProviderWrapper(Invoker invoker, URL providerUrl) {
-        String serviceUniqueName = providerUrl.getServiceKey();
-        Set<ProviderInvokerWrapper> invokers = providerInvokers.get(serviceUniqueName);
-        if (invokers == null) {
-            return null;
-        }
-        return invokers.remove(new ProviderIndvokerWrapper(invoker, null, null));
-    }*/
-
-    public static Set<ProviderInvokerWrapper> getProviderInvoker(String serviceUniqueName) {
-        ConcurrentMap<Invoker, ProviderInvokerWrapper> invokers = providerInvokers.get(serviceUniqueName);
-        if (invokers == null) {
-            return Collections.emptySet();
-        }
-        return new HashSet<>(invokers.values());
-    }
-
-    public static <T> ProviderInvokerWrapper<T> getProviderWrapper(URL registeredProviderUrl, Invoker<T> invoker) {
-        String serviceUniqueName = registeredProviderUrl.getServiceKey();
-        ConcurrentMap<Invoker, ProviderInvokerWrapper> invokers = providerInvokers.get(serviceUniqueName);
-        if (invokers == null) {
-            return null;
-        }
-
-        for (Map.Entry<Invoker, ProviderInvokerWrapper> entry : invokers.entrySet()) {
-            if (entry.getKey() == invoker) {
-                return entry.getValue();
-            }
-        }
-
-        return null;
-    }
-
-    public static void registerConsumer(Invoker invoker, URL registryUrl, URL consumerUrl, RegistryDirectory registryDirectory) {
-        ConsumerInvokerWrapper wrapperInvoker = new ConsumerInvokerWrapper(invoker, registryUrl, consumerUrl, registryDirectory);
-        String serviceUniqueName = consumerUrl.getServiceKey();
-        Set<ConsumerInvokerWrapper> invokers = consumerInvokers.get(serviceUniqueName);
-        if (invokers == null) {
-            consumerInvokers.putIfAbsent(serviceUniqueName, new ConcurrentHashSet<ConsumerInvokerWrapper>());
-            invokers = consumerInvokers.get(serviceUniqueName);
-        }
-        invokers.add(wrapperInvoker);
-    }
-
-    public static Set<ConsumerInvokerWrapper> getConsumerInvoker(String serviceUniqueName) {
-        Set<ConsumerInvokerWrapper> invokers = consumerInvokers.get(serviceUniqueName);
-        return invokers == null ? Collections.emptySet() : invokers;
-    }
-
-    public static boolean isRegistered(String serviceUniqueName) {
-        Set<ProviderInvokerWrapper> providerInvokerWrapperSet = ProviderConsumerRegTable.getProviderInvoker(serviceUniqueName);
-        return providerInvokerWrapperSet.stream().anyMatch(ProviderInvokerWrapper::isReg);
-    }
-
-    public static int getConsumerAddressNum(String serviceUniqueName) {
-        Set<ConsumerInvokerWrapper> providerInvokerWrapperSet = ProviderConsumerRegTable.getConsumerInvoker(serviceUniqueName);
-        return providerInvokerWrapperSet.stream()
-                .map(w -> w.getRegistryDirectory().getUrlInvokerMap())
-                .filter(Objects::nonNull)
-                .mapToInt(Map::size).sum();
-    }
-}
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/support/ServiceOrientedRegistry.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/support/ServiceOrientedRegistry.java
index 945df0d..3d1f613 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/support/ServiceOrientedRegistry.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/support/ServiceOrientedRegistry.java
@@ -20,15 +20,15 @@ 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.LocalMetadataService;
 import org.apache.dubbo.metadata.MetadataService;
 import org.apache.dubbo.metadata.ServiceNameMapping;
+import org.apache.dubbo.metadata.WritableMetadataService;
 import org.apache.dubbo.registry.NotifyListener;
 import org.apache.dubbo.registry.Registry;
 import org.apache.dubbo.registry.client.ServiceDiscovery;
 import org.apache.dubbo.registry.client.ServiceDiscoveryFactory;
 import org.apache.dubbo.registry.client.ServiceInstance;
-import org.apache.dubbo.registry.client.metadata.MetadataServiceProxyFactory;
+import org.apache.dubbo.registry.client.metadata.proxy.MetadataServiceProxyFactory;
 import org.apache.dubbo.registry.client.selector.ServiceInstanceSelector;
 
 import java.util.ArrayList;
@@ -50,6 +50,7 @@ import static java.util.stream.Collectors.toSet;
 import static java.util.stream.Stream.of;
 import static org.apache.dubbo.common.constants.CommonConstants.DUBBO_PROTOCOL;
 import static org.apache.dubbo.common.constants.CommonConstants.GROUP_KEY;
+import static org.apache.dubbo.common.constants.CommonConstants.METADATA_DEFAULT;
 import static org.apache.dubbo.common.constants.CommonConstants.PROTOCOL_KEY;
 import static org.apache.dubbo.common.constants.CommonConstants.PROVIDER_SIDE;
 import static org.apache.dubbo.common.constants.CommonConstants.SIDE_KEY;
@@ -61,6 +62,7 @@ import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoad
 import static org.apache.dubbo.common.utils.CollectionUtils.isEmpty;
 import static org.apache.dubbo.common.utils.CollectionUtils.isNotEmpty;
 import static org.apache.dubbo.common.utils.StringUtils.isBlank;
+import static org.apache.dubbo.metadata.support.Constants.METADATA_REPORT_KEY;
 import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.getExportedServicesRevision;
 import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.getMetadataServiceURLsParams;
 import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.getProviderHost;
@@ -87,18 +89,19 @@ public class ServiceOrientedRegistry extends FailbackRegistry {
 
     private final ServiceNameMapping serviceNameMapping;
 
-    private final LocalMetadataService localMetadataService;
+    private final WritableMetadataService writableMetadataService;
 
     private final MetadataServiceProxyFactory metadataServiceProxyFactory;
 
-
     public ServiceOrientedRegistry(URL registryURL) {
         super(registryURL);
         this.serviceDiscovery = buildServiceDiscovery(registryURL);
         this.subscribedServices = buildSubscribedServices(registryURL);
         this.serviceNameMapping = ServiceNameMapping.getDefaultExtension();
-        this.localMetadataService = LocalMetadataService.getDefaultExtension();
-        this.metadataServiceProxyFactory = MetadataServiceProxyFactory.getDefaultExtension();
+
+        String metadata = registryURL.getParameter(METADATA_REPORT_KEY, METADATA_DEFAULT);
+        this.writableMetadataService = WritableMetadataService.getExtension(metadata);
+        this.metadataServiceProxyFactory = MetadataServiceProxyFactory.getExtension(metadata);
     }
 
     private Set<String> buildSubscribedServices(URL url) {
@@ -140,7 +143,7 @@ public class ServiceOrientedRegistry extends FailbackRegistry {
         if (!shouldRegister(url)) { // Should Not Register
             return;
         }
-        if (localMetadataService.exportURL(url)) {
+        if (writableMetadataService.exportURL(url)) {
             if (logger.isInfoEnabled()) {
                 logger.info(format("The URL[%s] registered successfully.", url.toString()));
             }
@@ -156,7 +159,7 @@ public class ServiceOrientedRegistry extends FailbackRegistry {
         if (!shouldRegister(url)) {
             return;
         }
-        if (localMetadataService.unexportURL(url)) {
+        if (writableMetadataService.unexportURL(url)) {
             if (logger.isInfoEnabled()) {
                 logger.info(format("The URL[%s] deregistered successfully.", url.toString()));
             }
@@ -177,7 +180,7 @@ public class ServiceOrientedRegistry extends FailbackRegistry {
 
     @Override
     public void doUnsubscribe(URL url, NotifyListener listener) {
-        localMetadataService.unsubscribeURL(url);
+        writableMetadataService.unsubscribeURL(url);
     }
 
     @Override
@@ -194,7 +197,7 @@ public class ServiceOrientedRegistry extends FailbackRegistry {
 
     protected void subscribeURLs(URL url, NotifyListener listener) {
 
-        localMetadataService.subscribeURL(url);
+        writableMetadataService.subscribeURL(url);
 
         Set<String> serviceNames = getServices(url);
 
@@ -397,7 +400,7 @@ public class ServiceOrientedRegistry extends FailbackRegistry {
         String protocol = subscribedURL.getParameter(PROTOCOL_KEY);
 
         try {
-            MetadataService metadataService = metadataServiceProxyFactory.createProxy(providerInstance);
+            MetadataService metadataService = metadataServiceProxyFactory.getProxy(providerInstance);
             List<String> urls = metadataService.getExportedURLs(serviceInterface, group, version, protocol);
             exportedURLs = urls.stream().map(URL::valueOf).collect(Collectors.toList());
         } catch (Throwable e) {
diff --git a/dubbo-registry/dubbo-registry-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.client.metadata.proxy.MetadataServiceProxyFactory b/dubbo-registry/dubbo-registry-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.client.metadata.proxy.MetadataServiceProxyFactory
new file mode 100644
index 0000000..d9283de
--- /dev/null
+++ b/dubbo-registry/dubbo-registry-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.client.metadata.proxy.MetadataServiceProxyFactory
@@ -0,0 +1,2 @@
+local=org.apache.dubbo.registry.client.metadata.proxy.DefaultMetadataServiceProxyFactory
+remote=org.apache.dubbo.registry.client.metadata.proxy.RemoteMetadataServiceProxyFactory
\ No newline at end of file
diff --git a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/support/ServiceOrientedRegistryTest.java b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/support/ServiceOrientedRegistryTest.java
index bcbd846..73b88d4 100644
--- a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/support/ServiceOrientedRegistryTest.java
+++ b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/support/ServiceOrientedRegistryTest.java
@@ -17,7 +17,7 @@
 package org.apache.dubbo.registry.support;
 
 import org.apache.dubbo.common.URL;
-import org.apache.dubbo.metadata.LocalMetadataService;
+import org.apache.dubbo.metadata.WritableMetadataService;
 import org.apache.dubbo.registry.NotifyListener;
 
 import org.junit.jupiter.api.BeforeEach;
@@ -66,7 +66,7 @@ public class ServiceOrientedRegistryTest {
 
     private static URL url2 = url.setProtocol("rest");
 
-    private LocalMetadataService metadataService;
+    private WritableMetadataService metadataService;
 
     private ServiceOrientedRegistry registry;
 
@@ -75,7 +75,7 @@ public class ServiceOrientedRegistryTest {
     @BeforeEach
     public void init() {
         registry = ServiceOrientedRegistry.create(registryURL);
-        metadataService = LocalMetadataService.getDefaultExtension();
+        metadataService = WritableMetadataService.getDefaultExtension();
         notifyListener = new MyNotifyListener();
     }
 
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 65ba64f..929b17e 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
@@ -19,10 +19,6 @@ import org.apache.dubbo.common.URL;
 import org.apache.dubbo.registry.client.ServiceDiscovery;
 import org.apache.dubbo.registry.client.ServiceDiscoveryFactory;
 
-import com.alibaba.nacos.api.naming.NamingService;
-
-import static org.apache.dubbo.registry.nacos.util.NacosNamingServiceUtils.createNamingService;
-
 /**
  * Nacos {@link ServiceDiscoveryFactory}
  *
diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/model/ApplicationModel.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/model/ApplicationModel.java
index 33dcc90..2860a29 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/model/ApplicationModel.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/model/ApplicationModel.java
@@ -16,10 +16,14 @@
  */
 package org.apache.dubbo.rpc.model;
 
+import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.logger.Logger;
 import org.apache.dubbo.common.logger.LoggerFactory;
+import org.apache.dubbo.rpc.Invoker;
+import org.apache.dubbo.rpc.model.invoker.ProviderInvokerWrapper;
 
 import java.util.Collection;
+import java.util.Collections;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 
@@ -33,15 +37,14 @@ import java.util.concurrent.ConcurrentMap;
  * adjust project structure in order to fully utilize the methods introduced here.
  */
 public class ApplicationModel {
-
     protected static final Logger LOGGER = LoggerFactory.getLogger(ApplicationModel.class);
 
     /**
-     * full qualified class name -> provided service
+     * serviceKey -> exported service
      */
     private static final ConcurrentMap<String, ProviderModel> PROVIDED_SERVICES = new ConcurrentHashMap<>();
     /**
-     * full qualified class name -> subscribe service
+     * serviceKey -> referred service
      */
     private static final ConcurrentMap<String, ConsumerModel> CONSUMED_SERVICES = new ConcurrentHashMap<>();
 
@@ -55,12 +58,12 @@ public class ApplicationModel {
         return PROVIDED_SERVICES.values();
     }
 
-    public static ProviderModel getProviderModel(String serviceName) {
-        return PROVIDED_SERVICES.get(serviceName);
+    public static ProviderModel getProviderModel(String serviceKey) {
+        return PROVIDED_SERVICES.get(serviceKey);
     }
 
-    public static ConsumerModel getConsumerModel(String serviceName) {
-        return CONSUMED_SERVICES.get(serviceName);
+    public static ConsumerModel getConsumerModel(String serviceKey) {
+        return CONSUMED_SERVICES.get(serviceKey);
     }
 
     public static void initConsumerModel(String serviceName, ConsumerModel consumerModel) {
@@ -83,6 +86,39 @@ public class ApplicationModel {
         ApplicationModel.application = application;
     }
 
+    public static <T> ProviderInvokerWrapper<T> registerProviderInvoker(Invoker<T> invoker, URL registryUrl, URL providerUrl) {
+        ProviderInvokerWrapper<T> wrapperInvoker = new ProviderInvokerWrapper<>(invoker, registryUrl, providerUrl);
+        ProviderModel providerModel = getProviderModel(providerUrl.getServiceKey());
+        providerModel.addInvoker(wrapperInvoker);
+        return wrapperInvoker;
+    }
+
+    public static Collection<ProviderInvokerWrapper> getProviderInvokers(String serviceKey) {
+        ProviderModel providerModel = getProviderModel(serviceKey);
+        if (providerModel == null) {
+            return Collections.emptySet();
+        }
+        return providerModel.getInvokers();
+    }
+
+    public static <T> ProviderInvokerWrapper<T> getProviderInvoker(String serviceKey, Invoker<T> invoker) {
+        ProviderModel providerModel = getProviderModel(serviceKey);
+        return providerModel.getInvoker(invoker.getUrl().getProtocol());
+    }
+
+    public static boolean isRegistered(String serviceKey) {
+        return getProviderInvokers(serviceKey).stream().anyMatch(ProviderInvokerWrapper::isReg);
+    }
+
+    public static void registerConsumerInvoker(Invoker invoker, String serviceKey) {
+        ConsumerModel consumerModel = getConsumerModel(serviceKey);
+        consumerModel.setInvoker(invoker);
+    }
+
+    public static <T> Invoker<T> getConsumerInvoker(String serviceKey) {
+        return (Invoker<T>) getConsumerModel(serviceKey).getInvoker();
+    }
+
     /**
      * For unit test
      */
diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/model/ConsumerModel.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/model/ConsumerModel.java
index 4c990a5..851cd06 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/model/ConsumerModel.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/model/ConsumerModel.java
@@ -17,6 +17,7 @@
 package org.apache.dubbo.rpc.model;
 
 import org.apache.dubbo.common.utils.Assert;
+import org.apache.dubbo.rpc.Invoker;
 
 import java.lang.reflect.Method;
 import java.util.ArrayList;
@@ -29,34 +30,35 @@ import java.util.Optional;
  * Consumer Model which is about subscribed services.
  */
 public class ConsumerModel {
-    private final Object proxyObject;
-    private final String serviceName;
+    private final String serviceKey;
     private final Class<?> serviceInterfaceClass;
 
     private final Map<Method, ConsumerMethodModel> methodModels = new IdentityHashMap<Method, ConsumerMethodModel>();
 
+    private Object proxyObject;
+    private Invoker<?> invoker;
+
     /**
      *  This constructor create an instance of ConsumerModel and passed objects should not be null.
      *  If service name, service instance, proxy object,methods should not be null. If these are null
      *  then this constructor will throw {@link IllegalArgumentException}
-     * @param serviceName Name of the service.
+     * @param serviceKey Name of the service.
      * @param serviceInterfaceClass Service interface class.
      * @param proxyObject  Proxy object.
      * @param methods Methods of service class
      * @param attributes Attributes of methods.
      */
-    public ConsumerModel(String serviceName
+    public ConsumerModel(String serviceKey
             , Class<?> serviceInterfaceClass
             , Object proxyObject
             , Method[] methods
             , Map<String, Object> attributes) {
 
-        Assert.notEmptyString(serviceName, "Service name can't be null or blank");
+        Assert.notEmptyString(serviceKey, "Service name can't be null or blank");
         Assert.notNull(serviceInterfaceClass, "Service interface class can't null");
-        Assert.notNull(proxyObject, "Proxy object can't be null");
         Assert.notNull(methods, "Methods can't be null");
 
-        this.serviceName = serviceName;
+        this.serviceKey = serviceKey;
         this.serviceInterfaceClass = serviceInterfaceClass;
         this.proxyObject = proxyObject;
         for (Method method : methods) {
@@ -106,7 +108,19 @@ public class ConsumerModel {
         return serviceInterfaceClass;
     }
 
-    public String getServiceName() {
-        return serviceName;
+    public String getServiceKey() {
+        return serviceKey;
+    }
+
+    public void setProxyObject(Object proxyObject) {
+        this.proxyObject = proxyObject;
+    }
+
+    public Invoker<?> getInvoker() {
+        return invoker;
+    }
+
+    public void setInvoker(Invoker<?> invoker) {
+        this.invoker = invoker;
     }
 }
diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/model/ProviderModel.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/model/ProviderModel.java
index 6fb9beb..48d9ac7 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/model/ProviderModel.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/model/ProviderModel.java
@@ -16,9 +16,13 @@
  */
 package org.apache.dubbo.rpc.model;
 
+import org.apache.dubbo.rpc.model.invoker.ProviderInvokerWrapper;
+
 import java.lang.reflect.Method;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -27,17 +31,20 @@ import java.util.Map;
  * ProviderModel which is about published services
  */
 public class ProviderModel {
-    private final String serviceName;
+    private final String serviceKey;
     private final Object serviceInstance;
     private final Class<?> serviceInterfaceClass;
     private final Map<String, List<ProviderMethodModel>> methods = new HashMap<String, List<ProviderMethodModel>>();
 
-    public ProviderModel(String serviceName, Object serviceInstance, Class<?> serviceInterfaceClass) {
+    private Map<String, ProviderInvokerWrapper> protocolInvokers = new HashMap<>();
+
+
+    public ProviderModel(String serviceKey, Object serviceInstance, Class<?> serviceInterfaceClass) {
         if (null == serviceInstance) {
-            throw new IllegalArgumentException("Service[" + serviceName + "]Target is NULL.");
+            throw new IllegalArgumentException("Service[" + serviceKey + "]Target is NULL.");
         }
 
-        this.serviceName = serviceName;
+        this.serviceKey = serviceKey;
         this.serviceInstance = serviceInstance;
         this.serviceInterfaceClass = serviceInterfaceClass;
 
@@ -45,8 +52,8 @@ public class ProviderModel {
     }
 
 
-    public String getServiceName() {
-        return serviceName;
+    public String getServiceKey() {
+        return serviceKey;
     }
 
     public Class<?> getServiceInterfaceClass() {
@@ -89,8 +96,20 @@ public class ProviderModel {
                 methodModels = new ArrayList<ProviderMethodModel>(1);
                 methods.put(method.getName(), methodModels);
             }
-            methodModels.add(new ProviderMethodModel(method, serviceName));
+            methodModels.add(new ProviderMethodModel(method, serviceKey));
         }
     }
 
+
+    public void addInvoker(ProviderInvokerWrapper invoker) {
+        protocolInvokers.put(invoker.getUrl().getProtocol(), invoker);
+    }
+
+    public ProviderInvokerWrapper getInvoker(String protocol) {
+        return protocolInvokers.get(protocol);
+    }
+
+    public Collection<ProviderInvokerWrapper> getInvokers() {
+        return Collections.unmodifiableCollection(protocolInvokers.values());
+    }
 }
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/support/ProviderInvokerWrapper.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/model/invoker/ProviderInvokerWrapper.java
similarity index 95%
rename from dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/support/ProviderInvokerWrapper.java
rename to dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/model/invoker/ProviderInvokerWrapper.java
index ce079b7..cc19589 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/support/ProviderInvokerWrapper.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/model/invoker/ProviderInvokerWrapper.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.registry.support;
+package org.apache.dubbo.rpc.model.invoker;
 
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.rpc.Invocation;
@@ -32,7 +32,7 @@ public class ProviderInvokerWrapper<T> implements Invoker {
     private URL providerUrl;
     private volatile boolean isReg;
 
-    public ProviderInvokerWrapper(Invoker<T> invoker,URL registryUrl,URL providerUrl) {
+    public ProviderInvokerWrapper(Invoker<T> invoker, URL registryUrl, URL providerUrl) {
         this.invoker = invoker;
         this.originUrl = URL.valueOf(invoker.getUrl().toFullString());
         this.registryUrl = URL.valueOf(registryUrl.toFullString());
diff --git a/dubbo-rpc/dubbo-rpc-dubbo/pom.xml b/dubbo-rpc/dubbo-rpc-dubbo/pom.xml
index dc6cd22..99fdf5a 100644
--- a/dubbo-rpc/dubbo-rpc-dubbo/pom.xml
+++ b/dubbo-rpc/dubbo-rpc-dubbo/pom.xml
@@ -41,8 +41,8 @@
         </dependency>
         <dependency>
             <groupId>org.apache.dubbo</groupId>
-            <artifactId>dubbo-config-api</artifactId>
-            <version>${project.version}</version>
+            <artifactId>dubbo-cluster</artifactId>
+            <version>${project.parent.version}</version>
         </dependency>
         <dependency>
             <groupId>org.apache.dubbo</groupId>
@@ -61,11 +61,6 @@
         </dependency>
         <dependency>
             <groupId>org.apache.dubbo</groupId>
-            <artifactId>dubbo-configcenter-api</artifactId>
-            <version>${project.parent.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.dubbo</groupId>
             <artifactId>dubbo-remoting-netty4</artifactId>
             <version>${project.parent.version}</version>
             <scope>test</scope>
diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/telnet/InvokeTelnetHandler.java b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/telnet/InvokeTelnetHandler.java
index 3998026..de3a2a5 100644
--- a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/telnet/InvokeTelnetHandler.java
+++ b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/telnet/InvokeTelnetHandler.java
@@ -152,7 +152,7 @@ public class InvokeTelnetHandler implements TelnetHandler {
 
 
     private boolean isServiceMatch(String service, ProviderModel provider) {
-        return provider.getServiceName().equalsIgnoreCase(service)
+        return provider.getServiceKey().equalsIgnoreCase(service)
                 || provider.getServiceInterfaceClass().getSimpleName().equalsIgnoreCase(service)
                 || provider.getServiceInterfaceClass().getName().equalsIgnoreCase(service)
                 || StringUtils.isEmpty(service);
diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/telnet/ListTelnetHandler.java b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/telnet/ListTelnetHandler.java
index 0eaf1a2..9dd0a8a 100644
--- a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/telnet/ListTelnetHandler.java
+++ b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/telnet/ListTelnetHandler.java
@@ -22,6 +22,7 @@ import org.apache.dubbo.common.utils.StringUtils;
 import org.apache.dubbo.remoting.Channel;
 import org.apache.dubbo.remoting.telnet.TelnetHandler;
 import org.apache.dubbo.remoting.telnet.support.Help;
+import org.apache.dubbo.rpc.cluster.support.AbstractClusterInvoker;
 import org.apache.dubbo.rpc.model.ApplicationModel;
 import org.apache.dubbo.rpc.model.ConsumerMethodModel;
 import org.apache.dubbo.rpc.model.ConsumerModel;
@@ -30,9 +31,6 @@ import org.apache.dubbo.rpc.model.ProviderModel;
 
 import java.lang.reflect.Method;
 
-import static org.apache.dubbo.registry.support.ProviderConsumerRegTable.getConsumerAddressNum;
-import static org.apache.dubbo.registry.support.ProviderConsumerRegTable.isRegistered;
-
 /**
  * ListTelnetHandler handler list services and its methods details.
  */
@@ -87,11 +85,11 @@ public class ListTelnetHandler implements TelnetHandler {
         }
 
         for (ProviderModel provider : ApplicationModel.allProviderModels()) {
-            buf.append(provider.getServiceName());
+            buf.append(provider.getServiceKey());
             if (detail) {
                 buf.append(" -> ");
                 buf.append(" published: ");
-                buf.append(isRegistered(provider.getServiceName()) ? "Y" : "N");
+                buf.append(ApplicationModel.isRegistered(provider.getServiceKey()) ? "Y" : "N");
             }
             buf.append("\r\n");
         }
@@ -103,11 +101,11 @@ public class ListTelnetHandler implements TelnetHandler {
         }
 
         for (ConsumerModel consumer : ApplicationModel.allConsumerModels()) {
-            buf.append(consumer.getServiceName());
+            buf.append(consumer.getServiceKey());
             if (detail) {
                 buf.append(" -> ");
                 buf.append(" addresses: ");
-                buf.append(getConsumerAddressNum(consumer.getServiceName()));
+                buf.append(((AbstractClusterInvoker) consumer.getInvoker()).getDirectory().getAllInvokers().size());
             }
         }
     }
@@ -120,7 +118,7 @@ public class ListTelnetHandler implements TelnetHandler {
     private void printSpecifiedProvidedService(String service, StringBuilder buf, boolean detail) {
         for (ProviderModel provider : ApplicationModel.allProviderModels()) {
             if (isProviderMatched(service,provider)) {
-                buf.append(provider.getServiceName()).append(" (as provider):\r\n");
+                buf.append(provider.getServiceKey()).append(" (as provider):\r\n");
                 for (ProviderMethodModel method : provider.getAllMethods()) {
                     printMethod(method.getMethod(), buf, detail);
                 }
@@ -131,7 +129,7 @@ public class ListTelnetHandler implements TelnetHandler {
     private void printSpecifiedReferredService(String service, StringBuilder buf, boolean detail) {
         for (ConsumerModel consumer : ApplicationModel.allConsumerModels()) {
             if (isConsumerMatcher(service,consumer)) {
-                buf.append(consumer.getServiceName()).append(" (as consumer):\r\n");
+                buf.append(consumer.getServiceKey()).append(" (as consumer):\r\n");
                 for (ConsumerMethodModel method : consumer.getAllMethods()) {
                     printMethod(method.getMethod(), buf, detail);
                 }
@@ -149,13 +147,13 @@ public class ListTelnetHandler implements TelnetHandler {
     }
 
     private boolean isProviderMatched(String service, ProviderModel provider) {
-        return service.equalsIgnoreCase(provider.getServiceName())
+        return service.equalsIgnoreCase(provider.getServiceKey())
                 || service.equalsIgnoreCase(provider.getServiceInterfaceClass().getName())
                 || service.equalsIgnoreCase(provider.getServiceInterfaceClass().getSimpleName());
     }
 
     private boolean isConsumerMatcher(String service,ConsumerModel consumer) {
-        return service.equalsIgnoreCase(consumer.getServiceName())
+        return service.equalsIgnoreCase(consumer.getServiceKey())
                 || service.equalsIgnoreCase(consumer.getServiceInterfaceClass().getName())
                 || service.equalsIgnoreCase(consumer.getServiceInterfaceClass().getSimpleName());
     }
diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.remoting.telnet.TelnetHandler b/dubbo-rpc/dubbo-rpc-dubbo/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.remoting.telnet.TelnetHandler
index 9911163..ef32515 100644
--- a/dubbo-rpc/dubbo-rpc-dubbo/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.remoting.telnet.TelnetHandler
+++ b/dubbo-rpc/dubbo-rpc-dubbo/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.remoting.telnet.TelnetHandler
@@ -5,5 +5,4 @@ pwd=org.apache.dubbo.rpc.protocol.dubbo.telnet.CurrentTelnetHandler
 invoke=org.apache.dubbo.rpc.protocol.dubbo.telnet.InvokeTelnetHandler
 trace=org.apache.dubbo.rpc.protocol.dubbo.telnet.TraceTelnetHandler
 count=org.apache.dubbo.rpc.protocol.dubbo.telnet.CountTelnetHandler
-select=org.apache.dubbo.rpc.protocol.dubbo.telnet.SelectTelnetHandler
-shutdown=org.apache.dubbo.rpc.protocol.dubbo.telnet.ShutdownTelnetHandler
\ No newline at end of file
+select=org.apache.dubbo.rpc.protocol.dubbo.telnet.SelectTelnetHandler
\ No newline at end of file
diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/FutureFilterTest.java b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/FutureFilterTest.java
index 500a95e..1a1b0fd 100644
--- a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/FutureFilterTest.java
+++ b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/FutureFilterTest.java
@@ -30,7 +30,6 @@ import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.Test;
 
-import static org.apache.dubbo.config.Constants.ON_THROW_METHOD_KEY;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.mockito.BDDMockito.given;
 import static org.mockito.Mockito.mock;
@@ -77,7 +76,7 @@ public class FutureFilterTest {
             AppResponse result = new AppResponse();
             result.setException(new RuntimeException());
             given(invoker.invoke(invocation)).willReturn(result);
-            URL url = URL.valueOf("test://test:11/test?group=dubbo&version=1.1&" + ON_THROW_METHOD_KEY + "=echo");
+            URL url = URL.valueOf("test://test:11/test?group=dubbo&version=1.1&onthrow.method=echo");
             given(invoker.getUrl()).willReturn(url);
 
             eventFilter.invoke(invoker, invocation).recreate();
diff --git a/pom.xml b/pom.xml
index 0846744..7bdde08 100644
--- a/pom.xml
+++ b/pom.xml
@@ -146,7 +146,6 @@
         <module>dubbo-bom</module>
         <module>dubbo-all</module>
         <module>dubbo-distribution</module>
-        <module>dubbo-metadata-report</module>
         <module>dubbo-configcenter</module>
         <module>dubbo-dependencies</module>
         <module>dubbo-event</module>