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/29 08:49:44 UTC

[dubbo] branch cloud-native updated (374899c -> f4b4ce7)

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

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


    from 374899c  add gRPC framework support
     new 7725906  nacos
     new 1fa487e  Merge branch 'cloud-native' of github.com:apache/incubator-dubbo into cloud-native
     new 4a21c6b  Merge branch 'cloud-native' of github.com:apache/incubator-dubbo into cloud-native
     new e41963b  merge
     new 3cc4981  merge
     new 95d85e5  Merge branch 'cloud-native' of github.com:apache/incubator-dubbo into cloud-native
     new ef4415e  unit test
     new f4b4ce7  unit test

The 8 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 dubbo-bootstrap/pom.xml                            |   7 +
 .../EtcdDubboServiceConsumerBootstrap.java         |   2 +-
 .../EtcdDubboServiceProviderBootstrap.java         |   6 +-
 .../NacosDubboServiceConsumerBootstrap.java        |   3 +
 .../store/InMemoryWritableMetadataService.java     |  52 +++++-
 .../store/RemoteWritableMetadataService.java       |  30 ++--
 .../RemoteWritableMetadataServiceDelegate.java     |  14 +-
 .../store/InMemoryWritableMetadataServiceTest.java |  79 +++++++++
 .../store/RemoteWritableMeatadataServiceTest.java  |  88 ++++++++--
 .../RemoteWritableMetadataServiceDelegateTest.java | 182 +++++++++++++++++++++
 .../metadata/test/JTestMetadataReport4Test.java    |  13 +-
 .../metadata/proxy/RemoteMetadataServiceProxy.java |  17 +-
 12 files changed, 441 insertions(+), 52 deletions(-)
 create mode 100644 dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/store/InMemoryWritableMetadataServiceTest.java
 create mode 100644 dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/store/RemoteWritableMetadataServiceDelegateTest.java


[dubbo] 06/08: Merge branch 'cloud-native' of github.com:apache/incubator-dubbo into cloud-native

Posted by vi...@apache.org.
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 95d85e514e010f178056fccf05c75cd80deb7121
Merge: 3cc4981 615941d
Author: cvictory <sh...@gmail.com>
AuthorDate: Tue Aug 27 14:57:24 2019 +0800

    Merge branch 'cloud-native' of github.com:apache/incubator-dubbo into cloud-native

 .../registry/client/ServiceDiscoveryRegistry.java  | 89 +++++++---------------
 .../listener/ServiceInstancesChangedListener.java  |  8 +-
 .../ServiceInstancesChangedListenerTest.java       |  2 +-
 .../zookeeper/ZookeeperServiceDiscoveryTest.java   |  3 +-
 4 files changed, 30 insertions(+), 72 deletions(-)


[dubbo] 02/08: Merge branch 'cloud-native' of github.com:apache/incubator-dubbo into cloud-native

Posted by vi...@apache.org.
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 1fa487e274f3ff2e3ce93ed82c5751d3365230f8
Merge: 7725906 df0d39c
Author: cvictory <sh...@gmail.com>
AuthorDate: Fri Aug 23 11:13:11 2019 +0800

    Merge branch 'cloud-native' of github.com:apache/incubator-dubbo into cloud-native

 dubbo-bootstrap/pom.xml                            |   6 +
 .../bootstrap/DubboServiceConsumerBootstrap.java   |  15 +-
 .../bootstrap/DubboServiceProviderBootstrap.java   |   2 +-
 .../DubboServiceProviderMinimumBootstrap.java      |   2 +-
 .../dubbo/common/constants/RegistryConstants.java  |   9 +-
 .../registry/client/DefaultServiceInstance.java    |   2 +-
 .../registry/client/ServiceDiscoveryRegistry.java  |  10 +-
 .../client/ServiceInstanceMetadataCustomizer.java  |  18 +-
 ...ExportedServicesRevisionMetadataCustomizer.java |  33 +-
 ...MetadataServiceURLParamsMetadataCustomizer.java |   8 +-
 .../metadata/ServiceInstanceMetadataUtils.java     |  58 ++--
 ...bscribedServicesRevisionMetadataCustomizer.java |  34 +-
 ...ataCustomizer.java => URLRevisionResolver.java} |  54 +--
 .../metadata/proxy/RemoteMetadataServiceProxy.java |   5 +-
 .../client/metadata/URLRevisionResolverTest.java   |  47 +++
 .../registry/consul/ConsulServiceDiscovery.java    |   2 +-
 dubbo-registry/dubbo-registry-eureka/pom.xml       |  20 +-
 .../eureka/ConfigurableEurekaInstanceConfig.java   | 369 +++++++++++++++++++++
 .../registry/eureka/EurekaServiceDiscovery.java    | 278 ++++++++++++++++
 .../apache/dubbo/registry/eureka/package-info.java |  20 +-
 ...g.apache.dubbo.registry.client.ServiceDiscovery |   1 +
 .../eureka/EurekaServiceDiscoveryTest.java         |  66 ++++
 22 files changed, 910 insertions(+), 149 deletions(-)



[dubbo] 08/08: unit test

Posted by vi...@apache.org.
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 f4b4ce719187ce348cdfe87caee5fbe74976534b
Merge: ef4415e 374899c
Author: cvictory <sh...@gmail.com>
AuthorDate: Thu Aug 29 16:48:57 2019 +0800

    unit test

 .gitignore                                         |    6 +-
 LICENSE                                            |    3 +
 NOTICE                                             |   10 +
 dubbo-all/pom.xml                                  |    8 +
 dubbo-bom/pom.xml                                  |    5 +
 .../org/apache/dubbo/bootstrap/DubboBootstrap.java |    8 +-
 .../dubbo/common/constants/CommonConstants.java    |    4 +-
 .../org/apache/dubbo/config/ReferenceConfig.java   |    4 +-
 .../org/apache/dubbo/config/ServiceConfig.java     |    4 +-
 .../dubbo-demo-xml/dubbo-demo-xml-consumer/pom.xml |    4 +
 dubbo-demo/dubbo-demo-xml/pom.xml                  |    8 +
 dubbo-dependencies-bom/pom.xml                     |   17 +
 dubbo-distribution/src/assembly/source-release.xml |    1 +
 .../dubbo/metadata/WritableMetadataService.java    |    4 +-
 ...g.apache.dubbo.metadata.WritableMetadataService |    4 +-
 .../store/RemoteWritableMeatadataServiceTest.java  |    2 +-
 .../RemoteWritableMetadataServiceDelegateTest.java |    5 +-
 .../registry/client/ServiceDiscoveryRegistry.java  |  446 ++++--
 .../metadata/ServiceInstanceMetadataUtils.java     |    6 +-
 .../proxy/RemoteMetadataServiceProxyFactory.java   |    4 -
 .../registry/eureka/EurekaServiceDiscovery.java    |    4 +-
 .../.gradle/4.3/fileChanges/last-build.bin         |  Bin 0 -> 1 bytes
 .../4.3/fileContent/annotation-processors.bin      |  Bin 0 -> 19793 bytes
 .../.gradle/4.3/fileContent/fileContent.lock       |  Bin 0 -> 17 bytes
 .../compiler/.gradle/4.3/fileHashes/fileHashes.bin |  Bin 0 -> 523091 bytes
 .../.gradle/4.3/fileHashes/fileHashes.lock         |  Bin 0 -> 17 bytes
 .../.gradle/4.3/fileHashes/resourceHashesCache.bin |  Bin 0 -> 193707 bytes
 .../.gradle/4.3/nativeCompile/nativeCompile.bin    |  Bin 0 -> 18497 bytes
 .../.gradle/4.3/nativeCompile/nativeCompile.lock   |  Bin 0 -> 17 bytes
 .../.gradle/4.3/taskHistory/taskHistory.bin        |  Bin 0 -> 5498488 bytes
 .../.gradle/4.3/taskHistory/taskHistory.lock       |  Bin 0 -> 17 bytes
 .../.gradle/4.9/fileChanges/last-build.bin         |  Bin 0 -> 1 bytes
 .../4.9/fileContent/annotation-processors.bin      |  Bin 0 -> 19064 bytes
 .../.gradle/4.9/fileContent/fileContent.lock       |  Bin 0 -> 17 bytes
 .../.gradle/4.9/fileContent/parsedCSource.bin      |  Bin 0 -> 4542342 bytes
 .../compiler/.gradle/4.9/fileHashes/fileHashes.bin |  Bin 0 -> 882335 bytes
 .../.gradle/4.9/fileHashes/fileHashes.lock         |  Bin 0 -> 17 bytes
 .../.gradle/4.9/fileHashes/resourceHashesCache.bin |  Bin 0 -> 397477 bytes
 .../.gradle/4.9/nativeCompile/nativeCompile.bin    |  Bin 0 -> 50817 bytes
 .../.gradle/4.9/nativeCompile/nativeCompile.lock   |  Bin 0 -> 17 bytes
 .../.gradle/4.9/taskHistory/taskHistory.bin        |  Bin 0 -> 12054698 bytes
 .../.gradle/4.9/taskHistory/taskHistory.lock       |  Bin 0 -> 17 bytes
 .../buildOutputCleanup/buildOutputCleanup.lock     |  Bin 0 -> 17 bytes
 .../.gradle/buildOutputCleanup/cache.properties    |    2 +
 .../.gradle/buildOutputCleanup/outputFiles.bin     |  Bin 0 -> 57533 bytes
 .../compiler/.gradle/vcsWorkingDirs/gc.properties  |    0
 dubbo-rpc/dubbo-rpc-grpc/compiler/BUILD.bazel      |   12 +
 dubbo-rpc/dubbo-rpc-grpc/compiler/README.md        |  171 +++
 dubbo-rpc/dubbo-rpc-grpc/compiler/build.gradle     |  405 +++++
 .../dubbo-rpc-grpc/compiler/check-artifact.sh      |  131 ++
 .../gradle/wrapper/gradle-wrapper.properties       |    5 +
 dubbo-rpc/dubbo-rpc-grpc/compiler/gradlew          |  172 +++
 dubbo-rpc/dubbo-rpc-grpc/compiler/gradlew.bat      |   84 ++
 .../src/java_plugin/cpp/java_generator.cpp         | 1553 ++++++++++++++++++++
 .../compiler/src/java_plugin/cpp/java_generator.h  |   57 +
 .../compiler/src/java_plugin/cpp/java_plugin.cpp   |   70 +
 .../src/test/golden/TestDeprecatedService.java.txt |  316 ++++
 .../compiler/src/test/golden/TestService.java.txt  |  665 +++++++++
 .../test/proto/grpc/testing/compiler/test.proto    |   83 ++
 .../testLite/golden/TestDeprecatedService.java.txt |  279 ++++
 .../src/testLite/golden/TestService.java.txt       |  623 ++++++++
 .../testNano/golden/TestDeprecatedService.java.txt |  305 ++++
 .../src/testNano/golden/TestService.java.txt       |  664 +++++++++
 dubbo-rpc/{ => dubbo-rpc-grpc}/pom.xml             |   56 +-
 .../rpc/protocol/grpc/DubboHandlerRegistry.java    |   70 +
 .../dubbo/rpc/protocol/grpc/GrpcProtocol.java      |  200 +++
 .../dubbo/internal/org.apache.dubbo.rpc.Protocol   |    1 +
 dubbo-rpc/pom.xml                                  |    1 +
 pom.xml                                            |   24 +-
 69 files changed, 6281 insertions(+), 225 deletions(-)

diff --cc dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/store/RemoteWritableMetadataServiceDelegateTest.java
index 10b3eec,0000000..2f02975
mode 100644,000000..100644
--- a/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/store/RemoteWritableMetadataServiceDelegateTest.java
+++ b/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/store/RemoteWritableMetadataServiceDelegateTest.java
@@@ -1,183 -1,0 +1,182 @@@
 +package org.apache.dubbo.metadata.store;
 +
 +import org.apache.dubbo.common.URL;
 +import org.apache.dubbo.common.utils.NetUtils;
 +import org.apache.dubbo.metadata.WritableMetadataService;
 +import org.apache.dubbo.metadata.report.MetadataReportInstance;
 +import org.apache.dubbo.metadata.report.identifier.KeyTypeEnum;
 +import org.apache.dubbo.metadata.report.identifier.ServiceMetadataIdentifier;
 +import org.apache.dubbo.metadata.report.identifier.SubscriberMetadataIdentifier;
 +import org.apache.dubbo.metadata.test.JTestMetadataReport4Test;
 +import org.apache.dubbo.rpc.model.ApplicationModel;
 +
 +import org.junit.jupiter.api.Assertions;
 +import org.junit.jupiter.api.BeforeAll;
 +import org.junit.jupiter.api.BeforeEach;
 +import org.junit.jupiter.api.Test;
 +
 +import java.util.SortedSet;
 +
- import static org.apache.dubbo.common.constants.CommonConstants.METADATA_REMOTE;
 +
 +/**
 + * 2019-08-27
 + */
 +public class RemoteWritableMetadataServiceDelegateTest {
 +    static URL metadataURL = URL.valueOf("JTest://" + NetUtils.getLocalAddress().getHostName() + ":4444/org.apache.dubbo.Tes33tService?version=1.0.0&application=vic");
 +
 +    RemoteWritableMetadataServiceDelegate metadataReportService;
 +
 +    String interfaceName = "org.apache.dubbo.metadata.store.InterfaceNameTestService80", version = "0.6.9", group = null;
 +    URL url = URL.valueOf("dubbo://" + NetUtils.getLocalAddress().getHostName() + ":4444/?interface=" + interfaceName + "&version="
 +            + version + "&application=vicpubprovder&side=provider");
 +
 +    @BeforeAll
 +    public static void beforeAll() {
 +        MetadataReportInstance.init(metadataURL);
 +    }
 +
 +    @BeforeEach
 +    public void before() {
 +        metadataReportService = new RemoteWritableMetadataServiceDelegate();
 +    }
 +
 +
 +    @Test
 +    public void testInstance() {
-         WritableMetadataService metadataReportService1 = WritableMetadataService.getExtension(METADATA_REMOTE);
-         WritableMetadataService metadataReportService2 = WritableMetadataService.getExtension(METADATA_REMOTE);
++        WritableMetadataService metadataReportService1 = WritableMetadataService.getExtension("remote");
++        WritableMetadataService metadataReportService2 = WritableMetadataService.getExtension("remote");
 +        Assertions.assertSame(metadataReportService1, metadataReportService2);
 +        Assertions.assertTrue(metadataReportService1 instanceof RemoteWritableMetadataServiceDelegate);
 +    }
 +
 +    @Test
 +    public void testPublishServiceDefinition() throws InterruptedException {
 +        String interfaceName = "org.apache.dubbo.metadata.store.InterfaceNameTestService2", version = "0.9.9", group = null;
 +        URL tmpUrl = URL.valueOf("dubbo://" + NetUtils.getLocalAddress().getHostName() + ":4444/?interface=" + interfaceName + "&version="
 +                + version + "&application=vicpubprovder&side=provider");
 +        metadataReportService.publishServiceDefinition(tmpUrl);
 +        Thread.sleep(150);
 +        String v = metadataReportService.getServiceDefinition(interfaceName, version, group);
 +        Assertions.assertNotNull(v);
 +    }
 +
 +    @Test
 +    public void testExportURL() throws InterruptedException {
 +        URL url = URL.valueOf("dubbo://" + NetUtils.getLocalAddress().getHostName() + ":4444/org.apache.dubbo.Test567Service?version=1.0.44&application=vicpubprovder&side=provider");
 +        metadataReportService.exportURL(url);
 +        Thread.sleep(100);
 +        Assertions.assertTrue(getInMemoryWriableMetadataService().exportedServiceURLs.size() == 1);
 +        Assertions.assertEquals(getInMemoryWriableMetadataService().exportedServiceURLs.get(url.getServiceKey()).first(), url);
 +    }
 +
 +    @Test
 +    public void testSubscribeURL() throws InterruptedException {
 +        URL url = URL.valueOf("subscriber://" + NetUtils.getLocalAddress().getHostName() + ":4444/org.apache.dubbo.Test0678Service?version=1.3.144&application=vicpubprovder&side=provider");
 +        int origSize = getInMemoryWriableMetadataService().subscribedServiceURLs.size();
 +        metadataReportService.subscribeURL(url);
 +        Thread.sleep(100);
 +        int size = getInMemoryWriableMetadataService().subscribedServiceURLs.size();
 +        Assertions.assertTrue(size - origSize == 1);
 +        Assertions.assertEquals(getInMemoryWriableMetadataService().subscribedServiceURLs.get(url.getServiceKey()).first(), url);
 +    }
 +
 +    @Test
 +    public void testUnExportURL() throws InterruptedException {
 +        URL url = URL.valueOf("dubbo://" + NetUtils.getLocalAddress().getHostName() + ":4444/org.apache.dubbo.Test0567Service?version=1.2.44&application=vicpubprovder&side=provider");
 +        int origSize = getInMemoryWriableMetadataService().exportedServiceURLs.size();
 +        metadataReportService.exportURL(url);
 +        Thread.sleep(100);
 +        int size = getInMemoryWriableMetadataService().exportedServiceURLs.size();
 +        Assertions.assertTrue(size - origSize == 1);
 +        Assertions.assertEquals(getInMemoryWriableMetadataService().exportedServiceURLs.get(url.getServiceKey()).first(), url);
 +
 +        metadataReportService.unexportURL(url);
 +        int unexportSize = getInMemoryWriableMetadataService().exportedServiceURLs.size();
 +        Assertions.assertTrue(size - unexportSize == 1);
 +    }
 +
 +    @Test
 +    public void testUnSubscribeURL() throws InterruptedException {
 +        URL url = URL.valueOf("subscriber://" + NetUtils.getLocalAddress().getHostName() + ":4444/org.apache.dubbo.Test0678Service?version=1.5.477&application=vicpubprovder&side=provider");
 +        int origSize = getInMemoryWriableMetadataService().subscribedServiceURLs.size();
 +        metadataReportService.subscribeURL(url);
 +        Thread.sleep(100);
 +        int size = getInMemoryWriableMetadataService().subscribedServiceURLs.size();
 +        Assertions.assertTrue(size - origSize == 1);
 +        Assertions.assertEquals(getInMemoryWriableMetadataService().subscribedServiceURLs.get(url.getServiceKey()).first(), url);
 +
 +        metadataReportService.unsubscribeURL(url);
 +        Thread.sleep(100);
 +        Assertions.assertTrue(getInMemoryWriableMetadataService().subscribedServiceURLs.size() == 0);
 +    }
 +
 +    @Test
 +    public void testRefreshMetadataService() throws InterruptedException {
 +        URL publishUrl = URL.valueOf("dubbo://" + NetUtils.getLocalAddress().getHostName() + ":4444/org.apache.dubbo.TestRefreshMetadataService?version=1.6.8&application=vicpubprovder&side=provider");
 +        URL publishUrl2 = URL.valueOf("dubbo://" + NetUtils.getLocalAddress().getHostName() + ":4444/org.apache.dubbo.TestRefreshMetadata2Service?version=1.6.5&application=vicpubprovder&side=provider");
 +        metadataReportService.exportURL(publishUrl);
 +        metadataReportService.exportURL(publishUrl2);
 +        String exportedRevision = "9999";
 +        JTestMetadataReport4Test jTestMetadataReport4Test = (JTestMetadataReport4Test) MetadataReportInstance.getMetadataReport(true);
 +        int origSize = jTestMetadataReport4Test.store.size();
 +        int num = countNum();
 +        Assertions.assertTrue(metadataReportService.refreshMetadata(exportedRevision, "1109"));
 +        Thread.sleep(200);
 +        int size = jTestMetadataReport4Test.store.size();
 +        Assertions.assertTrue(size - origSize == num);
 +        Assertions.assertEquals(jTestMetadataReport4Test.store.get(getServiceMetadataIdentifier(publishUrl, exportedRevision).getUniqueKey(KeyTypeEnum.UNIQUE_KEY)), publishUrl.toFullString());
 +        Assertions.assertEquals(jTestMetadataReport4Test.store.get(getServiceMetadataIdentifier(publishUrl2, exportedRevision).getUniqueKey(KeyTypeEnum.UNIQUE_KEY)), publishUrl2.toFullString());
 +    }
 +
 +
 +    @Test
 +    public void testRefreshMetadataSubscription() throws InterruptedException {
 +        URL subscriberUrl1 = URL.valueOf("subscriber://" + NetUtils.getLocalAddress().getHostName() + ":4444/org.apache.dubbo.TestRefreshMetadata00Service?version=2.0.8&application=vicpubprovder&side=provider");
 +        URL subscriberUrl2 = URL.valueOf("subscriber://" + NetUtils.getLocalAddress().getHostName() + ":4444/org.apache.dubbo.TestRefreshMetadata09Service?version=2.0.5&application=vicpubprovder&side=provider");
 +        metadataReportService.subscribeURL(subscriberUrl1);
 +        metadataReportService.subscribeURL(subscriberUrl2);
 +        String exportedRevision = "9999";
 +        String subscriberRevision = "2099";
 +        String applicationName = "wriableMetadataService";
 +        JTestMetadataReport4Test jTestMetadataReport4Test = (JTestMetadataReport4Test) MetadataReportInstance.getMetadataReport(true);
 +        int origSize = jTestMetadataReport4Test.store.size();
 +        ApplicationModel.setApplication(applicationName);
 +        Assertions.assertTrue(metadataReportService.refreshMetadata(exportedRevision, subscriberRevision));
 +        Thread.sleep(200);
 +        int size = jTestMetadataReport4Test.store.size();
 +        Assertions.assertTrue(size - origSize == 1);
 +        String r = jTestMetadataReport4Test.store.get(getSubscriberMetadataIdentifier(
 +                subscriberRevision).getUniqueKey(KeyTypeEnum.UNIQUE_KEY));
 +        Assertions.assertNotNull(r);
 +    }
 +
 +
 +    private ServiceMetadataIdentifier getServiceMetadataIdentifier(URL publishUrl, String exportedRevision) {
 +        ServiceMetadataIdentifier serviceMetadataIdentifier = new ServiceMetadataIdentifier(publishUrl);
 +        serviceMetadataIdentifier.setRevision(exportedRevision);
 +        serviceMetadataIdentifier.setProtocol(publishUrl.getProtocol());
 +        return serviceMetadataIdentifier;
 +    }
 +
 +    private SubscriberMetadataIdentifier getSubscriberMetadataIdentifier(String subscriberRevision) {
 +        SubscriberMetadataIdentifier subscriberMetadataIdentifier = new SubscriberMetadataIdentifier();
 +        subscriberMetadataIdentifier.setRevision(subscriberRevision);
 +        subscriberMetadataIdentifier.setApplication(ApplicationModel.getApplication());
 +        return subscriberMetadataIdentifier;
 +    }
 +
 +    private InMemoryWritableMetadataService getInMemoryWriableMetadataService() {
 +        return (InMemoryWritableMetadataService) metadataReportService.defaultWritableMetadataService;
 +    }
 +
 +    private int countNum() {
 +        int num = 0;
 +        for (SortedSet<URL> tmp : getInMemoryWriableMetadataService().exportedServiceURLs.values()) {
 +            num += tmp.size();
 +        }
 +        if (!getInMemoryWriableMetadataService().subscribedServiceURLs.values().isEmpty()) {
 +            num++;
 +        }
 +        return num;
 +    }
 +}


[dubbo] 03/08: Merge branch 'cloud-native' of github.com:apache/incubator-dubbo into cloud-native

Posted by vi...@apache.org.
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 4a21c6bb07b533bf76c12aa081b9fdee9a1ed3a3
Merge: 1fa487e a485c15
Author: cvictory <sh...@gmail.com>
AuthorDate: Mon Aug 26 09:44:20 2019 +0800

    Merge branch 'cloud-native' of github.com:apache/incubator-dubbo into cloud-native

 .../bootstrap/DubboServiceConsumerBootstrap.java   |  10 +-
 .../DubboServiceProviderMinimumBootstrap.java      |  10 +-
 .../cluster/loadbalance/AbstractLoadBalance.java   |  38 ++-
 .../cluster/support/AbstractClusterInvoker.java    |   9 -
 .../support/RegistryAwareClusterInvoker.java       |  61 ----
 .../ZoneAwareCluster.java}                         |  14 +-
 .../support/registry/ZoneAwareClusterInvoker.java  |  98 ++++++
 .../cluster/support/wrapper/AbstractCluster.java   | 110 +++++++
 .../support/wrapper/MockClusterWrapper.java        |   7 +-
 .../internal/org.apache.dubbo.rpc.cluster.Cluster  |   2 +-
 .../dubbo/common/constants/RegistryConstants.java  |   4 +
 .../dubbo/common/extension/ExtensionLoader.java    |  22 +-
 .../apache/dubbo/common/infra/InfraAdapter.java    |  88 ++---
 .../dubbo/common/infra/support/CmdbAdapter.java    |  28 +-
 .../common/infra/support/EnvironmentAdapter.java   |  72 ++++
 .../common/infra/support/KubernetesAdapter.java    |  26 +-
 .../org.apache.dubbo.common.infra.InfraAdapter     |   1 +
 .../org/apache/dubbo/config/ApplicationConfig.java |  67 ++--
 .../org/apache/dubbo/config/ReferenceConfig.java   |   8 +-
 .../org/apache/dubbo/config/RegistryConfig.java    |  34 ++
 .../org/apache/dubbo/config/ServiceConfig.java     |   1 +
 .../dubbo/config/builders/RegistryBuilder.java     |  15 +
 .../src/main/resources/META-INF/compat/dubbo.xsd   |   5 +
 .../src/main/resources/META-INF/dubbo.xsd          |   5 +
 .../client/EventPublishingServiceDiscovery.java    |   1 +
 .../dubbo/registry/client/ServiceDiscovery.java    |  60 +++-
 .../registry/client/ServiceDiscoveryRegistry.java  | 366 +++++++++++++++------
 .../listener/ServiceInstancesChangedListener.java  |  13 +
 .../CompositeMetadataServiceURLBuilder.java        |   4 +-
 .../metadata/proxy/MetadataServiceProxy.java       | 122 -------
 .../selector/RandomServiceInstanceSelector.java    |   2 +-
 .../dubbo/registry/etcd/EtcdServiceDiscovery.java  |   3 +-
 .../registry/nacos/NacosServiceDiscovery.java      |   3 +-
 .../zookeeper/ZookeeperServiceDiscovery.java       |   3 +-
 .../ZookeeperServiceDiscoveryChangeWatcher.java    |  15 +-
 .../org/apache/dubbo/rpc/ClusterInterceptor.java   |  83 +++--
 .../main/java/org/apache/dubbo/rpc/Constants.java  |   2 +
 .../main/java/org/apache/dubbo/rpc/RpcContext.java |  14 +-
 .../java/org/apache/dubbo/rpc/ZoneDetector.java    |  22 +-
 .../org/apache/dubbo/rpc/filter/ContextFilter.java |   2 +
 .../ConsumerContextClusterInterceptor.java}        | 134 ++++----
 .../interceptors/ZoneAwareClusterInterceptor.java  |  61 ++++
 .../org.apache.dubbo.rpc.ClusterInterceptor        |   2 +
 .../dubbo/internal/org.apache.dubbo.rpc.Filter     |   1 -
 .../rpc/filter/ConsumerContextFilterTest.java      |  53 ---
 45 files changed, 1067 insertions(+), 634 deletions(-)


[dubbo] 05/08: merge

Posted by vi...@apache.org.
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 3cc498191ce1ee65d7bb9b020143ddd2c0311755
Merge: e41963b 4cf629d
Author: cvictory <sh...@gmail.com>
AuthorDate: Tue Aug 27 14:57:14 2019 +0800

    merge

 .../org/apache/dubbo/bootstrap/DubboBootstrap.java |  38 +++++-
 .../bootstrap/DubboServiceConsumerBootstrap.java   |  11 +-
 .../NacosDubboServiceConsumerBootstrap.java        |  13 +-
 .../cluster/loadbalance/AbstractLoadBalance.java   |   3 +-
 .../support/registry/ZoneAwareClusterInvoker.java  |   6 +-
 .../file/FileSystemDynamicConfiguration.java       |  11 +-
 .../dubbo/common/constants/CommonConstants.java    |   2 +-
 .../dubbo/common/constants/QosConstants.java       |   6 -
 .../dubbo/common/constants/RegistryConstants.java  |   2 +
 .../org/apache/dubbo/common/utils/StringUtils.java |  83 ++++++++++++
 .../org/apache/dubbo/config/AbstractConfig.java    |   6 +-
 .../org/apache/dubbo/config/ApplicationConfig.java |   9 +-
 .../org/apache/dubbo/config/RegistryConfig.java    |   2 +-
 .../apache/dubbo/config/context/ConfigManager.java |  68 +++++-----
 ...DubboLifecycleComponentApplicationListener.java |   9 +-
 .../zookeeper/ZookeeperDynamicConfiguration.java   |   2 +-
 .../dubbo/metadata/WritableMetadataService.java    |  14 +-
 ...g.apache.dubbo.metadata.WritableMetadataService |   2 +-
 .../client/DefaultServiceDiscoveryFactory.java     |   2 +-
 .../registry/client/ServiceDiscoveryRegistry.java  | 150 ++++++++++++++++-----
 .../client/event/ServiceInstancesChangedEvent.java |   1 +
 .../listener/ServiceInstancesChangedListener.java  |   8 +-
 .../RestProtocolSubscribedURLsSynthesizer.java     |  91 +++++++++++++
 .../metadata/ServiceInstanceMetadataUtils.java     |  31 +++--
 .../StandardMetadataServiceURLBuilder.java         |   6 +
 .../client/metadata/SubscribedURLsSynthesizer.java |  53 ++++++++
 ...istry.client.metadata.SubscribedURLsSynthesizer |   1 +
 .../ServiceInstancesChangedListenerTest.java       |   2 +-
 .../registry/consul/ConsulServiceDiscovery.java    |  84 ++++++++++--
 .../registry/eureka/EurekaServiceDiscovery.java    |   4 +-
 .../zookeeper/ZookeeperServiceDiscoveryTest.java   |   3 +-
 .../java/org/apache/dubbo/rpc/ZoneDetector.java    |   2 +-
 32 files changed, 563 insertions(+), 162 deletions(-)

diff --cc dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/NacosDubboServiceConsumerBootstrap.java
index 551a46d,22a2a39..c298f9d
--- a/dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/NacosDubboServiceConsumerBootstrap.java
+++ b/dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/NacosDubboServiceConsumerBootstrap.java
@@@ -35,13 -35,8 +35,11 @@@ public class NacosDubboServiceConsumerB
  //        applicationConfig.setMetadataType("remote");
          new DubboBootstrap()
                  .application(applicationConfig)
 +                // Zookeeper
 +//                .registry("nacos", builder -> builder.address("nacos://127.0.0.1:8848?registry.type=service&subscribed.services=dubbo-nacos-provider-demo"))
-                 .registry("nacos", builder -> builder.address("nacos://127.0.0.1:8848?registry-type=service&subscribed-services=dubbo-nacos-provider-demo"))
++//                .registry("nacos", builder -> builder.address("nacos://127.0.0.1:8848?registry-type=service&subscribed-services=dubbo-nacos-provider-demo"))
+                 .registry("nacos", builder -> builder.address("nacos://127.0.0.1:8848?registry-type=service&subscribed-services=service-provider"))
                  .metadataReport(new MetadataReportConfig("nacos://127.0.0.1:8848"))
-                 // 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"))
                  .reference("user", builder -> builder.interfaceClass(UserService.class).protocol("rest"))
                  .start()
                  .await();


[dubbo] 04/08: merge

Posted by vi...@apache.org.
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 e41963b966d6ccc169bbb30df4205762e732e3ba
Merge: 4a21c6b f8288cb
Author: cvictory <sh...@gmail.com>
AuthorDate: Tue Aug 27 09:57:59 2019 +0800

    merge

 .../EtcdDubboServiceConsumerBootstrap.java         |  2 +-
 .../EtcdDubboServiceProviderBootstrap.java         |  6 +-
 .../NacosDubboServiceConsumerBootstrap.java        |  6 +-
 .../NacosDubboServiceProviderBootstrap.java        |  4 +-
 ...=> ZookeeperDubboServiceConsumerBootstrap.java} | 18 ++---
 .../ZookeeperDubboServiceProviderBootstrap.java    | 38 +++++++++
 .../support/nacos/NacosDynamicConfiguration.java   | 71 ++++++++++++++++-
 .../nacos/NacosDynamicConfigurationTest.java       | 13 ++++
 .../registry/client/ServiceDiscoveryRegistry.java  | 52 ++++++-------
 .../metadata/ProtocolPortsMetadataCustomizer.java  | 51 +++++++++++++
 .../metadata/ServiceInstanceMetadataUtils.java     | 89 +++++++++++-----------
 .../StandardMetadataServiceURLBuilder.java         | 14 ++--
 .../client/metadata/URLRevisionResolver.java       | 58 +++++++++++---
 .../metadata/proxy/RemoteMetadataServiceProxy.java | 17 ++++-
 ...dubbo.registry.client.ServiceInstanceCustomizer |  1 +
 dubbo-registry/dubbo-registry-eureka/pom.xml       | 13 ++++
 16 files changed, 333 insertions(+), 120 deletions(-)

diff --cc dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/EtcdDubboServiceConsumerBootstrap.java
index e9c9dd2,e9c9dd2..4e815a5
--- a/dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/EtcdDubboServiceConsumerBootstrap.java
+++ b/dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/EtcdDubboServiceConsumerBootstrap.java
@@@ -34,7 -34,7 +34,7 @@@ public class EtcdDubboServiceConsumerBo
                  .application("dubbo-consumer-demo")
                  // Zookeeper
                  .protocol(builder -> builder.port(20887).name("dubbo"))
--                .registry("etcd3", builder -> builder.address("etcd3://127.0.0.1:2379?registry.type=service&subscribed.services=dubbo-provider-demo"))
++                .registry("etcd3", builder -> builder.address("etcd3://127.0.0.1:2379?registry-type=service&subscribed-services=dubbo-provider-demo"))
                  .metadataReport(new MetadataReportConfig("etcd://127.0.0.1:2379"))
                  // Nacos
  //                .registry("consul", builder -> builder.address("consul://127.0.0.1:8500?registry.type=service&subscribed.services=dubbo-provider-demo").group("namespace1"))
diff --cc dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/EtcdDubboServiceProviderBootstrap.java
index 9a59273,9a59273..8a7501a
--- a/dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/EtcdDubboServiceProviderBootstrap.java
+++ b/dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/EtcdDubboServiceProviderBootstrap.java
@@@ -49,7 -49,7 +49,7 @@@ public class EtcdDubboServiceProviderBo
  
          RegistryConfig serviceRegistry = new RegistryConfig();
          serviceRegistry.setId("serviceRegistry");
--        serviceRegistry.setAddress("etcd3://127.0.0.1:2379?registry.type=service");
++        serviceRegistry.setAddress("etcd3://127.0.0.1:2379?registry-type=service");
  
          ServiceConfig<EchoService> echoService = new ServiceConfig<>();
          echoService.setInterface(EchoService.class.getName());
@@@ -63,7 -63,7 +63,7 @@@
  //        userService.setRegistries(Arrays.asList(interfaceRegistry, serviceRegistry));
  
          ApplicationConfig applicationConfig = new ApplicationConfig("dubbo-provider-demo");
--        applicationConfig.setMetadataType("remote");
++//        applicationConfig.setMetadataType("remote");
          new DubboBootstrap()
                  .application(applicationConfig)
                  // Zookeeper in service registry type
@@@ -73,7 -73,7 +73,7 @@@
                  .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("etcd://127.0.0.1:2379"))
++//                .metadataReport(new MetadataReportConfig("etcd://127.0.0.1:2379"))
                  .service(echoService)
                  .service(userService)
                  .start()
diff --cc dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/NacosDubboServiceConsumerBootstrap.java
index 69f430c,aeb8eb7..551a46d
--- a/dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/NacosDubboServiceConsumerBootstrap.java
+++ b/dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/NacosDubboServiceConsumerBootstrap.java
@@@ -36,8 -36,7 +36,8 @@@ public class NacosDubboServiceConsumerB
          new DubboBootstrap()
                  .application(applicationConfig)
                  // Zookeeper
-                 .registry("nacos", builder -> builder.address("nacos://127.0.0.1:8848?registry.type=service&subscribed.services=dubbo-nacos-provider-demo"))
- //                .metadataReport(new MetadataReportConfig("nacos://127.0.0.1:8848"))
++//                .registry("nacos", builder -> builder.address("nacos://127.0.0.1:8848?registry.type=service&subscribed.services=dubbo-nacos-provider-demo"))
+                 .registry("nacos", builder -> builder.address("nacos://127.0.0.1:8848?registry-type=service&subscribed-services=dubbo-nacos-provider-demo"))
                  .metadataReport(new MetadataReportConfig("nacos://127.0.0.1:8848"))
                  // Nacos
  //                .registry("consul", builder -> builder.address("consul://127.0.0.1:8500?registry.type=service&subscribed.services=dubbo-provider-demo").group("namespace1"))
diff --cc dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/proxy/RemoteMetadataServiceProxy.java
index 3f1745d,3f1745d..3b0cd2e
--- 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
@@@ -25,12 -25,12 +25,12 @@@ public class RemoteMetadataServiceProx
      protected final Logger logger = LoggerFactory.getLogger(getClass());
  
      private String serviceName;
--    // FIXME this is provider revison. it also need consumer revison.
      private String revision;
  
  
      public RemoteMetadataServiceProxy(ServiceInstance serviceInstance) {
          this.serviceName = serviceInstance.getServiceName();
++        // this is ServiceInstance of registry(Provider)
          this.revision = serviceInstance.getMetadata()
                  .getOrDefault(ServiceInstanceMetadataUtils.EXPORTED_SERVICES_REVISION_PROPERTY_NAME, "");
      }
@@@ -40,7 -40,7 +40,6 @@@
          return serviceName;
      }
  
--    // TODO, protocol should be used
      @Override
      public SortedSet<String> getExportedURLs(String serviceInterface, String group, String version, String protocol) {
          return toSortedStrings(getMetadataReport().getExportedURLs(
@@@ -60,8 -60,8 +59,18 @@@
      @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));
++        String serviceInterface = services[0];
++        // if version or group is not exist
++        String version = null;
++        if (services.length > 1) {
++            version = services[1];
++        }
++        String group = null;
++        if (services.length > 2) {
++            group = services[2];
++        }
++        return getMetadataReport().getServiceDefinition(new MetadataIdentifier(serviceInterface,
++                version, group, PROVIDER_SIDE, serviceName));
      }
  
      MetadataReport getMetadataReport() {


[dubbo] 01/08: nacos

Posted by vi...@apache.org.
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 7725906c779ecf226f9917681e3f64d0c474be1f
Author: cvictory <sh...@gmail.com>
AuthorDate: Fri Aug 23 11:12:58 2019 +0800

    nacos
---
 dubbo-bootstrap/pom.xml                                            | 7 +++++++
 .../apache/dubbo/bootstrap/NacosDubboServiceConsumerBootstrap.java | 1 +
 2 files changed, 8 insertions(+)

diff --git a/dubbo-bootstrap/pom.xml b/dubbo-bootstrap/pom.xml
index 9818a3a..18ec6fa 100644
--- a/dubbo-bootstrap/pom.xml
+++ b/dubbo-bootstrap/pom.xml
@@ -81,6 +81,13 @@
 
         <dependency>
             <groupId>org.apache.dubbo</groupId>
+            <artifactId>dubbo-metadata-report-redis</artifactId>
+            <version>${project.parent.version}</version>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.dubbo</groupId>
             <artifactId>dubbo-configcenter-zookeeper</artifactId>
             <version>${project.parent.version}</version>
             <scope>test</scope>
diff --git a/dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/NacosDubboServiceConsumerBootstrap.java b/dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/NacosDubboServiceConsumerBootstrap.java
index 1bddcd3..69f430c 100644
--- a/dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/NacosDubboServiceConsumerBootstrap.java
+++ b/dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/NacosDubboServiceConsumerBootstrap.java
@@ -37,6 +37,7 @@ public class NacosDubboServiceConsumerBootstrap {
                 .application(applicationConfig)
                 // Zookeeper
                 .registry("nacos", builder -> builder.address("nacos://127.0.0.1:8848?registry.type=service&subscribed.services=dubbo-nacos-provider-demo"))
+//                .metadataReport(new MetadataReportConfig("nacos://127.0.0.1:8848"))
                 .metadataReport(new MetadataReportConfig("nacos://127.0.0.1:8848"))
                 // Nacos
 //                .registry("consul", builder -> builder.address("consul://127.0.0.1:8500?registry.type=service&subscribed.services=dubbo-provider-demo").group("namespace1"))


[dubbo] 07/08: unit test

Posted by vi...@apache.org.
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 ef4415e82545254de1da7e8d4840531cf5abf622
Author: cvictory <sh...@gmail.com>
AuthorDate: Thu Aug 29 16:46:00 2019 +0800

    unit test
---
 .../store/InMemoryWritableMetadataService.java     |  52 +++++-
 .../store/RemoteWritableMetadataService.java       |  30 ++--
 .../RemoteWritableMetadataServiceDelegate.java     |  14 +-
 .../store/InMemoryWritableMetadataServiceTest.java |  79 +++++++++
 .../store/RemoteWritableMeatadataServiceTest.java  |  88 ++++++++--
 .../RemoteWritableMetadataServiceDelegateTest.java | 183 +++++++++++++++++++++
 .../metadata/test/JTestMetadataReport4Test.java    |  13 +-
 7 files changed, 415 insertions(+), 44 deletions(-)

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 7c34e67..749f234 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,6 +17,8 @@
 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;
@@ -25,11 +27,14 @@ import org.apache.dubbo.metadata.definition.model.ServiceDefinition;
 
 import com.google.gson.Gson;
 
+import java.util.Collection;
 import java.util.Comparator;
 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;
 
@@ -46,19 +51,42 @@ import static org.apache.dubbo.common.utils.CollectionUtils.isEmpty;
  *
  * @see MetadataService
  * @see WritableMetadataService
- * @since 2.7.4
+ * @since 2.7.5
  */
-public class InMemoryWritableMetadataService extends BaseWritableMetadataService implements WritableMetadataService {
-
+public class InMemoryWritableMetadataService implements WritableMetadataService {
 
+    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}
+     */
+    ConcurrentNavigableMap<String, SortedSet<URL>> subscribedServiceURLs = new ConcurrentSkipListMap<>();
+
+    ConcurrentNavigableMap<String, String> serviceDefinitions = new ConcurrentSkipListMap<>();
+
     @Override
     public SortedSet<String> getSubscribedURLs() {
-        return super.getSubscribedURLs();
+        return getAllUnmodifiableServiceURLs(subscribedServiceURLs);
+    }
+
+    SortedSet<String> getAllUnmodifiableServiceURLs(Map<String, SortedSet<URL>> serviceURLs) {
+        return MetadataService.toSortedStrings(serviceURLs.values().stream().flatMap(Collection::stream));
     }
 
     @Override
@@ -129,8 +157,14 @@ public class InMemoryWritableMetadataService extends BaseWritableMetadataService
 
     boolean removeURL(Map<String, SortedSet<URL>> serviceURLs, URL url) {
         return executeMutually(() -> {
-            SortedSet<URL> urls = serviceURLs.getOrDefault(url.getServiceKey(), emptySortedSet());
-            return urls.remove(url);
+            String key = url.getServiceKey();
+            SortedSet<URL> urls = serviceURLs.getOrDefault(key, emptySortedSet());
+            boolean r = urls.remove(url);
+            // if it is empty
+            if (urls.isEmpty()) {
+                serviceURLs.remove(key);
+            }
+            return r;
         });
     }
 
@@ -155,8 +189,8 @@ public class InMemoryWritableMetadataService extends BaseWritableMetadataService
         return success;
     }
 
-    private static SortedSet<String> getServiceURLs(Map<String, SortedSet<URL>> exportedServiceURLs, String serviceKey,
-                                                    String protocol) {
+    private SortedSet<String> getServiceURLs(Map<String, SortedSet<URL>> exportedServiceURLs, String serviceKey,
+                                             String protocol) {
 
         SortedSet<URL> serviceURLs = exportedServiceURLs.get(serviceKey);
 
@@ -167,7 +201,7 @@ public class InMemoryWritableMetadataService extends BaseWritableMetadataService
         return MetadataService.toSortedStrings(serviceURLs.stream().filter(url -> isAcceptableProtocol(protocol, url)));
     }
 
-    private static boolean isAcceptableProtocol(String protocol, URL url) {
+    private boolean isAcceptableProtocol(String protocol, URL url) {
         return protocol == null
                 || protocol.equals(url.getParameter(PROTOCOL_KEY))
                 || protocol.equals(url.getProtocol());
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 90181ee..22c028d 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
@@ -19,6 +19,7 @@ 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.CollectionUtils;
 import org.apache.dubbo.common.utils.StringUtils;
 import org.apache.dubbo.metadata.WritableMetadataService;
 import org.apache.dubbo.metadata.definition.ServiceDefinitionBuilder;
@@ -54,13 +55,15 @@ import static org.apache.dubbo.common.constants.CommonConstants.VERSION_KEY;
  *
  * @since 2.7.5
  */
-public class RemoteWritableMetadataService extends BaseWritableMetadataService implements WritableMetadataService {
+public class RemoteWritableMetadataService implements WritableMetadataService {
 
     protected final Logger logger = LoggerFactory.getLogger(getClass());
     private volatile String exportedRevision;
     private volatile String subscribedRevision;
+    private InMemoryWritableMetadataService writableMetadataService;
 
-    public RemoteWritableMetadataService() {
+    public RemoteWritableMetadataService(InMemoryWritableMetadataService writableMetadataService) {
+        this.writableMetadataService = writableMetadataService;
     }
 
     public MetadataReport getMetadataReport() {
@@ -93,13 +96,15 @@ public class RemoteWritableMetadataService extends BaseWritableMetadataService i
     public void publishProvider(URL providerUrl) throws RpcException {
         //first add into the list
         // remove the individul param
-        providerUrl = providerUrl.removeParameters(PID_KEY, TIMESTAMP_KEY, Constants.BIND_IP_KEY, Constants.BIND_PORT_KEY, TIMESTAMP_KEY);
+        providerUrl = providerUrl.removeParameters(PID_KEY, TIMESTAMP_KEY, Constants.BIND_IP_KEY,
+                Constants.BIND_PORT_KEY, TIMESTAMP_KEY);
 
         try {
             String interfaceName = providerUrl.getParameter(INTERFACE_KEY);
             if (StringUtils.isNotEmpty(interfaceName)) {
                 Class interfaceClass = Class.forName(interfaceName);
-                FullServiceDefinition fullServiceDefinition = ServiceDefinitionBuilder.buildFullDefinition(interfaceClass, providerUrl.getParameters());
+                FullServiceDefinition fullServiceDefinition = ServiceDefinitionBuilder.buildFullDefinition(interfaceClass,
+                        providerUrl.getParameters());
                 getMetadataReport().storeProviderMetadata(new MetadataIdentifier(providerUrl.getServiceInterface(),
                         providerUrl.getParameter(VERSION_KEY), providerUrl.getParameter(GROUP_KEY),
                         PROVIDER_SIDE, providerUrl.getParameter(APPLICATION_KEY)), fullServiceDefinition);
@@ -114,7 +119,8 @@ public class RemoteWritableMetadataService extends BaseWritableMetadataService i
 
     @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);
+        consumerURL = consumerURL.removeParameters(PID_KEY, TIMESTAMP_KEY, Constants.BIND_IP_KEY,
+                Constants.BIND_PORT_KEY, TIMESTAMP_KEY);
         getMetadataReport().storeConsumerMetadata(new MetadataIdentifier(consumerURL.getServiceInterface(),
                 consumerURL.getParameter(VERSION_KEY), consumerURL.getParameter(GROUP_KEY), CONSUMER_SIDE,
                 consumerURL.getParameter(APPLICATION_KEY)), consumerURL.getParameters());
@@ -153,12 +159,14 @@ public class RemoteWritableMetadataService extends BaseWritableMetadataService i
                 result = false;
             }
         }
-        if (!StringUtils.isEmpty(subscribedRevision) && !subscribedRevision.equals(this.subscribedRevision)) {
+        if (!StringUtils.isEmpty(subscribedRevision) && !subscribedRevision.equals(this.subscribedRevision)
+                && CollectionUtils.isNotEmpty(writableMetadataService.getSubscribedURLs())) {
             this.subscribedRevision = subscribedRevision;
             SubscriberMetadataIdentifier metadataIdentifier = new SubscriberMetadataIdentifier();
             metadataIdentifier.setApplication(serviceName());
             metadataIdentifier.setRevision(subscribedRevision);
-            boolean executeResult = throwableAction(getMetadataReport()::saveSubscribedData, metadataIdentifier, super.getSubscribedURLs());
+            boolean executeResult = throwableAction(getMetadataReport()::saveSubscribedData, metadataIdentifier,
+                    writableMetadataService.getSubscribedURLs());
             if (!executeResult) {
                 result = false;
             }
@@ -168,7 +176,7 @@ public class RemoteWritableMetadataService extends BaseWritableMetadataService i
 
     private boolean saveServiceMetadata() {
         boolean result = true;
-        for (SortedSet<URL> urls : exportedServiceURLs.values()) {
+        for (SortedSet<URL> urls : writableMetadataService.exportedServiceURLs.values()) {
             Iterator<URL> iterator = urls.iterator();
             while (iterator.hasNext()) {
                 URL url = iterator.next();
@@ -200,7 +208,8 @@ public class RemoteWritableMetadataService extends BaseWritableMetadataService i
         return null;
     }
 
-    boolean throwableAction(BiConsumer<ServiceMetadataIdentifier, URL> consumer, ServiceMetadataIdentifier metadataIdentifier, URL url) {
+    boolean throwableAction(BiConsumer<ServiceMetadataIdentifier, URL> consumer,
+                            ServiceMetadataIdentifier metadataIdentifier, URL url) {
         try {
             consumer.accept(metadataIdentifier, url);
         } catch (Exception e) {
@@ -210,7 +219,8 @@ public class RemoteWritableMetadataService extends BaseWritableMetadataService i
         return true;
     }
 
-    boolean throwableAction(BiConsumer<SubscriberMetadataIdentifier, Set<String>> consumer, SubscriberMetadataIdentifier metadataIdentifier, Set<String> urls) {
+    boolean throwableAction(BiConsumer<SubscriberMetadataIdentifier, Set<String>> consumer,
+                            SubscriberMetadataIdentifier metadataIdentifier, Set<String> urls) {
         try {
             consumer.accept(metadataIdentifier, urls);
         } catch (Exception e) {
diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/store/RemoteWritableMetadataServiceDelegate.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/store/RemoteWritableMetadataServiceDelegate.java
index f46bf21..eed9e43 100644
--- a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/store/RemoteWritableMetadataServiceDelegate.java
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/store/RemoteWritableMetadataServiceDelegate.java
@@ -1,6 +1,7 @@
 package org.apache.dubbo.metadata.store;
 
 import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.config.InmemoryConfiguration;
 import org.apache.dubbo.metadata.WritableMetadataService;
 
 import java.util.SortedSet;
@@ -12,12 +13,12 @@ import java.util.function.BiFunction;
  * @since 2.7.5
  */
 public class RemoteWritableMetadataServiceDelegate implements WritableMetadataService {
-    private WritableMetadataService defaultWritableMetadataService;
-    private RemoteWritableMetadataService remoteWritableMetadataService;
+    InMemoryWritableMetadataService defaultWritableMetadataService;
+    RemoteWritableMetadataService remoteWritableMetadataService;
 
     public RemoteWritableMetadataServiceDelegate() {
-        defaultWritableMetadataService = WritableMetadataService.getDefaultExtension();
-        remoteWritableMetadataService = new RemoteWritableMetadataService();
+        defaultWritableMetadataService = (InMemoryWritableMetadataService) WritableMetadataService.getExtension("local");
+        remoteWritableMetadataService = new RemoteWritableMetadataService(defaultWritableMetadataService);
     }
 
     private WritableMetadataService getDefaultWritableMetadataService() {
@@ -79,9 +80,6 @@ public class RemoteWritableMetadataServiceDelegate implements WritableMetadataSe
     }
 
     private boolean doFunction(BiFunction<WritableMetadataService, URL, Boolean> func, URL url) {
-        boolean result = true;
-        result &= func.apply(defaultWritableMetadataService, url);
-        result &= func.apply(remoteWritableMetadataService, url);
-        return result;
+        return func.apply(defaultWritableMetadataService, url) && func.apply(remoteWritableMetadataService, url);
     }
 }
diff --git a/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/store/InMemoryWritableMetadataServiceTest.java b/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/store/InMemoryWritableMetadataServiceTest.java
new file mode 100644
index 0000000..c032843
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/store/InMemoryWritableMetadataServiceTest.java
@@ -0,0 +1,79 @@
+package org.apache.dubbo.metadata.store;
+
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.utils.NetUtils;
+import org.apache.dubbo.metadata.report.MetadataReportInstance;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+/**
+ * 2019-08-29
+ */
+public class InMemoryWritableMetadataServiceTest {
+
+    String interfaceName = "org.apache.dubbo.metadata.store.InterfaceNameTestService2", version = "0.9.9", group = null;
+    URL url = URL.valueOf("dubbo://" + NetUtils.getLocalAddress().getHostName() + ":4444/?interface=" + interfaceName + "&version="
+            + version + "&application=vicpubprovder&side=provider");
+
+    @BeforeEach
+    public void before() {
+    }
+
+    @Test
+    public void testPublishServiceDefinition() {
+        InMemoryWritableMetadataService inMemoryWritableMetadataService = new InMemoryWritableMetadataService();
+        inMemoryWritableMetadataService.publishServiceDefinition(url);
+
+        String v = inMemoryWritableMetadataService.getServiceDefinition(interfaceName, version, group);
+        Assertions.assertNotNull(v);
+    }
+
+    @Test
+    public void testExportURL() {
+        InMemoryWritableMetadataService inMemoryWritableMetadataService = new InMemoryWritableMetadataService();
+        URL url = URL.valueOf("dubbo://" + NetUtils.getLocalAddress().getHostName() + ":4444/org.apache.dubbo.Test567Service?version=1.0.44&application=vicpubprovder&side=provider");
+        inMemoryWritableMetadataService.exportURL(url);
+
+        Assertions.assertTrue(inMemoryWritableMetadataService.exportedServiceURLs.size() == 1);
+        Assertions.assertEquals(inMemoryWritableMetadataService.exportedServiceURLs.get(url.getServiceKey()).first(), url);
+    }
+
+    @Test
+    public void testSubscribeURL() {
+        InMemoryWritableMetadataService inMemoryWritableMetadataService = new InMemoryWritableMetadataService();
+        URL url = URL.valueOf("subscriber://" + NetUtils.getLocalAddress().getHostName() + ":4444/org.apache.dubbo.Test678Service?version=1.0.44&application=vicpubprovder&side=provider");
+        inMemoryWritableMetadataService.subscribeURL(url);
+
+        Assertions.assertTrue(inMemoryWritableMetadataService.subscribedServiceURLs.size() == 1);
+        Assertions.assertEquals(inMemoryWritableMetadataService.subscribedServiceURLs.get(url.getServiceKey()).first(), url);
+    }
+
+    @Test
+    public void testUnExportURL() {
+        InMemoryWritableMetadataService inMemoryWritableMetadataService = new InMemoryWritableMetadataService();
+        URL url = URL.valueOf("dubbo://" + NetUtils.getLocalAddress().getHostName() + ":4444/org.apache.dubbo.Test567Service?version=1.0.44&application=vicpubprovder&side=provider");
+        inMemoryWritableMetadataService.exportURL(url);
+
+        Assertions.assertTrue(inMemoryWritableMetadataService.exportedServiceURLs.size() == 1);
+        Assertions.assertEquals(inMemoryWritableMetadataService.exportedServiceURLs.get(url.getServiceKey()).first(), url);
+
+        inMemoryWritableMetadataService.unexportURL(url);
+        Assertions.assertTrue(inMemoryWritableMetadataService.exportedServiceURLs.size() == 0);
+    }
+
+    @Test
+    public void testUnSubscribeURL() {
+        InMemoryWritableMetadataService inMemoryWritableMetadataService = new InMemoryWritableMetadataService();
+        URL url = URL.valueOf("subscriber://" + NetUtils.getLocalAddress().getHostName() + ":4444/org.apache.dubbo.Test678Service?version=1.0.44&application=vicpubprovder&side=provider");
+        inMemoryWritableMetadataService.subscribeURL(url);
+
+        Assertions.assertTrue(inMemoryWritableMetadataService.subscribedServiceURLs.size() == 1);
+        Assertions.assertEquals(inMemoryWritableMetadataService.subscribedServiceURLs.get(url.getServiceKey()).first(), url);
+
+        inMemoryWritableMetadataService.unsubscribeURL(url);
+        Assertions.assertTrue(inMemoryWritableMetadataService.subscribedServiceURLs.size() == 0);
+    }
+
+}
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 fe2b4f6..beeb1bd 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
@@ -21,7 +21,11 @@ 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.report.identifier.KeyTypeEnum;
+import org.apache.dubbo.metadata.report.identifier.ServiceMetadataIdentifier;
+import org.apache.dubbo.metadata.report.identifier.SubscriberMetadataIdentifier;
 import org.apache.dubbo.metadata.test.JTestMetadataReport4Test;
+import org.apache.dubbo.rpc.model.ApplicationModel;
 
 import com.google.gson.Gson;
 import org.junit.jupiter.api.Assertions;
@@ -38,24 +42,17 @@ import static org.apache.dubbo.common.constants.CommonConstants.METADATA_REMOTE;
 public class RemoteWritableMeatadataServiceTest {
     URL url = URL.valueOf("JTest://" + NetUtils.getLocalAddress().getHostName() + ":4444/org.apache.dubbo.TestService?version=1.0.0&application=vic");
     RemoteWritableMetadataService metadataReportService1;
+    InMemoryWritableMetadataService inMemoryWritableMetadataService;
 
     @BeforeEach
     public void before() {
-        metadataReportService1 = (RemoteWritableMetadataService) WritableMetadataService.getExtension(METADATA_REMOTE);
+        inMemoryWritableMetadataService = new InMemoryWritableMetadataService();
+        metadataReportService1 = new RemoteWritableMetadataService(inMemoryWritableMetadataService);
         MetadataReportInstance.init(url);
     }
 
     @Test
-    public void testInstance() {
-
-        RemoteWritableMetadataService metadataReportService2 = (RemoteWritableMetadataService) WritableMetadataService.getExtension(METADATA_REMOTE);
-        Assertions.assertSame(metadataReportService1, metadataReportService2);
-    }
-
-    @Test
     public void testPublishProviderNoInterfaceName() {
-
-
         URL publishUrl = URL.valueOf("dubbo://" + NetUtils.getLocalAddress().getHostName() + ":4444/org.apache.dubbo.TestService?version=1.0.0&application=vicpubprovder&side=provider");
         metadataReportService1.publishProvider(publishUrl);
 
@@ -93,7 +90,7 @@ public class RemoteWritableMeatadataServiceTest {
 
         String value = jTestMetadataReport4Test.store.get(JTestMetadataReport4Test.getProviderKey(publishUrl));
         FullServiceDefinition fullServiceDefinition = toServiceDefinition(value);
-        Map<String,String> map = fullServiceDefinition.getParameters();
+        Map<String, String> map = fullServiceDefinition.getParameters();
         Assertions.assertEquals(map.get("application"), "vicpubp");
         Assertions.assertEquals(map.get("version"), "1.0.3");
         Assertions.assertEquals(map.get("interface"), "org.apache.dubbo.metadata.store.InterfaceNameTestService");
@@ -119,6 +116,75 @@ public class RemoteWritableMeatadataServiceTest {
 
     }
 
+    @Test
+    public void testPublishServiceDefinition() {
+        URL publishUrl = URL.valueOf("dubbo://" + NetUtils.getLocalAddress().getHostName() + ":4444/org.apache.dubbo.TestService?version=1.0.0&application=vicpubprovder&side=provider");
+        metadataReportService1.publishServiceDefinition(publishUrl);
+
+        Assertions.assertTrue(metadataReportService1.getMetadataReport() instanceof JTestMetadataReport4Test);
+
+        JTestMetadataReport4Test jTestMetadataReport4Test = (JTestMetadataReport4Test) metadataReportService1.getMetadataReport();
+        Assertions.assertTrue(!jTestMetadataReport4Test.store.containsKey(JTestMetadataReport4Test.getProviderKey(publishUrl)));
+
+    }
+
+    @Test
+    public void testUnexportURL() {
+
+    }
+
+    @Test
+    public void testRefreshMetadataService() throws InterruptedException {
+        URL publishUrl = URL.valueOf("dubbo://" + NetUtils.getLocalAddress().getHostName() + ":4444/org.apache.dubbo.TestRefreshMetadataService?version=1.0.8&application=vicpubprovder&side=provider");
+        URL publishUrl2 = URL.valueOf("dubbo://" + NetUtils.getLocalAddress().getHostName() + ":4444/org.apache.dubbo.TestRefreshMetadata2Service?version=1.0.5&application=vicpubprovder&side=provider");
+        inMemoryWritableMetadataService.exportURL(publishUrl);
+        inMemoryWritableMetadataService.exportURL(publishUrl2);
+        String exportedRevision = "9999";
+        JTestMetadataReport4Test jTestMetadataReport4Test = (JTestMetadataReport4Test) metadataReportService1.getMetadataReport();
+        int origSize = jTestMetadataReport4Test.store.size();
+        Assertions.assertTrue(metadataReportService1.refreshMetadata(exportedRevision, "1109"));
+        Thread.sleep(200);
+        int size = jTestMetadataReport4Test.store.size();
+        Assertions.assertTrue(size - origSize == 2);
+        Assertions.assertEquals(jTestMetadataReport4Test.store.get(getServiceMetadataIdentifier(publishUrl, exportedRevision).getUniqueKey(KeyTypeEnum.UNIQUE_KEY)), publishUrl.toFullString());
+        Assertions.assertEquals(jTestMetadataReport4Test.store.get(getServiceMetadataIdentifier(publishUrl2, exportedRevision).getUniqueKey(KeyTypeEnum.UNIQUE_KEY)), publishUrl2.toFullString());
+    }
+
+    @Test
+    public void testRefreshMetadataSubscription() throws InterruptedException {
+        URL subscriberUrl1 = URL.valueOf("subscriber://" + NetUtils.getLocalAddress().getHostName() + ":4444/org.apache.dubbo.TestRefreshMetadata00Service?version=1.0.8&application=vicpubprovder&side=provider");
+        URL subscriberUrl2 = URL.valueOf("subscriber://" + NetUtils.getLocalAddress().getHostName() + ":4444/org.apache.dubbo.TestRefreshMetadata09Service?version=1.0.5&application=vicpubprovder&side=provider");
+        inMemoryWritableMetadataService.subscribeURL(subscriberUrl1);
+        inMemoryWritableMetadataService.subscribeURL(subscriberUrl2);
+        String exportedRevision = "9999";
+        String subscriberRevision = "2099";
+        String applicationName = "wriableMetadataService";
+        JTestMetadataReport4Test jTestMetadataReport4Test = (JTestMetadataReport4Test) metadataReportService1.getMetadataReport();
+        int origSize = jTestMetadataReport4Test.store.size();
+        ApplicationModel.setApplication(applicationName);
+        Assertions.assertTrue(metadataReportService1.refreshMetadata(exportedRevision, subscriberRevision));
+        Thread.sleep(200);
+        int size = jTestMetadataReport4Test.store.size();
+        Assertions.assertTrue(size - origSize == 1);
+        String r = jTestMetadataReport4Test.store.get(getSubscriberMetadataIdentifier(
+                subscriberRevision).getUniqueKey(KeyTypeEnum.UNIQUE_KEY));
+        Assertions.assertNotNull(r);
+    }
+
+    private ServiceMetadataIdentifier getServiceMetadataIdentifier(URL publishUrl, String exportedRevision) {
+        ServiceMetadataIdentifier serviceMetadataIdentifier = new ServiceMetadataIdentifier(publishUrl);
+        serviceMetadataIdentifier.setRevision(exportedRevision);
+        serviceMetadataIdentifier.setProtocol(publishUrl.getProtocol());
+        return serviceMetadataIdentifier;
+    }
+
+    private SubscriberMetadataIdentifier getSubscriberMetadataIdentifier(String subscriberRevision) {
+        SubscriberMetadataIdentifier subscriberMetadataIdentifier = new SubscriberMetadataIdentifier();
+        subscriberMetadataIdentifier.setRevision(subscriberRevision);
+        subscriberMetadataIdentifier.setApplication(ApplicationModel.getApplication());
+        return subscriberMetadataIdentifier;
+    }
+
     private FullServiceDefinition toServiceDefinition(String urlQuery) {
         Gson gson = new Gson();
         return gson.fromJson(urlQuery, FullServiceDefinition.class);
diff --git a/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/store/RemoteWritableMetadataServiceDelegateTest.java b/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/store/RemoteWritableMetadataServiceDelegateTest.java
new file mode 100644
index 0000000..10b3eec
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/store/RemoteWritableMetadataServiceDelegateTest.java
@@ -0,0 +1,183 @@
+package org.apache.dubbo.metadata.store;
+
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.utils.NetUtils;
+import org.apache.dubbo.metadata.WritableMetadataService;
+import org.apache.dubbo.metadata.report.MetadataReportInstance;
+import org.apache.dubbo.metadata.report.identifier.KeyTypeEnum;
+import org.apache.dubbo.metadata.report.identifier.ServiceMetadataIdentifier;
+import org.apache.dubbo.metadata.report.identifier.SubscriberMetadataIdentifier;
+import org.apache.dubbo.metadata.test.JTestMetadataReport4Test;
+import org.apache.dubbo.rpc.model.ApplicationModel;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import java.util.SortedSet;
+
+import static org.apache.dubbo.common.constants.CommonConstants.METADATA_REMOTE;
+
+/**
+ * 2019-08-27
+ */
+public class RemoteWritableMetadataServiceDelegateTest {
+    static URL metadataURL = URL.valueOf("JTest://" + NetUtils.getLocalAddress().getHostName() + ":4444/org.apache.dubbo.Tes33tService?version=1.0.0&application=vic");
+
+    RemoteWritableMetadataServiceDelegate metadataReportService;
+
+    String interfaceName = "org.apache.dubbo.metadata.store.InterfaceNameTestService80", version = "0.6.9", group = null;
+    URL url = URL.valueOf("dubbo://" + NetUtils.getLocalAddress().getHostName() + ":4444/?interface=" + interfaceName + "&version="
+            + version + "&application=vicpubprovder&side=provider");
+
+    @BeforeAll
+    public static void beforeAll() {
+        MetadataReportInstance.init(metadataURL);
+    }
+
+    @BeforeEach
+    public void before() {
+        metadataReportService = new RemoteWritableMetadataServiceDelegate();
+    }
+
+
+    @Test
+    public void testInstance() {
+        WritableMetadataService metadataReportService1 = WritableMetadataService.getExtension(METADATA_REMOTE);
+        WritableMetadataService metadataReportService2 = WritableMetadataService.getExtension(METADATA_REMOTE);
+        Assertions.assertSame(metadataReportService1, metadataReportService2);
+        Assertions.assertTrue(metadataReportService1 instanceof RemoteWritableMetadataServiceDelegate);
+    }
+
+    @Test
+    public void testPublishServiceDefinition() throws InterruptedException {
+        String interfaceName = "org.apache.dubbo.metadata.store.InterfaceNameTestService2", version = "0.9.9", group = null;
+        URL tmpUrl = URL.valueOf("dubbo://" + NetUtils.getLocalAddress().getHostName() + ":4444/?interface=" + interfaceName + "&version="
+                + version + "&application=vicpubprovder&side=provider");
+        metadataReportService.publishServiceDefinition(tmpUrl);
+        Thread.sleep(150);
+        String v = metadataReportService.getServiceDefinition(interfaceName, version, group);
+        Assertions.assertNotNull(v);
+    }
+
+    @Test
+    public void testExportURL() throws InterruptedException {
+        URL url = URL.valueOf("dubbo://" + NetUtils.getLocalAddress().getHostName() + ":4444/org.apache.dubbo.Test567Service?version=1.0.44&application=vicpubprovder&side=provider");
+        metadataReportService.exportURL(url);
+        Thread.sleep(100);
+        Assertions.assertTrue(getInMemoryWriableMetadataService().exportedServiceURLs.size() == 1);
+        Assertions.assertEquals(getInMemoryWriableMetadataService().exportedServiceURLs.get(url.getServiceKey()).first(), url);
+    }
+
+    @Test
+    public void testSubscribeURL() throws InterruptedException {
+        URL url = URL.valueOf("subscriber://" + NetUtils.getLocalAddress().getHostName() + ":4444/org.apache.dubbo.Test0678Service?version=1.3.144&application=vicpubprovder&side=provider");
+        int origSize = getInMemoryWriableMetadataService().subscribedServiceURLs.size();
+        metadataReportService.subscribeURL(url);
+        Thread.sleep(100);
+        int size = getInMemoryWriableMetadataService().subscribedServiceURLs.size();
+        Assertions.assertTrue(size - origSize == 1);
+        Assertions.assertEquals(getInMemoryWriableMetadataService().subscribedServiceURLs.get(url.getServiceKey()).first(), url);
+    }
+
+    @Test
+    public void testUnExportURL() throws InterruptedException {
+        URL url = URL.valueOf("dubbo://" + NetUtils.getLocalAddress().getHostName() + ":4444/org.apache.dubbo.Test0567Service?version=1.2.44&application=vicpubprovder&side=provider");
+        int origSize = getInMemoryWriableMetadataService().exportedServiceURLs.size();
+        metadataReportService.exportURL(url);
+        Thread.sleep(100);
+        int size = getInMemoryWriableMetadataService().exportedServiceURLs.size();
+        Assertions.assertTrue(size - origSize == 1);
+        Assertions.assertEquals(getInMemoryWriableMetadataService().exportedServiceURLs.get(url.getServiceKey()).first(), url);
+
+        metadataReportService.unexportURL(url);
+        int unexportSize = getInMemoryWriableMetadataService().exportedServiceURLs.size();
+        Assertions.assertTrue(size - unexportSize == 1);
+    }
+
+    @Test
+    public void testUnSubscribeURL() throws InterruptedException {
+        URL url = URL.valueOf("subscriber://" + NetUtils.getLocalAddress().getHostName() + ":4444/org.apache.dubbo.Test0678Service?version=1.5.477&application=vicpubprovder&side=provider");
+        int origSize = getInMemoryWriableMetadataService().subscribedServiceURLs.size();
+        metadataReportService.subscribeURL(url);
+        Thread.sleep(100);
+        int size = getInMemoryWriableMetadataService().subscribedServiceURLs.size();
+        Assertions.assertTrue(size - origSize == 1);
+        Assertions.assertEquals(getInMemoryWriableMetadataService().subscribedServiceURLs.get(url.getServiceKey()).first(), url);
+
+        metadataReportService.unsubscribeURL(url);
+        Thread.sleep(100);
+        Assertions.assertTrue(getInMemoryWriableMetadataService().subscribedServiceURLs.size() == 0);
+    }
+
+    @Test
+    public void testRefreshMetadataService() throws InterruptedException {
+        URL publishUrl = URL.valueOf("dubbo://" + NetUtils.getLocalAddress().getHostName() + ":4444/org.apache.dubbo.TestRefreshMetadataService?version=1.6.8&application=vicpubprovder&side=provider");
+        URL publishUrl2 = URL.valueOf("dubbo://" + NetUtils.getLocalAddress().getHostName() + ":4444/org.apache.dubbo.TestRefreshMetadata2Service?version=1.6.5&application=vicpubprovder&side=provider");
+        metadataReportService.exportURL(publishUrl);
+        metadataReportService.exportURL(publishUrl2);
+        String exportedRevision = "9999";
+        JTestMetadataReport4Test jTestMetadataReport4Test = (JTestMetadataReport4Test) MetadataReportInstance.getMetadataReport(true);
+        int origSize = jTestMetadataReport4Test.store.size();
+        int num = countNum();
+        Assertions.assertTrue(metadataReportService.refreshMetadata(exportedRevision, "1109"));
+        Thread.sleep(200);
+        int size = jTestMetadataReport4Test.store.size();
+        Assertions.assertTrue(size - origSize == num);
+        Assertions.assertEquals(jTestMetadataReport4Test.store.get(getServiceMetadataIdentifier(publishUrl, exportedRevision).getUniqueKey(KeyTypeEnum.UNIQUE_KEY)), publishUrl.toFullString());
+        Assertions.assertEquals(jTestMetadataReport4Test.store.get(getServiceMetadataIdentifier(publishUrl2, exportedRevision).getUniqueKey(KeyTypeEnum.UNIQUE_KEY)), publishUrl2.toFullString());
+    }
+
+
+    @Test
+    public void testRefreshMetadataSubscription() throws InterruptedException {
+        URL subscriberUrl1 = URL.valueOf("subscriber://" + NetUtils.getLocalAddress().getHostName() + ":4444/org.apache.dubbo.TestRefreshMetadata00Service?version=2.0.8&application=vicpubprovder&side=provider");
+        URL subscriberUrl2 = URL.valueOf("subscriber://" + NetUtils.getLocalAddress().getHostName() + ":4444/org.apache.dubbo.TestRefreshMetadata09Service?version=2.0.5&application=vicpubprovder&side=provider");
+        metadataReportService.subscribeURL(subscriberUrl1);
+        metadataReportService.subscribeURL(subscriberUrl2);
+        String exportedRevision = "9999";
+        String subscriberRevision = "2099";
+        String applicationName = "wriableMetadataService";
+        JTestMetadataReport4Test jTestMetadataReport4Test = (JTestMetadataReport4Test) MetadataReportInstance.getMetadataReport(true);
+        int origSize = jTestMetadataReport4Test.store.size();
+        ApplicationModel.setApplication(applicationName);
+        Assertions.assertTrue(metadataReportService.refreshMetadata(exportedRevision, subscriberRevision));
+        Thread.sleep(200);
+        int size = jTestMetadataReport4Test.store.size();
+        Assertions.assertTrue(size - origSize == 1);
+        String r = jTestMetadataReport4Test.store.get(getSubscriberMetadataIdentifier(
+                subscriberRevision).getUniqueKey(KeyTypeEnum.UNIQUE_KEY));
+        Assertions.assertNotNull(r);
+    }
+
+
+    private ServiceMetadataIdentifier getServiceMetadataIdentifier(URL publishUrl, String exportedRevision) {
+        ServiceMetadataIdentifier serviceMetadataIdentifier = new ServiceMetadataIdentifier(publishUrl);
+        serviceMetadataIdentifier.setRevision(exportedRevision);
+        serviceMetadataIdentifier.setProtocol(publishUrl.getProtocol());
+        return serviceMetadataIdentifier;
+    }
+
+    private SubscriberMetadataIdentifier getSubscriberMetadataIdentifier(String subscriberRevision) {
+        SubscriberMetadataIdentifier subscriberMetadataIdentifier = new SubscriberMetadataIdentifier();
+        subscriberMetadataIdentifier.setRevision(subscriberRevision);
+        subscriberMetadataIdentifier.setApplication(ApplicationModel.getApplication());
+        return subscriberMetadataIdentifier;
+    }
+
+    private InMemoryWritableMetadataService getInMemoryWriableMetadataService() {
+        return (InMemoryWritableMetadataService) metadataReportService.defaultWritableMetadataService;
+    }
+
+    private int countNum() {
+        int num = 0;
+        for (SortedSet<URL> tmp : getInMemoryWriableMetadataService().exportedServiceURLs.values()) {
+            num += tmp.size();
+        }
+        if (!getInMemoryWriableMetadataService().subscribedServiceURLs.values().isEmpty()) {
+            num++;
+        }
+        return num;
+    }
+}
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 dc1571f..34ebce3 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
@@ -25,6 +25,7 @@ import org.apache.dubbo.metadata.report.identifier.ServiceMetadataIdentifier;
 import org.apache.dubbo.metadata.report.identifier.SubscriberMetadataIdentifier;
 import org.apache.dubbo.metadata.report.support.AbstractMetadataReport;
 
+import java.util.Arrays;
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
@@ -43,7 +44,7 @@ public class JTestMetadataReport4Test extends AbstractMetadataReport {
         super(url);
     }
 
-    public Map<String, String> store = new ConcurrentHashMap<>();
+    public volatile Map<String, String> store = new ConcurrentHashMap<>();
 
 
     private static String getProtocol(URL url) {
@@ -64,22 +65,22 @@ public class JTestMetadataReport4Test extends AbstractMetadataReport {
 
     @Override
     protected void doSaveMetadata(ServiceMetadataIdentifier metadataIdentifier, URL url) {
-        throw new UnsupportedOperationException("This extension does not support working as a remote metadata center.");
+        store.put(metadataIdentifier.getUniqueKey(KeyTypeEnum.UNIQUE_KEY), url.toFullString());
     }
 
     @Override
     protected void doRemoveMetadata(ServiceMetadataIdentifier metadataIdentifier) {
-        throw new UnsupportedOperationException("This extension does not support working as a remote metadata center.");
+        store.remove(metadataIdentifier.getUniqueKey(KeyTypeEnum.UNIQUE_KEY));
     }
 
     @Override
     protected List<String> doGetExportedURLs(ServiceMetadataIdentifier metadataIdentifier) {
-        throw new UnsupportedOperationException("This extension does not support working as a remote metadata center.");
+        return Arrays.asList(store.getOrDefault(metadataIdentifier.getUniqueKey(KeyTypeEnum.UNIQUE_KEY), ""));
     }
 
     @Override
     protected void doSaveSubscriberData(SubscriberMetadataIdentifier subscriberMetadataIdentifier, String urls) {
-
+        store.put(subscriberMetadataIdentifier.getUniqueKey(KeyTypeEnum.UNIQUE_KEY), urls);
     }
 
     @Override
@@ -97,6 +98,6 @@ public class JTestMetadataReport4Test extends AbstractMetadataReport {
 
     @Override
     public String getServiceDefinition(MetadataIdentifier consumerMetadataIdentifier) {
-        return null;
+        return store.get(consumerMetadataIdentifier.getUniqueKey(KeyTypeEnum.UNIQUE_KEY));
     }
 }