You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@dubbo.apache.org by vi...@apache.org on 2019/08/12 08:59:47 UTC

[dubbo] 01/03: refactor metadata

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

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

commit a09ba30001b6e9e39d68746fac1d39a6a0701014
Author: cvictory <sh...@gmail.com>
AuthorDate: Mon Aug 12 09:57:27 2019 +0800

    refactor metadata
---
 .../org/apache/dubbo/bootstrap/DubboBootstrap.java |  5 +-
 .../DynamicConfigurationServiceNameMapping.java    |  6 +-
 .../apache/dubbo/metadata/MetadataConstants.java   | 11 ++++
 .../org/apache/dubbo/metadata/MetadataUtil.java    |  8 +--
 .../dubbo/metadata/report/MetadataReport.java      |  6 +-
 .../metadata/report/MetadataReportInstance.java    | 52 +++++++++++++++
 .../report/identifier/BaseMetadataIdentifier.java  | 67 +++++++++++++++++++
 .../report/identifier/MetadataIdentifier.java      | 49 ++------------
 .../identifier/ServiceMetadataIdentifier.java      | 51 +++++++++++++++
 .../report/support/AbstractMetadataReport.java     | 17 ++---
 .../store/InMemoryWritableMetadataService.java     |  2 +-
 .../store/RemoteWritableMetadataService.java       | 76 +++++-----------------
 .../store/RemoteWritableMeatadataServiceTest.java  |  3 +-
 .../store/consul/ConsulMetadataReport.java         |  5 +-
 .../metadata/store/etcd/EtcdMetadataReport.java    |  5 +-
 .../metadata/store/nacos/NacosMetadataReport.java  |  5 +-
 .../metadata/store/redis/RedisMetadataReport.java  |  7 +-
 dubbo-registry/dubbo-registry-api/pom.xml          |  5 --
 .../CompositeMetadataServiceURLBuilder.java        |  1 +
 .../proxy/BaseMetadataServiceProxyFactory.java     | 23 +++++++
 .../proxy/DefaultMetadataServiceProxyFactory.java  |  7 +-
 .../metadata/{ => proxy}/MetadataServiceProxy.java |  4 +-
 .../metadata/proxy/RemoteMetadataServiceProxy.java | 70 ++++++++++++++++++++
 .../proxy/RemoteMetadataServiceProxyFactory.java   |  6 +-
 24 files changed, 341 insertions(+), 150 deletions(-)

diff --git a/dubbo-bootstrap/src/main/java/org/apache/dubbo/bootstrap/DubboBootstrap.java b/dubbo-bootstrap/src/main/java/org/apache/dubbo/bootstrap/DubboBootstrap.java
index 005f11d..2c992f5 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
@@ -48,6 +48,7 @@ import org.apache.dubbo.config.metadata.ConfigurableMetadataServiceExporter;
 import org.apache.dubbo.event.EventDispatcher;
 import org.apache.dubbo.event.EventListener;
 import org.apache.dubbo.metadata.WritableMetadataService;
+import org.apache.dubbo.metadata.report.MetadataReportInstance;
 import org.apache.dubbo.metadata.store.RemoteWritableMetadataService;
 import org.apache.dubbo.registry.client.AbstractServiceDiscoveryFactory;
 import org.apache.dubbo.registry.client.DefaultServiceInstance;
@@ -584,9 +585,7 @@ public class DubboBootstrap {
             return;
         }
 
-        RemoteWritableMetadataService remoteMetadataService =
-                (RemoteWritableMetadataService) WritableMetadataService.getExtension(metadataType);
-        remoteMetadataService.initMetadataReport(metadataReportConfig.toUrl());
+        MetadataReportInstance.init(metadataReportConfig.toUrl());
     }
 
     private void startConfigCenter() {
diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/DynamicConfigurationServiceNameMapping.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/DynamicConfigurationServiceNameMapping.java
index db22c6c..f7c6440 100644
--- a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/DynamicConfigurationServiceNameMapping.java
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/DynamicConfigurationServiceNameMapping.java
@@ -81,9 +81,9 @@ public class DynamicConfigurationServiceNameMapping implements ServiceNameMappin
     protected static String buildGroup(String serviceInterface, String group, String version, String protocol) {
         //        the issue : https://github.com/apache/dubbo/issues/4671
         //        StringBuilder groupBuilder = new StringBuilder(serviceInterface)
-        //                .append(SEPARATOR).append(defaultString(group))
-        //                .append(SEPARATOR).append(defaultString(version))
-        //                .append(SEPARATOR).append(defaultString(protocol));
+        //                .append(KEY_SEPARATOR).append(defaultString(group))
+        //                .append(KEY_SEPARATOR).append(defaultString(version))
+        //                .append(KEY_SEPARATOR).append(defaultString(protocol));
         //        return groupBuilder.toString();
         return serviceInterface;
     }
diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/MetadataConstants.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/MetadataConstants.java
new file mode 100644
index 0000000..cc4da29
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/MetadataConstants.java
@@ -0,0 +1,11 @@
+package org.apache.dubbo.metadata;
+
+/**
+ * @author cvictory ON 2019-08-09
+ */
+public class MetadataConstants {
+    public static final String KEY_SEPARATOR = ":";
+    public static final String DEFAULT_PATH_TAG = "metadata";
+    public static final String META_DATA_STORE_TAG = ".metaData";
+    public static final String SERVICE_META_DATA_STORE_TAG = ".smd";
+}
diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/MetadataUtil.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/MetadataUtil.java
index 6418571..51f5b5f 100644
--- a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/MetadataUtil.java
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/MetadataUtil.java
@@ -12,10 +12,10 @@ public class MetadataUtil {
 //
 //    private String getIdentifierKey() {
 //        return serviceInterface
-//                + SEPARATOR + (version == null ? "" : version)
-//                + SEPARATOR + (group == null ? "" : group)
-//                + SEPARATOR + (side == null ? "" : side)
-//                + SEPARATOR + application;
+//                + KEY_SEPARATOR + (version == null ? "" : version)
+//                + KEY_SEPARATOR + (group == null ? "" : group)
+//                + KEY_SEPARATOR + (side == null ? "" : side)
+//                + KEY_SEPARATOR + application;
 //    }
 //
 //    private String getFilePathKey() {
diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/MetadataReport.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/MetadataReport.java
index ab6f7a8..63b5385 100644
--- a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/MetadataReport.java
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/MetadataReport.java
@@ -20,11 +20,13 @@ package org.apache.dubbo.metadata.report;
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.metadata.definition.model.ServiceDefinition;
 import org.apache.dubbo.metadata.report.identifier.MetadataIdentifier;
+import org.apache.dubbo.metadata.report.identifier.ServiceMetadataIdentifier;
 
 import java.util.List;
 import java.util.Map;
 
 /**
+ *
  */
 public interface MetadataReport {
 
@@ -32,9 +34,9 @@ public interface MetadataReport {
 
     void storeConsumerMetadata(MetadataIdentifier consumerMetadataIdentifier, Map<String, String> serviceParameterMap);
 
-    void saveMetadata(URL url);
+    void saveServiceMetadata(ServiceMetadataIdentifier serviceMetadataIdentifier, URL url);
 
-    void removeMetadata(URL url);
+    void removeServiceMetadata(ServiceMetadataIdentifier serviceMetadataIdentifier, URL url);
 
     List<String> getExportedURLs(MetadataIdentifier metadataIdentifier);
 
diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/MetadataReportInstance.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/MetadataReportInstance.java
new file mode 100644
index 0000000..c3418b7
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/MetadataReportInstance.java
@@ -0,0 +1,52 @@
+package org.apache.dubbo.metadata.report;
+
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.URLBuilder;
+import org.apache.dubbo.common.extension.ExtensionLoader;
+
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_DIRECTORY;
+import static org.apache.dubbo.metadata.report.support.Constants.METADATA_REPORT_KEY;
+
+/**
+ * 2019-08-09
+ */
+public class MetadataReportInstance {
+
+    private static AtomicBoolean init = new AtomicBoolean(false);
+
+    private static MetadataReport metadataReport;
+
+    public static void init(URL metadataReportURL) {
+        if (init.get()) {
+            return;
+        }
+        MetadataReportFactory metadataReportFactory = ExtensionLoader.getExtensionLoader(MetadataReportFactory.class).getAdaptiveExtension();
+        if (METADATA_REPORT_KEY.equals(metadataReportURL.getProtocol())) {
+            String protocol = metadataReportURL.getParameter(METADATA_REPORT_KEY, DEFAULT_DIRECTORY);
+            metadataReportURL = URLBuilder.from(metadataReportURL)
+                    .setProtocol(protocol)
+                    .removeParameter(METADATA_REPORT_KEY)
+                    .build();
+        }
+        metadataReport = metadataReportFactory.getMetadataReport(metadataReportURL);
+    }
+
+    public static MetadataReport getMetadataReport() {
+        return getMetadataReport(false);
+    }
+
+    public static MetadataReport getMetadataReport(boolean checked) {
+        if (checked) {
+            checkInit();
+        }
+        return metadataReport;
+    }
+
+    private static void checkInit() {
+        if (!init.get()) {
+            throw new IllegalStateException("the metadata report was not inited.");
+        }
+    }
+}
diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/identifier/BaseMetadataIdentifier.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/identifier/BaseMetadataIdentifier.java
new file mode 100644
index 0000000..79f517d
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/identifier/BaseMetadataIdentifier.java
@@ -0,0 +1,67 @@
+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.PATH_SEPARATOR;
+import static org.apache.dubbo.metadata.MetadataConstants.DEFAULT_PATH_TAG;
+import static org.apache.dubbo.metadata.MetadataConstants.KEY_SEPARATOR;
+
+/**
+ * @author cvictory ON 2019-08-09
+ */
+public class BaseMetadataIdentifier {
+    String serviceInterface;
+    String version;
+    String group;
+    String side;
+
+    String getUniqueKey(MetadataIdentifier.KeyTypeEnum keyType, String... params) {
+        if (keyType == MetadataIdentifier.KeyTypeEnum.PATH) {
+            return getFilePathKey(params);
+        }
+        return getIdentifierKey(params);
+    }
+
+    String getIdentifierKey(String... params) {
+
+        return serviceInterface
+                + KEY_SEPARATOR + (version == null ? "" : version)
+                + KEY_SEPARATOR + (group == null ? "" : group)
+                + KEY_SEPARATOR + (side == null ? "" : side)
+                + joinParams(KEY_SEPARATOR, params);
+    }
+
+    private String joinParams(String joinChar, String... params) {
+        if (params == null || params.length == 0) {
+            return "";
+        }
+        StringBuilder sb = new StringBuilder();
+        for (String param : params) {
+            sb.append(joinChar);
+            sb.append(param);
+        }
+        return sb.toString();
+    }
+
+    private String getFilePathKey(String... params) {
+        return getFilePathKey(DEFAULT_PATH_TAG, params);
+    }
+
+    private String getFilePathKey(String pathTag, String... params) {
+        return pathTag
+                + (StringUtils.isEmpty(toServicePath()) ? "" : (PATH_SEPARATOR + toServicePath()))
+                + (version == null ? "" : (PATH_SEPARATOR + version))
+                + (group == null ? "" : (PATH_SEPARATOR + group))
+                + (side == null ? "" : (PATH_SEPARATOR + side))
+                + joinParams(PATH_SEPARATOR, params);
+    }
+
+    private String toServicePath() {
+        if (ANY_VALUE.equals(serviceInterface)) {
+            return "";
+        }
+        return URL.encode(serviceInterface);
+    }
+}
diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/identifier/MetadataIdentifier.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/identifier/MetadataIdentifier.java
index 1e70a1d..7cdc759 100644
--- a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/identifier/MetadataIdentifier.java
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/identifier/MetadataIdentifier.java
@@ -17,28 +17,20 @@
 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;
 import static org.apache.dubbo.common.constants.CommonConstants.GROUP_KEY;
-import static org.apache.dubbo.common.constants.CommonConstants.PATH_SEPARATOR;
 import static org.apache.dubbo.common.constants.CommonConstants.SIDE_KEY;
 import static org.apache.dubbo.common.constants.CommonConstants.VERSION_KEY;
+import static org.apache.dubbo.metadata.MetadataConstants.KEY_SEPARATOR;
 
 /**
+ * The MetadataIdentifier is used to store method descriptor.
+ * <p>
  * 2018/10/25
  */
-public class MetadataIdentifier {
+public class MetadataIdentifier extends BaseMetadataIdentifier {
 
-    public static final String SEPARATOR = ":";
-    public final static String DEFAULT_PATH_TAG = "metadata";
-    public final static String META_DATA_STORE_TAG = ".metaData";
-
-    private String serviceInterface;
-    private String version;
-    private String group;
-    private String side;
     private String application;
 
     public MetadataIdentifier() {
@@ -52,6 +44,7 @@ public class MetadataIdentifier {
         this.application = application;
     }
 
+
     public MetadataIdentifier(URL url) {
         this.serviceInterface = url.getServiceInterface();
         this.version = url.getParameter(VERSION_KEY);
@@ -61,41 +54,13 @@ public class MetadataIdentifier {
     }
 
     public String getUniqueKey(KeyTypeEnum keyType) {
-        if (keyType == KeyTypeEnum.PATH) {
-            return getFilePathKey();
-        }
-        return getIdentifierKey();
+        return super.getUniqueKey(keyType, application);
     }
 
     public String getIdentifierKey() {
-        return serviceInterface
-                + SEPARATOR + (version == null ? "" : version)
-                + SEPARATOR + (group == null ? "" : group)
-                + SEPARATOR + (side == null ? "" : side)
-                + SEPARATOR + application;
+        return super.getIdentifierKey(application);
     }
 
-    private String getFilePathKey() {
-        return getFilePathKey(DEFAULT_PATH_TAG);
-    }
-
-    private String getFilePathKey(String pathTag) {
-        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() {
-        if (ANY_VALUE.equals(serviceInterface)) {
-            return "";
-        }
-        return URL.encode(serviceInterface);
-    }
-
-
     public String getServiceInterface() {
         return serviceInterface;
     }
diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/identifier/ServiceMetadataIdentifier.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/identifier/ServiceMetadataIdentifier.java
new file mode 100644
index 0000000..6b07605
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/identifier/ServiceMetadataIdentifier.java
@@ -0,0 +1,51 @@
+package org.apache.dubbo.metadata.report.identifier;
+
+import org.apache.dubbo.common.URL;
+
+import static org.apache.dubbo.common.constants.CommonConstants.GROUP_KEY;
+import static org.apache.dubbo.common.constants.CommonConstants.REVISION_KEY;
+import static org.apache.dubbo.common.constants.CommonConstants.SIDE_KEY;
+import static org.apache.dubbo.common.constants.CommonConstants.VERSION_KEY;
+
+/**
+ * The ServiceMetadataIdentifier is used to store the {@link org.apache.dubbo.common.URL}
+ * that are from provider and consumer
+ * <p>
+ * 2019-08-09
+ */
+public class ServiceMetadataIdentifier extends BaseMetadataIdentifier {
+
+    private String serviceInterface;
+    private String version;
+    private String group;
+    private String side;
+    private String revision;
+
+    public ServiceMetadataIdentifier() {
+    }
+
+    public ServiceMetadataIdentifier(String serviceInterface, String version, String group, String side, String revision) {
+        this.serviceInterface = serviceInterface;
+        this.version = version;
+        this.group = group;
+        this.side = side;
+        this.revision = revision;
+    }
+
+
+    public ServiceMetadataIdentifier(URL url) {
+        this.serviceInterface = url.getServiceInterface();
+        this.version = url.getParameter(VERSION_KEY);
+        this.group = url.getParameter(GROUP_KEY);
+        this.side = url.getParameter(SIDE_KEY);
+        this.revision = (url.getParameter(REVISION_KEY));
+    }
+
+    public String getUniqueKey(MetadataIdentifier.KeyTypeEnum keyType) {
+        return super.getUniqueKey(keyType, revision);
+    }
+
+    public String getIdentifierKey() {
+        return super.getIdentifierKey(revision);
+    }
+}
diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/support/AbstractMetadataReport.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/support/AbstractMetadataReport.java
index a64c887..5d3576c 100644
--- a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/support/AbstractMetadataReport.java
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/support/AbstractMetadataReport.java
@@ -25,6 +25,7 @@ import org.apache.dubbo.metadata.definition.model.FullServiceDefinition;
 import org.apache.dubbo.metadata.definition.model.ServiceDefinition;
 import org.apache.dubbo.metadata.report.MetadataReport;
 import org.apache.dubbo.metadata.report.identifier.MetadataIdentifier;
+import org.apache.dubbo.metadata.report.identifier.ServiceMetadataIdentifier;
 
 import com.google.gson.Gson;
 
@@ -284,20 +285,20 @@ public abstract class AbstractMetadataReport implements MetadataReport {
     }
 
     @Override
-    public void saveMetadata(URL url) {
+    public void saveServiceMetadata(ServiceMetadataIdentifier metadataIdentifier, URL url) {
         if (syncReport) {
-            doSaveMetadata(url);
+            doSaveMetadata(metadataIdentifier, url);
         } else {
-            reportCacheExecutor.execute(() -> doSaveMetadata(url));
+            reportCacheExecutor.execute(() -> doSaveMetadata(metadataIdentifier, url));
         }
     }
 
     @Override
-    public void removeMetadata(URL url) {
+    public void removeServiceMetadata(ServiceMetadataIdentifier metadataIdentifier, URL url) {
         if (syncReport) {
-            doRemoveMetadata(url);
+            doRemoveMetadata(metadataIdentifier, url);
         } else {
-            reportCacheExecutor.execute(() -> doRemoveMetadata(url));
+            reportCacheExecutor.execute(() -> doRemoveMetadata(metadataIdentifier, url));
         }
     }
 
@@ -422,9 +423,9 @@ public abstract class AbstractMetadataReport implements MetadataReport {
 
     protected abstract void doStoreConsumerMetadata(MetadataIdentifier consumerMetadataIdentifier, String serviceParameterString);
 
-    protected abstract void doSaveMetadata(URL url);
+    protected abstract void doSaveMetadata(ServiceMetadataIdentifier metadataIdentifier, URL url);
 
-    protected abstract void doRemoveMetadata(URL url);
+    protected abstract void doRemoveMetadata(ServiceMetadataIdentifier metadataIdentifier, URL url);
 
     protected abstract List<String> doGetExportedURLs();
 
diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/store/InMemoryWritableMetadataService.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/store/InMemoryWritableMetadataService.java
index 7902477..50ec417 100644
--- a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/store/InMemoryWritableMetadataService.java
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/store/InMemoryWritableMetadataService.java
@@ -52,7 +52,7 @@ import static org.apache.dubbo.common.utils.CollectionUtils.isEmpty;
 
 /**
  * The {@link WritableMetadataService} implementation stores the metadata of Dubbo services in memory locally when they
- * exported.
+ * exported. It is used by server (provider).
  *
  * @see MetadataService
  * @see WritableMetadataService
diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/store/RemoteWritableMetadataService.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/store/RemoteWritableMetadataService.java
index 0888b5d..e7144ef 100644
--- a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/store/RemoteWritableMetadataService.java
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/store/RemoteWritableMetadataService.java
@@ -17,71 +17,52 @@
 package org.apache.dubbo.metadata.store;
 
 import org.apache.dubbo.common.URL;
-import org.apache.dubbo.common.URLBuilder;
-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.definition.model.ServiceDefinition;
 import org.apache.dubbo.metadata.report.MetadataReport;
-import org.apache.dubbo.metadata.report.MetadataReportFactory;
+import org.apache.dubbo.metadata.report.MetadataReportInstance;
 import org.apache.dubbo.metadata.report.identifier.MetadataIdentifier;
 import org.apache.dubbo.remoting.Constants;
 import org.apache.dubbo.rpc.RpcException;
 
-import java.util.Collection;
-import java.util.Collections;
-import java.util.SortedSet;
-import java.util.TreeSet;
 import java.util.concurrent.atomic.AtomicBoolean;
 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;
-import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_DIRECTORY;
 import static org.apache.dubbo.common.constants.CommonConstants.GROUP_KEY;
 import static org.apache.dubbo.common.constants.CommonConstants.INTERFACE_KEY;
 import static org.apache.dubbo.common.constants.CommonConstants.PID_KEY;
 import static org.apache.dubbo.common.constants.CommonConstants.PROVIDER_SIDE;
-import static org.apache.dubbo.common.constants.CommonConstants.REVISION_KEY;
 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.report.support.Constants.METADATA_REPORT_KEY;
 
 /**
+ * The {@link WritableMetadataService} implementation stores the metadata of Dubbo services in metadata center when they
+ * exported.
+ * It is used by server (provider).
+ *
  * @since 2.7.0
  */
 public class RemoteWritableMetadataService extends InMemoryWritableMetadataService implements WritableMetadataService {
 
     protected final Logger logger = LoggerFactory.getLogger(getClass());
 
-    private MetadataReportFactory metadataReportFactory = ExtensionLoader.getExtensionLoader(MetadataReportFactory.class).getAdaptiveExtension();
-    private MetadataReport metadataReport;
+
     private AtomicBoolean init;
 
     public RemoteWritableMetadataService() {
-    }
 
-    public void initMetadataReport(URL metadataReportURL) {
-        if (!init.compareAndSet(false, true)) {
-            return;
-        }
-        if (METADATA_REPORT_KEY.equals(metadataReportURL.getProtocol())) {
-            String protocol = metadataReportURL.getParameter(METADATA_REPORT_KEY, DEFAULT_DIRECTORY);
-            metadataReportURL = URLBuilder.from(metadataReportURL)
-                    .setProtocol(protocol)
-                    .removeParameter(METADATA_REPORT_KEY)
-                    .build();
-        }
-        metadataReport = metadataReportFactory.getMetadataReport(metadataReportURL);
     }
 
+
     public MetadataReport getMetadataReport() {
-        return metadataReport;
+        return MetadataReportInstance.getMetadataReport(true);
     }
 
     @Override
@@ -91,7 +72,7 @@ public class RemoteWritableMetadataService extends InMemoryWritableMetadataServi
             if (StringUtils.isNotEmpty(interfaceName)) {
                 Class interfaceClass = Class.forName(interfaceName);
                 ServiceDefinition serviceDefinition = ServiceDefinitionBuilder.build(interfaceClass);
-                metadataReport.storeProviderMetadata(new MetadataIdentifier(providerUrl.getServiceInterface(),
+                getMetadataReport().storeProviderMetadata(new MetadataIdentifier(providerUrl.getServiceInterface(),
                         providerUrl.getParameter(VERSION_KEY), providerUrl.getParameter(GROUP_KEY),
                         null, null), serviceDefinition);
                 return;
@@ -117,7 +98,7 @@ public class RemoteWritableMetadataService extends InMemoryWritableMetadataServi
             if (StringUtils.isNotEmpty(interfaceName)) {
                 Class interfaceClass = Class.forName(interfaceName);
                 FullServiceDefinition fullServiceDefinition = ServiceDefinitionBuilder.buildFullDefinition(interfaceClass, providerUrl.getParameters());
-                metadataReport.storeProviderMetadata(new MetadataIdentifier(providerUrl.getServiceInterface(),
+                getMetadataReport().storeProviderMetadata(new MetadataIdentifier(providerUrl.getServiceInterface(),
                         providerUrl.getParameter(VERSION_KEY), providerUrl.getParameter(GROUP_KEY),
                         PROVIDER_SIDE, providerUrl.getParameter(APPLICATION_KEY)), fullServiceDefinition);
                 return;
@@ -132,7 +113,7 @@ public class RemoteWritableMetadataService extends InMemoryWritableMetadataServi
     @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(),
+        getMetadataReport().storeConsumerMetadata(new MetadataIdentifier(consumerURL.getServiceInterface(),
                 consumerURL.getParameter(VERSION_KEY), consumerURL.getParameter(GROUP_KEY), CONSUMER_SIDE,
                 consumerURL.getParameter(APPLICATION_KEY)), consumerURL.getParameters());
     }
@@ -145,53 +126,26 @@ public class RemoteWritableMetadataService extends InMemoryWritableMetadataServi
     @Override
     public boolean unexportURL(URL url) {
         super.unexportURL(url);
-        return throwableAction(metadataReport::removeMetadata, url);
+        return throwableAction(getMetadataReport()::removeServiceMetadata, url);
     }
 
     @Override
     public boolean subscribeURL(URL url) {
         super.subscribeURL(url);
-        return throwableAction(metadataReport::saveMetadata, url);
+        return throwableAction(getMetadataReport()::saveServiceMetadata, url);
     }
 
     @Override
     public boolean unsubscribeURL(URL url) {
         super.unsubscribeURL(url);
-        return throwableAction(metadataReport::removeMetadata, url);
+        return throwableAction(getMetadataReport()::removeServiceMetadata, url);
     }
 
     @Override
     protected boolean finishRefreshExportedMetadata(URL url) {
-        return throwableAction(metadataReport::saveMetadata, url);
+        return throwableAction(getMetadataReport()::saveServiceMetadata, url);
     }
 
-    @Override
-    public SortedSet<String> getSubscribedURLs() {
-        return toSortedStrings(metadataReport.getSubscribedURLs());
-    }
-
-    // TODO, protocol should be used
-    @Override
-    public SortedSet<String> getExportedURLs(String serviceInterface, String group, String version, String protocol) {
-        return toSortedStrings(metadataReport.getExportedURLs(new MetadataIdentifier(serviceInterface, group, version, null, null)));
-    }
-
-    private static SortedSet<String> toSortedStrings(Collection<String> values) {
-        return Collections.unmodifiableSortedSet(new TreeSet<>(values));
-    }
-
-    @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 {
diff --git a/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/store/RemoteWritableMeatadataServiceTest.java b/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/store/RemoteWritableMeatadataServiceTest.java
index 18e8b70..fe2b4f6 100644
--- a/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/store/RemoteWritableMeatadataServiceTest.java
+++ b/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/store/RemoteWritableMeatadataServiceTest.java
@@ -20,6 +20,7 @@ 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.report.MetadataReportInstance;
 import org.apache.dubbo.metadata.test.JTestMetadataReport4Test;
 
 import com.google.gson.Gson;
@@ -41,7 +42,7 @@ public class RemoteWritableMeatadataServiceTest {
     @BeforeEach
     public void before() {
         metadataReportService1 = (RemoteWritableMetadataService) WritableMetadataService.getExtension(METADATA_REMOTE);
-        metadataReportService1.initMetadataReport(url);
+        MetadataReportInstance.init(url);
     }
 
     @Test
diff --git a/dubbo-metadata/dubbo-metadata-report-consul/src/main/java/org/apache/dubbo/metadata/store/consul/ConsulMetadataReport.java b/dubbo-metadata/dubbo-metadata-report-consul/src/main/java/org/apache/dubbo/metadata/store/consul/ConsulMetadataReport.java
index 89227e5..3c84263 100644
--- a/dubbo-metadata/dubbo-metadata-report-consul/src/main/java/org/apache/dubbo/metadata/store/consul/ConsulMetadataReport.java
+++ b/dubbo-metadata/dubbo-metadata-report-consul/src/main/java/org/apache/dubbo/metadata/store/consul/ConsulMetadataReport.java
@@ -21,6 +21,7 @@ import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.logger.Logger;
 import org.apache.dubbo.common.logger.LoggerFactory;
 import org.apache.dubbo.metadata.report.identifier.MetadataIdentifier;
+import org.apache.dubbo.metadata.report.identifier.ServiceMetadataIdentifier;
 import org.apache.dubbo.metadata.report.support.AbstractMetadataReport;
 import org.apache.dubbo.rpc.RpcException;
 
@@ -56,12 +57,12 @@ public class ConsulMetadataReport extends AbstractMetadataReport {
     }
 
     @Override
-    protected void doSaveMetadata(URL url) {
+    protected void doSaveMetadata(ServiceMetadataIdentifier serviceMetadataIdentifier, URL url) {
         throw new UnsupportedOperationException("This extension does not support working as a remote metadata center.");
     }
 
     @Override
-    protected void doRemoveMetadata(URL url) {
+    protected void doRemoveMetadata(ServiceMetadataIdentifier serviceMetadataIdentifier, URL url) {
         throw new UnsupportedOperationException("This extension does not support working as a remote metadata center.");
     }
 
diff --git a/dubbo-metadata/dubbo-metadata-report-etcd/src/main/java/org/apache/dubbo/metadata/store/etcd/EtcdMetadataReport.java b/dubbo-metadata/dubbo-metadata-report-etcd/src/main/java/org/apache/dubbo/metadata/store/etcd/EtcdMetadataReport.java
index d01e02d..30609fb 100644
--- a/dubbo-metadata/dubbo-metadata-report-etcd/src/main/java/org/apache/dubbo/metadata/store/etcd/EtcdMetadataReport.java
+++ b/dubbo-metadata/dubbo-metadata-report-etcd/src/main/java/org/apache/dubbo/metadata/store/etcd/EtcdMetadataReport.java
@@ -37,6 +37,7 @@ import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.logger.Logger;
 import org.apache.dubbo.common.logger.LoggerFactory;
 import org.apache.dubbo.metadata.report.identifier.MetadataIdentifier;
+import org.apache.dubbo.metadata.report.identifier.ServiceMetadataIdentifier;
 import org.apache.dubbo.metadata.report.support.AbstractMetadataReport;
 import org.apache.dubbo.remoting.etcd.jetcd.JEtcdClient;
 
@@ -83,12 +84,12 @@ public class EtcdMetadataReport extends AbstractMetadataReport {
     }
 
     @Override
-    protected void doSaveMetadata(URL url) {
+    protected void doSaveMetadata(ServiceMetadataIdentifier serviceMetadataIdentifier, URL url) {
         throw new UnsupportedOperationException("This extension does not support working as a remote metadata center.");
     }
 
     @Override
-    protected void doRemoveMetadata(URL url) {
+    protected void doRemoveMetadata(ServiceMetadataIdentifier serviceMetadataIdentifier, URL url) {
         throw new UnsupportedOperationException("This extension does not support working as a remote metadata center.");
     }
 
diff --git a/dubbo-metadata/dubbo-metadata-report-nacos/src/main/java/org/apache/dubbo/metadata/store/nacos/NacosMetadataReport.java b/dubbo-metadata/dubbo-metadata-report-nacos/src/main/java/org/apache/dubbo/metadata/store/nacos/NacosMetadataReport.java
index 1f3fc1a..bdaadeb 100644
--- a/dubbo-metadata/dubbo-metadata-report-nacos/src/main/java/org/apache/dubbo/metadata/store/nacos/NacosMetadataReport.java
+++ b/dubbo-metadata/dubbo-metadata-report-nacos/src/main/java/org/apache/dubbo/metadata/store/nacos/NacosMetadataReport.java
@@ -22,6 +22,7 @@ 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.report.identifier.MetadataIdentifier;
+import org.apache.dubbo.metadata.report.identifier.ServiceMetadataIdentifier;
 import org.apache.dubbo.metadata.report.support.AbstractMetadataReport;
 import org.apache.dubbo.rpc.RpcException;
 
@@ -124,12 +125,12 @@ public class NacosMetadataReport extends AbstractMetadataReport {
     }
 
     @Override
-    protected void doSaveMetadata(URL url) {
+    protected void doSaveMetadata(ServiceMetadataIdentifier serviceMetadataIdentifier, URL url) {
         throw new UnsupportedOperationException("This extension does not support working as a remote metadata center.");
     }
 
     @Override
-    protected void doRemoveMetadata(URL url) {
+    protected void doRemoveMetadata(ServiceMetadataIdentifier serviceMetadataIdentifier, URL url) {
         throw new UnsupportedOperationException("This extension does not support working as a remote metadata center.");
     }
 
diff --git a/dubbo-metadata/dubbo-metadata-report-redis/src/main/java/org/apache/dubbo/metadata/store/redis/RedisMetadataReport.java b/dubbo-metadata/dubbo-metadata-report-redis/src/main/java/org/apache/dubbo/metadata/store/redis/RedisMetadataReport.java
index 9a0ad1f..8232b44 100644
--- a/dubbo-metadata/dubbo-metadata-report-redis/src/main/java/org/apache/dubbo/metadata/store/redis/RedisMetadataReport.java
+++ b/dubbo-metadata/dubbo-metadata-report-redis/src/main/java/org/apache/dubbo/metadata/store/redis/RedisMetadataReport.java
@@ -20,6 +20,7 @@ import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.logger.Logger;
 import org.apache.dubbo.common.logger.LoggerFactory;
 import org.apache.dubbo.metadata.report.identifier.MetadataIdentifier;
+import org.apache.dubbo.metadata.report.identifier.ServiceMetadataIdentifier;
 import org.apache.dubbo.metadata.report.support.AbstractMetadataReport;
 import org.apache.dubbo.rpc.RpcException;
 
@@ -37,7 +38,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.report.identifier.MetadataIdentifier.META_DATA_STORE_TAG;
+import static org.apache.dubbo.metadata.MetadataConstants.META_DATA_STORE_TAG;
 
 /**
  * RedisMetadataReport
@@ -79,12 +80,12 @@ public class RedisMetadataReport extends AbstractMetadataReport {
     }
 
     @Override
-    protected void doSaveMetadata(URL url) {
+    protected void doSaveMetadata(ServiceMetadataIdentifier serviceMetadataIdentifier, URL url) {
 
     }
 
     @Override
-    protected void doRemoveMetadata(URL url) {
+    protected void doRemoveMetadata(ServiceMetadataIdentifier serviceMetadataIdentifier, URL url) {
 
     }
 
diff --git a/dubbo-registry/dubbo-registry-api/pom.xml b/dubbo-registry/dubbo-registry-api/pom.xml
index db0c175..9d47281 100644
--- a/dubbo-registry/dubbo-registry-api/pom.xml
+++ b/dubbo-registry/dubbo-registry-api/pom.xml
@@ -68,11 +68,6 @@
             <artifactId>dubbo-metadata-api</artifactId>
             <version>${project.parent.version}</version>
         </dependency>
-        <dependency>
-            <groupId>org.apache.dubbo</groupId>
-            <artifactId>dubbo-metadata-api</artifactId>
-            <version>${project.parent.version}</version>
-        </dependency>
 
         <dependency>
             <groupId>org.apache.curator</groupId>
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/CompositeMetadataServiceURLBuilder.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/CompositeMetadataServiceURLBuilder.java
index 9ced03a..8006c85 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/CompositeMetadataServiceURLBuilder.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/CompositeMetadataServiceURLBuilder.java
@@ -19,6 +19,7 @@ package org.apache.dubbo.registry.client.metadata;
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.metadata.MetadataService;
 import org.apache.dubbo.registry.client.ServiceInstance;
+import org.apache.dubbo.registry.client.metadata.proxy.MetadataServiceProxy;
 
 import java.util.Iterator;
 import java.util.LinkedList;
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/proxy/BaseMetadataServiceProxyFactory.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/proxy/BaseMetadataServiceProxyFactory.java
new file mode 100644
index 0000000..eba2553
--- /dev/null
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/proxy/BaseMetadataServiceProxyFactory.java
@@ -0,0 +1,23 @@
+package org.apache.dubbo.registry.client.metadata.proxy;
+
+import org.apache.dubbo.metadata.MetadataService;
+import org.apache.dubbo.registry.client.ServiceInstance;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.apache.dubbo.common.constants.CommonConstants.REVISION_KEY;
+
+/**
+ * 2019-08-09
+ */
+abstract class BaseMetadataServiceProxyFactory implements MetadataServiceProxyFactory {
+    private final Map<String, MetadataService> proxies = new HashMap<>();
+
+    public final MetadataService getProxy(ServiceInstance serviceInstance) {
+        return proxies.computeIfAbsent(serviceInstance.getServiceName() + "##" +
+                serviceInstance.getMetadata().getOrDefault(REVISION_KEY, ""), id -> createProxy(serviceInstance));
+    }
+
+    protected abstract MetadataService createProxy(ServiceInstance serviceInstance);
+}
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
index 06248f9..f25f492 100644
--- 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
@@ -39,9 +39,8 @@ import static org.apache.dubbo.registry.client.metadata.MetadataServiceURLBuilde
  *
  * @since 2.7.4
  */
-public class DefaultMetadataServiceProxyFactory implements MetadataServiceProxyFactory {
+public class DefaultMetadataServiceProxyFactory extends BaseMetadataServiceProxyFactory implements MetadataServiceProxyFactory {
 
-    private final Map<String, MetadataService> proxies = new HashMap<>();
 
     private ProxyFactory proxyFactory;
 
@@ -57,10 +56,6 @@ public class DefaultMetadataServiceProxyFactory implements MetadataServiceProxyF
         this.proxyFactory = proxyFactory;
     }
 
-    @Override
-    public MetadataService getProxy(ServiceInstance serviceInstance) {
-        return proxies.computeIfAbsent(serviceInstance.getId(), id -> createProxy(serviceInstance));
-    }
 
     protected MetadataService createProxy(ServiceInstance serviceInstance) {
         List<URL> urls = composite().build(serviceInstance);
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/MetadataServiceProxy.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/proxy/MetadataServiceProxy.java
similarity index 97%
rename from dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/MetadataServiceProxy.java
rename to dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/proxy/MetadataServiceProxy.java
index 45ce42a..018460e 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/MetadataServiceProxy.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/proxy/MetadataServiceProxy.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.registry.client.metadata;
+package org.apache.dubbo.registry.client.metadata.proxy;
 
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.logger.Logger;
@@ -41,7 +41,7 @@ import static org.apache.dubbo.registry.client.metadata.MetadataServiceURLBuilde
  * @see MetadataService
  * @since 2.7.4
  */
-class MetadataServiceProxy implements MetadataService {
+public class MetadataServiceProxy implements MetadataService {
 
     private final Logger logger = LoggerFactory.getLogger(getClass());
 
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/proxy/RemoteMetadataServiceProxy.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/proxy/RemoteMetadataServiceProxy.java
new file mode 100644
index 0000000..2c661b9
--- /dev/null
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/proxy/RemoteMetadataServiceProxy.java
@@ -0,0 +1,70 @@
+package org.apache.dubbo.registry.client.metadata.proxy;
+
+import org.apache.dubbo.common.logger.Logger;
+import org.apache.dubbo.common.logger.LoggerFactory;
+import org.apache.dubbo.common.utils.UrlUtils;
+import org.apache.dubbo.metadata.MetadataService;
+import org.apache.dubbo.metadata.report.MetadataReport;
+import org.apache.dubbo.metadata.report.MetadataReportInstance;
+import org.apache.dubbo.metadata.report.identifier.MetadataIdentifier;
+import org.apache.dubbo.registry.client.ServiceInstance;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+import static org.apache.dubbo.common.constants.CommonConstants.PROVIDER_SIDE;
+
+/**
+ * 2019-08-09
+ */
+public class RemoteMetadataServiceProxy implements MetadataService {
+    protected final Logger logger = LoggerFactory.getLogger(getClass());
+
+    private String serviceName;
+
+
+    public RemoteMetadataServiceProxy(ServiceInstance serviceInstance) {
+        this.serviceName = serviceInstance.getServiceName();
+    }
+
+    @Override
+    public String serviceName() {
+        return serviceName;
+    }
+
+    @Override
+    public SortedSet<String> getSubscribedURLs() {
+        return toSortedStrings(getMetadataReport().getSubscribedURLs());
+    }
+
+    // TODO, protocol should be used
+    @Override
+    public SortedSet<String> getExportedURLs(String serviceInterface, String group, String version, String protocol) {
+        return toSortedStrings(getMetadataReport().getExportedURLs(new MetadataIdentifier(serviceInterface, group, version, null, null)));
+    }
+
+    private static SortedSet<String> toSortedStrings(Collection<String> values) {
+        return Collections.unmodifiableSortedSet(new TreeSet<>(values));
+    }
+
+    @Override
+    public String getServiceDefinition(String interfaceName, String version, String group) {
+        return getMetadataReport().getServiceDefinition(new MetadataIdentifier(interfaceName,
+                version, group, PROVIDER_SIDE, serviceName));
+    }
+
+    @Override
+    public String getServiceDefinition(String serviceKey) {
+        String[] services = UrlUtils.parseServiceKey(serviceKey);
+        return getMetadataReport().getServiceDefinition(new MetadataIdentifier(services[1],
+                services[0], services[2], PROVIDER_SIDE, serviceName));
+    }
+
+    MetadataReport getMetadataReport() {
+        return MetadataReportInstance.getMetadataReport(true);
+    }
+
+
+}
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/proxy/RemoteMetadataServiceProxyFactory.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/proxy/RemoteMetadataServiceProxyFactory.java
index 3544294..add90c8 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/proxy/RemoteMetadataServiceProxyFactory.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/proxy/RemoteMetadataServiceProxyFactory.java
@@ -25,11 +25,11 @@ import static org.apache.dubbo.common.constants.CommonConstants.METADATA_REMOTE;
 /**
  *
  */
-public class RemoteMetadataServiceProxyFactory implements MetadataServiceProxyFactory {
+public class RemoteMetadataServiceProxyFactory extends BaseMetadataServiceProxyFactory implements MetadataServiceProxyFactory {
 
     @Override
-    public MetadataService getProxy(ServiceInstance serviceInstance) {
-        return WritableMetadataService.getExtension(METADATA_REMOTE);
+    public MetadataService createProxy(ServiceInstance serviceInstance) {
+        return new RemoteMetadataServiceProxy();
     }
 
 }