You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@dubbo.apache.org by GitBox <gi...@apache.org> on 2018/09/14 09:31:20 UTC

[GitHub] chickenlj closed pull request #2468: Simplify registry data and add a new service data store seperated from registry #2030

chickenlj closed pull request #2468: Simplify registry data and add a new service data store seperated from registry #2030
URL: https://github.com/apache/incubator-dubbo/pull/2468
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git a/dubbo-bom/pom.xml b/dubbo-bom/pom.xml
index a1d8277897..ad64f3fd4e 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 4d35c78489..bf32cad6dd 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 @@
     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 0e82118a6b..49b0bd1acb 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 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 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";
@@ -434,6 +438,17 @@
 
     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
      */
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 a83ca91e22..312b691876 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 static URL valueOf(String url) {
         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 static URL valueOf(String url) {
         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 da0a2877f9..7a2229c868 100644
--- a/dubbo-config/dubbo-config-api/pom.xml
+++ b/dubbo-config/dubbo-config-api/pom.xml
@@ -34,6 +34,11 @@
             <artifactId>dubbo-registry-api</artifactId>
             <version>${project.parent.version}</version>
         </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>
@@ -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 70ab62e449..0e4f93e7e0 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.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 @@
     // 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 @@ protected URL loadMonitor(URL registryURL) {
         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 String getScope() {
     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 1a82c6af67..43e3ca0da2 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.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 @@ private T createProxy(Map<String, String> map) {
         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 a9a8145e29..5678a2e968 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 @@
 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 @@
     // 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 void setDefault(Boolean isDefault) {
         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 e9d5e6b567..200cb34218 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.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 @@ private void doExportUrlsFor1Protocol(ProtocolConfig protocolConfig, List<URL> r
                     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 0000000000..1a31c90db7
--- /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 e6a2a1fddb..2eb44759f4 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.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 void afterPropertiesSet() throws Exception {
                 }
             }
         }
+        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 5b41b247c8..ddf1608b3e 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.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 void afterPropertiesSet() throws Exception {
                 }
             }
         }
+        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 9f16c39cfa..57701c624b 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.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 void init() {
         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 59245913fd..39ad36b288 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 ecec23acc0..69526662ae 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 91468c8075..cc25019c65 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 68494f514e..86472c523e 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 b9f46b1783..8045fad284 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 96ebae1523..7604b32c5b 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 c6494e4671..88a5000ada 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 dc86b558d7..7c112e283d 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.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 void register(URL registryUrl, URL registedProviderUrl) {
 
         // 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 @@ private URL getRegistryUrl(Invoker<?> originInvoker) {
      * @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 @@ private Cluster getMergeableCluster() {
         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 @@ private Cluster getMergeableCluster() {
         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 0000000000..af5d30b150
--- /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-servicedata/dubbo-servicedata-api/src/main/java/org/apache/dubbo/servicedata/ServiceStore.java b/dubbo-servicedata/dubbo-servicedata-api/src/main/java/org/apache/dubbo/servicedata/ServiceStore.java
new file mode 100644
index 0000000000..cfad3fc8fc
--- /dev/null
+++ b/dubbo-servicedata/dubbo-servicedata-api/src/main/java/org/apache/dubbo/servicedata/ServiceStore.java
@@ -0,0 +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.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-servicedata/dubbo-servicedata-api/src/main/java/org/apache/dubbo/servicedata/ServiceStoreFactory.java b/dubbo-servicedata/dubbo-servicedata-api/src/main/java/org/apache/dubbo/servicedata/ServiceStoreFactory.java
new file mode 100644
index 0000000000..f5d351fc75
--- /dev/null
+++ b/dubbo-servicedata/dubbo-servicedata-api/src/main/java/org/apache/dubbo/servicedata/ServiceStoreFactory.java
@@ -0,0 +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.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 0000000000..8fad3a835e
--- /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 0000000000..5002b52f87
--- /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 0000000000..96fe7e92d8
--- /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 0000000000..75aa87cd83
--- /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 0000000000..94cf1bfca9
--- /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 0000000000..2134296f40
--- /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 0000000000..2896c330b3
--- /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 0000000000..52a2861550
--- /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 0000000000..eccf4333dc
--- /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 0000000000..b5caef2bdf
--- /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 0000000000..a9f9805da5
--- /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 0000000000..486c8c0b27
--- /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 0000000000..4f0deb8534
--- /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 0000000000..ed32c44b7c
--- /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 0000000000..25964ff3f0
--- /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 5bd895dc60..d326e85153 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>


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@dubbo.apache.org
For additional commands, e-mail: notifications-help@dubbo.apache.org