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 2018/09/14 09:31:26 UTC

[incubator-dubbo] branch dev-metadata updated: Merge pull request #2468, Simplify registry data and add a new service data store seperated from registry #2030 (#2468)

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

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


The following commit(s) were added to refs/heads/dev-metadata by this push:
     new 577eb77  Merge pull request #2468, Simplify registry data and add a new service data store seperated from registry #2030 (#2468)
577eb77 is described below

commit 577eb77cce6cd0e52fe581e406f7d9b2e9a34a7c
Author: cvictory <sh...@gmail.com>
AuthorDate: Fri Sep 14 17:31:18 2018 +0800

    Merge pull request #2468, Simplify registry data and add a new service data store seperated from registry #2030 (#2468)
---
 dubbo-bom/pom.xml                                  |  15 ++
 .../apache/dubbo/rpc/cluster/RouterFactory.java    |   2 +-
 .../java/org/apache/dubbo/common/Constants.java    |  15 ++
 .../src/main/java/org/apache/dubbo/common/URL.java |  43 +++-
 dubbo-config/dubbo-config-api/pom.xml              |   7 +-
 .../dubbo/config/AbstractInterfaceConfig.java      |  66 ++++-
 .../org/apache/dubbo/config/ReferenceConfig.java   |  10 +
 .../org/apache/dubbo/config/RegistryConfig.java    |  30 ++-
 .../org/apache/dubbo/config/ServiceConfig.java     |  11 +
 .../apache/dubbo/config/ServiceStoreConfig.java    |  94 +++++++
 .../apache/dubbo/config/spring/ReferenceBean.java  |  10 +
 .../apache/dubbo/config/spring/ServiceBean.java    |  10 +
 .../spring/schema/DubboNamespaceHandler.java       |   2 +
 .../src/main/resources/META-INF/compat/dubbo.xsd   |  54 +++-
 .../src/main/resources/META-INF/dubbo.xsd          |  47 ++++
 dubbo-demo/dubbo-demo-consumer/pom.xml             |   6 +-
 .../META-INF/spring/dubbo-demo-consumer.xml        |   6 +-
 dubbo-demo/dubbo-demo-provider/pom.xml             |  10 +-
 .../META-INF/spring/dubbo-demo-provider.xml        |  82 +++---
 dubbo-registry/dubbo-registry-api/pom.xml          |   2 +-
 .../registry/integration/RegistryProtocol.java     |  71 ++++--
 dubbo-servicedata/dubbo-servicedata-api/pom.xml    |  41 +++
 .../org/apache/dubbo/servicedata/ServiceStore.java |  92 +++----
 .../dubbo/servicedata/ServiceStoreFactory.java     |  82 +++---
 .../integration/ServiceStoreService.java           |  81 ++++++
 .../servicedata/support/AbstractServiceStore.java  | 279 +++++++++++++++++++++
 .../support/AbstractServiceStoreFactory.java       |  80 ++++++
 .../integration/ServiceStoreServiceTest.java       |   7 +
 .../support/AbstractServiceStoreFactoryTest.java   |  72 ++++++
 .../support/AbstractServiceStoreTest.java          | 110 ++++++++
 dubbo-servicedata/dubbo-servicedata-redis/pom.xml  |  34 +++
 .../dubbo/servicedata/redis/RedisServiceStore.java |  73 ++++++
 .../redis/RedisServiceStoreFactory.java            |  36 +++
 ...rg.apache.dubbo.servicedata.ServiceStoreFactory |   1 +
 .../dubbo-servicedata-zookeeper/pom.xml            |  31 +++
 .../zookeeper/ZookeeperServiceStore.java           | 132 ++++++++++
 .../zookeeper/ZookeeperServiceStoreFactory.java    |  41 +++
 ...rg.apache.dubbo.servicedata.ServiceStoreFactory |   1 +
 dubbo-servicedata/pom.xml                          |  21 ++
 pom.xml                                            |   1 +
 40 files changed, 1639 insertions(+), 169 deletions(-)

diff --git a/dubbo-bom/pom.xml b/dubbo-bom/pom.xml
index a1d8277..ad64f3f 100644
--- a/dubbo-bom/pom.xml
+++ b/dubbo-bom/pom.xml
@@ -293,6 +293,21 @@
                 <artifactId>dubbo-compatible</artifactId>
                 <version>${project.version}</version>
             </dependency>
+            <dependency>
+                <groupId>org.apache.dubbo</groupId>
+                <artifactId>dubbo-servicedata-api</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.apache.dubbo</groupId>
+                <artifactId>dubbo-servicedata-zookeeper</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.apache.dubbo</groupId>
+                <artifactId>dubbo-servicedata-redis</artifactId>
+                <version>${project.version}</version>
+            </dependency>
         </dependencies>
     </dependencyManagement>
 
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/RouterFactory.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/RouterFactory.java
index 4d35c78..bf32cad 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/RouterFactory.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/RouterFactory.java
@@ -49,4 +49,4 @@ public interface RouterFactory {
     default Router getRouter(DynamicConfiguration dynamicConfiguration, URL url) {
         return null;
     }
-}
\ No newline at end of file
+}
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/Constants.java b/dubbo-common/src/main/java/org/apache/dubbo/common/Constants.java
index 0e82118..49b0bd1 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/Constants.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/Constants.java
@@ -84,6 +84,8 @@ public class Constants {
 
     public static final String REGISTRY_PROTOCOL = "registry";
 
+    public static final String SERVICE_STORE_PROTOCOL = "servicestore";
+
     public static final String $INVOKE = "$invoke";
 
     public static final String $ECHO = "$echo";
@@ -178,6 +180,8 @@ public class Constants {
 
     public static final String REGISTRY_KEY = "registry";
 
+    public static final String SERVICE_STORE_KEY = "servicestore";
+
     public static final String MONITOR_KEY = "monitor";
 
     public static final String SIDE_KEY = "side";
@@ -435,6 +439,17 @@ public class Constants {
     public static final String MERGER_KEY = "merger";
 
     /**
+     * simple the registry.
+     * @since 2.7.0
+     */
+    public static final String SIMPLE_KEY = "simple";
+    /**
+     * After simplify the registry, should add some paramter individually.
+     * @since 2.7.0
+     */
+    public static final String ADD_PARAM_KEYS_KEY = "addParamKeys";
+
+    /**
      * To decide whether to exclude unavailable invoker from the cluster
      */
     public static final String CLUSTER_AVAILABLE_CHECK_KEY = "cluster.availablecheck";
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/URL.java b/dubbo-common/src/main/java/org/apache/dubbo/common/URL.java
index a83ca91..312b691 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/URL.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/URL.java
@@ -187,7 +187,7 @@ public /**final**/ class URL implements Serializable {
         int port = 0;
         String path = null;
         Map<String, String> parameters = null;
-        int i = url.indexOf("?"); // seperator between body and parameters 
+        int i = url.indexOf("?"); // seperator between body and parameters
         if (i >= 0) {
             String[] parts = url.substring(i + 1).split("\\&");
             parameters = new HashMap<String, String>();
@@ -250,6 +250,47 @@ public /**final**/ class URL implements Serializable {
         return new URL(protocol, username, password, host, port, path, parameters);
     }
 
+    public static URL valueOf(String url, String... reserveParams){
+        URL result = valueOf(url);
+        if (reserveParams == null || reserveParams.length == 0){
+            return result;
+        }
+        Map<String, String> newMap = new HashMap<String,String>(reserveParams.length);
+        Map<String, String> oldMap = result.getParameters();
+        for(String reserveParam : reserveParams){
+            String tmp = oldMap.get(reserveParam);
+            if(StringUtils.isNotEmpty(tmp)){
+                newMap.put(reserveParam, tmp);
+            }
+        }
+        return result.clearParameters().addParameters(newMap);
+    }
+
+    public static URL valueOf(URL url, String[] reserveParams, String[] reserveParamPrefixs) {
+        Map<String, String> newMap = new HashMap<String, String>();
+        Map<String, String> oldMap = url.getParameters();
+        if (reserveParamPrefixs != null && reserveParamPrefixs.length != 0) {
+            for (Map.Entry<String, String> entry : oldMap.entrySet()) {
+                for (String reserveParamPrefix : reserveParamPrefixs){
+                    if (entry.getKey().startsWith(reserveParamPrefix) && StringUtils.isNotEmpty(entry.getValue())){
+                        newMap.put(entry.getKey(), entry.getValue());
+                    }
+                }
+            }
+        }
+
+        if (reserveParams != null) {
+            for (String reserveParam : reserveParams) {
+                String tmp = oldMap.get(reserveParam);
+                if (StringUtils.isNotEmpty(tmp)) {
+                    newMap.put(reserveParam, tmp);
+                }
+            }
+        }
+
+        return newMap.isEmpty() ? url : url.clearParameters().addParameters(newMap);
+    }
+
     public static String encode(String value) {
         if (value == null || value.length() == 0) {
             return "";
diff --git a/dubbo-config/dubbo-config-api/pom.xml b/dubbo-config/dubbo-config-api/pom.xml
index da0a287..7a2229c 100644
--- a/dubbo-config/dubbo-config-api/pom.xml
+++ b/dubbo-config/dubbo-config-api/pom.xml
@@ -36,6 +36,11 @@
         </dependency>
         <dependency>
             <groupId>org.apache.dubbo</groupId>
+            <artifactId>dubbo-servicedata-api</artifactId>
+            <version>${project.parent.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.dubbo</groupId>
             <artifactId>dubbo-monitor-api</artifactId>
             <version>${project.parent.version}</version>
         </dependency>
@@ -123,4 +128,4 @@
             <scope>test</scope>
         </dependency>
     </dependencies>
-</project>
\ No newline at end of file
+</project>
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractInterfaceConfig.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractInterfaceConfig.java
index 70ab62e..0e4f93e 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractInterfaceConfig.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractInterfaceConfig.java
@@ -35,11 +35,14 @@ import org.apache.dubbo.rpc.InvokerListener;
 import org.apache.dubbo.rpc.ProxyFactory;
 import org.apache.dubbo.rpc.cluster.Cluster;
 import org.apache.dubbo.rpc.support.MockInvoker;
+import org.apache.dubbo.servicedata.ServiceStoreFactory;
+import org.apache.dubbo.servicedata.integration.ServiceStoreService;
 
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.function.Supplier;
 
 /**
  * AbstractDefaultConfig
@@ -102,6 +105,9 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig {
     // the scope for referring/exporting a service, if it's local, it means searching in current JVM only.
     private String scope;
 
+    protected ServiceStoreConfig serviceStoreConfig;
+
+
     protected void checkRegistry() {
         // for backward compatibility
         if (registries == null || registries.isEmpty()) {
@@ -255,6 +261,55 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig {
         return null;
     }
 
+    protected URL loadServiceStore(boolean provider) {
+        // FIXME
+        // checkRegistry();
+        if(serviceStoreConfig == null){
+            return null;
+        }
+        URL loadServiceUrl ;
+
+        String address = serviceStoreConfig.getAddress();
+        if (address == null || address.length() == 0) {
+            address = Constants.ANYHOST_VALUE;
+        }
+
+        if (address.length() > 0 && !RegistryConfig.NO_AVAILABLE.equalsIgnoreCase(address)) {
+            Map<String, String> map = new HashMap<String, String>();
+            appendParameters(map, application);
+            appendParameters(map, serviceStoreConfig);
+            map.put("path", ServiceStoreConfig.class.getName());
+            map.put("dubbo", Version.getProtocolVersion());
+            map.put(Constants.TIMESTAMP_KEY, String.valueOf(System.currentTimeMillis()));
+            if (ConfigUtils.getPid() > 0) {
+                map.put(Constants.PID_KEY, String.valueOf(ConfigUtils.getPid()));
+            }
+            if (!map.containsKey("protocol")) {
+                if (ExtensionLoader.getExtensionLoader(ServiceStoreFactory.class).hasExtension("remote")) {
+                    map.put("protocol", "remote");
+                } else {
+                    map.put("protocol", "dubbo");
+                }
+            }
+            URL url = UrlUtils.parseURL(address, map);
+            url = url.addParameter(Constants.SERVICE_STORE_KEY, url.getProtocol()).setProtocol(Constants.SERVICE_STORE_PROTOCOL);
+            if ((provider && url.getParameter(Constants.REGISTER_KEY, true))
+                    || (!provider && url.getParameter(Constants.SUBSCRIBE_KEY, true))) {
+                return url;
+            }
+        }
+        return null;
+    }
+
+    protected ServiceStoreService getServiceStoreService() {
+        if (serviceStoreConfig == null) {
+            return null;
+        }
+        return ServiceStoreService.instance(() -> {
+            return loadServiceStore(true);
+        });
+    }
+
     protected void checkInterfaceAndMethods(Class<?> interfaceClass, List<MethodConfig> methods) {
         // interface cannot be null
         if (interfaceClass == null) {
@@ -522,4 +577,13 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig {
     public void setScope(String scope) {
         this.scope = scope;
     }
-}
\ No newline at end of file
+
+    public ServiceStoreConfig getServiceStoreConfig() {
+        return serviceStoreConfig;
+    }
+
+    public void setServiceStoreConfig(ServiceStoreConfig serviceStoreConfig) {
+        this.serviceStoreConfig = serviceStoreConfig;
+    }
+
+}
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ReferenceConfig.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ReferenceConfig.java
index 1a82c6a..43e3ca0 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ReferenceConfig.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ReferenceConfig.java
@@ -41,6 +41,7 @@ import org.apache.dubbo.rpc.cluster.support.ClusterUtils;
 import org.apache.dubbo.rpc.protocol.injvm.InjvmProtocol;
 import org.apache.dubbo.rpc.service.GenericService;
 import org.apache.dubbo.rpc.support.ProtocolUtils;
+import org.apache.dubbo.servicedata.integration.ServiceStoreService;
 
 import java.io.File;
 import java.io.FileInputStream;
@@ -427,6 +428,15 @@ public class ReferenceConfig<T> extends AbstractReferenceConfig {
         if (logger.isInfoEnabled()) {
             logger.info("Refer dubbo service " + interfaceClass.getName() + " from url " + invoker.getUrl());
         }
+        /**
+         * @since 2.7.0
+         * ServiceData Store
+         */
+        ServiceStoreService serviceStoreService = null;
+        if ((serviceStoreService = getServiceStoreService()) != null){
+            URL consumerURL = new URL(Constants.CONSUMER_PROTOCOL, map.remove(Constants.REGISTER_IP_KEY), 0, map.get(Constants.INTERFACE_KEY), map);
+            serviceStoreService.publishConsumer(consumerURL);
+        }
         // create service proxy
         return (T) proxyFactory.getProxy(invoker);
     }
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/RegistryConfig.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/RegistryConfig.java
index a9a8145..5678a2e 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/RegistryConfig.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/RegistryConfig.java
@@ -19,6 +19,7 @@ package org.apache.dubbo.config;
 import org.apache.dubbo.common.Constants;
 import org.apache.dubbo.config.support.Parameter;
 
+import java.util.List;
 import java.util.Map;
 
 /**
@@ -88,6 +89,18 @@ public class RegistryConfig extends AbstractConfig {
     // if it's default
     private Boolean isDefault;
 
+    /**
+     * simple the registry.
+     * @since 2.7.0
+     */
+    private Boolean simple;
+    /**
+     * After simplify the registry, should add some paramter individually.
+     * addionalParameterKeys = addParamKeys
+     * @since 2.7.0
+     */
+    private String addParamKeys;
+
     public RegistryConfig() {
     }
 
@@ -321,4 +334,19 @@ public class RegistryConfig extends AbstractConfig {
         this.isDefault = isDefault;
     }
 
-}
\ No newline at end of file
+    public Boolean getSimple() {
+        return simple;
+    }
+
+    public void setSimple(Boolean simple) {
+        this.simple = simple;
+    }
+
+    public String getAddParamKeys() {
+        return addParamKeys;
+    }
+
+    public void setAddParamKeys(String addParamKeys) {
+        this.addParamKeys = addParamKeys;
+    }
+}
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ServiceConfig.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ServiceConfig.java
index e9d5e6b..200cb34 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ServiceConfig.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ServiceConfig.java
@@ -38,6 +38,7 @@ import org.apache.dubbo.rpc.ServiceClassHolder;
 import org.apache.dubbo.rpc.cluster.ConfiguratorFactory;
 import org.apache.dubbo.rpc.service.GenericService;
 import org.apache.dubbo.rpc.support.ProtocolUtils;
+import org.apache.dubbo.servicedata.integration.ServiceStoreService;
 
 import java.lang.reflect.Method;
 import java.net.InetAddress;
@@ -520,6 +521,16 @@ public class ServiceConfig<T> extends AbstractServiceConfig {
                     Exporter<?> exporter = protocol.export(wrapperInvoker);
                     exporters.add(exporter);
                 }
+                /**
+                 * @since 2.7.0
+                 * ServiceData Store
+                 */
+                ServiceStoreService serviceStoreService = null;
+                if ((serviceStoreService = getServiceStoreService()) != null){
+//                    String protocol = url.getProtocol();
+//                    url = url.setProtocol(Constants.PROVIDER_PROTOCOL).addParameter(Constants.SIDE_KEY, Constants.PROVIDER_SIDE).addParameter(Constants.PROTOCOL_KEY, protocol);
+                    serviceStoreService.publishProvider(url);
+                }
             }
         }
         this.urls.add(url);
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ServiceStoreConfig.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ServiceStoreConfig.java
new file mode 100644
index 0000000..1a31c90
--- /dev/null
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ServiceStoreConfig.java
@@ -0,0 +1,94 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.config;
+
+import org.apache.dubbo.common.Constants;
+import org.apache.dubbo.config.support.Parameter;
+
+import java.util.Map;
+
+/**
+ * RegistryConfig
+ *
+ * @export
+ */
+public class ServiceStoreConfig extends AbstractConfig {
+
+    public static final String NO_AVAILABLE = "N/A";
+    private static final long serialVersionUID = 55233L;
+    // register center address
+    private String address;
+
+    // username to login register center
+    private String username;
+
+    // password to login register center
+    private String password;
+
+    // request timeout in milliseconds for register center
+    private Integer timeout;
+
+    // customized parameters
+    private Map<String, String> parameters;
+
+    public ServiceStoreConfig() {
+    }
+
+    public ServiceStoreConfig(String address) {
+        setAddress(address);
+    }
+
+    public String getAddress() {
+        return address;
+    }
+
+    public void setAddress(String address) {
+        this.address = address;
+    }
+
+    public String getUsername() {
+        return username;
+    }
+
+    public void setUsername(String username) {
+        this.username = username;
+    }
+
+    public String getPassword() {
+        return password;
+    }
+
+    public void setPassword(String password) {
+        this.password = password;
+    }
+
+    public Integer getTimeout() {
+        return timeout;
+    }
+
+    public void setTimeout(Integer timeout) {
+        this.timeout = timeout;
+    }
+
+    public Map<String, String> getParameters() {
+        return parameters;
+    }
+
+    public void setParameters(Map<String, String> parameters) {
+        this.parameters = parameters;
+    }
+}
diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/ReferenceBean.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/ReferenceBean.java
index e6a2a1f..2eb4475 100644
--- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/ReferenceBean.java
+++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/ReferenceBean.java
@@ -22,6 +22,7 @@ import org.apache.dubbo.config.ModuleConfig;
 import org.apache.dubbo.config.MonitorConfig;
 import org.apache.dubbo.config.ReferenceConfig;
 import org.apache.dubbo.config.RegistryConfig;
+import org.apache.dubbo.config.ServiceStoreConfig;
 import org.apache.dubbo.config.annotation.Reference;
 import org.apache.dubbo.config.spring.extension.SpringExtensionFactory;
 import org.apache.dubbo.config.support.Parameter;
@@ -149,6 +150,15 @@ public class ReferenceBean<T> extends ReferenceConfig<T> implements FactoryBean,
                 }
             }
         }
+        if (getServiceStoreConfig() == null) {
+            Map<String, ServiceStoreConfig> serviceStoreConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ServiceStoreConfig.class, false, false);
+            if (serviceStoreConfigMap != null && serviceStoreConfigMap.size() == 1) {
+                // first elements
+                super.setServiceStoreConfig(serviceStoreConfigMap.values().iterator().next());
+            } else if(serviceStoreConfigMap != null && serviceStoreConfigMap.size() > 1){
+                throw new IllegalStateException("Multiple ServiceStore configs: " + serviceStoreConfigMap);
+            }
+        }
         if (getMonitor() == null
                 && (getConsumer() == null || getConsumer().getMonitor() == null)
                 && (getApplication() == null || getApplication().getMonitor() == null)) {
diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/ServiceBean.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/ServiceBean.java
index 5b41b24..ddf1608 100644
--- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/ServiceBean.java
+++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/ServiceBean.java
@@ -23,6 +23,7 @@ import org.apache.dubbo.config.ProtocolConfig;
 import org.apache.dubbo.config.ProviderConfig;
 import org.apache.dubbo.config.RegistryConfig;
 import org.apache.dubbo.config.ServiceConfig;
+import org.apache.dubbo.config.ServiceStoreConfig;
 import org.apache.dubbo.config.annotation.Service;
 import org.apache.dubbo.config.spring.extension.SpringExtensionFactory;
 import org.springframework.aop.support.AopUtils;
@@ -219,6 +220,15 @@ public class ServiceBean<T> extends ServiceConfig<T> implements InitializingBean
                 }
             }
         }
+        if (getServiceStoreConfig() == null) {
+            Map<String, ServiceStoreConfig> serviceStoreConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ServiceStoreConfig.class, false, false);
+            if (serviceStoreConfigMap != null && serviceStoreConfigMap.size() == 1) {
+                // 第一个元素
+                super.setServiceStoreConfig(serviceStoreConfigMap.values().iterator().next());
+            } else if(serviceStoreConfigMap != null && serviceStoreConfigMap.size() > 1){
+                throw new IllegalStateException("Multiple ServiceStore configs: " + serviceStoreConfigMap);
+            }
+        }
         if (getMonitor() == null
                 && (getProvider() == null || getProvider().getMonitor() == null)
                 && (getApplication() == null || getApplication().getMonitor() == null)) {
diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/schema/DubboNamespaceHandler.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/schema/DubboNamespaceHandler.java
index 9f16c39..57701c6 100644
--- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/schema/DubboNamespaceHandler.java
+++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/schema/DubboNamespaceHandler.java
@@ -24,6 +24,7 @@ import org.apache.dubbo.config.MonitorConfig;
 import org.apache.dubbo.config.ProtocolConfig;
 import org.apache.dubbo.config.ProviderConfig;
 import org.apache.dubbo.config.RegistryConfig;
+import org.apache.dubbo.config.ServiceStoreConfig;
 import org.apache.dubbo.config.spring.ReferenceBean;
 import org.apache.dubbo.config.spring.ServiceBean;
 import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
@@ -44,6 +45,7 @@ public class DubboNamespaceHandler extends NamespaceHandlerSupport {
         registerBeanDefinitionParser("application", new DubboBeanDefinitionParser(ApplicationConfig.class, true));
         registerBeanDefinitionParser("module", new DubboBeanDefinitionParser(ModuleConfig.class, true));
         registerBeanDefinitionParser("registry", new DubboBeanDefinitionParser(RegistryConfig.class, true));
+        registerBeanDefinitionParser("servicestore", new DubboBeanDefinitionParser(ServiceStoreConfig.class, true));
         registerBeanDefinitionParser("monitor", new DubboBeanDefinitionParser(MonitorConfig.class, true));
         registerBeanDefinitionParser("provider", new DubboBeanDefinitionParser(ProviderConfig.class, true));
         registerBeanDefinitionParser("consumer", new DubboBeanDefinitionParser(ConsumerConfig.class, true));
diff --git a/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/compat/dubbo.xsd b/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/compat/dubbo.xsd
index 5924591..39ad36b 100644
--- a/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/compat/dubbo.xsd
+++ b/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/compat/dubbo.xsd
@@ -550,6 +550,47 @@
                 <xsd:documentation><![CDATA[ Is default. ]]></xsd:documentation>
             </xsd:annotation>
         </xsd:attribute>
+        <xsd:attribute name="simple" type="xsd:boolean">
+            <xsd:annotation>
+                <xsd:documentation><![CDATA[ Is simple. ]]></xsd:documentation>
+            </xsd:annotation>
+        </xsd:attribute>
+        <xsd:attribute name="addParamKeys" type="xsd:string">
+            <xsd:annotation>
+                <xsd:documentation><![CDATA[ Addtional Parameter Keys. ]]></xsd:documentation>
+            </xsd:annotation>
+        </xsd:attribute>
+    </xsd:complexType>
+
+    <xsd:complexType name="serviceStoreType">
+        <xsd:sequence minOccurs="0" maxOccurs="unbounded">
+            <xsd:element ref="parameter" minOccurs="0" maxOccurs="unbounded"/>
+        </xsd:sequence>
+        <xsd:attribute name="id" type="xsd:ID">
+            <xsd:annotation>
+                <xsd:documentation><![CDATA[ The unique identifier for a bean. ]]></xsd:documentation>
+            </xsd:annotation>
+        </xsd:attribute>
+        <xsd:attribute name="address" type="xsd:string" use="optional">
+            <xsd:annotation>
+                <xsd:documentation><![CDATA[ The servicestore address. ]]></xsd:documentation>
+            </xsd:annotation>
+        </xsd:attribute>
+        <xsd:attribute name="username" type="xsd:string" use="optional">
+            <xsd:annotation>
+                <xsd:documentation><![CDATA[ The servicestore username. ]]></xsd:documentation>
+            </xsd:annotation>
+        </xsd:attribute>
+        <xsd:attribute name="password" type="xsd:string" use="optional">
+            <xsd:annotation>
+                <xsd:documentation><![CDATA[ The servicestore password. ]]></xsd:documentation>
+            </xsd:annotation>
+        </xsd:attribute>
+        <xsd:attribute name="timeout" type="xsd:string" use="optional">
+            <xsd:annotation>
+                <xsd:documentation><![CDATA[ The request timeout. ]]></xsd:documentation>
+            </xsd:annotation>
+        </xsd:attribute>
     </xsd:complexType>
 
     <xsd:complexType name="monitorType">
@@ -1211,6 +1252,17 @@
         </xsd:annotation>
     </xsd:element>
 
+    <xsd:element name="servicestore" type="servicestoreType">
+        <xsd:annotation>
+            <xsd:documentation><![CDATA[ The servicestore config ]]></xsd:documentation>
+            <xsd:appinfo>
+                <tool:annotation>
+                    <tool:exports type="org.apache.dubbo.config.ServiceStoreConfig"/>
+                </tool:annotation>
+            </xsd:appinfo>
+        </xsd:annotation>
+    </xsd:element>
+
     <xsd:element name="monitor" type="monitorType">
         <xsd:annotation>
             <xsd:documentation><![CDATA[ The logstat monitor config ]]></xsd:documentation>
@@ -1305,4 +1357,4 @@
         </xsd:annotation>
     </xsd:element>
 
-</xsd:schema>
\ No newline at end of file
+</xsd:schema>
diff --git a/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/dubbo.xsd b/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/dubbo.xsd
index ecec23a..6952666 100644
--- a/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/dubbo.xsd
+++ b/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/dubbo.xsd
@@ -544,6 +544,47 @@
                 <xsd:documentation><![CDATA[ Is default. ]]></xsd:documentation>
             </xsd:annotation>
         </xsd:attribute>
+        <xsd:attribute name="simple" type="xsd:boolean">
+            <xsd:annotation>
+                <xsd:documentation><![CDATA[ Is simple. ]]></xsd:documentation>
+            </xsd:annotation>
+        </xsd:attribute>
+        <xsd:attribute name="addParamKeys" type="xsd:string">
+            <xsd:annotation>
+                <xsd:documentation><![CDATA[ Addtional Parameter Keys. ]]></xsd:documentation>
+            </xsd:annotation>
+        </xsd:attribute>
+    </xsd:complexType>
+
+    <xsd:complexType name="serviceStoreType">
+        <xsd:sequence minOccurs="0" maxOccurs="unbounded">
+            <xsd:element ref="parameter" minOccurs="0" maxOccurs="unbounded"/>
+        </xsd:sequence>
+        <xsd:attribute name="id" type="xsd:ID">
+            <xsd:annotation>
+                <xsd:documentation><![CDATA[ The unique identifier for a bean. ]]></xsd:documentation>
+            </xsd:annotation>
+        </xsd:attribute>
+        <xsd:attribute name="address" type="xsd:string" use="optional">
+            <xsd:annotation>
+                <xsd:documentation><![CDATA[ The servicestore address. ]]></xsd:documentation>
+            </xsd:annotation>
+        </xsd:attribute>
+        <xsd:attribute name="username" type="xsd:string" use="optional">
+            <xsd:annotation>
+                <xsd:documentation><![CDATA[ The servicestore username. ]]></xsd:documentation>
+            </xsd:annotation>
+        </xsd:attribute>
+        <xsd:attribute name="password" type="xsd:string" use="optional">
+            <xsd:annotation>
+                <xsd:documentation><![CDATA[ The servicestore password. ]]></xsd:documentation>
+            </xsd:annotation>
+        </xsd:attribute>
+        <xsd:attribute name="timeout" type="xsd:string" use="optional">
+            <xsd:annotation>
+                <xsd:documentation><![CDATA[ The request timeout. ]]></xsd:documentation>
+            </xsd:annotation>
+        </xsd:attribute>
     </xsd:complexType>
 
     <xsd:complexType name="monitorType">
@@ -1205,6 +1246,12 @@
         </xsd:annotation>
     </xsd:element>
 
+    <xsd:element name="servicestore" type="serviceStoreType">
+        <xsd:annotation>
+            <xsd:documentation><![CDATA[ The servicestore config ]]></xsd:documentation>
+        </xsd:annotation>
+    </xsd:element>
+
     <xsd:element name="monitor" type="monitorType">
         <xsd:annotation>
             <xsd:documentation><![CDATA[ The logstat monitor config ]]></xsd:documentation>
diff --git a/dubbo-demo/dubbo-demo-consumer/pom.xml b/dubbo-demo/dubbo-demo-consumer/pom.xml
index 91468c8..cc25019 100644
--- a/dubbo-demo/dubbo-demo-consumer/pom.xml
+++ b/dubbo-demo/dubbo-demo-consumer/pom.xml
@@ -62,5 +62,9 @@
             <groupId>org.apache.dubbo</groupId>
             <artifactId>dubbo-config-dynamic</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.apache.dubbo</groupId>
+            <artifactId>dubbo-servicedata-zookeeper</artifactId>
+        </dependency>
     </dependencies>
-</project>
\ No newline at end of file
+</project>
diff --git a/dubbo-demo/dubbo-demo-consumer/src/main/resources/META-INF/spring/dubbo-demo-consumer.xml b/dubbo-demo/dubbo-demo-consumer/src/main/resources/META-INF/spring/dubbo-demo-consumer.xml
index 68494f5..86472c5 100644
--- a/dubbo-demo/dubbo-demo-consumer/src/main/resources/META-INF/spring/dubbo-demo-consumer.xml
+++ b/dubbo-demo/dubbo-demo-consumer/src/main/resources/META-INF/spring/dubbo-demo-consumer.xml
@@ -31,8 +31,10 @@
     <!-- use multicast registry center to discover service -->
     <dubbo:registry address="zookeeper://127.0.0.1:2181"/>
 
+    <dubbo:servicestore address="zookeeper://127.0.0.1:2181"/>
+
     <!-- generate proxy for the remote service, then demoService can be used in the same way as the
     local regular interface -->
-    <dubbo:reference id="demoService" check="false" interface="org.apache.dubbo.demo.DemoService"/>
+    <dubbo:reference id="demoService" check="false" interface="org.apache.dubbo.demo.DemoService" version="1.0.2"/>
 
-</beans>
\ No newline at end of file
+</beans>
diff --git a/dubbo-demo/dubbo-demo-provider/pom.xml b/dubbo-demo/dubbo-demo-provider/pom.xml
index b9f46b1..8045fad 100644
--- a/dubbo-demo/dubbo-demo-provider/pom.xml
+++ b/dubbo-demo/dubbo-demo-provider/pom.xml
@@ -63,5 +63,13 @@
             <groupId>org.apache.dubbo</groupId>
             <artifactId>dubbo-config-dynamic</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.apache.dubbo</groupId>
+            <artifactId>dubbo-servicedata-zookeeper</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.dubbo</groupId>
+            <artifactId>dubbo-servicedata-redis</artifactId>
+        </dependency>
     </dependencies>
-</project>
\ No newline at end of file
+</project>
diff --git a/dubbo-demo/dubbo-demo-provider/src/main/resources/META-INF/spring/dubbo-demo-provider.xml b/dubbo-demo/dubbo-demo-provider/src/main/resources/META-INF/spring/dubbo-demo-provider.xml
index 96ebae1..7604b32 100644
--- a/dubbo-demo/dubbo-demo-provider/src/main/resources/META-INF/spring/dubbo-demo-provider.xml
+++ b/dubbo-demo/dubbo-demo-provider/src/main/resources/META-INF/spring/dubbo-demo-provider.xml
@@ -1,40 +1,42 @@
-<?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">
-
-    <!-- provider's application name, used for tracing dependency relationship -->
-    <dubbo:application name="demo-provider"/>
-    <!--<dubbo:provider tag="tag3"/>-->
-
-    <!-- use multicast registry center to export service -->
-    <dubbo:registry address="zookeeper://127.0.0.1:2181"/>
-
-    <!-- use dubbo protocol to export service on port 20880 -->
-    <dubbo:protocol name="dubbo" port="-1"/>
-
-    <!-- service implementation, as same as regular local bean -->
-    <bean id="demoService" class="org.apache.dubbo.demo.provider.DemoServiceImpl"/>
-
-    <!-- declare the service interface to be exported -->
-    <dubbo:service interface="org.apache.dubbo.demo.DemoService" ref="demoService"/>
-
-</beans>
\ No newline at end of file
+<?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">
+
+    <!-- provider's application name, used for tracing dependency relationship -->
+    <dubbo:application name="demo-provider"/>
+    <!--<dubbo:provider tag="tag3"/>-->
+
+    <!-- use multicast registry center to export service -->
+    <dubbo:registry address="zookeeper://127.0.0.1:2181" simple="true" />
+
+    <dubbo:servicestore address="redis://127.0.0.1:6379"/>
+
+    <!-- use dubbo protocol to export service on port 20880 -->
+    <dubbo:protocol name="dubbo" port="-1"/>
+
+    <!-- service implementation, as same as regular local bean -->
+    <bean id="demoService" class="org.apache.dubbo.demo.provider.DemoServiceImpl"/>
+
+    <!-- declare the service interface to be exported -->
+    <dubbo:service interface="org.apache.dubbo.demo.DemoService" ref="demoService" version="1.0.2"/>
+
+</beans>
diff --git a/dubbo-registry/dubbo-registry-api/pom.xml b/dubbo-registry/dubbo-registry-api/pom.xml
index c6494e4..88a5000 100644
--- a/dubbo-registry/dubbo-registry-api/pom.xml
+++ b/dubbo-registry/dubbo-registry-api/pom.xml
@@ -55,4 +55,4 @@
             </exclusions>
         </dependency>
     </dependencies>
-</project>
\ No newline at end of file
+</project>
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryProtocol.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryProtocol.java
index dc86b55..7c112e2 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryProtocol.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryProtocol.java
@@ -16,6 +16,7 @@
  */
 package org.apache.dubbo.registry.integration;
 
+import org.apache.commons.lang.ArrayUtils;
 import org.apache.dubbo.common.Constants;
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.extension.ExtensionLoader;
@@ -57,16 +58,34 @@ import java.util.concurrent.Executors;
 import java.util.stream.Collectors;
 
 import static org.apache.dubbo.common.Constants.ACCEPT_FOREIGN_IP;
+import static org.apache.dubbo.common.Constants.ADD_PARAM_KEYS_KEY;
 import static org.apache.dubbo.common.Constants.APPLICATION_KEY;
+import static org.apache.dubbo.common.Constants.CLUSTER_KEY;
+import static org.apache.dubbo.common.Constants.CODEC_KEY;
 import static org.apache.dubbo.common.Constants.CONFIGURATORS_SUFFIX;
 import static org.apache.dubbo.common.Constants.CONFIG_PROTOCOL;
+import static org.apache.dubbo.common.Constants.CONNECTIONS_KEY;
+import static org.apache.dubbo.common.Constants.DEPRECATED_KEY;
+import static org.apache.dubbo.common.Constants.EXCHANGER_KEY;
 import static org.apache.dubbo.common.Constants.EXPORT_KEY;
+import static org.apache.dubbo.common.Constants.GROUP_KEY;
 import static org.apache.dubbo.common.Constants.INTERFACES;
 import static org.apache.dubbo.common.Constants.INTERFACE_KEY;
+import static org.apache.dubbo.common.Constants.LOADBALANCE_KEY;
+import static org.apache.dubbo.common.Constants.METHODS_KEY;
+import static org.apache.dubbo.common.Constants.MOCK_KEY;
+import static org.apache.dubbo.common.Constants.PATH_KEY;
 import static org.apache.dubbo.common.Constants.QOS_ENABLE;
 import static org.apache.dubbo.common.Constants.QOS_PORT;
 import static org.apache.dubbo.common.Constants.REFER_KEY;
+import static org.apache.dubbo.common.Constants.SERIALIZATION_KEY;
+import static org.apache.dubbo.common.Constants.TIMEOUT_KEY;
+import static org.apache.dubbo.common.Constants.TIMESTAMP_KEY;
+import static org.apache.dubbo.common.Constants.TOKEN_KEY;
 import static org.apache.dubbo.common.Constants.VALIDATION_KEY;
+import static org.apache.dubbo.common.Constants.VERSION_KEY;
+import static org.apache.dubbo.common.Constants.WARMUP_KEY;
+import static org.apache.dubbo.common.Constants.WEIGHT_KEY;
 
 /**
  * RegistryProtocol
@@ -162,7 +181,7 @@ public class RegistryProtocol implements Protocol {
 
         // url to registry
         final Registry registry = getRegistry(originInvoker);
-        final URL registeredProviderUrl = getRegistedProviderUrl(providerUrl);
+        final URL registeredProviderUrl = getRegistedProviderUrl(providerUrl, registryUrl);
 
         ProviderConsumerRegTable.registerProvider(originInvoker, registryUrl, registeredProviderUrl);
 
@@ -280,18 +299,28 @@ public class RegistryProtocol implements Protocol {
      * @param providerUrl
      * @return url to registry.
      */
-    private URL getRegistedProviderUrl(final URL providerUrl) {
+    private URL getRegistedProviderUrl(final URL providerUrl, final URL registryUrl) {
         //The address you see at the registry
-        final URL registedProviderUrl = providerUrl.removeParameters(getFilteredKeys(providerUrl))
-                .removeParameter(Constants.MONITOR_KEY)
-                .removeParameter(Constants.BIND_IP_KEY)
-                .removeParameter(Constants.BIND_PORT_KEY)
-                .removeParameter(QOS_ENABLE)
-                .removeParameter(QOS_PORT)
-                .removeParameter(ACCEPT_FOREIGN_IP)
-                .removeParameter(VALIDATION_KEY)
-                .removeParameter(INTERFACES);
-        return registedProviderUrl;
+        if(!registryUrl.getParameter(Constants.SIMPLE_KEY,false)){
+            final URL registedProviderUrl = providerUrl.removeParameters(getFilteredKeys(providerUrl))
+                    .removeParameter(Constants.MONITOR_KEY)
+                    .removeParameter(Constants.BIND_IP_KEY)
+                    .removeParameter(Constants.BIND_PORT_KEY)
+                    .removeParameter(QOS_ENABLE)
+                    .removeParameter(QOS_PORT)
+                    .removeParameter(ACCEPT_FOREIGN_IP)
+                    .removeParameter(VALIDATION_KEY)
+                    .removeParameter(INTERFACES);
+            return registedProviderUrl;
+        }else{
+            String[] addionalParameterKeys = registryUrl.getParameter(ADD_PARAM_KEYS_KEY, new String[0]);
+            String[] registryParams = {APPLICATION_KEY, CODEC_KEY, EXCHANGER_KEY, SERIALIZATION_KEY, CLUSTER_KEY, CONNECTIONS_KEY, DEPRECATED_KEY,
+                    GROUP_KEY, LOADBALANCE_KEY, MOCK_KEY, PATH_KEY, TIMEOUT_KEY, TOKEN_KEY, VERSION_KEY, WARMUP_KEY, WEIGHT_KEY, TIMESTAMP_KEY};
+            ArrayUtils.addAll(registryParams, addionalParameterKeys);
+            String[] methods = providerUrl.getParameter(METHODS_KEY, (String[]) null);
+            return URL.valueOf(providerUrl, registryParams, methods);
+        }
+
     }
 
     private URL getSubscribedOverrideUrl(URL registedProviderUrl) {
@@ -363,8 +392,7 @@ public class RegistryProtocol implements Protocol {
         URL subscribeUrl = new URL(Constants.CONSUMER_PROTOCOL, parameters.remove(Constants.REGISTER_IP_KEY), 0, type.getName(), parameters);
         if (!Constants.ANY_VALUE.equals(url.getServiceInterface())
                 && url.getParameter(Constants.REGISTER_KEY, true)) {
-            registry.register(subscribeUrl.addParameters(Constants.CATEGORY_KEY, Constants.CONSUMERS_CATEGORY,
-                    Constants.CHECK_KEY, String.valueOf(false)));
+            registry.register(getRegistedConsumerUrl(subscribeUrl, directory.getUrl()));
         }
         directory.subscribe(subscribeUrl.addParameter(Constants.CATEGORY_KEY,
                 Constants.PROVIDERS_CATEGORY
@@ -376,6 +404,21 @@ public class RegistryProtocol implements Protocol {
         return invoker;
     }
 
+    private URL getRegistedConsumerUrl(final URL consumerUrl, URL registryUrl) {
+        if(!registryUrl.getParameter(Constants.SIMPLE_KEY,false)){
+            return consumerUrl.addParameters(Constants.CATEGORY_KEY, Constants.CONSUMERS_CATEGORY,
+                    Constants.CHECK_KEY, String.valueOf(false));
+        }else{
+            String[] addionalParameterKeys = registryUrl.getParameter(ADD_PARAM_KEYS_KEY, new String[0]);
+            String[] registryParams = {APPLICATION_KEY, CODEC_KEY, EXCHANGER_KEY, SERIALIZATION_KEY, CLUSTER_KEY, CONNECTIONS_KEY, DEPRECATED_KEY,
+                    GROUP_KEY, LOADBALANCE_KEY, MOCK_KEY, PATH_KEY, TIMEOUT_KEY, TOKEN_KEY, VERSION_KEY, WARMUP_KEY, WEIGHT_KEY, TIMESTAMP_KEY};
+            ArrayUtils.addAll(registryParams, addionalParameterKeys);
+            String[] methods = consumerUrl.getParameter(METHODS_KEY, (String[]) null);
+            return URL.valueOf(consumerUrl, registryParams, methods).addParameters(Constants.CATEGORY_KEY, Constants.CONSUMERS_CATEGORY,
+                    Constants.CHECK_KEY, String.valueOf(false));
+        }
+    }
+
     @Override
     public void destroy() {
         List<Exporter<?>> exporters = new ArrayList<Exporter<?>>(bounds.values());
diff --git a/dubbo-servicedata/dubbo-servicedata-api/pom.xml b/dubbo-servicedata/dubbo-servicedata-api/pom.xml
new file mode 100644
index 0000000..af5d30b
--- /dev/null
+++ b/dubbo-servicedata/dubbo-servicedata-api/pom.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>dubbo-servicedata</artifactId>
+        <groupId>org.apache.dubbo</groupId>
+        <version>2.7.0-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>dubbo-servicedata-api</artifactId>
+    <packaging>jar</packaging>
+
+    <properties>
+        <skip_maven_deploy>false</skip_maven_deploy>
+    </properties>
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.dubbo</groupId>
+            <artifactId>dubbo-cluster</artifactId>
+            <version>${project.parent.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.dubbo</groupId>
+            <artifactId>dubbo-common</artifactId>
+            <version>${project.parent.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.dubbo</groupId>
+            <artifactId>dubbo-container-api</artifactId>
+            <version>${project.parent.version}</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.mortbay.jetty</groupId>
+                    <artifactId>jetty</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+    </dependencies>
+</project>
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/RouterFactory.java b/dubbo-servicedata/dubbo-servicedata-api/src/main/java/org/apache/dubbo/servicedata/ServiceStore.java
similarity index 50%
copy from dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/RouterFactory.java
copy to dubbo-servicedata/dubbo-servicedata-api/src/main/java/org/apache/dubbo/servicedata/ServiceStore.java
index 4d35c78..cfad3fc 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/RouterFactory.java
+++ b/dubbo-servicedata/dubbo-servicedata-api/src/main/java/org/apache/dubbo/servicedata/ServiceStore.java
@@ -1,52 +1,40 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.dubbo.rpc.cluster;
-
-import org.apache.dubbo.common.URL;
-import org.apache.dubbo.common.extension.Adaptive;
-import org.apache.dubbo.common.extension.SPI;
-import org.apache.dubbo.config.dynamic.DynamicConfiguration;
-
-/**
- * RouterFactory. (SPI, Singleton, ThreadSafe)
- * <p>
- * <a href="http://en.wikipedia.org/wiki/Routing">Routing</a>
- *
- * @see org.apache.dubbo.rpc.cluster.Cluster#join(Directory)
- * @see org.apache.dubbo.rpc.cluster.Directory#list(org.apache.dubbo.rpc.Invocation)
- */
-@SPI
-public interface RouterFactory {
-
-    /**
-     * Create router.
-     *
-     * @param url
-     * @return router
-     */
-    @Adaptive("protocol")
-    Router getRouter(URL url);
-
-    /**
-     * @param dynamicConfiguration
-     * @param url                  reserved for future usage.
-     * @return
-     */
-    default Router getRouter(DynamicConfiguration dynamicConfiguration, URL url) {
-        return null;
-    }
-}
\ No newline at end of file
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.servicedata;
+
+
+import org.apache.dubbo.common.URL;
+
+/**
+ */
+public interface ServiceStore {
+
+    /**
+     *
+     * @param url  e.g: dubbo://10.20.153.10/org.apache.dubbo.foo.BarService?version=1.0.0&application=kylin or
+     *             consumer://10.20.153.10/org.apache.dubbo.foo.BarService?version=1.0.0&application=kylin
+     */
+    void put(URL url);
+
+    /**
+     *
+     * @param url eg: dubbo://10.20.153.10/org.apache.dubbo.foo.BarService?version=1.0.0&application=cvictory&category=provider  or
+     *            eg: consumer://10.20.153.10/org.apache.dubbo.foo.BarService?version=1.0.0&application=cvictory&category=consumer
+     * @return
+     */
+    URL peek(URL url);
+}
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/RouterFactory.java b/dubbo-servicedata/dubbo-servicedata-api/src/main/java/org/apache/dubbo/servicedata/ServiceStoreFactory.java
similarity index 53%
copy from dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/RouterFactory.java
copy to dubbo-servicedata/dubbo-servicedata-api/src/main/java/org/apache/dubbo/servicedata/ServiceStoreFactory.java
index 4d35c78..f5d351f 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/RouterFactory.java
+++ b/dubbo-servicedata/dubbo-servicedata-api/src/main/java/org/apache/dubbo/servicedata/ServiceStoreFactory.java
@@ -1,52 +1,30 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.dubbo.rpc.cluster;
-
-import org.apache.dubbo.common.URL;
-import org.apache.dubbo.common.extension.Adaptive;
-import org.apache.dubbo.common.extension.SPI;
-import org.apache.dubbo.config.dynamic.DynamicConfiguration;
-
-/**
- * RouterFactory. (SPI, Singleton, ThreadSafe)
- * <p>
- * <a href="http://en.wikipedia.org/wiki/Routing">Routing</a>
- *
- * @see org.apache.dubbo.rpc.cluster.Cluster#join(Directory)
- * @see org.apache.dubbo.rpc.cluster.Directory#list(org.apache.dubbo.rpc.Invocation)
- */
-@SPI
-public interface RouterFactory {
-
-    /**
-     * Create router.
-     *
-     * @param url
-     * @return router
-     */
-    @Adaptive("protocol")
-    Router getRouter(URL url);
-
-    /**
-     * @param dynamicConfiguration
-     * @param url                  reserved for future usage.
-     * @return
-     */
-    default Router getRouter(DynamicConfiguration dynamicConfiguration, URL url) {
-        return null;
-    }
-}
\ No newline at end of file
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.servicedata;
+
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.extension.Adaptive;
+import org.apache.dubbo.common.extension.SPI;
+
+/**
+ */
+@SPI("dubbo")
+public interface ServiceStoreFactory {
+
+    @Adaptive({"protocol"})
+    ServiceStore getServiceStore(URL url);
+}
diff --git a/dubbo-servicedata/dubbo-servicedata-api/src/main/java/org/apache/dubbo/servicedata/integration/ServiceStoreService.java b/dubbo-servicedata/dubbo-servicedata-api/src/main/java/org/apache/dubbo/servicedata/integration/ServiceStoreService.java
new file mode 100644
index 0000000..8fad3a8
--- /dev/null
+++ b/dubbo-servicedata/dubbo-servicedata-api/src/main/java/org/apache/dubbo/servicedata/integration/ServiceStoreService.java
@@ -0,0 +1,81 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.servicedata.integration;
+
+import org.apache.dubbo.common.Constants;
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.extension.ExtensionLoader;
+import org.apache.dubbo.rpc.RpcException;
+import org.apache.dubbo.servicedata.ServiceStore;
+import org.apache.dubbo.servicedata.ServiceStoreFactory;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.function.Supplier;
+
+/**
+ */
+public class ServiceStoreService {
+
+    private ServiceStoreFactory serviceStoreFactory = ExtensionLoader.getExtensionLoader(ServiceStoreFactory.class).getAdaptiveExtension();
+    private static final Set<URL> providerURLs = new HashSet<URL>();
+    private static final Set<URL> consumerURLs = new HashSet<URL>();
+    private ServiceStore serviceStore;
+
+    private URL serviceStoreUrl;
+
+    private ServiceStoreService(URL serviceStoreURL) {
+        if (Constants.SERVICE_STORE_KEY.equals(serviceStoreURL.getProtocol())) {
+            String protocol = serviceStoreURL.getParameter(Constants.SERVICE_STORE_KEY, Constants.DEFAULT_DIRECTORY);
+            serviceStoreURL = serviceStoreURL.setProtocol(protocol).removeParameter(Constants.SERVICE_STORE_KEY);
+        }
+        this.serviceStoreUrl = serviceStoreURL;
+        serviceStore = serviceStoreFactory.getServiceStore(this.serviceStoreUrl);
+    }
+
+    private static ServiceStoreService serviceStoreService;
+    private static Object lock = new Object();
+
+    public static ServiceStoreService instance(Supplier<URL> loadServiceStoreUrl) {
+        if (serviceStoreService == null) {
+            synchronized (lock) {
+                if (serviceStoreService == null) {
+                    URL serviceStoreURL = loadServiceStoreUrl.get();
+                    if (serviceStoreURL == null) {
+                        return null;
+                    }
+                    serviceStoreService = new ServiceStoreService(serviceStoreURL);
+                }
+            }
+        }
+        return serviceStoreService;
+    }
+
+    public void publishProvider(URL providerUrl) throws RpcException {
+        providerURLs.add(providerUrl);
+        serviceStore.put(providerUrl);
+    }
+
+    public void publishConsumer(URL consumerURL) throws RpcException {
+        consumerURLs.add(consumerURL);
+        serviceStore.put(consumerURL);
+    }
+
+}
diff --git a/dubbo-servicedata/dubbo-servicedata-api/src/main/java/org/apache/dubbo/servicedata/support/AbstractServiceStore.java b/dubbo-servicedata/dubbo-servicedata-api/src/main/java/org/apache/dubbo/servicedata/support/AbstractServiceStore.java
new file mode 100644
index 0000000..5002b52
--- /dev/null
+++ b/dubbo-servicedata/dubbo-servicedata-api/src/main/java/org/apache/dubbo/servicedata/support/AbstractServiceStore.java
@@ -0,0 +1,279 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.servicedata.support;
+
+import org.apache.dubbo.common.Constants;
+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.ConcurrentHashSet;
+import org.apache.dubbo.common.utils.ConfigUtils;
+import org.apache.dubbo.common.utils.NamedThreadFactory;
+import org.apache.dubbo.servicedata.ServiceStore;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.RandomAccessFile;
+import java.nio.channels.FileChannel;
+import java.nio.channels.FileLock;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Properties;
+import java.util.Set;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicLong;
+
+/**
+ */
+public abstract class AbstractServiceStore implements ServiceStore {
+
+
+    // URL address separator, used in file cache, service provider URL separation
+    private static final char URL_SEPARATOR = ' ';
+    // URL address separated regular expression for parsing the service provider URL list in the file cache
+    private static final String URL_SPLIT = "\\s+";
+    // Log output
+    protected final Logger logger = LoggerFactory.getLogger(getClass());
+    // Local disk cache, where the special key value.registies records the list of registry centers, and the others are the list of notified service providers
+    final Properties properties = new Properties();
+    // File cache timing writing
+    private final ExecutorService servicestoreCacheExecutor = Executors.newFixedThreadPool(1, new NamedThreadFactory("DubboSaveServicestoreCache", true));
+
+    private final AtomicLong lastCacheChanged = new AtomicLong();
+    private final Set<URL> registered = new ConcurrentHashSet<URL>();
+    final Set<URL> failedServiceStore = new ConcurrentHashSet<URL>();
+    private URL serviceStoreURL;
+    // Local disk cache file
+    File file;
+    private AtomicBoolean INIT = new AtomicBoolean(false);
+    private final ScheduledExecutorService retryExecutor = Executors.newScheduledThreadPool(0, new NamedThreadFactory("DubboRegistryFailedRetryTimer", true));
+    private AtomicInteger retryTimes = new AtomicInteger(0);
+
+    public AbstractServiceStore(URL servicestoreURL) {
+        setUrl(servicestoreURL);
+        // Start file save timer
+        String filename = servicestoreURL.getParameter(Constants.FILE_KEY, System.getProperty("user.home") + "/.dubbo/dubbo-servicestore-" + servicestoreURL.getParameter(Constants.APPLICATION_KEY) + "-" + servicestoreURL.getAddress() + ".cache");
+        File file = null;
+        if (ConfigUtils.isNotEmpty(filename)) {
+            file = new File(filename);
+            if (!file.exists() && file.getParentFile() != null && !file.getParentFile().exists()) {
+                if (!file.getParentFile().mkdirs()) {
+                    throw new IllegalArgumentException("Invalid service store file " + file + ", cause: Failed to create directory " + file.getParentFile() + "!");
+                }
+            }
+            // if this file exist, firstly delete it.
+            if (!INIT.getAndSet(true) && file.exists()) {
+                file.delete();
+            }
+        }
+        this.file = file;
+        loadProperties();
+        retryExecutor.scheduleWithFixedDelay(new Runnable() {
+            @Override
+            public void run() {
+                // Check and connect to the registry
+                try {
+                    retry();
+                } catch (Throwable t) { // Defensive fault tolerance
+                    logger.error("Unexpected error occur at failed retry, cause: " + t.getMessage(), t);
+                }
+            }
+        }, 100, 100, TimeUnit.MILLISECONDS);
+    }
+
+    public URL getUrl() {
+        return serviceStoreURL;
+    }
+
+    protected void setUrl(URL url) {
+        if (url == null) {
+            throw new IllegalArgumentException("servicestore url == null");
+        }
+        this.serviceStoreURL = url;
+    }
+
+    public Set<URL> getRegistered() {
+        return registered;
+    }
+
+    private void doSaveProperties(long version) {
+        if (version < lastCacheChanged.get()) {
+            return;
+        }
+        if (file == null) {
+            return;
+        }
+        // Save
+        try {
+            File lockfile = new File(file.getAbsolutePath() + ".lock");
+            if (!lockfile.exists()) {
+                lockfile.createNewFile();
+            }
+            RandomAccessFile raf = new RandomAccessFile(lockfile, "rw");
+            try {
+                FileChannel channel = raf.getChannel();
+                try {
+                    FileLock lock = channel.tryLock();
+                    if (lock == null) {
+                        throw new IOException("Can not lock the servicestore cache file " + file.getAbsolutePath() + ", ignore and retry later, maybe multi java process use the file, please config: dubbo.servicestore.file=xxx.properties");
+                    }
+                    // Save
+                    try {
+                        if (!file.exists()) {
+                            file.createNewFile();
+                        }
+                        FileOutputStream outputFile = new FileOutputStream(file);
+                        try {
+                            properties.store(outputFile, "Dubbo Servicestore Cache");
+                        } finally {
+                            outputFile.close();
+                        }
+                    } finally {
+                        lock.release();
+                    }
+                } finally {
+                    channel.close();
+                }
+            } finally {
+                raf.close();
+            }
+        } catch (Throwable e) {
+            if (version < lastCacheChanged.get()) {
+                return;
+            } else {
+                servicestoreCacheExecutor.execute(new SaveProperties(lastCacheChanged.incrementAndGet()));
+            }
+            logger.warn("Failed to save service store file, cause: " + e.getMessage(), e);
+        }
+    }
+
+    void loadProperties() {
+        if (file != null && file.exists()) {
+            InputStream in = null;
+            try {
+                in = new FileInputStream(file);
+                properties.load(in);
+                if (logger.isInfoEnabled()) {
+                    logger.info("Load service store file " + file + ", data: " + properties);
+                }
+            } catch (Throwable e) {
+                logger.warn("Failed to load service store file " + file, e);
+            } finally {
+                if (in != null) {
+                    try {
+                        in.close();
+                    } catch (IOException e) {
+                        logger.warn(e.getMessage(), e);
+                    }
+                }
+            }
+        }
+    }
+
+    private void saveProperties(URL url, boolean add) {
+        if (file == null) {
+            return;
+        }
+
+        try {
+            if (add) {
+                properties.setProperty(url.getServiceKey(), url.toFullString());
+            } else {
+                properties.remove(url.getServiceKey());
+            }
+            long version = lastCacheChanged.incrementAndGet();
+            servicestoreCacheExecutor.execute(new SaveProperties(version));
+        } catch (Throwable t) {
+            logger.warn(t.getMessage(), t);
+        }
+    }
+
+    @Override
+    public String toString() {
+        return getUrl().toString();
+    }
+
+    private class SaveProperties implements Runnable {
+        private long version;
+
+        private SaveProperties(long version) {
+            this.version = version;
+        }
+
+        @Override
+        public void run() {
+            doSaveProperties(version);
+        }
+    }
+
+    public void put(URL url) {
+        try {
+            // remove the individul param
+            url = url.removeParameters(Constants.PID_KEY, Constants.TIMESTAMP_KEY);
+            if (logger.isInfoEnabled()) {
+                logger.info("Servicestore Put: " + url);
+            }
+            failedServiceStore.remove(url);
+            doPutService(url);
+            saveProperties(url, true);
+        } catch (Exception e) {
+            // retry again. If failed again, throw exception.
+            failedServiceStore.add(url);
+            logger.error("Failed to put servicestore " + url + " in  " + getUrl().toFullString() + ", cause: " + e.getMessage(), e);
+        }
+    }
+
+
+    public URL peek(URL url) {
+        try {
+            if (logger.isInfoEnabled()) {
+                logger.info("Servicestore Peek: " + url);
+            }
+            return doPeekService(url);
+        } catch (Exception e) {
+            logger.error("Failed to peek servicestore " + url + " in  " + getUrl().toFullString() + ", cause: " + e.getMessage(), e);
+        }
+        return null;
+    }
+
+    public void retry() {
+        if (retryTimes.incrementAndGet() > 120000 && failedServiceStore.isEmpty()) {
+            retryExecutor.shutdown();
+        }
+        if (failedServiceStore.isEmpty()) {
+            return;
+        }
+        for (URL url : new HashSet<URL>(failedServiceStore)) {
+            this.put(url);
+        }
+    }
+
+
+    protected abstract void doPutService(URL url);
+
+    protected abstract URL doPeekService(URL url);
+
+}
diff --git a/dubbo-servicedata/dubbo-servicedata-api/src/main/java/org/apache/dubbo/servicedata/support/AbstractServiceStoreFactory.java b/dubbo-servicedata/dubbo-servicedata-api/src/main/java/org/apache/dubbo/servicedata/support/AbstractServiceStoreFactory.java
new file mode 100644
index 0000000..96fe7e9
--- /dev/null
+++ b/dubbo-servicedata/dubbo-servicedata-api/src/main/java/org/apache/dubbo/servicedata/support/AbstractServiceStoreFactory.java
@@ -0,0 +1,80 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.servicedata.support;
+
+import org.apache.dubbo.common.Constants;
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.logger.Logger;
+import org.apache.dubbo.common.logger.LoggerFactory;
+import org.apache.dubbo.servicedata.ServiceStore;
+import org.apache.dubbo.servicedata.ServiceStoreFactory;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.locks.ReentrantLock;
+
+/**
+ */
+public abstract class AbstractServiceStoreFactory implements ServiceStoreFactory {
+
+    // Log output
+    private static final Logger LOGGER = LoggerFactory.getLogger(AbstractServiceStoreFactory.class);
+
+    // The lock for the acquisition process of the registry
+    private static final ReentrantLock LOCK = new ReentrantLock();
+
+    // Registry Collection Map<RegistryAddress, Registry>
+    private static final Map<String, ServiceStore> SERVICE_STORE_MAP = new ConcurrentHashMap<String, ServiceStore>();
+
+    /**
+     * Get all registries
+     *
+     * @return all registries
+     */
+    public static Collection<ServiceStore> getServiceStores() {
+        return Collections.unmodifiableCollection(SERVICE_STORE_MAP.values());
+    }
+
+    @Override
+    public ServiceStore getServiceStore(URL url) {
+        url = url.setPath(ServiceStore.class.getName())
+                .addParameter(Constants.INTERFACE_KEY, ServiceStore.class.getName())
+                .removeParameters(Constants.EXPORT_KEY, Constants.REFER_KEY);
+        String key = url.toServiceString();
+        // Lock the registry access process to ensure a single instance of the registry
+        LOCK.lock();
+        try {
+            ServiceStore serviceStore = SERVICE_STORE_MAP.get(key);
+            if (serviceStore != null) {
+                return serviceStore;
+            }
+            serviceStore = createServiceStore(url);
+            if (serviceStore == null) {
+                throw new IllegalStateException("Can not create servicestore " + url);
+            }
+            SERVICE_STORE_MAP.put(key, serviceStore);
+            return serviceStore;
+        } finally {
+            // Release the lock
+            LOCK.unlock();
+        }
+    }
+
+    protected abstract ServiceStore createServiceStore(URL url);
+}
diff --git a/dubbo-servicedata/dubbo-servicedata-api/src/test/java/org/apache/dubbo/servicedata/integration/ServiceStoreServiceTest.java b/dubbo-servicedata/dubbo-servicedata-api/src/test/java/org/apache/dubbo/servicedata/integration/ServiceStoreServiceTest.java
new file mode 100644
index 0000000..75aa87c
--- /dev/null
+++ b/dubbo-servicedata/dubbo-servicedata-api/src/test/java/org/apache/dubbo/servicedata/integration/ServiceStoreServiceTest.java
@@ -0,0 +1,7 @@
+package org.apache.dubbo.servicedata.integration;
+
+/**
+ * @author cvictory ON 2018/9/14
+ */
+public class ServiceStoreServiceTest {
+}
diff --git a/dubbo-servicedata/dubbo-servicedata-api/src/test/java/org/apache/dubbo/servicedata/support/AbstractServiceStoreFactoryTest.java b/dubbo-servicedata/dubbo-servicedata-api/src/test/java/org/apache/dubbo/servicedata/support/AbstractServiceStoreFactoryTest.java
new file mode 100644
index 0000000..94cf1bf
--- /dev/null
+++ b/dubbo-servicedata/dubbo-servicedata-api/src/test/java/org/apache/dubbo/servicedata/support/AbstractServiceStoreFactoryTest.java
@@ -0,0 +1,72 @@
+package org.apache.dubbo.servicedata.support;
+
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.utils.NetUtils;
+import org.apache.dubbo.servicedata.ServiceStore;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * @author cvictory ON 2018/9/14
+ */
+public class AbstractServiceStoreFactoryTest {
+
+    private AbstractServiceStoreFactory serviceStoreFactory = new AbstractServiceStoreFactory() {
+        @Override
+        protected ServiceStore createServiceStore(URL url) {
+            return new ServiceStore() {
+
+                Map<String, String> store = new ConcurrentHashMap<>();
+
+                @Override
+                public void put(URL url) {
+                    store.put(url.getServiceKey(), url.toParameterString());
+                }
+
+                @Override
+                public URL peek(URL url) {
+                    String queryV = store.get(url.getServiceKey());
+                    return url.clearParameters().addParameterString(queryV);
+                }
+            };
+        }
+    };
+
+    @Test
+    public void testGetOneServiceStore() {
+        URL url = URL.valueOf("zookeeper://" + NetUtils.getLocalAddress().getHostName() + ":4444/org.apache.dubbo.TestService?version=1.0.0&application=vic");
+        ServiceStore serviceStore1 = serviceStoreFactory.getServiceStore(url);
+        ServiceStore serviceStore2 = serviceStoreFactory.getServiceStore(url);
+        Assert.assertEquals(serviceStore1, serviceStore2);
+    }
+
+    @Test
+    public void testGetOneServiceStoreForIpFormat() {
+        URL url1 = URL.valueOf("zookeeper://" + NetUtils.getLocalAddress().getHostName() + ":4444/org.apache.dubbo.TestService?version=1.0.0&application=vic");
+        URL url2 = URL.valueOf("zookeeper://" + NetUtils.getLocalAddress().getHostAddress() + ":4444/org.apache.dubbo.TestService?version=1.0.0&application=vic");
+        ServiceStore serviceStore1 = serviceStoreFactory.getServiceStore(url1);
+        ServiceStore serviceStore2 = serviceStoreFactory.getServiceStore(url2);
+        Assert.assertEquals(serviceStore1, serviceStore2);
+    }
+
+    @Test
+    public void testGetForDiffService() {
+        URL url1 = URL.valueOf("zookeeper://" + NetUtils.getLocalAddress().getHostName() + ":4444/org.apache.dubbo.TestService1?version=1.0.0&application=vic");
+        URL url2 = URL.valueOf("zookeeper://" + NetUtils.getLocalAddress().getHostName() + ":4444/org.apache.dubbo.TestService2?version=1.0.0&application=vic");
+        ServiceStore serviceStore1 = serviceStoreFactory.getServiceStore(url1);
+        ServiceStore serviceStore2 = serviceStoreFactory.getServiceStore(url2);
+        Assert.assertEquals(serviceStore1, serviceStore2);
+    }
+
+    @Test
+    public void testGetForDiffGroup() {
+        URL url1 = URL.valueOf("zookeeper://" + NetUtils.getLocalAddress().getHostName() + ":4444/org.apache.dubbo.TestService?version=1.0.0&application=vic&group=aaa");
+        URL url2 = URL.valueOf("zookeeper://" + NetUtils.getLocalAddress().getHostName() + ":4444/org.apache.dubbo.TestService?version=1.0.0&application=vic&group=bbb");
+        ServiceStore serviceStore1 = serviceStoreFactory.getServiceStore(url1);
+        ServiceStore serviceStore2 = serviceStoreFactory.getServiceStore(url2);
+        Assert.assertNotEquals(serviceStore1, serviceStore2);
+    }
+}
diff --git a/dubbo-servicedata/dubbo-servicedata-api/src/test/java/org/apache/dubbo/servicedata/support/AbstractServiceStoreTest.java b/dubbo-servicedata/dubbo-servicedata-api/src/test/java/org/apache/dubbo/servicedata/support/AbstractServiceStoreTest.java
new file mode 100644
index 0000000..2134296
--- /dev/null
+++ b/dubbo-servicedata/dubbo-servicedata-api/src/test/java/org/apache/dubbo/servicedata/support/AbstractServiceStoreTest.java
@@ -0,0 +1,110 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.servicedata.support;
+
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.utils.NetUtils;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ *
+ */
+public class AbstractServiceStoreTest {
+
+    private NewServiceStore abstractServiceStore;
+    private NewServiceStore singleServiceStore;
+
+    @Before
+    public void before() {
+        URL url = URL.valueOf("zookeeper://" + NetUtils.getLocalAddress().getHostName() + ":4444/org.apache.dubbo.TestService?version=1.0.0&application=vic");
+        abstractServiceStore = new NewServiceStore(url);
+        URL singleUrl = URL.valueOf("redis://" + NetUtils.getLocalAddress().getHostName() + ":4444/org.apache.dubbo.TestService?version=1.0.0&application=singleTest");
+        singleServiceStore = new NewServiceStore(singleUrl);
+    }
+
+    @Test
+    public void testPutUsual() {
+        URL url = URL.valueOf("dubbo://" + NetUtils.getLocalAddress().getHostName() + ":4444/org.apache.dubbo.TestService?version=1.0.0&application=vic");
+        abstractServiceStore.put(url);
+        Assert.assertNotNull(abstractServiceStore.store.get(url.getServiceKey()));
+    }
+
+    @Test
+    public void testPutNoServiceKeyUrl() {
+        URL urlTmp = URL.valueOf("rmi://wrongHost:90?application=vic");
+        abstractServiceStore.put(urlTmp);
+        Assert.assertNull(urlTmp.getServiceKey());
+        // key is null, will add failed list.
+        Assert.assertFalse(abstractServiceStore.failedServiceStore.isEmpty());
+    }
+
+    @Test
+    public void testPutNotFullServiceKeyUrl() {
+        URL urlTmp = URL.valueOf("rmi://wrongHost:90/org.dubbo.TestService");
+        abstractServiceStore.put(urlTmp);
+        Assert.assertNotNull(abstractServiceStore.store.get(urlTmp.getServiceKey()));
+    }
+
+    @Test
+    public void testFileExistAfterPut() throws InterruptedException {
+        Assert.assertFalse(singleServiceStore.file.exists());
+        URL url = URL.valueOf("dubbo://" + NetUtils.getLocalAddress().getHostName() + ":4444/org.apache.dubbo.TestService?version=1.0.0&application=vic");
+        singleServiceStore.put(url);
+        Thread.sleep(2000);
+        Assert.assertTrue(singleServiceStore.file.exists());
+        Assert.assertTrue(singleServiceStore.properties.containsKey(url.getServiceKey()));
+    }
+
+    @Test
+    public void testPeek() {
+        URL url = URL.valueOf("dubbo://" + NetUtils.getLocalAddress().getHostName() + ":4444/org.apache.dubbo.TestService?version=1.0.0&application=vic");
+        abstractServiceStore.put(url);
+        URL result = abstractServiceStore.peek(url);
+        Assert.assertEquals(url, result);
+    }
+
+
+    private static class NewServiceStore extends AbstractServiceStore {
+
+        Map<String, String> store = new ConcurrentHashMap<>();
+
+        public NewServiceStore(URL servicestoreURL) {
+            super(servicestoreURL);
+        }
+
+        @Override
+        protected void doPutService(URL url) {
+            store.put(url.getServiceKey(), url.toParameterString());
+        }
+
+        @Override
+        protected URL doPeekService(URL url) {
+            String queryV = store.get(url.getServiceKey());
+            URL urlTmp = url.clearParameters().addParameterString(queryV);
+            return urlTmp;
+        }
+    }
+
+
+}
diff --git a/dubbo-servicedata/dubbo-servicedata-redis/pom.xml b/dubbo-servicedata/dubbo-servicedata-redis/pom.xml
new file mode 100644
index 0000000..2896c33
--- /dev/null
+++ b/dubbo-servicedata/dubbo-servicedata-redis/pom.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>dubbo-servicedata</artifactId>
+        <groupId>org.apache.dubbo</groupId>
+        <version>2.7.0-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>dubbo-servicedata-redis</artifactId>
+    <properties>
+        <jedis.version>2.9.0</jedis.version>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.dubbo</groupId>
+            <artifactId>dubbo-servicedata-api</artifactId>
+            <version>${project.parent.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>redis.clients</groupId>
+            <artifactId>jedis</artifactId>
+            <version>${jedis.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.curator</groupId>
+            <artifactId>curator-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+</project>
diff --git a/dubbo-servicedata/dubbo-servicedata-redis/src/main/java/org/apache/dubbo/servicedata/redis/RedisServiceStore.java b/dubbo-servicedata/dubbo-servicedata-redis/src/main/java/org/apache/dubbo/servicedata/redis/RedisServiceStore.java
new file mode 100644
index 0000000..52a2861
--- /dev/null
+++ b/dubbo-servicedata/dubbo-servicedata-redis/src/main/java/org/apache/dubbo/servicedata/redis/RedisServiceStore.java
@@ -0,0 +1,73 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.servicedata.redis;
+
+import org.apache.dubbo.common.Constants;
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.logger.Logger;
+import org.apache.dubbo.common.logger.LoggerFactory;
+import org.apache.dubbo.rpc.RpcException;
+import org.apache.dubbo.servicedata.support.AbstractServiceStore;
+import redis.clients.jedis.Jedis;
+import redis.clients.jedis.JedisPool;
+import redis.clients.jedis.JedisPoolConfig;
+
+/**
+ * ZookeeperRegistry
+ */
+public class RedisServiceStore extends AbstractServiceStore {
+
+    private final static Logger logger = LoggerFactory.getLogger(RedisServiceStore.class);
+
+    private final static String TAG = "sd.";
+
+    private final JedisPool pool;
+
+    public RedisServiceStore(URL url) {
+        super(url);
+        pool = new JedisPool(new JedisPoolConfig(), url.getHost(), url.getPort());
+    }
+
+    @Override
+    protected void doPutService(URL url) {
+        try (Jedis jedis = pool.getResource()) {
+            jedis.set(TAG + getProtocol(url) + "." + url.getServiceKey(), url.toParameterString());
+        } catch (Throwable e) {
+            logger.error("Failed to put " + url + " to redis " + url + ", cause: " + e.getMessage(), e);
+            throw new RpcException("Failed to put " + url + " to redis " + getUrl() + ", cause: " + e.getMessage(), e);
+        }
+    }
+
+    @Override
+    protected URL doPeekService(URL url) {
+        try (Jedis jedis = pool.getResource()) {
+            String value = jedis.get(TAG + getProtocol(url) + "." + url.getServiceKey());
+            return url.addParameterString(value);
+        } catch (Throwable e) {
+            logger.error("Failed to peek " + url + " to redis " + url + ", cause: " + e.getMessage(), e);
+            throw new RpcException("Failed to put " + url + " to redis " + getUrl() + ", cause: " + e.getMessage(), e);
+        }
+    }
+
+    private String getProtocol(URL url) {
+        String protocol = url.getParameter(Constants.SIDE_KEY);
+        protocol = protocol == null ? url.getProtocol() : protocol;
+        return protocol;
+    }
+
+
+}
diff --git a/dubbo-servicedata/dubbo-servicedata-redis/src/main/java/org/apache/dubbo/servicedata/redis/RedisServiceStoreFactory.java b/dubbo-servicedata/dubbo-servicedata-redis/src/main/java/org/apache/dubbo/servicedata/redis/RedisServiceStoreFactory.java
new file mode 100644
index 0000000..eccf433
--- /dev/null
+++ b/dubbo-servicedata/dubbo-servicedata-redis/src/main/java/org/apache/dubbo/servicedata/redis/RedisServiceStoreFactory.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.servicedata.redis;
+
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.remoting.zookeeper.ZookeeperTransporter;
+import org.apache.dubbo.servicedata.ServiceStore;
+import org.apache.dubbo.servicedata.support.AbstractServiceStoreFactory;
+
+/**
+ * ZookeeperRegistryFactory.
+ *
+ */
+public class RedisServiceStoreFactory extends AbstractServiceStoreFactory {
+
+
+    @Override
+    public ServiceStore createServiceStore(URL url) {
+        return new RedisServiceStore(url);
+    }
+
+}
diff --git a/dubbo-servicedata/dubbo-servicedata-redis/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.servicedata.ServiceStoreFactory b/dubbo-servicedata/dubbo-servicedata-redis/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.servicedata.ServiceStoreFactory
new file mode 100644
index 0000000..b5caef2
--- /dev/null
+++ b/dubbo-servicedata/dubbo-servicedata-redis/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.servicedata.ServiceStoreFactory
@@ -0,0 +1 @@
+redis=org.apache.dubbo.servicedata.redis.RedisServiceStoreFactory
diff --git a/dubbo-servicedata/dubbo-servicedata-zookeeper/pom.xml b/dubbo-servicedata/dubbo-servicedata-zookeeper/pom.xml
new file mode 100644
index 0000000..a9f9805
--- /dev/null
+++ b/dubbo-servicedata/dubbo-servicedata-zookeeper/pom.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>dubbo-servicedata</artifactId>
+        <groupId>org.apache.dubbo</groupId>
+        <version>2.7.0-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>dubbo-servicedata-zookeeper</artifactId>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.dubbo</groupId>
+            <artifactId>dubbo-servicedata-api</artifactId>
+            <version>${project.parent.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.dubbo</groupId>
+            <artifactId>dubbo-remoting-zookeeper</artifactId>
+            <version>${project.parent.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.curator</groupId>
+            <artifactId>curator-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+</project>
diff --git a/dubbo-servicedata/dubbo-servicedata-zookeeper/src/main/java/org/apache/dubbo/servicedata/zookeeper/ZookeeperServiceStore.java b/dubbo-servicedata/dubbo-servicedata-zookeeper/src/main/java/org/apache/dubbo/servicedata/zookeeper/ZookeeperServiceStore.java
new file mode 100644
index 0000000..486c8c0
--- /dev/null
+++ b/dubbo-servicedata/dubbo-servicedata-zookeeper/src/main/java/org/apache/dubbo/servicedata/zookeeper/ZookeeperServiceStore.java
@@ -0,0 +1,132 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.servicedata.zookeeper;
+
+import org.apache.dubbo.common.Constants;
+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.UrlUtils;
+import org.apache.dubbo.remoting.zookeeper.ZookeeperClient;
+import org.apache.dubbo.remoting.zookeeper.ZookeeperTransporter;
+import org.apache.dubbo.rpc.RpcException;
+import org.apache.dubbo.servicedata.support.AbstractServiceStore;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * ZookeeperRegistry
+ */
+public class ZookeeperServiceStore extends AbstractServiceStore {
+
+    private final static Logger logger = LoggerFactory.getLogger(ZookeeperServiceStore.class);
+
+    private final static String DEFAULT_ROOT = "dubbo";
+
+    private final static String TAG = "servicestore";
+
+    private final String root;
+
+    private final ZookeeperClient zkClient;
+
+    public ZookeeperServiceStore(URL url, ZookeeperTransporter zookeeperTransporter) {
+        super(url);
+        if (url.isAnyHost()) {
+            throw new IllegalStateException("registry address == null");
+        }
+        String group = url.getParameter(Constants.GROUP_KEY, DEFAULT_ROOT);
+        if (!group.startsWith(Constants.PATH_SEPARATOR)) {
+            group = Constants.PATH_SEPARATOR + group;
+        }
+        this.root = group;
+        zkClient = zookeeperTransporter.connect(url);
+    }
+
+    @Override
+    protected void doPutService(URL url) {
+        try {
+            deletePath(url);
+            url = url.removeParameters(Constants.BIND_IP_KEY, Constants.BIND_PORT_KEY, Constants.TIMESTAMP_KEY);
+            zkClient.create(toUrlPathWithParameter(url), false);
+        } catch (Throwable e) {
+            logger.error("Failed to put " + url + " to zookeeper " + url + ", cause: " + e.getMessage(), e);
+            throw new RpcException("Failed to put " + url + " to zookeeper " + getUrl() + ", cause: " + e.getMessage(), e);
+        }
+    }
+
+    private void deletePath(URL url) {
+        String path = toCategoryPath(url);
+        List<String> urlStrs = zkClient.getChildren(path);
+        if (CollectionUtils.isEmpty(urlStrs)) {
+            return;
+        }
+        for (String urlStr : urlStrs) {
+            zkClient.delete(path + Constants.PATH_SEPARATOR + urlStr);
+        }
+    }
+
+    @Override
+    protected URL doPeekService(final URL url) {
+        try {
+            List<String> urlStrs = zkClient.getChildren((toCategoryPath(url)));
+            List<URL> urls = new ArrayList<URL>();
+            if (urlStrs != null && !urlStrs.isEmpty()) {
+                for (String urlStr : urlStrs) {
+                    urlStr = URL.decode(urlStr);
+                    if (urlStr.contains("://")) {
+                        urls.add(URL.valueOf(urlStr));
+                    }
+                }
+            }
+            return urls.isEmpty() ? null : urls.get(0);
+        } catch (Throwable e) {
+            logger.error("Failed to peek " + url + " to zookeeper " + url + ", cause: " + e.getMessage(), e);
+            throw new RpcException("Failed to peek " + url + " to zookeeper " + getUrl() + ", cause: " + e.getMessage(), e);
+        }
+    }
+
+    private String toRootDir() {
+        if (root.equals(Constants.PATH_SEPARATOR)) {
+            return root;
+        }
+        return root + Constants.PATH_SEPARATOR;
+    }
+
+    private String toRootPath() {
+        return root;
+    }
+
+    private String toServicePath(URL url) {
+        String name = url.getServiceInterface();
+        if (Constants.ANY_VALUE.equals(name)) {
+            return toRootPath();
+        }
+        return toRootDir() + URL.encode(name);
+    }
+
+    private String toCategoryPath(URL url) {
+        String protocol = url.getParameter(Constants.SIDE_KEY);
+        return toServicePath(url) + Constants.PATH_SEPARATOR + TAG + Constants.PATH_SEPARATOR + (protocol != null ? protocol : url.getProtocol());
+    }
+
+    private String toUrlPathWithParameter(URL url) {
+        return toCategoryPath(url) + Constants.PATH_SEPARATOR + URL.encode(url.toParameterString());
+    }
+
+}
diff --git a/dubbo-servicedata/dubbo-servicedata-zookeeper/src/main/java/org/apache/dubbo/servicedata/zookeeper/ZookeeperServiceStoreFactory.java b/dubbo-servicedata/dubbo-servicedata-zookeeper/src/main/java/org/apache/dubbo/servicedata/zookeeper/ZookeeperServiceStoreFactory.java
new file mode 100644
index 0000000..4f0deb8
--- /dev/null
+++ b/dubbo-servicedata/dubbo-servicedata-zookeeper/src/main/java/org/apache/dubbo/servicedata/zookeeper/ZookeeperServiceStoreFactory.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.servicedata.zookeeper;
+
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.remoting.zookeeper.ZookeeperTransporter;
+import org.apache.dubbo.servicedata.ServiceStore;
+import org.apache.dubbo.servicedata.support.AbstractServiceStoreFactory;
+
+/**
+ * ZookeeperRegistryFactory.
+ *
+ */
+public class ZookeeperServiceStoreFactory extends AbstractServiceStoreFactory {
+
+    private ZookeeperTransporter zookeeperTransporter;
+
+    public void setZookeeperTransporter(ZookeeperTransporter zookeeperTransporter) {
+        this.zookeeperTransporter = zookeeperTransporter;
+    }
+
+    @Override
+    public ServiceStore createServiceStore(URL url) {
+        return new ZookeeperServiceStore(url, zookeeperTransporter);
+    }
+
+}
diff --git a/dubbo-servicedata/dubbo-servicedata-zookeeper/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.servicedata.ServiceStoreFactory b/dubbo-servicedata/dubbo-servicedata-zookeeper/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.servicedata.ServiceStoreFactory
new file mode 100644
index 0000000..ed32c44
--- /dev/null
+++ b/dubbo-servicedata/dubbo-servicedata-zookeeper/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.servicedata.ServiceStoreFactory
@@ -0,0 +1 @@
+zookeeper=org.apache.dubbo.servicedata.zookeeper.ZookeeperServiceStoreFactory
diff --git a/dubbo-servicedata/pom.xml b/dubbo-servicedata/pom.xml
new file mode 100644
index 0000000..25964ff
--- /dev/null
+++ b/dubbo-servicedata/pom.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>dubbo-parent</artifactId>
+        <groupId>org.apache.dubbo</groupId>
+        <version>2.7.0-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>dubbo-servicedata</artifactId>
+    <packaging>pom</packaging>
+    <modules>
+        <module>dubbo-servicedata-api</module>
+        <module>dubbo-servicedata-zookeeper</module>
+        <module>dubbo-servicedata-redis</module>
+    </modules>
+
+
+</project>
diff --git a/pom.xml b/pom.xml
index 5bd895d..d326e85 100644
--- a/pom.xml
+++ b/pom.xml
@@ -145,6 +145,7 @@
         <module>dubbo-bom</module>
         <module>dubbo-all</module>
         <module>dubbo-distribution</module>
+        <module>dubbo-servicedata</module>
     </modules>
 
     <dependencyManagement>