You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@dubbo.apache.org by li...@apache.org on 2020/08/07 06:45:39 UTC

[dubbo] branch 3.0-to-master updated: add sofa service discovery registry (#6564)

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

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


The following commit(s) were added to refs/heads/3.0-to-master by this push:
     new d3155fd  add sofa service discovery registry (#6564)
d3155fd is described below

commit d3155fdceb27e6b1aa2fbba6342c2ebeed733940
Author: 斩秋 <qu...@users.noreply.github.com>
AuthorDate: Fri Aug 7 14:45:24 2020 +0800

    add sofa service discovery registry (#6564)
---
 .../dubbo-demo-service-consumer/pom.xml            |   4 +
 ...ionZKConsumer.java => ApplicationConsumer.java} |   3 +-
 .../spring/dubbo-consumer-sofaregistry.xml}        |  80 ++++---
 .../dubbo-demo-service-provider/pom.xml            |   4 +
 ...ionZKProvider.java => ApplicationProvider.java} |   3 +-
 .../provider/ServiceDemoMetadataParamsFilter.java  |  21 ++
 .../org.apache.dubbo.metadata.MetadataParamsFilter |   1 +
 ...ider-zk.xml => dubbo-provider-sofaregistry.xml} |   4 +-
 .../main/resources/spring/dubbo-provider-zk.xml    |   6 +-
 .../store/zookeeper/ZookeeperMetadataReport.java   |   6 +-
 .../dubbo/registry/sofa/SofaRegistryInstance.java  |  77 +++++++
 .../sofa/SofaRegistryServiceDiscovery.java         | 242 +++++++++++++++++++++
 .../sofa/SofaRegistryServiceDiscoveryFactory.java  |  16 ++
 ...g.apache.dubbo.registry.client.ServiceDiscovery |   1 +
 dubbo-registry/pom.xml                             |   2 +-
 15 files changed, 418 insertions(+), 52 deletions(-)

diff --git a/dubbo-demo/dubbo-demo-service/dubbo-demo-service-consumer/pom.xml b/dubbo-demo/dubbo-demo-service/dubbo-demo-service-consumer/pom.xml
index 40a94d2..2bf37d2 100644
--- a/dubbo-demo/dubbo-demo-service/dubbo-demo-service-consumer/pom.xml
+++ b/dubbo-demo/dubbo-demo-service/dubbo-demo-service-consumer/pom.xml
@@ -83,5 +83,9 @@
             <groupId>org.apache.dubbo</groupId>
             <artifactId>dubbo-serialization-hessian2</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.apache.dubbo</groupId>
+            <artifactId>dubbo-registry-sofa</artifactId>
+        </dependency>
     </dependencies>
 </project>
diff --git a/dubbo-demo/dubbo-demo-service/dubbo-demo-service-consumer/src/main/java/org/apache/dubbo/demo/consumer/ApplicationZKConsumer.java b/dubbo-demo/dubbo-demo-service/dubbo-demo-service-consumer/src/main/java/org/apache/dubbo/demo/consumer/ApplicationConsumer.java
similarity index 94%
rename from dubbo-demo/dubbo-demo-service/dubbo-demo-service-consumer/src/main/java/org/apache/dubbo/demo/consumer/ApplicationZKConsumer.java
rename to dubbo-demo/dubbo-demo-service/dubbo-demo-service-consumer/src/main/java/org/apache/dubbo/demo/consumer/ApplicationConsumer.java
index 549cb97..ca896d2 100644
--- a/dubbo-demo/dubbo-demo-service/dubbo-demo-service-consumer/src/main/java/org/apache/dubbo/demo/consumer/ApplicationZKConsumer.java
+++ b/dubbo-demo/dubbo-demo-service/dubbo-demo-service-consumer/src/main/java/org/apache/dubbo/demo/consumer/ApplicationConsumer.java
@@ -23,12 +23,13 @@ import org.springframework.context.support.ClassPathXmlApplicationContext;
 
 import java.util.concurrent.CompletableFuture;
 
-public class ApplicationZKConsumer {
+public class ApplicationConsumer {
     /**
      * In order to make sure multicast registry works, need to specify '-Djava.net.preferIPv4Stack=true' before
      * launch the application
      */
     public static void main(String[] args) throws Exception {
+        //ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring/dubbo-consumer-sofaregistry.xml");
         ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring/dubbo-consumer-zk.xml");
         context.start();
         DemoService demoService = context.getBean("demoService", DemoService.class);
diff --git a/dubbo-demo/dubbo-demo-service/dubbo-demo-service-provider/src/main/resources/spring/dubbo-provider-zk.xml b/dubbo-demo/dubbo-demo-service/dubbo-demo-service-consumer/src/main/resources/spring/dubbo-consumer-sofaregistry.xml
similarity index 63%
copy from dubbo-demo/dubbo-demo-service/dubbo-demo-service-provider/src/main/resources/spring/dubbo-provider-zk.xml
copy to dubbo-demo/dubbo-demo-service/dubbo-demo-service-consumer/src/main/resources/spring/dubbo-consumer-sofaregistry.xml
index 7ba04ef..c5ee4d5 100644
--- a/dubbo-demo/dubbo-demo-service/dubbo-demo-service-provider/src/main/resources/spring/dubbo-provider-zk.xml
+++ b/dubbo-demo/dubbo-demo-service/dubbo-demo-service-consumer/src/main/resources/spring/dubbo-consumer-sofaregistry.xml
@@ -1,43 +1,37 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-  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.
-  -->
-<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-       xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
-       xmlns="http://www.springframework.org/schema/beans"
-       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
-       http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd">
-
-    <dubbo:application name="demo-service-provider" metadata-type="remote">
-        <dubbo:parameter key="mapping-type" value="metadata"/>
-    </dubbo:application>
-
-    <dubbo:config-center address="zookeeper://127.0.0.1:2181"/>
-    <dubbo:metadata-report address="zookeeper://127.0.0.1:2181"/>
-    <dubbo:registry id="registry1" address="zookeeper://127.0.0.1:2181?registry-type=service">
-        <dubbo:parameter key="duplicate" value="false" />
-    </dubbo:registry>
-
-    <dubbo:protocol name="dubbo" port="-1"/>
-
-    <bean id="demoService" class="org.apache.dubbo.demo.provider.DemoServiceImpl"/>
-    <bean id="greetingService" class="org.apache.dubbo.demo.provider.GreetingServiceImpl"/>
-
-    <dubbo:service interface="org.apache.dubbo.demo.DemoService" timeout="3000" ref="demoService" registry="registry1"/>
-    <dubbo:service version="1.0.0" group="greeting" timeout="5000" interface="org.apache.dubbo.demo.GreetingService"
-                   ref="greetingService"/>
-
-</beans>
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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.
+  -->
+<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
+       xmlns="http://www.springframework.org/schema/beans"
+       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
+       http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd">
+
+    <dubbo:application name="demo-service-consumer" metadata-type="remote">
+        <dubbo:parameter key="mapping-type" value="metadata"/>
+    </dubbo:application>
+
+    <dubbo:metadata-report address="zookeeper://127.0.0.1:2181"/>
+
+    <dubbo:registry address="sofa://100.88.142.124:9603?registry-type=service"/>
+
+    <dubbo:reference id="demoService"  interface="org.apache.dubbo.demo.DemoService"/>
+
+    <dubbo:reference version="1.0.0" group="greeting" id="greetingService"
+                     interface="org.apache.dubbo.demo.GreetingService"/>
+
+</beans>
diff --git a/dubbo-demo/dubbo-demo-service/dubbo-demo-service-provider/pom.xml b/dubbo-demo/dubbo-demo-service/dubbo-demo-service-provider/pom.xml
index 74ef4a2..b22856e 100644
--- a/dubbo-demo/dubbo-demo-service/dubbo-demo-service-provider/pom.xml
+++ b/dubbo-demo/dubbo-demo-service/dubbo-demo-service-provider/pom.xml
@@ -103,5 +103,9 @@
             <groupId>log4j</groupId>
             <artifactId>log4j</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.apache.dubbo</groupId>
+            <artifactId>dubbo-registry-sofa</artifactId>
+        </dependency>
     </dependencies>
 </project>
diff --git a/dubbo-demo/dubbo-demo-service/dubbo-demo-service-provider/src/main/java/org/apache/dubbo/demo/provider/ApplicationZKProvider.java b/dubbo-demo/dubbo-demo-service/dubbo-demo-service-provider/src/main/java/org/apache/dubbo/demo/provider/ApplicationProvider.java
similarity index 87%
rename from dubbo-demo/dubbo-demo-service/dubbo-demo-service-provider/src/main/java/org/apache/dubbo/demo/provider/ApplicationZKProvider.java
rename to dubbo-demo/dubbo-demo-service/dubbo-demo-service-provider/src/main/java/org/apache/dubbo/demo/provider/ApplicationProvider.java
index 0b078e9..0769dc5 100644
--- a/dubbo-demo/dubbo-demo-service/dubbo-demo-service-provider/src/main/java/org/apache/dubbo/demo/provider/ApplicationZKProvider.java
+++ b/dubbo-demo/dubbo-demo-service/dubbo-demo-service-provider/src/main/java/org/apache/dubbo/demo/provider/ApplicationProvider.java
@@ -18,8 +18,9 @@ package org.apache.dubbo.demo.provider;
 
 import org.springframework.context.support.ClassPathXmlApplicationContext;
 
-public class ApplicationZKProvider {
+public class ApplicationProvider {
     public static void main(String[] args) throws Exception {
+        //ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring/dubbo-provider-sofaregistry.xml");
         ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring/dubbo-provider-zk.xml");
         context.start();
         System.in.read();
diff --git a/dubbo-demo/dubbo-demo-service/dubbo-demo-service-provider/src/main/java/org/apache/dubbo/demo/provider/ServiceDemoMetadataParamsFilter.java b/dubbo-demo/dubbo-demo-service/dubbo-demo-service-provider/src/main/java/org/apache/dubbo/demo/provider/ServiceDemoMetadataParamsFilter.java
new file mode 100644
index 0000000..bb03592
--- /dev/null
+++ b/dubbo-demo/dubbo-demo-service/dubbo-demo-service-provider/src/main/java/org/apache/dubbo/demo/provider/ServiceDemoMetadataParamsFilter.java
@@ -0,0 +1,21 @@
+package org.apache.dubbo.demo.provider;
+
+import org.apache.dubbo.common.extension.Activate;
+import org.apache.dubbo.metadata.MetadataParamsFilter;
+
+/**
+ * @author: hongwei.quhw
+ * @date: 2020-08-05 19:33
+ */
+@Activate
+public class ServiceDemoMetadataParamsFilter implements MetadataParamsFilter {
+    @Override
+    public String[] serviceParamsIncluded() {
+        return new String[] {"serviceKey1", "serviceKey2"};
+    }
+
+    @Override
+    public String[] instanceParamsIncluded() {
+        return new String[] {"instance1", "instance2"};
+    }
+}
diff --git a/dubbo-demo/dubbo-demo-service/dubbo-demo-service-provider/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.metadata.MetadataParamsFilter b/dubbo-demo/dubbo-demo-service/dubbo-demo-service-provider/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.metadata.MetadataParamsFilter
new file mode 100644
index 0000000..768fcdf
--- /dev/null
+++ b/dubbo-demo/dubbo-demo-service/dubbo-demo-service-provider/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.metadata.MetadataParamsFilter
@@ -0,0 +1 @@
+serviceDemo=org.apache.dubbo.demo.provider.ServiceDemoMetadataParamsFilter
\ No newline at end of file
diff --git a/dubbo-demo/dubbo-demo-service/dubbo-demo-service-provider/src/main/resources/spring/dubbo-provider-zk.xml b/dubbo-demo/dubbo-demo-service/dubbo-demo-service-provider/src/main/resources/spring/dubbo-provider-sofaregistry.xml
similarity index 92%
copy from dubbo-demo/dubbo-demo-service/dubbo-demo-service-provider/src/main/resources/spring/dubbo-provider-zk.xml
copy to dubbo-demo/dubbo-demo-service/dubbo-demo-service-provider/src/main/resources/spring/dubbo-provider-sofaregistry.xml
index 7ba04ef..37dd63c 100644
--- a/dubbo-demo/dubbo-demo-service/dubbo-demo-service-provider/src/main/resources/spring/dubbo-provider-zk.xml
+++ b/dubbo-demo/dubbo-demo-service/dubbo-demo-service-provider/src/main/resources/spring/dubbo-provider-sofaregistry.xml
@@ -27,9 +27,7 @@
 
     <dubbo:config-center address="zookeeper://127.0.0.1:2181"/>
     <dubbo:metadata-report address="zookeeper://127.0.0.1:2181"/>
-    <dubbo:registry id="registry1" address="zookeeper://127.0.0.1:2181?registry-type=service">
-        <dubbo:parameter key="duplicate" value="false" />
-    </dubbo:registry>
+    <dubbo:registry id="registry1" address="sofa://100.88.142.124:9603?registry-type=service"/>
 
     <dubbo:protocol name="dubbo" port="-1"/>
 
diff --git a/dubbo-demo/dubbo-demo-service/dubbo-demo-service-provider/src/main/resources/spring/dubbo-provider-zk.xml b/dubbo-demo/dubbo-demo-service/dubbo-demo-service-provider/src/main/resources/spring/dubbo-provider-zk.xml
index 7ba04ef..eb14cbc 100644
--- a/dubbo-demo/dubbo-demo-service/dubbo-demo-service-provider/src/main/resources/spring/dubbo-provider-zk.xml
+++ b/dubbo-demo/dubbo-demo-service/dubbo-demo-service-provider/src/main/resources/spring/dubbo-provider-zk.xml
@@ -23,6 +23,7 @@
 
     <dubbo:application name="demo-service-provider" metadata-type="remote">
         <dubbo:parameter key="mapping-type" value="metadata"/>
+        <dubbo:parameter key="instance1" value="xxx"/>
     </dubbo:application>
 
     <dubbo:config-center address="zookeeper://127.0.0.1:2181"/>
@@ -36,7 +37,10 @@
     <bean id="demoService" class="org.apache.dubbo.demo.provider.DemoServiceImpl"/>
     <bean id="greetingService" class="org.apache.dubbo.demo.provider.GreetingServiceImpl"/>
 
-    <dubbo:service interface="org.apache.dubbo.demo.DemoService" timeout="3000" ref="demoService" registry="registry1"/>
+    <dubbo:service interface="org.apache.dubbo.demo.DemoService" timeout="3000" ref="demoService" registry="registry1">
+        <dubbo:parameter key="serviceKey1" value="serviceKey1Value"/>
+    </dubbo:service>
+
     <dubbo:service version="1.0.0" group="greeting" timeout="5000" interface="org.apache.dubbo.demo.GreetingService"
                    ref="greetingService"/>
 
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 e31886a..92fb909 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
@@ -132,8 +132,10 @@ public class ZookeeperMetadataReport extends AbstractMetadataReport {
 
     @Override
     public void publishAppMetadata(SubscriberMetadataIdentifier identifier, MetadataInfo metadataInfo) {
-        zkClient.create(getNodePath(identifier), gson.toJson(metadataInfo), false);
-
+        String path = getNodePath(identifier);
+        if (StringUtils.isBlank(zkClient.getContent(path))) {
+            zkClient.create(path, gson.toJson(metadataInfo), false);
+        }
     }
 
     @Override
diff --git a/dubbo-registry/dubbo-registry-sofa/src/main/java/org/apache/dubbo/registry/sofa/SofaRegistryInstance.java b/dubbo-registry/dubbo-registry-sofa/src/main/java/org/apache/dubbo/registry/sofa/SofaRegistryInstance.java
new file mode 100644
index 0000000..4d772a5
--- /dev/null
+++ b/dubbo-registry/dubbo-registry-sofa/src/main/java/org/apache/dubbo/registry/sofa/SofaRegistryInstance.java
@@ -0,0 +1,77 @@
+package org.apache.dubbo.registry.sofa;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author: hongwei.quhw
+ * @date: 2020-08-06 14:26
+ */
+public class SofaRegistryInstance {
+    private String id;
+
+    private String host;
+
+    private int port;
+
+    private String name;
+
+    private Map<String, String> metadata = new HashMap<>();
+
+    private SofaRegistryInstance() {
+    }
+
+    public SofaRegistryInstance(String id, String host, int port, String name, Map<String, String> metadata) {
+        this.id = id;
+        this.host = host;
+        this.port = port;
+        this.name = name;
+        this.metadata = metadata;
+    }
+
+    public String getHost() {
+        return host;
+    }
+
+    public void setHost(String host) {
+        this.host = host;
+    }
+
+    public int getPort() {
+        return port;
+    }
+
+    public void setPort(int port) {
+        this.port = port;
+    }
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getName() {
+        return this.name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public Map<String, String> getMetadata() {
+        return this.metadata;
+    }
+
+    public void setMetadata(Map<String, String> metadata) {
+        this.metadata = metadata;
+    }
+
+    @Override
+    public String toString() {
+        return "SofaRegistryInstance{" + "id='" + this.id + '\''+ "host='" + this.host + '\'' + "port='" + this.port + '\''+ ", name='" + this.name
+                + '\'' + ", metadata=" + this.metadata + '}';
+    }
+}
diff --git a/dubbo-registry/dubbo-registry-sofa/src/main/java/org/apache/dubbo/registry/sofa/SofaRegistryServiceDiscovery.java b/dubbo-registry/dubbo-registry-sofa/src/main/java/org/apache/dubbo/registry/sofa/SofaRegistryServiceDiscovery.java
new file mode 100644
index 0000000..53559bd
--- /dev/null
+++ b/dubbo-registry/dubbo-registry-sofa/src/main/java/org/apache/dubbo/registry/sofa/SofaRegistryServiceDiscovery.java
@@ -0,0 +1,242 @@
+package org.apache.dubbo.registry.sofa;
+
+import com.alipay.sofa.registry.client.api.Publisher;
+import com.alipay.sofa.registry.client.api.RegistryClientConfig;
+import com.alipay.sofa.registry.client.api.Subscriber;
+import com.alipay.sofa.registry.client.api.model.RegistryType;
+import com.alipay.sofa.registry.client.api.model.UserData;
+import com.alipay.sofa.registry.client.api.registration.PublisherRegistration;
+import com.alipay.sofa.registry.client.api.registration.SubscriberRegistration;
+import com.alipay.sofa.registry.client.provider.DefaultRegistryClient;
+import com.alipay.sofa.registry.client.provider.DefaultRegistryClientConfigBuilder;
+import com.alipay.sofa.registry.core.model.ScopeEnum;
+import com.google.gson.Gson;
+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.ConfigUtils;
+import org.apache.dubbo.common.utils.DefaultPage;
+import org.apache.dubbo.common.utils.Page;
+import org.apache.dubbo.registry.client.DefaultServiceInstance;
+import org.apache.dubbo.registry.client.ServiceDiscovery;
+import org.apache.dubbo.registry.client.ServiceInstance;
+import org.apache.dubbo.registry.client.event.ServiceInstancesChangedEvent;
+import org.apache.dubbo.registry.client.event.listener.ServiceInstancesChangedListener;
+import org.apache.dubbo.rpc.RpcException;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import static org.apache.dubbo.registry.sofa.SofaRegistryConstants.*;
+
+/**
+ * @author: hongwei.quhw
+ * @date: 2020-08-06 14:25
+ */
+public class SofaRegistryServiceDiscovery implements ServiceDiscovery {
+    private static final Logger LOGGER = LoggerFactory.getLogger(SofaRegistryServiceDiscovery.class);
+
+    private static  final String DEFAULT_GROUP = "dubbo";
+
+    private URL registryURL;
+
+    private DefaultRegistryClient registryClient;
+
+    private int waitAddressTimeout;
+
+    private RegistryClientConfig registryClientConfig;
+
+    private final Map<String, Publisher> publishers = new ConcurrentHashMap<>();
+
+    private final Map<String, Subscriber> subscribers = new ConcurrentHashMap<>();
+
+    private ServiceInstance serviceInstance;
+
+    private Gson gson = new Gson();
+
+    @Override
+    public void initialize(URL registryURL) throws Exception {
+        this.registryURL = registryURL;
+
+        this.registryClientConfig = DefaultRegistryClientConfigBuilder.start()
+                .setDataCenter(LOCAL_DATA_CENTER)
+                .setZone(LOCAL_REGION)
+                .setRegistryEndpoint(registryURL.getHost())
+                .setRegistryEndpointPort(registryURL.getPort()).build();
+
+        registryClient = new DefaultRegistryClient(this.registryClientConfig);
+        registryClient.init();
+
+        this.waitAddressTimeout = Integer.parseInt(ConfigUtils.getProperty(ADDRESS_WAIT_TIME_KEY, "5000"));
+    }
+
+    @Override
+    public URL getUrl() {
+        return registryURL;
+    }
+
+    @Override
+    public void destroy() throws Exception {
+    }
+
+    @Override
+    public void register(ServiceInstance serviceInstance) throws RuntimeException {
+        SofaRegistryInstance sofaRegistryInstance = new SofaRegistryInstance(serviceInstance.getId(), serviceInstance.getHost(), serviceInstance.getPort(), serviceInstance.getServiceName(), serviceInstance.getMetadata());
+        Publisher publisher = publishers.get(serviceInstance.getServiceName());
+        this.serviceInstance = serviceInstance;
+        if (null == publisher) {
+            PublisherRegistration registration = new PublisherRegistration(serviceInstance.getServiceName());
+            registration.setGroup(DEFAULT_GROUP);
+            publisher = registryClient.register(registration, gson.toJson(sofaRegistryInstance));
+
+            publishers.put(serviceInstance.getServiceName(), publisher);
+        } else {
+            publisher.republish(gson.toJson(sofaRegistryInstance));
+        }
+    }
+
+    @Override
+    public void update(ServiceInstance serviceInstance) throws RuntimeException {
+        register(serviceInstance);
+    }
+
+    @Override
+    public void unregister(ServiceInstance serviceInstance) throws RuntimeException {
+        registryClient.unregister(serviceInstance.getServiceName(), DEFAULT_GROUP, RegistryType.PUBLISHER);
+    }
+
+    @Override
+    public void addServiceInstancesChangedListener(ServiceInstancesChangedListener listener) throws NullPointerException, IllegalArgumentException {
+        listener.getServiceNames().forEach(serviceName -> registerServiceWatcher(serviceName, listener));
+    }
+
+    protected void registerServiceWatcher(String serviceName, ServiceInstancesChangedListener listener) {
+        Subscriber subscriber = subscribers.get(serviceName);
+
+        if (null == subscriber) {
+            final CountDownLatch latch = new CountDownLatch(1);
+            SubscriberRegistration subscriberRegistration = new SubscriberRegistration(serviceName, (dataId, data) -> {
+                handleRegistryData(dataId, data, listener, latch);
+            });
+            subscriberRegistration.setGroup(DEFAULT_GROUP);
+            subscriberRegistration.setScopeEnum(ScopeEnum.global);
+
+            subscriber = registryClient.register(subscriberRegistration);
+            subscribers.put(serviceName, subscriber);
+            waitAddress(serviceName, latch);
+        }
+    }
+
+    @Override
+    public Page<ServiceInstance> getInstances(String serviceName, int offset, int pageSize, boolean healthyOnly)
+            throws NullPointerException, IllegalArgumentException, UnsupportedOperationException {
+        Subscriber subscriber = subscribers.get(serviceName);
+
+        if (null != subscriber) {
+            List<ServiceInstance> serviceInstanceList = handleRegistryData(serviceName, subscriber.peekData(), null, null);
+            return new DefaultPage<>(offset, pageSize, serviceInstanceList, serviceInstanceList.size());
+        }
+
+        throw new RpcException("getInstances error!");
+    }
+
+    private List<ServiceInstance> handleRegistryData(String dataId, UserData userData, ServiceInstancesChangedListener listener, CountDownLatch latch) {
+        try {
+            List<String> datas = getUserData(dataId, userData);
+            List<ServiceInstance> serviceInstances = new ArrayList<>(datas.size());
+
+            for (String  serviceData : datas) {
+                SofaRegistryInstance sri = gson.fromJson(serviceData, SofaRegistryInstance.class);
+
+                DefaultServiceInstance serviceInstance = new DefaultServiceInstance(sri.getId(), dataId, sri.getHost(), sri.getPort());
+                serviceInstance.setMetadata(sri.getMetadata());
+                serviceInstances.add(serviceInstance);
+            }
+
+            if (null != listener) {
+                listener.onEvent(new ServiceInstancesChangedEvent(dataId, serviceInstances));
+            }
+
+            return serviceInstances;
+        } finally {
+            if (null != latch) {
+                latch.countDown();
+            }
+        }
+    }
+
+    private void waitAddress(String serviceName, CountDownLatch countDownLatch) {
+        try {
+            if (!countDownLatch.await(waitAddressTimeout, TimeUnit.MILLISECONDS)) {
+                LOGGER.warn("Subscribe data failed by dataId " + serviceName);
+            }
+        } catch (Exception e) {
+            LOGGER.error("Error when wait Address!", e);
+        }
+    }
+
+    /**
+     * Print address data.
+     *
+     * @param dataId   the data id
+     * @param userData the user data
+     */
+    protected List<String> getUserData(String dataId, UserData userData) {
+
+        List<String> datas = null;
+        if (userData == null) {
+            datas = new ArrayList<>(0);
+        } else {
+            datas = flatUserData(userData);
+        }
+
+        StringBuilder sb = new StringBuilder();
+        for (String provider : datas) {
+            sb.append("  >>> ").append(provider).append("\n");
+        }
+        if (LOGGER.isInfoEnabled()) {
+            LOGGER.info("Receive updated RPC service addresses: service[" + dataId
+                    + "]\n  .Available target addresses size [" + datas.size() + "]\n"
+                    + sb.toString());
+        }
+
+        return datas;
+    }
+
+    /**
+     * Flat user data list.
+     *
+     * @param userData the user data
+     * @return the list
+     */
+    protected List<String> flatUserData(UserData userData) {
+        List<String> result = new ArrayList<>();
+        Map<String, List<String>> zoneData = userData.getZoneData();
+
+        for (Map.Entry<String, List<String>> entry : zoneData.entrySet()) {
+            result.addAll(entry.getValue());
+        }
+
+        return result;
+    }
+
+    @Override
+    public ServiceInstance getLocalInstance() {
+        return serviceInstance;
+    }
+
+    /**
+     * @TODO 后续确认下
+     * @return
+     */
+    @Override
+    public Set<String> getServices() {
+        return subscribers.keySet();
+    }
+
+}
diff --git a/dubbo-registry/dubbo-registry-sofa/src/main/java/org/apache/dubbo/registry/sofa/SofaRegistryServiceDiscoveryFactory.java b/dubbo-registry/dubbo-registry-sofa/src/main/java/org/apache/dubbo/registry/sofa/SofaRegistryServiceDiscoveryFactory.java
new file mode 100644
index 0000000..6077b99
--- /dev/null
+++ b/dubbo-registry/dubbo-registry-sofa/src/main/java/org/apache/dubbo/registry/sofa/SofaRegistryServiceDiscoveryFactory.java
@@ -0,0 +1,16 @@
+package org.apache.dubbo.registry.sofa;
+
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.registry.client.AbstractServiceDiscoveryFactory;
+import org.apache.dubbo.registry.client.ServiceDiscovery;
+
+/**
+ * @author: hongwei.quhw
+ * @date: 2020-08-06 14:23
+ */
+public class SofaRegistryServiceDiscoveryFactory extends AbstractServiceDiscoveryFactory {
+    @Override
+    protected ServiceDiscovery createDiscovery(URL registryURL) {
+        return new SofaRegistryServiceDiscovery();
+    }
+}
diff --git a/dubbo-registry/dubbo-registry-sofa/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.client.ServiceDiscovery b/dubbo-registry/dubbo-registry-sofa/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.client.ServiceDiscovery
new file mode 100644
index 0000000..4578cbd
--- /dev/null
+++ b/dubbo-registry/dubbo-registry-sofa/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.client.ServiceDiscovery
@@ -0,0 +1 @@
+sofa=org.apache.dubbo.registry.sofa.SofaRegistryServiceDiscovery
\ No newline at end of file
diff --git a/dubbo-registry/pom.xml b/dubbo-registry/pom.xml
index 5ab688a..d7de45b 100644
--- a/dubbo-registry/pom.xml
+++ b/dubbo-registry/pom.xml
@@ -39,7 +39,7 @@
         <!--        <module>dubbo-registry-etcd3</module>-->
         <!--        <module>dubbo-registry-nacos</module>-->
         <!--        <module>dubbo-registry-multiple</module>-->
-        <!--        <module>dubbo-registry-sofa</module>-->
+        <module>dubbo-registry-sofa</module>
         <!--        <module>dubbo-registry-eureka</module>-->
     </modules>
 </project>