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


The following commit(s) were added to refs/heads/cloud-native by this push:
     new 4baa0aa  fix review issue
4baa0aa is described below

commit 4baa0aad39ff313be9037c2b1aaf34cac49ab6aa
Author: cvictory <shenglic...@gmail.com>
AuthorDate: Wed Aug 14 15:37:29 2019 +0800

    fix review issue
---
 .../bootstrap/DubboServiceConsumerBootstrap.java   |   4 +-
 .../bootstrap/DubboServiceProviderBootstrap.java   |   2 +
 .../DubboInterfaceConsumerBootstrap.java           |   4 +-
 .../src/main/java/org/apache/dubbo/common/URL.java |   1 +
 .../dubbo/config/AbstractInterfaceConfig.java      |   7 ++
 .../apache/dubbo/config/MetadataReportConfig.java  |   9 +-
 .../org/apache/dubbo/metadata/MetadataService.java |   2 +
 .../dubbo/metadata/WritableMetadataService.java    |   2 +-
 .../dubbo/metadata/report/MetadataReport.java      |   9 +-
 .../identifier/ServiceMetadataIdentifier.java      |  21 ++++
 .../report/support/AbstractMetadataReport.java     |  45 ++++++---
 .../store/BaseWritableMetadataService.java         |  64 ++++++++++++
 .../store/InMemoryWritableMetadataService.java     |  66 +------------
 .../store/RemoteWritableMetadataService.java       | 108 ++++++++++++++++++---
 .../support/AbstractMetadataReportFactoryTest.java |   8 +-
 .../report/support/AbstractMetadataReportTest.java |  12 +--
 .../metadata/test/JTestMetadataReport4Test.java    |   6 +-
 .../store/consul/ConsulMetadataReport.java         |   6 +-
 .../metadata/store/etcd/EtcdMetadataReport.java    |   6 +-
 .../metadata/store/nacos/NacosMetadataReport.java  |   6 +-
 .../metadata/store/redis/RedisMetadataReport.java  |   6 +-
 .../store/zookeeper/ZookeeperMetadataReport.java   |  18 ++--
 .../metadata/RefreshServiceMetadataCustomizer.java |  19 +++-
 .../metadata/ServiceInstanceMetadataUtils.java     |  32 ++++++
 ...bscribedServicesRevisionMetadataCustomizer.java |  73 ++++++++++++++
 .../registry/service/ServiceOrientedRegistry.java  |  11 ++-
 ...dubbo.registry.client.ServiceInstanceCustomizer |   1 +
 27 files changed, 406 insertions(+), 142 deletions(-)

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 f082192..fe216ab 100644
--- 
a/dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/DubboServiceConsumerBootstrap.java
+++ 
b/dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/DubboServiceConsumerBootstrap.java
@@ -17,6 +17,7 @@
 package org.apache.dubbo.bootstrap;
 
 import org.apache.dubbo.bootstrap.rest.UserService;
+import org.apache.dubbo.config.MetadataReportConfig;
 import org.apache.dubbo.config.ReferenceConfig;
 import org.apache.dubbo.config.context.ConfigManager;
 
@@ -33,6 +34,7 @@ public class DubboServiceConsumerBootstrap {
                 .application("dubbo-consumer-demo")
                 // Zookeeper
                 .registry("zookeeper", builder -> 
builder.address("zookeeper://127.0.0.1:2181?registry.type=service&subscribed.services=dubbo-provider-demo"))
+                .metadataReport(new 
MetadataReportConfig("zookeeper://127.0.0.1:2181"))
                 // Nacos
 //                .registry("consul", builder -> 
builder.address("consul://127.0.0.1:8500?registry.type=service&subscribed.services=dubbo-provider-demo").group("namespace1"))
                 .reference("echo", builder -> 
builder.interfaceClass(EchoService.class).protocol("dubbo"))
@@ -43,7 +45,7 @@ public class DubboServiceConsumerBootstrap {
 
         ConfigManager configManager = ConfigManager.getInstance();
 
-        ReferenceConfig<EchoService> referenceConfig = 
configManager.getReferenceConfig("echo");
+        ReferenceConfig<EchoService> referenceConfig = 
configManager.getReference("echo");
 
         EchoService echoService = referenceConfig.get();
 
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 dd2060c..9bafe00 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
@@ -18,6 +18,7 @@ package org.apache.dubbo.bootstrap;
 
 import org.apache.dubbo.bootstrap.rest.UserService;
 import org.apache.dubbo.bootstrap.rest.UserServiceImpl;
+import org.apache.dubbo.config.MetadataReportConfig;
 import org.apache.dubbo.config.ProtocolConfig;
 import org.apache.dubbo.config.RegistryConfig;
 import org.apache.dubbo.config.ServiceConfig;
@@ -70,6 +71,7 @@ public class DubboServiceProviderBootstrap {
                 .registries(Arrays.asList(interfaceRegistry, serviceRegistry))
 //                
.registry(RegistryBuilder.newBuilder().address("consul://127.0.0.1:8500?registry.type=service").build())
                 .protocol(builder -> builder.port(-1).name("dubbo"))
+                .metadataReport(new 
MetadataReportConfig("zookeeper://127.0.0.1:2181"))
                 .service(echoService)
                 .service(userService)
                 .start()
diff --git 
a/dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/compatible/DubboInterfaceConsumerBootstrap.java
 
b/dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/compatible/DubboInterfaceConsumerBootstrap.java
index 59a8fb1..79a0030 100644
--- 
a/dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/compatible/DubboInterfaceConsumerBootstrap.java
+++ 
b/dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/compatible/DubboInterfaceConsumerBootstrap.java
@@ -49,10 +49,10 @@ public class DubboInterfaceConsumerBootstrap {
 
         ConfigManager configManager = ConfigManager.getInstance();
 
-        ReferenceConfig<EchoService> referenceConfig = 
configManager.getReferenceConfig("echo");
+        ReferenceConfig<EchoService> referenceConfig = 
configManager.getReference("echo");
         EchoService echoService = referenceConfig.get();
 
-        ReferenceConfig<UserService> referenceConfig1 = 
configManager.getReferenceConfig("user");
+        ReferenceConfig<UserService> referenceConfig1 = 
configManager.getReference("user");
         UserService userService = referenceConfig1.get();
 
         for (int i = 0; i < 500; i++) {
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/URL.java 
b/dubbo-common/src/main/java/org/apache/dubbo/common/URL.java
index 93cad0b..d986f66 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/URL.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/URL.java
@@ -1259,6 +1259,7 @@ class URL implements Serializable {
 
     /**
      * The format is "{interface}:[version]:[group]"
+     *
      * @return
      */
     public String getColonSeparatedKey() {
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 f1ad3d9..257cf5d 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
@@ -248,6 +248,13 @@ public abstract class AbstractInterfaceConfig extends 
AbstractMethodConfig {
     protected void checkMetadataReport() {
         // TODO get from ConfigManager first, only create if absent.
         if (metadataReportConfig == null) {
+            ConfigManager configManager = ConfigManager.getInstance();
+            if 
(CollectionUtils.isNotEmpty(configManager.getMetadataConfigs())) {
+                setMetadataReportConfig(configManager.getMetadataConfigs()
+                        .toArray(new 
MetadataReportConfig[configManager.getMetadataConfigs().size()])[0]);
+            }
+        }
+        if (metadataReportConfig == null) {
             setMetadataReportConfig(new MetadataReportConfig());
         }
         metadataReportConfig.refresh();
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 30e5bcb..506ac46 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
@@ -26,6 +26,7 @@ import java.util.Map;
 
 import static org.apache.dubbo.common.constants.CommonConstants.DUBBO;
 import static 
org.apache.dubbo.common.constants.CommonConstants.PROPERTIES_CHAR_SEPERATOR;
+import static 
org.apache.dubbo.metadata.report.support.Constants.METADATA_REPORT_KEY;
 
 /**
  * MetadataReportConfig
@@ -93,7 +94,13 @@ public class MetadataReportConfig extends AbstractConfig {
         }
         Map<String, String> map = new HashMap<String, String>();
         appendParameters(map, this);
-        return UrlUtils.parseURL(address, map);
+        if (!StringUtils.isEmpty(address)) {
+            URL url = URL.valueOf(address);
+            map.put(METADATA_REPORT_KEY, url.getProtocol());
+            return new URL(METADATA_REPORT_KEY, url.getUsername(), 
url.getPassword(), url.getHost(),
+                    url.getPort(), url.getPath(), map);
+        }
+        throw new IllegalArgumentException("The address of metadata report is 
invalid.");
     }
 
     @Parameter(excluded = true)
diff --git 
a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/MetadataService.java
 
b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/MetadataService.java
index 490abcb..c4cf250 100644
--- 
a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/MetadataService.java
+++ 
b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/MetadataService.java
@@ -43,6 +43,8 @@ import static java.util.stream.StreamSupport.stream;
  */
 public interface MetadataService {
 
+    //FIXME the value is default, it was used by testing temporarily
+    static final String DEFAULT_EXTENSION = "default";
 
     /**
      * The value of all service names
diff --git 
a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/WritableMetadataService.java
 
b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/WritableMetadataService.java
index 07cd5a5..7a8fd27 100644
--- 
a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/WritableMetadataService.java
+++ 
b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/WritableMetadataService.java
@@ -64,7 +64,7 @@ public interface WritableMetadataService extends 
MetadataService {
      *
      * @return If success , return <code>true</code>
      */
-    default boolean refreshMetadata(String revision){
+    default boolean refreshMetadata(String exportedRevision, String 
subscribedRevision){
         return true;
     }
 
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 2a03ce1..90ca45a 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
@@ -25,6 +25,7 @@ import 
org.apache.dubbo.metadata.report.identifier.SubscriberMetadataIdentifier;
 
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 /**
  *
@@ -35,15 +36,15 @@ public interface MetadataReport {
 
     void storeConsumerMetadata(MetadataIdentifier consumerMetadataIdentifier, 
Map<String, String> serviceParameterMap);
 
-    void saveServiceMetadata(URL url);
+    void saveServiceMetadata(ServiceMetadataIdentifier metadataIdentifier, URL 
url);
 
-    void removeServiceMetadata(URL url);
+    void removeServiceMetadata(ServiceMetadataIdentifier metadataIdentifier);
 
     List<String> getExportedURLs(ServiceMetadataIdentifier metadataIdentifier);
 
-    void saveSubscriberData(SubscriberMetadataIdentifier 
subscriberMetadataIdentifier, List<String> urls);
+    void saveSubscribedData(SubscriberMetadataIdentifier 
subscriberMetadataIdentifier, Set<String> urls);
 
     List<String> getSubscribedURLs(SubscriberMetadataIdentifier 
subscriberMetadataIdentifier);
 
-    String getServiceDefinition(MetadataIdentifier consumerMetadataIdentifier);
+    String getServiceDefinition(MetadataIdentifier metadataIdentifier);
 }
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
index e7f394f..a04492a 100644
--- 
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
@@ -37,6 +37,7 @@ public class ServiceMetadataIdentifier extends 
BaseServiceMetadataIdentifier {
         this.group = url.getParameter(GROUP_KEY);
         this.side = url.getParameter(SIDE_KEY);
         this.revision = (url.getParameter(REVISION_KEY));
+        this.protocol = url.getProtocol();
     }
 
     public String getUniqueKey(MetadataIdentifier.KeyTypeEnum keyType) {
@@ -46,4 +47,24 @@ public class ServiceMetadataIdentifier extends 
BaseServiceMetadataIdentifier {
     public String getIdentifierKey() {
         return super.getIdentifierKey(protocol, KEY_REVISON_PREFIX + revision);
     }
+
+    public void setRevision(String revision) {
+        this.revision = revision;
+    }
+
+    public void setProtocol(String protocol) {
+        this.protocol = protocol;
+    }
+
+    @Override
+    public String toString() {
+        return "ServiceMetadataIdentifier{" +
+                "revision='" + revision + '\'' +
+                ", protocol='" + protocol + '\'' +
+                ", serviceInterface='" + serviceInterface + '\'' +
+                ", version='" + version + '\'' +
+                ", group='" + group + '\'' +
+                ", side='" + side + '\'' +
+                "} " + super.toString();
+    }
 }
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 166fb90..f70e13e 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
@@ -19,6 +19,7 @@ package org.apache.dubbo.metadata.report.support;
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.logger.Logger;
 import org.apache.dubbo.common.logger.LoggerFactory;
+import org.apache.dubbo.common.utils.CollectionUtils;
 import org.apache.dubbo.common.utils.ConfigUtils;
 import org.apache.dubbo.common.utils.NamedThreadFactory;
 import org.apache.dubbo.metadata.definition.model.FullServiceDefinition;
@@ -29,6 +30,7 @@ import 
org.apache.dubbo.metadata.report.identifier.ServiceMetadataIdentifier;
 import 
org.apache.dubbo.metadata.report.identifier.SubscriberMetadataIdentifier;
 
 import com.google.gson.Gson;
+import com.google.gson.reflect.TypeToken;
 
 import java.io.File;
 import java.io.FileInputStream;
@@ -36,13 +38,17 @@ import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.RandomAccessFile;
+import java.lang.reflect.Type;
 import java.nio.channels.FileChannel;
 import java.nio.channels.FileLock;
+import java.util.ArrayList;
 import java.util.Calendar;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Properties;
+import java.util.Set;
+import java.util.SortedSet;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
@@ -286,20 +292,20 @@ public abstract class AbstractMetadataReport implements 
MetadataReport {
     }
 
     @Override
-    public void saveServiceMetadata(URL url) {
+    public void saveServiceMetadata(ServiceMetadataIdentifier 
metadataIdentifier, URL url) {
         if (syncReport) {
-            doSaveMetadata(new ServiceMetadataIdentifier(url), url);
+            doSaveMetadata(metadataIdentifier, url);
         } else {
             reportCacheExecutor.execute(() -> doSaveMetadata(new 
ServiceMetadataIdentifier(url), url));
         }
     }
 
     @Override
-    public void removeServiceMetadata(URL url) {
+    public void removeServiceMetadata(ServiceMetadataIdentifier 
metadataIdentifier) {
         if (syncReport) {
-            doRemoveMetadata(new ServiceMetadataIdentifier(url), url);
+            doRemoveMetadata(metadataIdentifier);
         } else {
-            reportCacheExecutor.execute(() -> doRemoveMetadata(new 
ServiceMetadataIdentifier(url), url));
+            reportCacheExecutor.execute(() -> 
doRemoveMetadata(metadataIdentifier));
         }
     }
 
@@ -310,19 +316,21 @@ public abstract class AbstractMetadataReport implements 
MetadataReport {
     }
 
     @Override
-    public void saveSubscriberData(SubscriberMetadataIdentifier 
subscriberMetadataIdentifier, List<String> urls) {
+    public void saveSubscribedData(SubscriberMetadataIdentifier 
subscriberMetadataIdentifier, Set<String> urls) {
         if (syncReport) {
-            doSaveSubscriberData(subscriberMetadataIdentifier, urls);
+            doSaveSubscriberData(subscriberMetadataIdentifier, new 
Gson().toJson(urls));
         } else {
-            reportCacheExecutor.execute(() -> 
doSaveSubscriberData(subscriberMetadataIdentifier, urls));
+            reportCacheExecutor.execute(() -> 
doSaveSubscriberData(subscriberMetadataIdentifier, new Gson().toJson(urls)));
         }
     }
 
 
     @Override
     public List<String> getSubscribedURLs(SubscriberMetadataIdentifier 
subscriberMetadataIdentifier) {
-        // TODO, fallback to local cache
-        return doGetSubscribedURLs(subscriberMetadataIdentifier);
+        String content = doGetSubscribedURLs(subscriberMetadataIdentifier);
+        Type setType = new TypeToken<SortedSet<String>>() {
+        }.getType();
+        return new Gson().fromJson(content, setType);
     }
 
     String getProtocol(URL url) {
@@ -430,18 +438,29 @@ public abstract class AbstractMetadataReport implements 
MetadataReport {
         }
     }
 
+    private void doSaveSubscriberData(SubscriberMetadataIdentifier 
subscriberMetadataIdentifier, List<String> urls) {
+        if (CollectionUtils.isEmpty(urls)) {
+            return;
+        }
+        List<String> encodedUrlList = new ArrayList<>(urls.size());
+        for (String url : urls) {
+            encodedUrlList.add(URL.encode(url));
+        }
+        doSaveSubscriberData(subscriberMetadataIdentifier, encodedUrlList);
+    }
+
     protected abstract void doStoreProviderMetadata(MetadataIdentifier 
providerMetadataIdentifier, String serviceDefinitions);
 
     protected abstract void doStoreConsumerMetadata(MetadataIdentifier 
consumerMetadataIdentifier, String serviceParameterString);
 
     protected abstract void doSaveMetadata(ServiceMetadataIdentifier 
metadataIdentifier, URL url);
 
-    protected abstract void doRemoveMetadata(ServiceMetadataIdentifier 
metadataIdentifier, URL url);
+    protected abstract void doRemoveMetadata(ServiceMetadataIdentifier 
metadataIdentifier);
 
     protected abstract List<String> 
doGetExportedURLs(ServiceMetadataIdentifier metadataIdentifier);
 
-    protected abstract void doSaveSubscriberData(SubscriberMetadataIdentifier 
subscriberMetadataIdentifier, List<String> urls);
+    protected abstract void doSaveSubscriberData(SubscriberMetadataIdentifier 
subscriberMetadataIdentifier, String urlListStr);
 
-    protected abstract List<String> 
doGetSubscribedURLs(SubscriberMetadataIdentifier subscriberMetadataIdentifier);
+    protected abstract String doGetSubscribedURLs(SubscriberMetadataIdentifier 
subscriberMetadataIdentifier);
 
 }
diff --git 
a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/store/BaseWritableMetadataService.java
 
b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/store/BaseWritableMetadataService.java
new file mode 100644
index 0000000..c751226
--- /dev/null
+++ 
b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/store/BaseWritableMetadataService.java
@@ -0,0 +1,64 @@
+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.metadata.MetadataService;
+import org.apache.dubbo.metadata.report.identifier.ServiceMetadataIdentifier;
+
+import java.util.Collection;
+import java.util.Map;
+import java.util.SortedSet;
+import java.util.concurrent.ConcurrentNavigableMap;
+import java.util.concurrent.ConcurrentSkipListMap;
+import java.util.function.BiConsumer;
+import java.util.function.Consumer;
+import java.util.function.Function;
+import java.util.function.Supplier;
+
+/**
+ * @author cvictory ON 2019-08-14
+ */
+public class BaseWritableMetadataService {
+    final Logger logger = LoggerFactory.getLogger(getClass());
+
+    // =================================== Registration 
=================================== //
+
+    /**
+     * All exported {@link URL urls} {@link Map} whose key is the return value 
of {@link URL#getServiceKey()} method
+     * and value is the {@link SortedSet sorted set} of the {@link URL URLs}
+     */
+    static ConcurrentNavigableMap<String, SortedSet<URL>> exportedServiceURLs 
= new ConcurrentSkipListMap<>();
+
+    // 
====================================================================================
 //
+
+    // =================================== Subscription 
=================================== //
+
+    /**
+     * The subscribed {@link URL urls} {@link Map} of {@link MetadataService},
+     * whose key is the return value of {@link URL#getServiceKey()} method and 
value is
+     * the {@link SortedSet sorted set} of the {@link URL URLs}
+     */
+    final static ConcurrentNavigableMap<String, SortedSet<URL>> 
subscribedServiceURLs = new ConcurrentSkipListMap<>();
+
+    final static ConcurrentNavigableMap<String, String> serviceDefinitions = 
new ConcurrentSkipListMap<>();
+
+
+    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;
+    }
+
+    public SortedSet<String> getSubscribedURLs() {
+        return getAllUnmodifiableServiceURLs(subscribedServiceURLs);
+    }
+
+    static SortedSet<String> getAllUnmodifiableServiceURLs(Map<String, 
SortedSet<URL>> serviceURLs) {
+        return 
MetadataService.toSortedStrings(serviceURLs.values().stream().flatMap(Collection::stream));
+    }
+}
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 0f73ebe..ce8fea5 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
@@ -17,8 +17,6 @@
 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;
@@ -27,18 +25,11 @@ import 
org.apache.dubbo.metadata.definition.model.ServiceDefinition;
 
 import com.google.gson.Gson;
 
-import java.util.ArrayList;
-import java.util.Collection;
 import java.util.Comparator;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
 import java.util.Map;
 import java.util.SortedSet;
 import java.util.TreeSet;
 import java.util.concurrent.Callable;
-import java.util.concurrent.ConcurrentNavigableMap;
-import java.util.concurrent.ConcurrentSkipListMap;
 import java.util.concurrent.locks.Lock;
 import java.util.concurrent.locks.ReentrantLock;
 
@@ -47,7 +38,6 @@ import static java.util.Collections.unmodifiableSortedSet;
 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.constants.CommonConstants.REVISION_KEY;
 import static org.apache.dubbo.common.utils.CollectionUtils.isEmpty;
 
 /**
@@ -58,32 +48,11 @@ import static 
org.apache.dubbo.common.utils.CollectionUtils.isEmpty;
  * @see WritableMetadataService
  * @since 2.7.4
  */
-public class InMemoryWritableMetadataService implements 
WritableMetadataService {
+public class InMemoryWritableMetadataService extends 
BaseWritableMetadataService implements WritableMetadataService {
 
-    private final Logger logger = LoggerFactory.getLogger(getClass());
 
-    private final Lock lock = new ReentrantLock();
-
-    // =================================== Registration 
=================================== //
-
-    /**
-     * All exported {@link URL urls} {@link Map} whose key is the return value 
of {@link URL#getServiceKey()} method
-     * and value is the {@link SortedSet sorted set} of the {@link URL URLs}
-     */
-    ConcurrentNavigableMap<String, SortedSet<URL>> exportedServiceURLs = new 
ConcurrentSkipListMap<>();
-
-    // 
====================================================================================
 //
 
-    // =================================== Subscription 
=================================== //
-
-    /**
-     * The subscribed {@link URL urls} {@link Map} of {@link MetadataService},
-     * whose key is the return value of {@link URL#getServiceKey()} method and 
value is
-     * the {@link SortedSet sorted set} of the {@link URL URLs}
-     */
-    final ConcurrentNavigableMap<String, SortedSet<URL>> subscribedServiceURLs 
= new ConcurrentSkipListMap<>();
-
-    final ConcurrentNavigableMap<String, String> serviceDefinitions = new 
ConcurrentSkipListMap<>();
+    private final Lock lock = new ReentrantLock();
 
     // 
====================================================================================
 //
 
@@ -122,33 +91,6 @@ public class InMemoryWritableMetadataService implements 
WritableMetadataService
     }
 
     @Override
-    public boolean refreshMetadata(String revision) {
-        boolean result = true;
-        for (SortedSet<URL> urls : exportedServiceURLs.values()) {
-            Iterator<URL> iterator = urls.iterator();
-            List<URL> newList = new ArrayList<>(urls.size());
-            while (iterator.hasNext()) {
-                URL url = iterator.next();
-                // refresh revision in urls
-                Map<String, String> parameters = new 
HashMap<>(url.getParameters());
-                parameters.put(REVISION_KEY, revision);
-                URL newUrl = new URL(url.getProtocol(), url.getUsername(), 
url.getPassword(), url.getHost(), url.getPort(), url.getPath(), parameters);
-                newList.add(newUrl);
-                if (!finishRefreshExportedMetadata(newUrl)) {
-                    result = false;
-                }
-            }
-            urls.clear();
-            urls.addAll(newList);
-        }
-        return result;
-    }
-
-    protected boolean finishRefreshExportedMetadata(URL url) {
-        return true;
-    }
-
-    @Override
     public void publishServiceDefinition(URL providerUrl) {
         try {
             String interfaceName = providerUrl.getParameter(INTERFACE_KEY);
@@ -231,10 +173,6 @@ public class InMemoryWritableMetadataService implements 
WritableMetadataService
                 || protocol.equals(url.getProtocol());
     }
 
-    private static SortedSet<String> getAllUnmodifiableServiceURLs(Map<String, 
SortedSet<URL>> serviceURLs) {
-        return 
MetadataService.toSortedStrings(serviceURLs.values().stream().flatMap(Collection::stream));
-    }
-
 
     static class URLComparator implements Comparator<URL> {
 
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 79090b1..a2aa24f 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
@@ -27,10 +27,15 @@ import 
org.apache.dubbo.metadata.definition.model.ServiceDefinition;
 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.metadata.report.identifier.ServiceMetadataIdentifier;
+import 
org.apache.dubbo.metadata.report.identifier.SubscriberMetadataIdentifier;
 import org.apache.dubbo.remoting.Constants;
 import org.apache.dubbo.rpc.RpcException;
 
-import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.Iterator;
+import java.util.Set;
+import java.util.SortedSet;
+import java.util.function.BiConsumer;
 import java.util.function.Consumer;
 
 import static 
org.apache.dubbo.common.constants.CommonConstants.APPLICATION_KEY;
@@ -47,11 +52,16 @@ import static 
org.apache.dubbo.common.constants.CommonConstants.VERSION_KEY;
  * exported.
  * It is used by server (provider).
  *
- * @since 2.7.0
+ * @since 2.7.5
  */
-public class RemoteWritableMetadataService extends 
InMemoryWritableMetadataService implements WritableMetadataService {
+public class RemoteWritableMetadataService extends BaseWritableMetadataService 
implements WritableMetadataService {
 
     protected final Logger logger = LoggerFactory.getLogger(getClass());
+    private volatile String exportedRevision;
+    private volatile String subscribedRevision;
+
+    public RemoteWritableMetadataService() {
+    }
 
     public MetadataReport getMetadataReport() {
         return MetadataReportInstance.getMetadataReport(true);
@@ -112,41 +122,109 @@ public class RemoteWritableMetadataService extends 
InMemoryWritableMetadataServi
 
     @Override
     public boolean exportURL(URL url) {
-        return super.exportURL(url);
+        return true;
     }
 
     @Override
     public boolean unexportURL(URL url) {
-        super.unexportURL(url);
-        return throwableAction(getMetadataReport()::removeServiceMetadata, 
url);
+        ServiceMetadataIdentifier metadataIdentifier = new 
ServiceMetadataIdentifier(url);
+        metadataIdentifier.setRevision(exportedRevision);
+        return throwableAction(getMetadataReport()::removeServiceMetadata, 
metadataIdentifier);
     }
 
     @Override
     public boolean subscribeURL(URL url) {
-        super.subscribeURL(url);
-        return throwableAction(getMetadataReport()::saveServiceMetadata, url);
+        return true;
     }
 
     @Override
     public boolean unsubscribeURL(URL url) {
-        super.unsubscribeURL(url);
-        return throwableAction(getMetadataReport()::removeServiceMetadata, 
url);
+        return true;
     }
 
     @Override
-    protected boolean finishRefreshExportedMetadata(URL url) {
-        return throwableAction(getMetadataReport()::saveServiceMetadata, url);
+    public boolean refreshMetadata(String exportedRevision, String 
subscribedRevision) {
+        boolean result = true;
+        if (!StringUtils.isEmpty(exportedRevision) && 
!exportedRevision.equals(this.exportedRevision)) {
+            this.exportedRevision = exportedRevision;
+            boolean executeResult = saveServiceMetadata();
+            if (!executeResult) {
+                result = false;
+            }
+        }
+        if (!StringUtils.isEmpty(subscribedRevision) && 
!subscribedRevision.equals(this.subscribedRevision)) {
+            this.subscribedRevision = subscribedRevision;
+            SubscriberMetadataIdentifier metadataIdentifier = new 
SubscriberMetadataIdentifier();
+            metadataIdentifier.setApplication(serviceName());
+            metadataIdentifier.setRevision(subscribedRevision);
+            boolean executeResult = 
throwableAction(getMetadataReport()::saveSubscribedData, metadataIdentifier, 
super.getSubscribedURLs());
+            if (!executeResult) {
+                result = false;
+            }
+        }
+        return result;
     }
 
+    private boolean saveServiceMetadata() {
+        boolean result = true;
+        for (SortedSet<URL> urls : exportedServiceURLs.values()) {
+            Iterator<URL> iterator = urls.iterator();
+            while (iterator.hasNext()) {
+                URL url = iterator.next();
+                // refresh revision in urls
+                ServiceMetadataIdentifier metadataIdentifier = new 
ServiceMetadataIdentifier(url);
+                metadataIdentifier.setRevision(exportedRevision);
+
+                boolean tmpResult = 
throwableAction(getMetadataReport()::saveServiceMetadata, metadataIdentifier, 
url);
+                if (!tmpResult) result = tmpResult;
+            }
+        }
+        return result;
+    }
 
-    private boolean throwableAction(Consumer<URL> consumer, URL url) {
+
+    @Override
+    public SortedSet<String> getExportedURLs(String serviceInterface, String 
group, String version, String protocol) {
+        return null;
+    }
+
+    @Override
+    public String getServiceDefinition(String interfaceName, String version, 
String group) {
+        return null;
+    }
+
+    @Override
+    public String getServiceDefinition(String serviceKey) {
+        return null;
+    }
+
+    boolean throwableAction(BiConsumer<ServiceMetadataIdentifier, URL> 
consumer, ServiceMetadataIdentifier metadataIdentifier, URL url) {
         try {
-            consumer.accept(url);
+            consumer.accept(metadataIdentifier, url);
         } catch (Exception e) {
-            logger.error("Failed to remove url metadata to remote center, url 
is: " + url);
+            logger.error("Failed to execute consumer, url is: " + url);
             return false;
         }
         return true;
     }
 
+    boolean throwableAction(BiConsumer<SubscriberMetadataIdentifier, 
Set<String>> consumer, SubscriberMetadataIdentifier metadataIdentifier, 
Set<String> urls) {
+        try {
+            consumer.accept(metadataIdentifier, urls);
+        } catch (Exception e) {
+            logger.error("Failed to execute consumer, url is: " + urls);
+            return false;
+        }
+        return true;
+    }
+
+    boolean throwableAction(Consumer<ServiceMetadataIdentifier> consumer, 
ServiceMetadataIdentifier metadataIdentifier) {
+        try {
+            consumer.accept(metadataIdentifier);
+        } catch (Exception e) {
+            logger.error("Failed to remove url metadata to remote center, 
metadataIdentifier is: " + metadataIdentifier);
+            return false;
+        }
+        return true;
+    }
 }
diff --git 
a/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/report/support/AbstractMetadataReportFactoryTest.java
 
b/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/report/support/AbstractMetadataReportFactoryTest.java
index 31fb771..e96f4cd 100644
--- 
a/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/report/support/AbstractMetadataReportFactoryTest.java
+++ 
b/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/report/support/AbstractMetadataReportFactoryTest.java
@@ -30,6 +30,7 @@ import org.junit.jupiter.api.Test;
 
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 
 /**
@@ -48,12 +49,12 @@ public class AbstractMetadataReportFactoryTest {
                 }
 
                 @Override
-                public void saveServiceMetadata(URL url) {
+                public void saveServiceMetadata(ServiceMetadataIdentifier 
metadataIdentifier, URL url) {
 
                 }
 
                 @Override
-                public void removeServiceMetadata(URL url) {
+                public void removeServiceMetadata(ServiceMetadataIdentifier 
metadataIdentifier) {
 
                 }
 
@@ -63,7 +64,8 @@ public class AbstractMetadataReportFactoryTest {
                 }
 
                 @Override
-                public void saveSubscriberData(SubscriberMetadataIdentifier 
subscriberMetadataIdentifier, List<String> urls) {
+                public void saveSubscribedData(SubscriberMetadataIdentifier 
subscriberMetadataIdentifier,
+                                               Set<String> urls) {
 
                 }
 
diff --git 
a/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/report/support/AbstractMetadataReportTest.java
 
b/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/report/support/AbstractMetadataReportTest.java
index 60d8f3d..24239e5 100644
--- 
a/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/report/support/AbstractMetadataReportTest.java
+++ 
b/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/report/support/AbstractMetadataReportTest.java
@@ -297,7 +297,7 @@ public class AbstractMetadataReportTest {
         }
 
         @Override
-        protected void doRemoveMetadata(ServiceMetadataIdentifier 
metadataIdentifier, URL url) {
+        protected void doRemoveMetadata(ServiceMetadataIdentifier 
metadataIdentifier) {
             throw new UnsupportedOperationException("This extension does not 
support working as a remote metadata center.");
         }
 
@@ -307,12 +307,12 @@ public class AbstractMetadataReportTest {
         }
 
         @Override
-        protected void doSaveSubscriberData(SubscriberMetadataIdentifier 
subscriberMetadataIdentifier, List<String> urls) {
+        protected void doSaveSubscriberData(SubscriberMetadataIdentifier 
subscriberMetadataIdentifier, String urls) {
 
         }
 
         @Override
-        protected List<String> 
doGetSubscribedURLs(SubscriberMetadataIdentifier metadataIdentifier) {
+        protected String doGetSubscribedURLs(SubscriberMetadataIdentifier 
metadataIdentifier) {
             throw new UnsupportedOperationException("This extension does not 
support working as a remote metadata center.");
         }
 
@@ -358,7 +358,7 @@ public class AbstractMetadataReportTest {
         }
 
         @Override
-        protected void doRemoveMetadata(ServiceMetadataIdentifier 
metadataIdentifier, URL url) {
+        protected void doRemoveMetadata(ServiceMetadataIdentifier 
metadataIdentifier) {
             throw new UnsupportedOperationException("This extension does not 
support working as a remote metadata center.");
         }
 
@@ -368,12 +368,12 @@ public class AbstractMetadataReportTest {
         }
 
         @Override
-        protected void doSaveSubscriberData(SubscriberMetadataIdentifier 
subscriberMetadataIdentifier, List<String> urls) {
+        protected void doSaveSubscriberData(SubscriberMetadataIdentifier 
subscriberMetadataIdentifier, String urls) {
 
         }
 
         @Override
-        protected List<String> 
doGetSubscribedURLs(SubscriberMetadataIdentifier metadataIdentifier) {
+        protected String doGetSubscribedURLs(SubscriberMetadataIdentifier 
metadataIdentifier) {
             throw new UnsupportedOperationException("This extension does not 
support working as a remote metadata center.");
         }
 
diff --git 
a/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/test/JTestMetadataReport4Test.java
 
b/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/test/JTestMetadataReport4Test.java
index 48b77b7..57d41ee 100644
--- 
a/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/test/JTestMetadataReport4Test.java
+++ 
b/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/test/JTestMetadataReport4Test.java
@@ -67,7 +67,7 @@ public class JTestMetadataReport4Test extends 
AbstractMetadataReport {
     }
 
     @Override
-    protected void doRemoveMetadata(ServiceMetadataIdentifier 
metadataIdentifier, URL url) {
+    protected void doRemoveMetadata(ServiceMetadataIdentifier 
metadataIdentifier) {
         throw new UnsupportedOperationException("This extension does not 
support working as a remote metadata center.");
     }
 
@@ -77,12 +77,12 @@ public class JTestMetadataReport4Test extends 
AbstractMetadataReport {
     }
 
     @Override
-    protected void doSaveSubscriberData(SubscriberMetadataIdentifier 
subscriberMetadataIdentifier, List<String> urls) {
+    protected void doSaveSubscriberData(SubscriberMetadataIdentifier 
subscriberMetadataIdentifier, String urls) {
 
     }
 
     @Override
-    protected List<String> doGetSubscribedURLs(SubscriberMetadataIdentifier 
metadataIdentifier) {
+    protected String doGetSubscribedURLs(SubscriberMetadataIdentifier 
metadataIdentifier) {
         throw new UnsupportedOperationException("This extension does not 
support working as a remote metadata center.");
     }
 
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 1ad4516..ba96a08 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
@@ -63,7 +63,7 @@ public class ConsulMetadataReport extends 
AbstractMetadataReport {
     }
 
     @Override
-    protected void doRemoveMetadata(ServiceMetadataIdentifier 
serviceMetadataIdentifier, URL url) {
+    protected void doRemoveMetadata(ServiceMetadataIdentifier 
serviceMetadataIdentifier) {
         throw new UnsupportedOperationException("This extension does not 
support working as a remote metadata center.");
     }
 
@@ -73,12 +73,12 @@ public class ConsulMetadataReport extends 
AbstractMetadataReport {
     }
 
     @Override
-    protected void doSaveSubscriberData(SubscriberMetadataIdentifier 
subscriberMetadataIdentifier, List<String> urls) {
+    protected void doSaveSubscriberData(SubscriberMetadataIdentifier 
subscriberMetadataIdentifier, String urlListStr) {
 
     }
 
     @Override
-    protected List<String> doGetSubscribedURLs(SubscriberMetadataIdentifier 
subscriberMetadataIdentifier) {
+    protected String doGetSubscribedURLs(SubscriberMetadataIdentifier 
subscriberMetadataIdentifier) {
         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 222eb19..507cd53 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
@@ -90,7 +90,7 @@ public class EtcdMetadataReport extends 
AbstractMetadataReport {
     }
 
     @Override
-    protected void doRemoveMetadata(ServiceMetadataIdentifier 
serviceMetadataIdentifier, URL url) {
+    protected void doRemoveMetadata(ServiceMetadataIdentifier 
serviceMetadataIdentifier) {
         throw new UnsupportedOperationException("This extension does not 
support working as a remote metadata center.");
     }
 
@@ -100,12 +100,12 @@ public class EtcdMetadataReport extends 
AbstractMetadataReport {
     }
 
     @Override
-    protected void doSaveSubscriberData(SubscriberMetadataIdentifier 
subscriberMetadataIdentifier, List<String> urls) {
+    protected void doSaveSubscriberData(SubscriberMetadataIdentifier 
subscriberMetadataIdentifier, String urlListStr) {
 
     }
 
     @Override
-    protected List<String> doGetSubscribedURLs(SubscriberMetadataIdentifier 
subscriberMetadataIdentifier) {
+    protected String doGetSubscribedURLs(SubscriberMetadataIdentifier 
subscriberMetadataIdentifier) {
         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 f1b5e90..bdbe759 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
@@ -131,7 +131,7 @@ public class NacosMetadataReport extends 
AbstractMetadataReport {
     }
 
     @Override
-    protected void doRemoveMetadata(ServiceMetadataIdentifier 
serviceMetadataIdentifier, URL url) {
+    protected void doRemoveMetadata(ServiceMetadataIdentifier 
serviceMetadataIdentifier) {
         throw new UnsupportedOperationException("This extension does not 
support working as a remote metadata center.");
     }
 
@@ -141,12 +141,12 @@ public class NacosMetadataReport extends 
AbstractMetadataReport {
     }
 
     @Override
-    protected void doSaveSubscriberData(SubscriberMetadataIdentifier 
subscriberMetadataIdentifier, List<String> urls) {
+    protected void doSaveSubscriberData(SubscriberMetadataIdentifier 
subscriberMetadataIdentifier, String urlListStr) {
         throw new UnsupportedOperationException("This extension does not 
support working as a remote metadata center.");
     }
 
     @Override
-    protected List<String> doGetSubscribedURLs(SubscriberMetadataIdentifier 
subscriberMetadataIdentifier) {
+    protected String doGetSubscribedURLs(SubscriberMetadataIdentifier 
subscriberMetadataIdentifier) {
         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 cebf14c..c9b3bb4 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
@@ -86,7 +86,7 @@ public class RedisMetadataReport extends 
AbstractMetadataReport {
     }
 
     @Override
-    protected void doRemoveMetadata(ServiceMetadataIdentifier 
serviceMetadataIdentifier, URL url) {
+    protected void doRemoveMetadata(ServiceMetadataIdentifier 
serviceMetadataIdentifier) {
 
     }
 
@@ -96,12 +96,12 @@ public class RedisMetadataReport extends 
AbstractMetadataReport {
     }
 
     @Override
-    protected void doSaveSubscriberData(SubscriberMetadataIdentifier 
subscriberMetadataIdentifier, List<String> urls) {
+    protected void doSaveSubscriberData(SubscriberMetadataIdentifier 
subscriberMetadataIdentifier, String urlListStr) {
         throw new UnsupportedOperationException("This extension does not 
support working as a remote metadata center.");
     }
 
     @Override
-    protected List<String> doGetSubscribedURLs(SubscriberMetadataIdentifier 
subscriberMetadataIdentifier) {
+    protected String doGetSubscribedURLs(SubscriberMetadataIdentifier 
subscriberMetadataIdentifier) {
         throw new UnsupportedOperationException("This extension does not 
support working as a remote metadata center.");
     }
 
diff --git 
a/dubbo-metadata/dubbo-metadata-report-zookeeper/src/main/java/org/apache/dubbo/metadata/store/zookeeper/ZookeeperMetadataReport.java
 
b/dubbo-metadata/dubbo-metadata-report-zookeeper/src/main/java/org/apache/dubbo/metadata/store/zookeeper/ZookeeperMetadataReport.java
index d1224cb..b370a62 100644
--- 
a/dubbo-metadata/dubbo-metadata-report-zookeeper/src/main/java/org/apache/dubbo/metadata/store/zookeeper/ZookeeperMetadataReport.java
+++ 
b/dubbo-metadata/dubbo-metadata-report-zookeeper/src/main/java/org/apache/dubbo/metadata/store/zookeeper/ZookeeperMetadataReport.java
@@ -80,7 +80,7 @@ public class ZookeeperMetadataReport extends 
AbstractMetadataReport {
     }
 
     @Override
-    protected void doRemoveMetadata(ServiceMetadataIdentifier 
metadataIdentifier, URL url) {
+    protected void doRemoveMetadata(ServiceMetadataIdentifier 
metadataIdentifier) {
         zkClient.delete(getNodePath(metadataIdentifier));
     }
 
@@ -90,18 +90,18 @@ public class ZookeeperMetadataReport extends 
AbstractMetadataReport {
     }
 
     @Override
-    protected void doSaveSubscriberData(SubscriberMetadataIdentifier 
subscriberMetadataIdentifier, List<String> urls) {
-
+    protected void doSaveSubscriberData(SubscriberMetadataIdentifier 
subscriberMetadataIdentifier, String urls) {
+        zkClient.create(getNodePath(subscriberMetadataIdentifier), urls, 
false);
     }
 
     @Override
-    protected List<String> doGetSubscribedURLs(SubscriberMetadataIdentifier 
subscriberMetadataIdentifier) {
-        return null;
+    protected String doGetSubscribedURLs(SubscriberMetadataIdentifier 
subscriberMetadataIdentifier) {
+        return zkClient.getContent(getNodePath(subscriberMetadataIdentifier));
     }
 
     @Override
-    public String getServiceDefinition(MetadataIdentifier 
consumerMetadataIdentifier) {
-        throw new UnsupportedOperationException("This extension does not 
support working as a remote metadata center.");
+    public String getServiceDefinition(MetadataIdentifier metadataIdentifier) {
+        return zkClient.getContent(getNodePath(metadataIdentifier));
     }
 
     private void storeMetadata(MetadataIdentifier metadataIdentifier, String 
v) {
@@ -116,5 +116,9 @@ public class ZookeeperMetadataReport extends 
AbstractMetadataReport {
         return toRootDir() + 
metadataIdentifier.getUniqueKey(MetadataIdentifier.KeyTypeEnum.PATH);
     }
 
+    String getNodePath(SubscriberMetadataIdentifier metadataIdentifier) {
+        return toRootDir() + 
metadataIdentifier.getUniqueKey(MetadataIdentifier.KeyTypeEnum.PATH);
+    }
+
 
 }
diff --git 
a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/RefreshServiceMetadataCustomizer.java
 
b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/RefreshServiceMetadataCustomizer.java
index 342681c..5681b98 100644
--- 
a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/RefreshServiceMetadataCustomizer.java
+++ 
b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/RefreshServiceMetadataCustomizer.java
@@ -6,7 +6,11 @@ import 
org.apache.dubbo.registry.client.ServiceInstanceCustomizer;
 
 import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_KEY;
 import static org.apache.dubbo.common.constants.CommonConstants.REVISION_KEY;
+import static 
org.apache.dubbo.metadata.WritableMetadataService.DEFAULT_EXTENSION;
 import static 
org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.EXPORTED_SERVICES_REVISION_KEY;
+import static 
org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.getExportedServicesRevision;
+import static 
org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.getMetadataStoredType;
+import static 
org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.getSubscribedServicesRevision;
 
 /**
  * An {@link ServiceInstanceCustomizer} to refresh metadata.
@@ -14,14 +18,19 @@ import static 
org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataU
  * 2019-08-08
  */
 public class RefreshServiceMetadataCustomizer implements 
ServiceInstanceCustomizer {
+
+    public int getPriority() {
+        return MAX_PRIORITY;
+    }
+
     @Override
     public void customize(ServiceInstance serviceInstance) {
         // FIXME to define the constant
+        String metadataStoredType = getMetadataStoredType(serviceInstance);
         WritableMetadataService remoteWritableMetadataService =
-                
WritableMetadataService.getExtension(serviceInstance.getMetadata().getOrDefault(REVISION_KEY,
 DEFAULT_KEY));
-        // FIXME  TEST
-        remoteWritableMetadataService =
-                WritableMetadataService.getExtension("remote");
-        
remoteWritableMetadataService.refreshMetadata(serviceInstance.getMetadata().get(EXPORTED_SERVICES_REVISION_KEY));
+                WritableMetadataService.getExtension(metadataStoredType == 
null ? DEFAULT_EXTENSION : metadataStoredType);
+
+        
remoteWritableMetadataService.refreshMetadata(getExportedServicesRevision(serviceInstance),
+                getSubscribedServicesRevision(serviceInstance));
     }
 }
diff --git 
a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/ServiceInstanceMetadataUtils.java
 
b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/ServiceInstanceMetadataUtils.java
index dcebcec..329dea8 100644
--- 
a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/ServiceInstanceMetadataUtils.java
+++ 
b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/ServiceInstanceMetadataUtils.java
@@ -65,6 +65,16 @@ public class ServiceInstanceMetadataUtils {
     public static String EXPORTED_SERVICES_REVISION_KEY = 
"dubbo.exported-services.revision";
 
     /**
+     * The key of The revision for all subscribed Dubbo services.
+     */
+    public static String SUBSCRIBER_SERVICES_REVISION_KEY = 
"dubbo.subscribed-services.revision";
+
+    /**
+     * The key of metadata store type.
+     */
+    public static String MEATADATA_STORED_TYPE_KEY = 
"dubbo.metadata.stored-type";
+
+    /**
      * The {@link URL url's} parameter name of Dubbo Provider host
      */
     public static final String HOST_PARAM_NAME = "provider.host";
@@ -159,6 +169,28 @@ public class ServiceInstanceMetadataUtils {
         return metadata.get(EXPORTED_SERVICES_REVISION_KEY);
     }
 
+    /**
+     * The revision for all subscribed Dubbo services from the specified 
{@link ServiceInstance}.
+     *
+     * @param serviceInstance the specified {@link ServiceInstance}
+     * @return <code>null</code> if not exits
+     */
+    public static String getSubscribedServicesRevision(ServiceInstance 
serviceInstance) {
+        Map<String, String> metadata = serviceInstance.getMetadata();
+        return metadata.get(SUBSCRIBER_SERVICES_REVISION_KEY);
+    }
+
+    /**
+     * The metadata is stored in the type used to which {@link 
org.apache.dubbo.metadata.WritableMetadataService} instance.
+     *
+     * @param serviceInstance the specified {@link ServiceInstance}
+     * @return <code>null</code> if not exits
+     */
+    public static String getMetadataStoredType(ServiceInstance 
serviceInstance) {
+        Map<String, String> metadata = serviceInstance.getMetadata();
+        return metadata.get(MEATADATA_STORED_TYPE_KEY);
+    }
+
     private static void setProviderHostParam(Map<String, String> params, URL 
providerURL) {
         params.put(HOST_PARAM_NAME, providerURL.getHost());
     }
diff --git 
a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/SubscribedServicesRevisionMetadataCustomizer.java
 
b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/SubscribedServicesRevisionMetadataCustomizer.java
new file mode 100644
index 0000000..7197e10
--- /dev/null
+++ 
b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/SubscribedServicesRevisionMetadataCustomizer.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;
+
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.compiler.support.ClassUtils;
+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;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.SortedSet;
+
+import static java.lang.String.valueOf;
+import static java.util.Objects.hash;
+import static org.apache.dubbo.common.constants.CommonConstants.METADATA_KEY;
+import static 
org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.EXPORTED_SERVICES_REVISION_KEY;
+import static 
org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.SUBSCRIBER_SERVICES_REVISION_KEY;
+
+/**
+ * The customizer to a add the metadata that the reversion of Dubbo subscribed 
services calculates.
+ * <p>
+ * The reversion is calculated on the methods that all Dubbo subscribed 
interfaces declare
+ *
+ * @since 2.7.5
+ */
+public class SubscribedServicesRevisionMetadataCustomizer extends 
ServiceInstanceMetadataCustomizer {
+
+    @Override
+    protected String buildMetadataKey(ServiceInstance serviceInstance) {
+        return SUBSCRIBER_SERVICES_REVISION_KEY;
+    }
+
+    @Override
+    protected String buildMetadataValue(ServiceInstance serviceInstance) {
+        WritableMetadataService writableMetadataService = 
WritableMetadataService.getExtension(
+                serviceInstance.getMetadata().get(METADATA_KEY)
+        );
+        SortedSet<String> subscribedURLs = 
writableMetadataService.getSubscribedURLs();
+        Object[] data = subscribedURLs.stream()
+                .map(URL::valueOf)                       // String to URL
+                .map(URL::getServiceInterface)           // get the service 
interface
+                .filter(this::isNotMetadataService)      // filter not 
MetadataService interface
+                .map(ClassUtils::forName)                // load business 
interface class
+                .map(Class::getMethods)                  // get all public 
methods from business interface
+                .map(Arrays::asList)                     // Array to List
+                .flatMap(Collection::stream)             // flat 
Stream<Stream> to be Stream
+                .map(Object::toString)                   // Method to String
+                .sorted()                                // sort methods 
marking sure the calculation of reversion is stable
+                .toArray();                              // Stream to Array
+        return valueOf(hash(data));                      // calculate the hash 
code as reversion
+    }
+
+    private boolean isNotMetadataService(String serviceInterface) {
+        return !MetadataService.class.getName().equals(serviceInterface);
+    }
+}
diff --git 
a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/service/ServiceOrientedRegistry.java
 
b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/service/ServiceOrientedRegistry.java
index 13b4eed..5fdc35f 100644
--- 
a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/service/ServiceOrientedRegistry.java
+++ 
b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/service/ServiceOrientedRegistry.java
@@ -66,9 +66,11 @@ 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.WritableMetadataService.DEFAULT_EXTENSION;
 import static 
org.apache.dubbo.metadata.report.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.getMetadataStoredType;
 import static 
org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.getProviderHost;
 import static 
org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.getProviderPort;
 
@@ -95,7 +97,6 @@ public class ServiceOrientedRegistry extends FailbackRegistry 
{
 
     private final WritableMetadataService writableMetadataService;
 
-    private final MetadataServiceProxyFactory metadataServiceProxyFactory;
 
     public ServiceOrientedRegistry(URL registryURL) {
         super(registryURL);
@@ -105,9 +106,7 @@ public class ServiceOrientedRegistry extends 
FailbackRegistry {
 
         String metadata = registryURL.getParameter(METADATA_REPORT_KEY, 
METADATA_DEFAULT);
         // FIXME
-        metadata = "remote";
         this.writableMetadataService = 
WritableMetadataService.getExtension(metadata);
-        this.metadataServiceProxyFactory = 
MetadataServiceProxyFactory.getExtension(metadata);
     }
 
     private Set<String> buildSubscribedServices(URL url) {
@@ -430,9 +429,12 @@ public class ServiceOrientedRegistry extends 
FailbackRegistry {
         String version = subscribedURL.getParameter(VERSION_KEY);
         // The subscribed protocol may be null
         String protocol = subscribedURL.getParameter(PROTOCOL_KEY);
+        String metadataServiceType = getMetadataStoredType(providerInstance);
 
         try {
-            MetadataService metadataService = 
metadataServiceProxyFactory.getProxy(providerInstance);
+            MetadataService metadataService = MetadataServiceProxyFactory
+                    .getExtension(metadataServiceType == null ? 
DEFAULT_EXTENSION : metadataServiceType)
+                    .getProxy(providerInstance);
             SortedSet<String> urls = 
metadataService.getExportedURLs(serviceInterface, group, version, protocol);
             exportedURLs = 
urls.stream().map(URL::valueOf).collect(Collectors.toList());
         } catch (Throwable e) {
@@ -440,7 +442,6 @@ public class ServiceOrientedRegistry extends 
FailbackRegistry {
                 logger.error(e.getMessage(), e);
             }
         }
-
         return exportedURLs;
     }
 
diff --git 
a/dubbo-registry/dubbo-registry-api/src/main/resources/META-INF/services/org.apache.dubbo.registry.client.ServiceInstanceCustomizer
 
b/dubbo-registry/dubbo-registry-api/src/main/resources/META-INF/services/org.apache.dubbo.registry.client.ServiceInstanceCustomizer
index 6c66ada..7b06893 100644
--- 
a/dubbo-registry/dubbo-registry-api/src/main/resources/META-INF/services/org.apache.dubbo.registry.client.ServiceInstanceCustomizer
+++ 
b/dubbo-registry/dubbo-registry-api/src/main/resources/META-INF/services/org.apache.dubbo.registry.client.ServiceInstanceCustomizer
@@ -1,3 +1,4 @@
 
org.apache.dubbo.registry.client.metadata.MetadataServiceURLParamsMetadataCustomizer
 
org.apache.dubbo.registry.client.metadata.ExportedServicesRevisionMetadataCustomizer
+org.apache.dubbo.registry.client.metadata.SubscribedServicesRevisionMetadataCustomizer
 org.apache.dubbo.registry.client.metadata.RefreshServiceMetadataCustomizer

Reply via email to