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

[incubator-dubbo] branch dev-metadata updated (1ab215e -> 701cf26)

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

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


    from 1ab215e  add dubbo specification version into registry for ops
     new c880720  if the registry type is zookeeper, use the address as default configcenter address.
     new 51146f7  Split the Environment into two parts: Environment in Common and ConfigurationUtils in ConfigCenter
     new 912498a  empty rule protection: "" should not be treated as delete.
     new 701cf26  Merge branch 'dev-metadata' of https://github.com/apache/incubator-dubbo into dev-metadata

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


Summary of changes:
 .../condition/config/ConfigConditionRouter.java    |   8 +-
 .../src/main/java/org/apache/dubbo/common/URL.java |   6 ++
 .../apache/dubbo/common/config}/Environment.java   |  64 +-----------
 .../org/apache/dubbo/common/utils/ConfigUtils.java |  25 -----
 .../apache/dubbo/common/utils/ConfigUtilsTest.java |  27 -----
 .../org/apache/dubbo/config/AbstractConfig.java    |   2 +-
 .../dubbo/config/AbstractInterfaceConfig.java      |  22 +++-
 .../apache/dubbo/config/ConfigCenterConfig.java    |  36 ++++++-
 .../org/apache/dubbo/config/RegistryConfig.java    |  20 ++++
 .../org/apache/dubbo/config/ServiceConfig.java     |   2 +-
 .../dubbo/config/spring/ConfigCenterBean.java      |  27 ++++-
 .../dubbo/configcenter/ConfigurationUtils.java     | 112 +++++++++++++++++++++
 .../dubbo/configcenter}/ConfigurationWrapper.java  |   2 +-
 .../dubbo/configcenter/DynamicConfiguration.java   |   2 +-
 .../support/apollo/ApolloDynamicConfiguration.java |   6 +-
 .../archaius/ArchaiusDynamicConfiguration.java     |   9 +-
 dubbo-container/dubbo-container-log4j/pom.xml      |   5 +
 .../dubbo/container/log4j/Log4jContainer.java      |   9 +-
 .../META-INF/spring/dubbo-demo-consumer.xml        |   6 +-
 .../META-INF/spring/dubbo-demo-provider.xml        |   6 +-
 .../registry/integration/RegistryDirectory.java    |   2 +-
 .../registry/integration/RegistryProtocol.java     |   6 +-
 .../java/org/apache/dubbo/registry/ZKTools.java    |  32 +++---
 dubbo-rpc/dubbo-rpc-dubbo/pom.xml                  |   5 +
 .../dubbo/rpc/protocol/dubbo/DubboInvoker.java     |   4 +-
 .../dubbo/rpc/protocol/dubbo/DubboProtocol.java    |   8 +-
 .../protocol/dubbo/DubboInvokerAvilableTest.java   |   4 +-
 .../dubbo/rpc/protocol/thrift/ThriftProtocol.java  |   4 +-
 28 files changed, 289 insertions(+), 172 deletions(-)
 rename {dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/context => dubbo-common/src/main/java/org/apache/dubbo/common/config}/Environment.java (65%)
 create mode 100644 dubbo-configcenter/dubbo-configcenter-api/src/main/java/org/apache/dubbo/configcenter/ConfigurationUtils.java
 rename {dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/context => dubbo-configcenter/dubbo-configcenter-api/src/main/java/org/apache/dubbo/configcenter}/ConfigurationWrapper.java (97%)


[incubator-dubbo] 03/04: empty rule protection: "" should not be treated as delete.

Posted by li...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 912498ab0830f9c7ae232fce58ed392489080ecc
Author: ken.lj <ke...@gmail.com>
AuthorDate: Tue Nov 20 14:35:17 2018 +0800

    empty rule protection: "" should not be treated as delete.
---
 .../configcenter/support/apollo/ApolloDynamicConfiguration.java  | 6 +++++-
 .../support/archaius/ArchaiusDynamicConfiguration.java           | 9 ++++++++-
 2 files changed, 13 insertions(+), 2 deletions(-)

diff --git a/dubbo-configcenter/dubbo-configcenter-apollo/src/main/java/org/apache/dubbo/configcenter/support/apollo/ApolloDynamicConfiguration.java b/dubbo-configcenter/dubbo-configcenter-apollo/src/main/java/org/apache/dubbo/configcenter/support/apollo/ApolloDynamicConfiguration.java
index ad16d50..f5f2cc0 100644
--- a/dubbo-configcenter/dubbo-configcenter-apollo/src/main/java/org/apache/dubbo/configcenter/support/apollo/ApolloDynamicConfiguration.java
+++ b/dubbo-configcenter/dubbo-configcenter-apollo/src/main/java/org/apache/dubbo/configcenter/support/apollo/ApolloDynamicConfiguration.java
@@ -133,7 +133,7 @@ public class ApolloDynamicConfiguration extends AbstractDynamicConfiguration<Con
     }
 
     public ConfigChangeType getChangeType(ConfigChange change) {
-        if (change.getChangeType() == PropertyChangeType.DELETED || StringUtils.isEmpty(change.getNewValue())) {
+        if (change.getChangeType() == PropertyChangeType.DELETED) {
             return ConfigChangeType.DELETED;
         }
         return ConfigChangeType.MODIFIED;
@@ -156,6 +156,10 @@ public class ApolloDynamicConfiguration extends AbstractDynamicConfiguration<Con
         public void onChange(ConfigChangeEvent changeEvent) {
             for (String key : changeEvent.changedKeys()) {
                 ConfigChange change = changeEvent.getChange(key);
+                if (StringUtils.isEmpty(change.getNewValue())) {
+                    logger.warn("We received an empty rule for " + key + ", the current working rule is " + change.getOldValue() + ", the empty rule will not take effect.");
+                    return;
+                }
                 // TODO Maybe we no longer need to identify the type of change. Because there's no scenario that a callback will subscribe for both configurators and routers
                 if (change.getPropertyName().endsWith(Constants.CONFIGURATORS_SUFFIX)) {
                     listener.process(new org.apache.dubbo.configcenter.ConfigChangeEvent(key, change.getNewValue(), ConfigType.CONFIGURATORS, getChangeType(change)));
diff --git a/dubbo-configcenter/dubbo-configcenter-zookeeper/src/main/java/org/apache/dubbo/configcenter/support/archaius/ArchaiusDynamicConfiguration.java b/dubbo-configcenter/dubbo-configcenter-zookeeper/src/main/java/org/apache/dubbo/configcenter/support/archaius/ArchaiusDynamicConfiguration.java
index 883339f..014958d 100644
--- a/dubbo-configcenter/dubbo-configcenter-zookeeper/src/main/java/org/apache/dubbo/configcenter/support/archaius/ArchaiusDynamicConfiguration.java
+++ b/dubbo-configcenter/dubbo-configcenter-zookeeper/src/main/java/org/apache/dubbo/configcenter/support/archaius/ArchaiusDynamicConfiguration.java
@@ -22,6 +22,8 @@ import com.netflix.config.DynamicStringProperty;
 import com.netflix.config.DynamicWatchedConfiguration;
 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.StringUtils;
 import org.apache.dubbo.configcenter.AbstractDynamicConfiguration;
 import org.apache.dubbo.configcenter.ConfigChangeEvent;
@@ -34,6 +36,7 @@ import org.apache.dubbo.configcenter.support.archaius.sources.ZooKeeperConfigura
  * Archaius supports various sources and it's extensiable: JDBC, ZK, Properties, ..., so should we make it extensiable?
  */
 public class ArchaiusDynamicConfiguration extends AbstractDynamicConfiguration<Runnable> {
+    private static final Logger logger = LoggerFactory.getLogger(ArchaiusDynamicConfiguration.class);
 
     public ArchaiusDynamicConfiguration() {
     }
@@ -142,10 +145,14 @@ public class ArchaiusDynamicConfiguration extends AbstractDynamicConfiguration<R
                     .getStringProperty(key, null);
             String newValue = prop.get();
             ConfigChangeEvent event = new ConfigChangeEvent(key, newValue, type);
-            if (StringUtils.isEmpty(newValue)) {
+            if (newValue == null) {
                 event.setChangeType(ConfigChangeType.DELETED);
                 listener.process(event);
             } else {
+                if (newValue.equals("")) {
+                    logger.warn("We received an empty rule for " + key + ", the current working rule is unknown, the empty rule will not take effect.");
+                    return;
+                }
                 event.setChangeType(ConfigChangeType.MODIFIED);
                 listener.process(event);
             }


[incubator-dubbo] 01/04: if the registry type is zookeeper, use the address as default configcenter address.

Posted by li...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit c880720724d27458475b638f9f70a0ebee5dd0b4
Author: ken.lj <ke...@gmail.com>
AuthorDate: Mon Nov 19 19:50:42 2018 +0800

    if the registry type is zookeeper, use the address as default configcenter address.
---
 .../dubbo/config/AbstractInterfaceConfig.java      | 18 ++++++++++++
 .../apache/dubbo/config/ConfigCenterConfig.java    | 34 +++++++++++++++++++++-
 .../org/apache/dubbo/config/RegistryConfig.java    | 16 ++++++++++
 .../dubbo/config/spring/ConfigCenterBean.java      | 21 +++++++++++++
 4 files changed, 88 insertions(+), 1 deletion(-)

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 b572f5e..34fc01f 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
@@ -20,6 +20,7 @@ import org.apache.dubbo.common.Constants;
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.Version;
 import org.apache.dubbo.common.extension.ExtensionLoader;
+import org.apache.dubbo.common.utils.CollectionUtils;
 import org.apache.dubbo.common.utils.ConfigUtils;
 import org.apache.dubbo.common.utils.NetUtils;
 import org.apache.dubbo.common.utils.ReflectUtils;
@@ -27,6 +28,7 @@ import org.apache.dubbo.common.utils.StringUtils;
 import org.apache.dubbo.common.utils.UrlUtils;
 import org.apache.dubbo.config.context.Environment;
 import org.apache.dubbo.config.support.Parameter;
+import org.apache.dubbo.configcenter.DynamicConfiguration;
 import org.apache.dubbo.metadata.integration.MetadataReportService;
 import org.apache.dubbo.monitor.MonitorFactory;
 import org.apache.dubbo.monitor.MonitorService;
@@ -41,6 +43,7 @@ import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 import static org.apache.dubbo.common.Constants.APPLICATION_KEY;
 
@@ -150,6 +153,17 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig {
                 throw new IllegalStateException("No registry config found or it's not a valid config!");
             }
         }
+
+        // For compatibility purpose, use registry as the default config center if there's no one specified explicitly.
+        RegistryConfig registry = registries.get(0);
+        if (registry.isZookeeperProtocol()) {
+            Set<Object> loadedConfigurations = ExtensionLoader.getExtensionLoader(DynamicConfiguration.class).getLoadedExtensionInstances();
+            if (CollectionUtils.isEmpty(loadedConfigurations)) {
+                ConfigCenterConfig configCenterConfig = new ConfigCenterConfig();
+                configCenterConfig.setProtocol(registry.getProtocol());
+                configCenterConfig.setAddress(registry.getAddress());
+            }
+        }
     }
 
     @SuppressWarnings("deprecation")
@@ -209,6 +223,10 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig {
         }
     }
 
+    protected void checkConfigCenter() {
+
+    }
+
     protected List<URL> loadRegistries(boolean provider) {
         // check && override if necessary
         checkRegistry();
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ConfigCenterConfig.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ConfigCenterConfig.java
index f753126..3d7c212 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ConfigCenterConfig.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ConfigCenterConfig.java
@@ -54,6 +54,7 @@ public class ConfigCenterConfig extends AbstractConfig {
     private String localconfigfile;
 
     private ApplicationConfig application;
+    private RegistryConfig registry;
 
     // customized parameters
     private Map<String, String> parameters;
@@ -93,6 +94,11 @@ public class ConfigCenterConfig extends AbstractConfig {
         // give jvm properties the chance to override local configs, e.g., -Ddubbo.configcenter.config.priority
 
         refresh();
+        // try to use registryConfig as the default configcenter, only applies to zookeeper.
+        if (!isValid() && registry != null && registry.isZookeeperProtocol()) {
+            setAddress(registry.getAddress());
+            setProtocol(registry.getProtocol());
+        }
 //        checkConfigCenter();
 
         URL url = toConfigUrl();
@@ -114,6 +120,10 @@ public class ConfigCenterConfig extends AbstractConfig {
             address = Constants.ANYHOST_VALUE;
         }
         map.put(Constants.PATH_KEY, ConfigCenterConfig.class.getSimpleName());
+        // use 'zookeeper' as the default configcenter.
+        if (StringUtils.isEmpty(map.get(Constants.PROTOCOL_KEY))) {
+            map.put(Constants.PROTOCOL_KEY, "zookeeper");
+        }
         return UrlUtils.parseURL(address, map);
     }
 
@@ -142,7 +152,6 @@ public class ConfigCenterConfig extends AbstractConfig {
         return map;
     }
 
-
     public String getProtocol() {
         return protocol;
     }
@@ -283,10 +292,33 @@ public class ConfigCenterConfig extends AbstractConfig {
         this.application = application;
     }
 
+    public RegistryConfig getRegistry() {
+        return registry;
+    }
+
+    public void setRegistry(RegistryConfig registry) {
+        this.registry = registry;
+    }
+
     private void checkConfigCenter() {
         if ((StringUtils.isEmpty(env) && StringUtils.isEmpty(address))
                 || (StringUtils.isEmpty(protocol) && (StringUtils.isEmpty(address) || !address.contains("://")))) {
             throw new IllegalStateException("You must specify the right parameter for configcenter.");
         }
     }
+
+    @Override
+    public boolean isValid() {
+        if (StringUtils.isEmpty(address) && StringUtils.isEmpty(env)) {
+            return false;
+        }
+        if (StringUtils.isNotEmpty(address)) {
+            if (!address.contains("://") && StringUtils.isEmpty(protocol)) {
+                return false;
+            }
+        } else if (StringUtils.isNotEmpty(env) && StringUtils.isEmpty(protocol)) {
+            return false;
+        }
+        return true;
+    }
 }
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 8089de2..4e4c354 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
@@ -335,6 +335,22 @@ public class RegistryConfig extends AbstractConfig {
         this.isDefault = isDefault;
     }
 
+    public boolean isZookeeperProtocol() {
+        boolean isZookeeper = StringUtils.isNotEmpty(this.getProtocol()) && this.getProtocol().equals("zookeeper");
+        if (!isZookeeper) {
+            String address = this.getAddress();
+            int index = address.indexOf("://");
+            if (StringUtils.isNotEmpty(address) && index >= 0) {
+                address = address.substring(0, index);
+            }
+            if (address.equals("zookeeper")) {
+                isZookeeper = true;
+            }
+        }
+        return isZookeeper;
+    }
+
+    @Override
     public boolean isValid() {
         // empty protocol will default to 'dubbo'
         return !StringUtils.isEmpty(address);
diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/ConfigCenterBean.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/ConfigCenterBean.java
index 0ff972a..1a20434 100644
--- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/ConfigCenterBean.java
+++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/ConfigCenterBean.java
@@ -18,6 +18,7 @@ package org.apache.dubbo.config.spring;
 
 import org.apache.dubbo.config.ApplicationConfig;
 import org.apache.dubbo.config.ConfigCenterConfig;
+import org.apache.dubbo.config.RegistryConfig;
 import org.apache.dubbo.config.spring.extension.SpringExtensionFactory;
 import org.apache.dubbo.config.support.Parameter;
 import org.springframework.beans.factory.BeanFactoryUtils;
@@ -30,7 +31,9 @@ import org.springframework.core.env.ConfigurableEnvironment;
 import org.springframework.core.env.Environment;
 import org.springframework.core.env.PropertySource;
 
+import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 
 /**
@@ -71,6 +74,24 @@ public class ConfigCenterBean extends ConfigCenterConfig implements Initializing
             }
         }
 
+        if ((getRegistry() == null)) {
+            List<RegistryConfig> registryConfigs = new ArrayList<>();
+            if (getApplication() == null || getApplication().getRegistries() == null || getApplication().getRegistries().isEmpty()) {
+                registryConfigs = getApplication().getRegistries();
+            } else {
+                Map<String, RegistryConfig> registryConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, RegistryConfig.class, false, false);
+                if (registryConfigMap != null && registryConfigMap.size() > 0) {
+                    registryConfigs.addAll(registryConfigMap.values());
+                }
+            }
+            for (RegistryConfig config : registryConfigs) {
+                if (config.isDefault() == null || config.isDefault() && config.isZookeeperProtocol()) {
+                    setRegistry(config);
+                    break;
+                }
+            }
+        }
+
         if (!auto) {
             this.init();
         }


[incubator-dubbo] 04/04: Merge branch 'dev-metadata' of https://github.com/apache/incubator-dubbo into dev-metadata

Posted by li...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 701cf26d918f58095377d4682b0c5d13dce82895
Merge: 912498a 1ab215e
Author: ken.lj <ke...@gmail.com>
AuthorDate: Tue Nov 20 14:36:21 2018 +0800

    Merge branch 'dev-metadata' of https://github.com/apache/incubator-dubbo into dev-metadata

 .../main/java/org/apache/dubbo/common/Constants.java |  6 ++++--
 .../org/apache/dubbo/config/ReferenceConfig.java     |  1 +
 .../java/org/apache/dubbo/config/ServiceConfig.java  |  1 +
 .../metadata/integration/MetadataReportService.java  |  2 +-
 .../apache/dubbo/metadata/store/MetadataReport.java  |  4 +++-
 .../metadata/support/AbstractMetadataReport.java     | 19 +++++++++++--------
 .../support/AbstractMetadataReportFactoryTest.java   |  4 ++--
 .../metadata/support/AbstractMetadataReportTest.java | 20 ++++++++++++++------
 .../store/redis/RedisMetadataReportTest.java         |  8 ++++++--
 .../store/zookeeper/ZookeeperMetadataReportTest.java |  9 ++++++---
 10 files changed, 49 insertions(+), 25 deletions(-)



[incubator-dubbo] 02/04: Split the Environment into two parts: Environment in Common and ConfigurationUtils in ConfigCenter

Posted by li...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 51146f726d38bc72b07547ddbf6de662976f2813
Author: ken.lj <ke...@gmail.com>
AuthorDate: Tue Nov 20 14:33:35 2018 +0800

    Split the Environment into two parts: Environment in Common and ConfigurationUtils in ConfigCenter
---
 .../condition/config/ConfigConditionRouter.java    |   8 +-
 .../src/main/java/org/apache/dubbo/common/URL.java |   6 ++
 .../apache/dubbo/common/config}/Environment.java   |  64 +-----------
 .../org/apache/dubbo/common/utils/ConfigUtils.java |  25 -----
 .../apache/dubbo/common/utils/ConfigUtilsTest.java |  27 -----
 .../org/apache/dubbo/config/AbstractConfig.java    |   2 +-
 .../dubbo/config/AbstractInterfaceConfig.java      |   6 +-
 .../apache/dubbo/config/ConfigCenterConfig.java    |   2 +-
 .../org/apache/dubbo/config/RegistryConfig.java    |   4 +
 .../org/apache/dubbo/config/ServiceConfig.java     |   2 +-
 .../dubbo/config/spring/ConfigCenterBean.java      |   8 +-
 .../dubbo/configcenter/ConfigurationUtils.java     | 112 +++++++++++++++++++++
 .../dubbo/configcenter}/ConfigurationWrapper.java  |   2 +-
 .../dubbo/configcenter/DynamicConfiguration.java   |   2 +-
 dubbo-container/dubbo-container-log4j/pom.xml      |   5 +
 .../dubbo/container/log4j/Log4jContainer.java      |   9 +-
 .../META-INF/spring/dubbo-demo-consumer.xml        |   6 +-
 .../META-INF/spring/dubbo-demo-provider.xml        |   6 +-
 .../registry/integration/RegistryDirectory.java    |   2 +-
 .../registry/integration/RegistryProtocol.java     |   6 +-
 .../java/org/apache/dubbo/registry/ZKTools.java    |  32 +++---
 dubbo-rpc/dubbo-rpc-dubbo/pom.xml                  |   5 +
 .../dubbo/rpc/protocol/dubbo/DubboInvoker.java     |   4 +-
 .../dubbo/rpc/protocol/dubbo/DubboProtocol.java    |   8 +-
 .../protocol/dubbo/DubboInvokerAvilableTest.java   |   4 +-
 .../dubbo/rpc/protocol/thrift/ThriftProtocol.java  |   4 +-
 26 files changed, 190 insertions(+), 171 deletions(-)

diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/config/ConfigConditionRouter.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/config/ConfigConditionRouter.java
index 3d994c7..f18254a 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/config/ConfigConditionRouter.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/config/ConfigConditionRouter.java
@@ -58,11 +58,9 @@ public class ConfigConditionRouter extends AbstractRouter implements Configurati
         this.configuration = configuration;
         this.force = false;
         this.url = url;
-        String app = this.url.getParameter(Constants.APPLICATION_KEY);
-        String serviceKey = this.url.getServiceKey();
         try {
-            String rawRule = this.configuration.getConfig(serviceKey + Constants.ROUTERS_SUFFIX, this);
-            String appRawRule = this.configuration.getConfig(app + Constants.ROUTERS_SUFFIX, this);
+            String rawRule = this.configuration.getConfig(url.getEncodedServiceKey() + Constants.ROUTERS_SUFFIX, this);
+            String appRawRule = this.configuration.getConfig(url.getParameter(Constants.APPLICATION_KEY) + Constants.ROUTERS_SUFFIX, this);
             if (!StringUtils.isEmpty(rawRule)) {
                 try {
                     routerRule = ConditionRuleParser.parse(rawRule);
@@ -81,7 +79,7 @@ public class ConfigConditionRouter extends AbstractRouter implements Configurati
             }
 
         } catch (Exception e) {
-            throw new IllegalStateException("Failed to init the condition router for service " + serviceKey + ", application " + app, e);
+            throw new IllegalStateException("Failed to init the condition router for service " + url.getServiceKey() + ", application " + url.getParameter(Constants.APPLICATION_KEY), e);
         }
     }
 
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 b0396bd..c94cb58 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
@@ -1285,6 +1285,12 @@ public /**final**/ class URL implements Serializable {
         return new InetSocketAddress(host, port);
     }
 
+    public String getEncodedServiceKey() {
+        String serviceKey = this.getServiceKey();
+        serviceKey = serviceKey.replaceFirst("/", "*");
+        return serviceKey;
+    }
+
     public String getServiceKey() {
         String inf = getServiceInterface();
         if (inf == null) {
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/context/Environment.java b/dubbo-common/src/main/java/org/apache/dubbo/common/config/Environment.java
similarity index 65%
rename from dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/context/Environment.java
rename to dubbo-common/src/main/java/org/apache/dubbo/common/config/Environment.java
index 870304e..0e77565 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/context/Environment.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/config/Environment.java
@@ -14,24 +14,13 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.config.context;
+package org.apache.dubbo.common.config;
 
 import org.apache.dubbo.common.Constants;
-import org.apache.dubbo.common.URL;
-import org.apache.dubbo.common.config.CompositeConfiguration;
-import org.apache.dubbo.common.config.EnvironmentConfiguration;
-import org.apache.dubbo.common.config.InmemoryConfiguration;
-import org.apache.dubbo.common.config.PropertiesConfiguration;
-import org.apache.dubbo.common.config.SystemConfiguration;
-import org.apache.dubbo.common.extension.ExtensionLoader;
-import org.apache.dubbo.common.utils.CollectionUtils;
 import org.apache.dubbo.common.utils.StringUtils;
-import org.apache.dubbo.config.ConfigCenterConfig;
-import org.apache.dubbo.configcenter.DynamicConfiguration;
 
 import java.util.HashMap;
 import java.util.Map;
-import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 
 /**
@@ -46,12 +35,8 @@ public class Environment {
     private volatile Map<String, InmemoryConfiguration> externalConfsHolder = new ConcurrentHashMap<>();
     private volatile Map<String, InmemoryConfiguration> appExternalConfsHolder = new ConcurrentHashMap<>();
     private volatile Map<String, CompositeConfiguration> startupCompositeConfsHolder = new ConcurrentHashMap<>();
-    private volatile Map<String, CompositeConfiguration> runtimeCompositeConfsHolder = new ConcurrentHashMap<>();
-
-    private volatile DynamicConfiguration dynamicConfiguration;
 
     private volatile boolean isConfigCenterFirst = true;
-    private volatile ConfigCenterConfig configCenter;
 
     private Map<String, String> externalConfigurationMap = new HashMap<>();
     private Map<String, String> appExternalConfigurationMap = new HashMap<>();
@@ -88,24 +73,12 @@ public class Environment {
         return environmentConfsHolder.computeIfAbsent(toKey(prefix, id), k -> new EnvironmentConfiguration(prefix, id));
     }
 
-    public void setConfigCenter(ConfigCenterConfig configCenter) {
-        this.configCenter = configCenter;
-    }
-
     public synchronized void setExternalConfiguration(Map<String, String> externalConfiguration) {
         this.externalConfigurationMap = externalConfiguration;
-        if (configCenter == null) {
-            configCenter = new ConfigCenterConfig();
-        }
-        configCenter.init();
     }
 
     public synchronized void setAppExternalConfiguration(Map<String, String> appExternalConfiguration) {
         this.appExternalConfigurationMap = appExternalConfiguration;
-        if (configCenter == null) {
-            configCenter = new ConfigCenterConfig();
-        }
-        configCenter.init();
     }
 
     public void updateExternalConfigurationMap(Map<String, String> externalMap) {
@@ -127,41 +100,6 @@ public class Environment {
         });
     }
 
-    /**
-     * FIXME This method will recreate Configuration for each RPC, how much latency affect will this action has on performance?
-     *
-     * @param url, the url metadata.
-     * @param method, the method name the RPC is trying to invoke.
-     * @return
-     */
-    public CompositeConfiguration getRuntimeCompositeConf(URL url, String method) {
-        CompositeConfiguration compositeConfiguration = new CompositeConfiguration();
-
-        String app = url.getParameter(Constants.APPLICATION_KEY);
-        String service = url.getServiceKey();
-        compositeConfiguration.addConfiguration(new ConfigurationWrapper(app, service, method, getDynamicConfiguration()));
-
-        compositeConfiguration.addConfiguration(url.toConfiguration());
-        compositeConfiguration.addConfiguration(this.getSystemConf(null, null));
-        compositeConfiguration.addConfiguration(this.getPropertiesConf(null, null));
-        return compositeConfiguration;
-    }
-
-    /**
-     * If user opens DynamicConfig, the extension instance must has been created during the initialization of ConfigCenterConfig with the right extension type user specified.
-     * If no DynamicConfig presents, NopDynamicConfiguration will be used.
-     *
-     * @return
-     */
-    public DynamicConfiguration getDynamicConfiguration() {
-        Set<Object> configurations = ExtensionLoader.getExtensionLoader(DynamicConfiguration.class).getLoadedExtensionInstances();
-        if (CollectionUtils.isEmpty(configurations)) {
-            return ExtensionLoader.getExtensionLoader(DynamicConfiguration.class).getDefaultExtension();
-        } else {
-            return (DynamicConfiguration) configurations.iterator().next();
-        }
-    }
-
     private static String toKey(String keypart1, String keypart2) {
         StringBuilder sb = new StringBuilder();
         if (StringUtils.isNotEmpty(keypart1)) {
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/ConfigUtils.java b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/ConfigUtils.java
index 436cf8f..fbab5ea 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/ConfigUtils.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/ConfigUtils.java
@@ -304,29 +304,4 @@ public class ConfigUtils {
         }
         return PID;
     }
-
-    @SuppressWarnings("deprecation")
-    public static int getServerShutdownTimeout() {
-        int timeout = Constants.DEFAULT_SERVER_SHUTDOWN_TIMEOUT;
-        String value = ConfigUtils.getProperty(Constants.SHUTDOWN_WAIT_KEY);
-        if (value != null && value.length() > 0) {
-            try {
-                timeout = Integer.parseInt(value);
-            } catch (Exception e) {
-                // ignore
-            }
-        } else {
-            value = ConfigUtils.getProperty(Constants.SHUTDOWN_WAIT_SECONDS_KEY);
-            if (value != null && value.length() > 0) {
-                try {
-                    timeout = Integer.parseInt(value) * 1000;
-                } catch (Exception e) {
-                    // ignore
-                }
-            }
-        }
-
-        return timeout;
-    }
-
 }
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/ConfigUtilsTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/utils/ConfigUtilsTest.java
index a540d64..97398a0 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/ConfigUtilsTest.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/utils/ConfigUtilsTest.java
@@ -256,31 +256,4 @@ public class ConfigUtilsTest {
     public void testGetPid() throws Exception {
         assertThat(ConfigUtils.getPid(), greaterThan(0));
     }
-
-    @Test
-    public void testGetServerShutdownTimeoutFromShutdownWait() throws Exception {
-        System.setProperty(Constants.SHUTDOWN_WAIT_KEY, "1234");
-        try {
-            assertThat(ConfigUtils.getServerShutdownTimeout(), equalTo(1234));
-        } finally {
-            System.clearProperty(Constants.SHUTDOWN_WAIT_KEY);
-        }
-    }
-
-    @Test
-    public void testGetServerShutdownTimeoutFromShutdownWaitSeconds() throws Exception {
-        System.setProperty(Constants.SHUTDOWN_WAIT_SECONDS_KEY, "1234");
-        try {
-            assertThat(ConfigUtils.getServerShutdownTimeout(), equalTo(1234 * 1000));
-        } finally {
-            System.clearProperty(Constants.SHUTDOWN_WAIT_SECONDS_KEY);
-        }
-    }
-
-    @Test
-    public void testGetServerShutdownTimeoutFromDefault() throws Exception {
-        System.clearProperty(Constants.SHUTDOWN_WAIT_KEY);
-        System.clearProperty(Constants.SHUTDOWN_WAIT_SECONDS_KEY);
-        assertThat(ConfigUtils.getServerShutdownTimeout(), equalTo(Constants.DEFAULT_SERVER_SHUTDOWN_TIMEOUT));
-    }
 }
\ No newline at end of file
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractConfig.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractConfig.java
index 0be4c41..f60b378 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractConfig.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractConfig.java
@@ -20,13 +20,13 @@ import org.apache.dubbo.common.Constants;
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.config.CompositeConfiguration;
 import org.apache.dubbo.common.config.Configuration;
+import org.apache.dubbo.common.config.Environment;
 import org.apache.dubbo.common.extension.ExtensionLoader;
 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.ReflectUtils;
 import org.apache.dubbo.common.utils.StringUtils;
-import org.apache.dubbo.config.context.Environment;
 import org.apache.dubbo.config.support.Parameter;
 import org.apache.dubbo.config.utils.ConfigConverter;
 import org.apache.dubbo.rpc.model.ConsumerMethodModel;
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 34fc01f..e8649f0 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
@@ -19,6 +19,7 @@ package org.apache.dubbo.config;
 import org.apache.dubbo.common.Constants;
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.Version;
+import org.apache.dubbo.common.config.Environment;
 import org.apache.dubbo.common.extension.ExtensionLoader;
 import org.apache.dubbo.common.utils.CollectionUtils;
 import org.apache.dubbo.common.utils.ConfigUtils;
@@ -26,7 +27,6 @@ import org.apache.dubbo.common.utils.NetUtils;
 import org.apache.dubbo.common.utils.ReflectUtils;
 import org.apache.dubbo.common.utils.StringUtils;
 import org.apache.dubbo.common.utils.UrlUtils;
-import org.apache.dubbo.config.context.Environment;
 import org.apache.dubbo.config.support.Parameter;
 import org.apache.dubbo.configcenter.DynamicConfiguration;
 import org.apache.dubbo.metadata.integration.MetadataReportService;
@@ -154,14 +154,16 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig {
             }
         }
 
-        // For compatibility purpose, use registry as the default config center if there's no one specified explicitly.
+        // For compatibility purpose, use registry as the default config center if the registry protocol is zookeeper and there's no config center specified explicitly.
         RegistryConfig registry = registries.get(0);
         if (registry.isZookeeperProtocol()) {
             Set<Object> loadedConfigurations = ExtensionLoader.getExtensionLoader(DynamicConfiguration.class).getLoadedExtensionInstances();
+            // we use the loading status of DynamicConfiguration to decide whether ConfigCenter has been initiated.
             if (CollectionUtils.isEmpty(loadedConfigurations)) {
                 ConfigCenterConfig configCenterConfig = new ConfigCenterConfig();
                 configCenterConfig.setProtocol(registry.getProtocol());
                 configCenterConfig.setAddress(registry.getAddress());
+                configCenterConfig.init();
             }
         }
     }
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ConfigCenterConfig.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ConfigCenterConfig.java
index 3d7c212..c957f1a 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ConfigCenterConfig.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ConfigCenterConfig.java
@@ -18,11 +18,11 @@ package org.apache.dubbo.config;
 
 import org.apache.dubbo.common.Constants;
 import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.config.Environment;
 import org.apache.dubbo.common.extension.ExtensionLoader;
 import org.apache.dubbo.common.utils.CollectionUtils;
 import org.apache.dubbo.common.utils.StringUtils;
 import org.apache.dubbo.common.utils.UrlUtils;
-import org.apache.dubbo.config.context.Environment;
 import org.apache.dubbo.config.support.Parameter;
 import org.apache.dubbo.configcenter.DynamicConfiguration;
 
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 4e4c354..5e8015c 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
@@ -335,7 +335,11 @@ public class RegistryConfig extends AbstractConfig {
         this.isDefault = isDefault;
     }
 
+    @Parameter(excluded = true)
     public boolean isZookeeperProtocol() {
+        if (!isValid()) {
+            return false;
+        }
         boolean isZookeeper = StringUtils.isNotEmpty(this.getProtocol()) && this.getProtocol().equals("zookeeper");
         if (!isZookeeper) {
             String address = this.getAddress();
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 0133b01..7c354ad 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
@@ -20,13 +20,13 @@ import org.apache.dubbo.common.Constants;
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.Version;
 import org.apache.dubbo.common.bytecode.Wrapper;
+import org.apache.dubbo.common.config.Environment;
 import org.apache.dubbo.common.extension.ExtensionLoader;
 import org.apache.dubbo.common.utils.ClassHelper;
 import org.apache.dubbo.common.utils.ConfigUtils;
 import org.apache.dubbo.common.utils.NamedThreadFactory;
 import org.apache.dubbo.common.utils.StringUtils;
 import org.apache.dubbo.config.annotation.Service;
-import org.apache.dubbo.config.context.Environment;
 import org.apache.dubbo.config.invoker.DelegateProviderMetaDataInvoker;
 import org.apache.dubbo.config.support.Parameter;
 import org.apache.dubbo.metadata.integration.MetadataReportService;
diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/ConfigCenterBean.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/ConfigCenterBean.java
index 1a20434..9ce2f46 100644
--- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/ConfigCenterBean.java
+++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/ConfigCenterBean.java
@@ -76,7 +76,7 @@ public class ConfigCenterBean extends ConfigCenterConfig implements Initializing
 
         if ((getRegistry() == null)) {
             List<RegistryConfig> registryConfigs = new ArrayList<>();
-            if (getApplication() == null || getApplication().getRegistries() == null || getApplication().getRegistries().isEmpty()) {
+            if (getApplication() != null && getApplication().getRegistries() != null && !getApplication().getRegistries().isEmpty()) {
                 registryConfigs = getApplication().getRegistries();
             } else {
                 Map<String, RegistryConfig> registryConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, RegistryConfig.class, false, false);
@@ -107,9 +107,9 @@ public class ConfigCenterBean extends ConfigCenterConfig implements Initializing
         if (auto) {
             Map<String, String> externalProperties = getConfigurations(getConfigfile(), environment);
             Map<String, String> appExternalProperties = getConfigurations("application." + getConfigfile(), environment);
-            org.apache.dubbo.config.context.Environment.getInstance().setConfigCenter(this);
-            org.apache.dubbo.config.context.Environment.getInstance().setExternalConfiguration(externalProperties);
-            org.apache.dubbo.config.context.Environment.getInstance().setAppExternalConfiguration(appExternalProperties);
+            org.apache.dubbo.common.config.Environment.getInstance().setExternalConfiguration(externalProperties);
+            org.apache.dubbo.common.config.Environment.getInstance().setAppExternalConfiguration(appExternalProperties);
+            this.init();
         }
     }
 
diff --git a/dubbo-configcenter/dubbo-configcenter-api/src/main/java/org/apache/dubbo/configcenter/ConfigurationUtils.java b/dubbo-configcenter/dubbo-configcenter-api/src/main/java/org/apache/dubbo/configcenter/ConfigurationUtils.java
new file mode 100644
index 0000000..cf57b67
--- /dev/null
+++ b/dubbo-configcenter/dubbo-configcenter-api/src/main/java/org/apache/dubbo/configcenter/ConfigurationUtils.java
@@ -0,0 +1,112 @@
+/*
+ * 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.configcenter;
+
+import org.apache.dubbo.common.Constants;
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.config.CompositeConfiguration;
+import org.apache.dubbo.common.config.Environment;
+import org.apache.dubbo.common.extension.ExtensionLoader;
+import org.apache.dubbo.common.utils.CollectionUtils;
+
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ *
+ */
+public class ConfigurationUtils {
+    private static final CompositeConfiguration compositeConfiguration;
+
+    static {
+        compositeConfiguration = new CompositeConfiguration();
+        compositeConfiguration.addConfiguration(getDynamicConfiguration());
+        compositeConfiguration.addConfiguration(Environment.getInstance().getAppExternalConfiguration(null, null));
+        compositeConfiguration.addConfiguration(Environment.getInstance().getExternalConfiguration(null, null));
+        compositeConfiguration.addConfiguration(Environment.getInstance().getSystemConf(null, null));
+        compositeConfiguration.addConfiguration(Environment.getInstance().getPropertiesConf(null, null));
+    }
+
+    private volatile Map<String, CompositeConfiguration> runtimeCompositeConfsHolder = new ConcurrentHashMap<>();
+
+    /**
+     * FIXME This method will recreate Configuration for each RPC, how much latency affect will this action has on performance?
+     *
+     * @param url,    the url metadata.
+     * @param method, the method name the RPC is trying to invoke.
+     * @return
+     */
+    public static CompositeConfiguration getRuntimeCompositeConf(URL url, String method) {
+        CompositeConfiguration compositeConfiguration = new CompositeConfiguration();
+
+        String app = url.getParameter(Constants.APPLICATION_KEY);
+        String service = url.getServiceKey();
+        compositeConfiguration.addConfiguration(new ConfigurationWrapper(app, service, method, getDynamicConfiguration()));
+
+        compositeConfiguration.addConfiguration(url.toConfiguration());
+
+        return compositeConfiguration;
+    }
+
+    /**
+     * If user opens DynamicConfig, the extension instance must has been created during the initialization of ConfigCenterConfig with the right extension type user specified.
+     * If no DynamicConfig presents, NopDynamicConfiguration will be used.
+     *
+     * @return
+     */
+    public static DynamicConfiguration getDynamicConfiguration() {
+        Set<Object> configurations = ExtensionLoader.getExtensionLoader(DynamicConfiguration.class).getLoadedExtensionInstances();
+        if (CollectionUtils.isEmpty(configurations)) {
+            return ExtensionLoader.getExtensionLoader(DynamicConfiguration.class).getDefaultExtension();
+        } else {
+            return (DynamicConfiguration) configurations.iterator().next();
+        }
+    }
+
+    @SuppressWarnings("deprecation")
+    public static int getServerShutdownTimeout() {
+        int timeout = Constants.DEFAULT_SERVER_SHUTDOWN_TIMEOUT;
+        String value = getProperty(Constants.SHUTDOWN_WAIT_KEY);
+        if (value != null && value.length() > 0) {
+            try {
+                timeout = Integer.parseInt(value);
+            } catch (Exception e) {
+                // ignore
+            }
+        } else {
+            value = getProperty(Constants.SHUTDOWN_WAIT_SECONDS_KEY);
+            if (value != null && value.length() > 0) {
+                try {
+                    timeout = Integer.parseInt(value) * 1000;
+                } catch (Exception e) {
+                    // ignore
+                }
+            }
+        }
+        return timeout;
+    }
+
+    public static String getProperty(String key) {
+        return compositeConfiguration.getString(key);
+    }
+
+    public static String getProperty(String key, String defaultValue) {
+        return compositeConfiguration.getString(key, defaultValue);
+    }
+
+}
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/context/ConfigurationWrapper.java b/dubbo-configcenter/dubbo-configcenter-api/src/main/java/org/apache/dubbo/configcenter/ConfigurationWrapper.java
similarity index 97%
rename from dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/context/ConfigurationWrapper.java
rename to dubbo-configcenter/dubbo-configcenter-api/src/main/java/org/apache/dubbo/configcenter/ConfigurationWrapper.java
index 2d758ae..9a22ddd 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/context/ConfigurationWrapper.java
+++ b/dubbo-configcenter/dubbo-configcenter-api/src/main/java/org/apache/dubbo/configcenter/ConfigurationWrapper.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.config.context;
+package org.apache.dubbo.configcenter;
 
 import org.apache.dubbo.common.config.AbstractConfiguration;
 import org.apache.dubbo.common.config.Configuration;
diff --git a/dubbo-configcenter/dubbo-configcenter-api/src/main/java/org/apache/dubbo/configcenter/DynamicConfiguration.java b/dubbo-configcenter/dubbo-configcenter-api/src/main/java/org/apache/dubbo/configcenter/DynamicConfiguration.java
index caf9fd9..7adcc47 100644
--- a/dubbo-configcenter/dubbo-configcenter-api/src/main/java/org/apache/dubbo/configcenter/DynamicConfiguration.java
+++ b/dubbo-configcenter/dubbo-configcenter-api/src/main/java/org/apache/dubbo/configcenter/DynamicConfiguration.java
@@ -23,7 +23,7 @@ import org.apache.dubbo.common.extension.SPI;
 /**
  *
  */
-@SPI("zookeeper")
+@SPI("nop")
 public interface DynamicConfiguration extends Configuration {
 
     void init();
diff --git a/dubbo-container/dubbo-container-log4j/pom.xml b/dubbo-container/dubbo-container-log4j/pom.xml
index 2197134..91814b3 100644
--- a/dubbo-container/dubbo-container-log4j/pom.xml
+++ b/dubbo-container/dubbo-container-log4j/pom.xml
@@ -34,5 +34,10 @@
             <artifactId>dubbo-container-api</artifactId>
             <version>${project.parent.version}</version>
         </dependency>
+        <dependency>
+            <groupId>org.apache.dubbo</groupId>
+            <artifactId>dubbo-configcenter-api</artifactId>
+            <version>${project.parent.version}</version>
+        </dependency>
     </dependencies>
 </project>
\ No newline at end of file
diff --git a/dubbo-container/dubbo-container-log4j/src/main/java/org/apache/dubbo/container/log4j/Log4jContainer.java b/dubbo-container/dubbo-container-log4j/src/main/java/org/apache/dubbo/container/log4j/Log4jContainer.java
index 3938e42..1d24236 100644
--- a/dubbo-container/dubbo-container-log4j/src/main/java/org/apache/dubbo/container/log4j/Log4jContainer.java
+++ b/dubbo-container/dubbo-container-log4j/src/main/java/org/apache/dubbo/container/log4j/Log4jContainer.java
@@ -16,9 +16,8 @@
  */
 package org.apache.dubbo.container.log4j;
 
-import org.apache.dubbo.common.utils.ConfigUtils;
+import org.apache.dubbo.configcenter.ConfigurationUtils;
 import org.apache.dubbo.container.Container;
-
 import org.apache.log4j.Appender;
 import org.apache.log4j.FileAppender;
 import org.apache.log4j.LogManager;
@@ -43,9 +42,9 @@ public class Log4jContainer implements Container {
     @Override
     @SuppressWarnings("unchecked")
     public void start() {
-        String file = ConfigUtils.getProperty(LOG4J_FILE);
+        String file = ConfigurationUtils.getProperty(LOG4J_FILE);
         if (file != null && file.length() > 0) {
-            String level = ConfigUtils.getProperty(LOG4J_LEVEL);
+            String level = ConfigurationUtils.getProperty(LOG4J_LEVEL);
             if (level == null || level.length() == 0) {
                 level = DEFAULT_LOG4J_LEVEL;
             }
@@ -59,7 +58,7 @@ public class Log4jContainer implements Container {
             properties.setProperty("log4j.appender.application.layout.ConversionPattern", "%d [%t] %-5p %C{6} (%F:%L) - %m%n");
             PropertyConfigurator.configure(properties);
         }
-        String subdirectory = ConfigUtils.getProperty(LOG4J_SUBDIRECTORY);
+        String subdirectory = ConfigurationUtils.getProperty(LOG4J_SUBDIRECTORY);
         if (subdirectory != null && subdirectory.length() > 0) {
             Enumeration<org.apache.log4j.Logger> ls = LogManager.getCurrentLoggers();
             while (ls.hasMoreElements()) {
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 60810c3..14b2718 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
@@ -25,10 +25,10 @@
 
     <!-- use multicast registry center to discover service -->
 
-    <!--<dubbo:registry group="dubboregistrygroup1" address="zookeeper://127.0.0.1:2181"/>-->
+    <dubbo:registry group="dubboregistrygroup1" address="zookeeper://127.0.0.1:2181"/>
 
-    <dubbo:configcenter address="zookeeper://127.0.0.1:2181" namespace="dubboregistrygroup1"
-                        configfile="dubbo.properties"/>
+    <!--<dubbo:configcenter address="zookeeper://127.0.0.1:2181" namespace="dubboregistrygroup1"-->
+    <!--configfile="dubbo.properties"/>-->
 
     <!-- generate proxy for the remote service, then demoService can be used in the same way as the
     local regular interface -->
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 87c6786..73878b0 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
@@ -25,11 +25,11 @@
     <dubbo:application name="demo-provider"/>
     <!--<dubbo:provider tag="tag3"/>-->
 
-    <dubbo:registry group="dubboregistrygroup1" address="zookeeper://127.0.0.1:2182">
+    <dubbo:registry group="dubboregistrygroup1" address="zookeeper://127.0.0.1:2181">
     </dubbo:registry>
 
-    <dubbo:configcenter address="zookeeper://127.0.0.1:2181?backup=127.0.0.1:2182" namespace="dubboregistrygroup1"
-                        configfile="dubbo.properties" appname="demo-provider"/>
+    <!--<dubbo:configcenter address="zookeeper://127.0.0.1:2181?backup=127.0.0.1:2182" namespace="dubboregistrygroup1"-->
+    <!--configfile="dubbo.properties" appname="demo-provider"/>-->
 
     <!-- use dubbo protocol to export service on port 20880 -->
     <dubbo:protocol name="dubbo" port="-1"/>
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryDirectory.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryDirectory.java
index 2a5e318..ac29f28 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryDirectory.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryDirectory.java
@@ -194,7 +194,7 @@ public class RegistryDirectory<T> extends AbstractDirectory<T> implements Notify
         setConsumerUrl(url);
         String rawConfig = null;
         try {
-            rawConfig = dynamicConfiguration.getConfig(url.getServiceKey() + Constants.CONFIGURATORS_SUFFIX, this);
+            rawConfig = dynamicConfiguration.getConfig(url.getEncodedServiceKey() + Constants.CONFIGURATORS_SUFFIX, this);
             if (StringUtils.isNotEmpty(rawConfig)) {
                 this.dynamicConfigurators = configToConfiguratiors(rawConfig);
             }
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 e0e0e48..2c4781f 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
@@ -22,13 +22,13 @@ import org.apache.dubbo.common.extension.ExtensionLoader;
 import org.apache.dubbo.common.logger.Logger;
 import org.apache.dubbo.common.logger.LoggerFactory;
 import org.apache.dubbo.common.utils.CollectionUtils;
-import org.apache.dubbo.common.utils.ConfigUtils;
 import org.apache.dubbo.common.utils.NamedThreadFactory;
 import org.apache.dubbo.common.utils.StringUtils;
 import org.apache.dubbo.common.utils.UrlUtils;
 import org.apache.dubbo.configcenter.ConfigChangeEvent;
 import org.apache.dubbo.configcenter.ConfigChangeType;
 import org.apache.dubbo.configcenter.ConfigurationListener;
+import org.apache.dubbo.configcenter.ConfigurationUtils;
 import org.apache.dubbo.configcenter.DynamicConfiguration;
 import org.apache.dubbo.registry.NotifyListener;
 import org.apache.dubbo.registry.Registry;
@@ -190,7 +190,7 @@ public class RegistryProtocol implements Protocol {
             listener.setAppDynamicConfigurators(appDynamicConfigurators);
             configurators.addAll(appDynamicConfigurators);
         }
-        String rawConfig = dynamicConfiguration.getConfig(providerUrl.getServiceKey() + Constants.CONFIGURATORS_SUFFIX, listener);
+        String rawConfig = dynamicConfiguration.getConfig(providerUrl.getEncodedServiceKey() + Constants.CONFIGURATORS_SUFFIX, listener);
         if (!StringUtils.isEmpty(rawConfig)) {
             List<Configurator> dynamicConfigurators = RegistryDirectory.configToConfiguratiors(rawConfig);
             listener.setDynamicConfigurators(dynamicConfigurators);
@@ -637,7 +637,7 @@ public class RegistryProtocol implements Protocol {
                 @Override
                 public void run() {
                     try {
-                        int timeout = ConfigUtils.getServerShutdownTimeout();
+                        int timeout = ConfigurationUtils.getServerShutdownTimeout();
                         if (timeout > 0) {
                             logger.info("Waiting " + timeout + "ms for registry to notify all consumers before unexport. Usually, this is called when you use dubbo API");
                             Thread.sleep(timeout);
diff --git a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/ZKTools.java b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/ZKTools.java
index ab0894d..15c002e 100644
--- a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/ZKTools.java
+++ b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/ZKTools.java
@@ -43,8 +43,8 @@ public class ZKTools {
                 new ExponentialBackoffRetry(1000, 3));
         client.start();
 
-        testStartupConfig();
-//        testProviderConfig();
+//        testStartupConfig();
+        testProviderConfig();
 //        testPathCache();
 //        testTreeCache();
 //        testCuratorListener();
@@ -72,20 +72,22 @@ public class ZKTools {
     }
 
     public static void testProviderConfig() {
-        String str = "{\n" +
-                "\t\"service\": \"org.apache.dubbo.demo.DemoService\",\n" +
-                "\t\"items\": [{\n" +
-                "\t\t\"addresses\": [\"30.5.120.49\"],\n" +
-                "\t\t\"rules\": [{\n" +
-                "\t\t\t\"key\": \"weight\",\n" +
-                "\t\t\t\"value\": 500\n" +
-                "\t\t}],\n" +
-                "\t\t\"app\": \"demo-provider\",\n" +
-                "\t\t\"side\": \"provider\"\n" +
-                "\t}]\n" +
-                "}";
+        String str = "---\n" +
+                "apiVersion: v2.7\n" +
+                "scope: service\n" +
+                "key: dd-test/org.apache.dubbo.demo.DemoService:1.0.4\n" +
+                "enabled: true\n" +
+                "configs:\n" +
+                "- addresses: ['0.0.0.0:20880']\n" +
+                "  side: provider\n" +
+                "  parameters:\n" +
+                "    timeout: 6000\n" +
+                "...";
+
+        System.out.println(str);
+
         try {
-            String path = "/dubbo/config/demo-provider/org.apache.dubbo.demo.DemoService.CONFIGURATORS";
+            String path = "/dubbo/config/dd-test*org.apache.dubbo.demo.DemoService:1.0.4/configurators";
             if (client.checkExists().forPath(path) == null) {
                 client.create().creatingParentsIfNeeded().forPath(path);
             }
diff --git a/dubbo-rpc/dubbo-rpc-dubbo/pom.xml b/dubbo-rpc/dubbo-rpc-dubbo/pom.xml
index 26915e4..bf2f63c 100644
--- a/dubbo-rpc/dubbo-rpc-dubbo/pom.xml
+++ b/dubbo-rpc/dubbo-rpc-dubbo/pom.xml
@@ -56,6 +56,11 @@
         </dependency>
         <dependency>
             <groupId>org.apache.dubbo</groupId>
+            <artifactId>dubbo-configcenter-api</artifactId>
+            <version>${project.parent.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.dubbo</groupId>
             <artifactId>dubbo-remoting-netty4</artifactId>
             <version>${project.parent.version}</version>
             <scope>test</scope>
diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboInvoker.java b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboInvoker.java
index 93343c0..60c56f0 100644
--- a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboInvoker.java
+++ b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboInvoker.java
@@ -19,7 +19,7 @@ package org.apache.dubbo.rpc.protocol.dubbo;
 import org.apache.dubbo.common.Constants;
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.utils.AtomicPositiveInteger;
-import org.apache.dubbo.common.utils.ConfigUtils;
+import org.apache.dubbo.configcenter.ConfigurationUtils;
 import org.apache.dubbo.remoting.RemotingException;
 import org.apache.dubbo.remoting.TimeoutException;
 import org.apache.dubbo.remoting.exchange.ExchangeClient;
@@ -148,7 +148,7 @@ public class DubboInvoker<T> extends AbstractInvoker<T> {
                 }
                 for (ExchangeClient client : clients) {
                     try {
-                        client.close(ConfigUtils.getServerShutdownTimeout());
+                        client.close(ConfigurationUtils.getServerShutdownTimeout());
                     } catch (Throwable t) {
                         logger.warn(t.getMessage(), t);
                     }
diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboProtocol.java b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboProtocol.java
index 334f0fb..2b7c156 100644
--- a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboProtocol.java
+++ b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboProtocol.java
@@ -22,9 +22,9 @@ import org.apache.dubbo.common.extension.ExtensionLoader;
 import org.apache.dubbo.common.serialize.support.SerializableClassRegistry;
 import org.apache.dubbo.common.serialize.support.SerializationOptimizer;
 import org.apache.dubbo.common.utils.ConcurrentHashSet;
-import org.apache.dubbo.common.utils.ConfigUtils;
 import org.apache.dubbo.common.utils.NetUtils;
 import org.apache.dubbo.common.utils.StringUtils;
+import org.apache.dubbo.configcenter.ConfigurationUtils;
 import org.apache.dubbo.remoting.Channel;
 import org.apache.dubbo.remoting.RemotingException;
 import org.apache.dubbo.remoting.Transporter;
@@ -454,7 +454,7 @@ public class DubboProtocol extends AbstractProtocol {
                     if (logger.isInfoEnabled()) {
                         logger.info("Close dubbo server: " + server.getLocalAddress());
                     }
-                    server.close(ConfigUtils.getServerShutdownTimeout());
+                    server.close(ConfigurationUtils.getServerShutdownTimeout());
                 } catch (Throwable t) {
                     logger.warn(t.getMessage(), t);
                 }
@@ -468,7 +468,7 @@ public class DubboProtocol extends AbstractProtocol {
                     if (logger.isInfoEnabled()) {
                         logger.info("Close dubbo connect: " + client.getLocalAddress() + "-->" + client.getRemoteAddress());
                     }
-                    client.close(ConfigUtils.getServerShutdownTimeout());
+                    client.close(ConfigurationUtils.getServerShutdownTimeout());
                 } catch (Throwable t) {
                     logger.warn(t.getMessage(), t);
                 }
@@ -482,7 +482,7 @@ public class DubboProtocol extends AbstractProtocol {
                     if (logger.isInfoEnabled()) {
                         logger.info("Close dubbo connect: " + client.getLocalAddress() + "-->" + client.getRemoteAddress());
                     }
-                    client.close(ConfigUtils.getServerShutdownTimeout());
+                    client.close(ConfigurationUtils.getServerShutdownTimeout());
                 } catch (Throwable t) {
                     logger.warn(t.getMessage(), t);
                 }
diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/DubboInvokerAvilableTest.java b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/DubboInvokerAvilableTest.java
index ced3d06..984ab71 100644
--- a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/DubboInvokerAvilableTest.java
+++ b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/DubboInvokerAvilableTest.java
@@ -20,8 +20,8 @@ package org.apache.dubbo.rpc.protocol.dubbo;
 import org.apache.dubbo.common.Constants;
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.extension.ExtensionLoader;
-import org.apache.dubbo.common.utils.ConfigUtils;
 import org.apache.dubbo.common.utils.NetUtils;
+import org.apache.dubbo.configcenter.ConfigurationUtils;
 import org.apache.dubbo.remoting.exchange.ExchangeClient;
 import org.apache.dubbo.rpc.Exporter;
 import org.apache.dubbo.rpc.ProxyFactory;
@@ -91,7 +91,7 @@ public class DubboInvokerAvilableTest {
 
         try{
             System.setProperty(Constants.SHUTDOWN_WAIT_KEY, "2000");
-            System.out.println("------------ConfigUtils.getServerShutdownTimeout(): " + ConfigUtils.getServerShutdownTimeout());
+            System.out.println("------------ConfigUtils.getServerShutdownTimeout(): " + ConfigurationUtils.getServerShutdownTimeout());
             protocol.destroy();
         }finally {
             System.getProperties().remove(Constants.SHUTDOWN_WAIT_KEY);
diff --git a/dubbo-rpc/dubbo-rpc-thrift/src/main/java/org/apache/dubbo/rpc/protocol/thrift/ThriftProtocol.java b/dubbo-rpc/dubbo-rpc-thrift/src/main/java/org/apache/dubbo/rpc/protocol/thrift/ThriftProtocol.java
index 96f4726..731e947 100644
--- a/dubbo-rpc/dubbo-rpc-thrift/src/main/java/org/apache/dubbo/rpc/protocol/thrift/ThriftProtocol.java
+++ b/dubbo-rpc/dubbo-rpc-thrift/src/main/java/org/apache/dubbo/rpc/protocol/thrift/ThriftProtocol.java
@@ -19,7 +19,7 @@ package org.apache.dubbo.rpc.protocol.thrift;
 import org.apache.dubbo.common.Constants;
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.extension.ExtensionLoader;
-import org.apache.dubbo.common.utils.ConfigUtils;
+import org.apache.dubbo.configcenter.ConfigurationUtils;
 import org.apache.dubbo.remoting.Channel;
 import org.apache.dubbo.remoting.RemotingException;
 import org.apache.dubbo.remoting.Transporter;
@@ -146,7 +146,7 @@ public class ThriftProtocol extends AbstractProtocol {
                     if (logger.isInfoEnabled()) {
                         logger.info("Close dubbo server: " + server.getLocalAddress());
                     }
-                    server.close(ConfigUtils.getServerShutdownTimeout());
+                    server.close(ConfigurationUtils.getServerShutdownTimeout());
                 } catch (Throwable t) {
                     logger.warn(t.getMessage(), t);
                 }