You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@servicecomb.apache.org by li...@apache.org on 2021/06/04 08:32:24 UTC

[servicecomb-java-chassis] branch master updated (3138a19 -> d666309)

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

liubao pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/servicecomb-java-chassis.git.


    from 3138a19  [#2272]fix problem of grey release not use latest version when version changed(#2384)
     new b74bcd7  [SCB-2273]support kie latest layered configuration. Part1: kie implementation
     new 23e0feb  [SCB-2273]support kie latest layered configuration. Part2: config center implementation
     new d666309  [SCB-2273]support kie latest layered configuration. Part3: add integration tests and fix all problems found

The 3 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:
 .../config/center/client/AddressManager.java       |   4 +
 .../config/center/client/ConfigCenterManager.java  |  20 +-
 .../servicecomb/config/common/ConfigConverter.java |  92 +++++
 .../servicecomb/config/kie/client/KieClient.java   | 148 ++-----
 .../config/kie/client/KieConfigManager.java        |  87 ++++-
 .../kie/client/model/ConfigurationsRequest.java    |  61 +--
 .../client/model/ConfigurationsRequestFactory.java |  94 +++++
 .../config/kie/client/model/KieAddressManager.java |  19 +-
 .../config/kie/client/model/KieConfiguration.java  | 152 ++++++++
 .../servicecomb/http/client/task/AbstractTask.java |  27 +-
 .../center/client/ServiceCenterDiscovery.java      |  35 +-
 .../center/client/ServiceCenterRegistration.java   |  38 +-
 .../client/model/ServiceCenterConfiguration.java   |  24 +-
 .../core/ConfigurationSpringInitializer.java       |  34 +-
 demo/README.md                                     |   6 +-
 demo/demo-cse-v1/README.md                         |  18 +
 demo/demo-cse-v1/consumer/pom.xml                  |  47 +++
 .../servicecomb/samples/ConsumerApplication.java   |  24 +-
 .../samples/ConsumerConfigController.java          |  50 +++
 .../samples/ConsumerConfigurationProperties.java   |  28 +-
 .../servicecomb/samples/ConsumerController.java    |  28 +-
 .../servicecomb/samples/ProviderService.java       |   6 +-
 .../consumer/src/main/resources/application.yml    |  45 +++
 .../consumer/src/main/resources/log4j2.xml         |  45 +++
 .../demo-cse-v1/gateway}/pom.xml                   |  51 +--
 .../servicecomb/samples/GatewayApplication.java    |  23 +-
 .../gateway/src/main/resources/application.yml     |  59 +++
 .../gateway/src/main/resources/log4j2.xml          |  45 +++
 .../config-kie => demo/demo-cse-v1}/pom.xml        |  50 +--
 demo/demo-cse-v1/provider/pom.xml                  |  51 +++
 .../servicecomb/samples/ProviderApplication.java   |  24 +-
 .../servicecomb/samples/ProviderController.java    |  23 +-
 .../provider/src/main/resources/application.yml    |  47 +++
 .../provider/src/main/resources/log4j2.xml         |  45 +++
 .../demo-cse-v1/test-client}/pom.xml               |  56 ++-
 .../org/apache/servicecomb/samples/Config.java     |  11 +-
 .../servicecomb/samples/ConsumerConfigIT.java      |  48 +++
 .../apache/servicecomb/samples/HelloWorldIT.java   |  37 +-
 .../servicecomb/samples/TestClientApplication.java |  47 +++
 .../test-client/src/main/resources/application.yml |  47 +++
 .../test-client/src/main/resources/log4j2.xml      |  45 +++
 demo/demo-cse-v2/README.md                         |  81 ++++
 demo/demo-cse-v2/consumer/pom.xml                  |  47 +++
 .../servicecomb/samples/ConsumerApplication.java   |  24 +-
 .../samples/ConsumerConfigController.java          |  60 +++
 .../samples/ConsumerConfigurationProperties.java   |  48 ++-
 .../servicecomb/samples/ConsumerController.java    |  28 +-
 .../servicecomb/samples/ProviderService.java       |   6 +-
 .../consumer/src/main/resources/application.yml    |  38 ++
 .../consumer/src/main/resources/log4j2.xml         |  45 +++
 .../demo-cse-v2/gateway}/pom.xml                   |  51 +--
 .../servicecomb/samples/GatewayApplication.java    |  23 +-
 .../gateway/src/main/resources/application.yml     |  59 +++
 .../gateway/src/main/resources/log4j2.xml          |  45 +++
 .../config-kie => demo/demo-cse-v2}/pom.xml        |  50 +--
 demo/demo-cse-v2/provider/pom.xml                  |  51 +++
 .../servicecomb/samples/ProviderApplication.java   |  24 +-
 .../servicecomb/samples/ProviderController.java    |  48 +--
 .../provider/src/main/resources/application.yml    |  40 ++
 .../provider/src/main/resources/log4j2.xml         |  45 +++
 .../demo-cse-v2/test-client}/pom.xml               |  56 ++-
 .../org/apache/servicecomb/samples/Config.java     |  19 +-
 .../servicecomb/samples/ConsumerConfigIT.java      |  56 +++
 .../apache/servicecomb/samples/HelloWorldIT.java   |  26 +-
 .../servicecomb/samples/TestClientApplication.java |  47 +++
 .../test-client/src/main/resources/application.yml |  47 +++
 .../test-client/src/main/resources/log4j2.xml      |  45 +++
 .../RegistryClientTest.java                        |   5 +-
 .../demo/springmvc/client/SpringmvcClient.java     |   2 -
 demo/pom.xml                                       |   2 +
 dynamic-config/config-cc/pom.xml                   |   4 +
 .../config/{client => }/ConfigCenterConfig.java    |  53 ++-
 .../ConfigCenterConfigurationSourceImpl.java       | 201 ++++++++++
 .../apache/servicecomb/config/TransportUtils.java  | 123 ++++++
 .../ConfigCenterConfigurationSourceImpl.java       | 171 ---------
 .../config/client/ConfigCenterClient.java          | 427 ---------------------
 .../client/ConfigCenterHttpClientOptionsSPI.java   | 177 ---------
 .../servicecomb/config/client/MemberDiscovery.java |  90 -----
 .../config/client/ParseConfigUtils.java            | 183 ---------
 .../apache/servicecomb/config/client/URIConst.java |  42 --
 ...comb.config.spi.ConfigCenterConfigurationSource |   2 +-
 .../TestConfigCenterConfigurationSource.java       | 124 ------
 .../config/client/TestConfigCenterClient.java      | 353 -----------------
 .../config/client/TestConfigCenterConfig.java      |  56 ---
 .../config/client/TestMemberDiscovery.java         |  84 ----
 .../config/client/TestParseConfigUtils.java        | 122 ------
 .../servicecomb/config/client/TestURIConst.java    |  60 ---
 ...TestConfigCenterDefaultDeploymentProvider.java} |   2 +-
 dynamic-config/config-kie/pom.xml                  |   4 +
 .../config/kie/{client => }/KieConfig.java         |  72 +++-
 .../config/kie/KieConfigurationSourceImpl.java     | 182 +++++++++
 .../servicecomb/config/kie/TransportUtils.java     | 123 ++++++
 .../sources/KieConfigurationSourceImpl.java        | 138 -------
 .../kie/client/ConfigKieHttpClientOptionsSPI.java  | 175 ---------
 .../servicecomb/config/kie/client/KieClient.java   | 176 ---------
 .../servicecomb/config/kie/client/KieUtil.java     | 154 --------
 .../servicecomb/config/kie/client/KieWatcher.java  |  86 -----
 .../servicecomb/config/kie/model/KVBody.java       |  65 ----
 .../apache/servicecomb/config/kie/model/KVDoc.java | 127 ------
 ...comb.config.spi.ConfigCenterConfigurationSource |   2 +-
 .../config/kie/client/TestKieClient.java           | 200 ----------
 .../config/kie/client/TestKieConfig.java           |  46 ---
 .../servicecomb/config/kie/client/TestKieUtil.java |  62 ---
 .../config/kie/client/TestKieWatcher.java          |  54 ---
 .../kie/sources/TestKieConfigurationSource.java    |  96 -----
 .../org/apache/servicecomb/config/ConfigUtil.java  |   7 +-
 {demo => integration-tests}/README.md              |   6 +-
 .../client/http/ServiceRegistryClientImpl.java     |   4 +-
 .../task/ServiceCenterTaskMonitor.java             |   2 +-
 solutions/solution-basic/pom.xml                   |   5 +-
 110 files changed, 3077 insertions(+), 3942 deletions(-)
 create mode 100644 clients/config-common/src/main/java/org/apache/servicecomb/config/common/ConfigConverter.java
 create mode 100644 clients/config-kie-client/src/main/java/org/apache/servicecomb/config/kie/client/model/ConfigurationsRequestFactory.java
 create mode 100644 clients/config-kie-client/src/main/java/org/apache/servicecomb/config/kie/client/model/KieConfiguration.java
 copy dynamic-config/config-cc/src/main/java/org/apache/servicecomb/config/client/ConnFailEvent.java => clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/model/ServiceCenterConfiguration.java (55%)
 create mode 100644 demo/demo-cse-v1/README.md
 create mode 100644 demo/demo-cse-v1/consumer/pom.xml
 copy clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/ServiceCenterConfiguration.java => demo/demo-cse-v1/consumer/src/main/java/org/apache/servicecomb/samples/ConsumerApplication.java (55%)
 create mode 100644 demo/demo-cse-v1/consumer/src/main/java/org/apache/servicecomb/samples/ConsumerConfigController.java
 rename dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/client/ConnFailEvent.java => demo/demo-cse-v1/consumer/src/main/java/org/apache/servicecomb/samples/ConsumerConfigurationProperties.java (61%)
 copy dynamic-config/config-cc/src/main/java/org/apache/servicecomb/config/client/ConnFailEvent.java => demo/demo-cse-v1/consumer/src/main/java/org/apache/servicecomb/samples/ConsumerController.java (50%)
 rename dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/client/ConnSuccEvent.java => demo/demo-cse-v1/consumer/src/main/java/org/apache/servicecomb/samples/ProviderService.java (88%)
 create mode 100644 demo/demo-cse-v1/consumer/src/main/resources/application.yml
 create mode 100644 demo/demo-cse-v1/consumer/src/main/resources/log4j2.xml
 copy {dynamic-config/config-kie => demo/demo-cse-v1/gateway}/pom.xml (51%)
 copy clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/ServiceCenterConfiguration.java => demo/demo-cse-v1/gateway/src/main/java/org/apache/servicecomb/samples/GatewayApplication.java (57%)
 create mode 100644 demo/demo-cse-v1/gateway/src/main/resources/application.yml
 create mode 100644 demo/demo-cse-v1/gateway/src/main/resources/log4j2.xml
 copy {dynamic-config/config-kie => demo/demo-cse-v1}/pom.xml (56%)
 create mode 100644 demo/demo-cse-v1/provider/pom.xml
 copy clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/ServiceCenterConfiguration.java => demo/demo-cse-v1/provider/src/main/java/org/apache/servicecomb/samples/ProviderApplication.java (55%)
 copy clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/ServiceCenterConfiguration.java => demo/demo-cse-v1/provider/src/main/java/org/apache/servicecomb/samples/ProviderController.java (58%)
 create mode 100644 demo/demo-cse-v1/provider/src/main/resources/application.yml
 create mode 100644 demo/demo-cse-v1/provider/src/main/resources/log4j2.xml
 copy {dynamic-config/config-kie => demo/demo-cse-v1/test-client}/pom.xml (51%)
 rename dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/model/ValueType.java => demo/demo-cse-v1/test-client/src/main/java/org/apache/servicecomb/samples/Config.java (86%)
 create mode 100644 demo/demo-cse-v1/test-client/src/main/java/org/apache/servicecomb/samples/ConsumerConfigIT.java
 rename dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/model/LabelDocResponse.java => demo/demo-cse-v1/test-client/src/main/java/org/apache/servicecomb/samples/HelloWorldIT.java (56%)
 create mode 100644 demo/demo-cse-v1/test-client/src/main/java/org/apache/servicecomb/samples/TestClientApplication.java
 create mode 100644 demo/demo-cse-v1/test-client/src/main/resources/application.yml
 create mode 100644 demo/demo-cse-v1/test-client/src/main/resources/log4j2.xml
 create mode 100644 demo/demo-cse-v2/README.md
 create mode 100644 demo/demo-cse-v2/consumer/pom.xml
 copy clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/ServiceCenterConfiguration.java => demo/demo-cse-v2/consumer/src/main/java/org/apache/servicecomb/samples/ConsumerApplication.java (55%)
 create mode 100644 demo/demo-cse-v2/consumer/src/main/java/org/apache/servicecomb/samples/ConsumerConfigController.java
 copy dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/model/KVResponse.java => demo/demo-cse-v2/consumer/src/main/java/org/apache/servicecomb/samples/ConsumerConfigurationProperties.java (50%)
 copy dynamic-config/config-cc/src/main/java/org/apache/servicecomb/config/client/ConnFailEvent.java => demo/demo-cse-v2/consumer/src/main/java/org/apache/servicecomb/samples/ConsumerController.java (50%)
 rename dynamic-config/config-cc/src/main/java/org/apache/servicecomb/config/client/ConnSuccEvent.java => demo/demo-cse-v2/consumer/src/main/java/org/apache/servicecomb/samples/ProviderService.java (88%)
 create mode 100644 demo/demo-cse-v2/consumer/src/main/resources/application.yml
 create mode 100644 demo/demo-cse-v2/consumer/src/main/resources/log4j2.xml
 copy {dynamic-config/config-kie => demo/demo-cse-v2/gateway}/pom.xml (51%)
 copy clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/ServiceCenterConfiguration.java => demo/demo-cse-v2/gateway/src/main/java/org/apache/servicecomb/samples/GatewayApplication.java (57%)
 create mode 100644 demo/demo-cse-v2/gateway/src/main/resources/application.yml
 create mode 100644 demo/demo-cse-v2/gateway/src/main/resources/log4j2.xml
 copy {dynamic-config/config-kie => demo/demo-cse-v2}/pom.xml (56%)
 create mode 100644 demo/demo-cse-v2/provider/pom.xml
 rename clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/ServiceCenterConfiguration.java => demo/demo-cse-v2/provider/src/main/java/org/apache/servicecomb/samples/ProviderApplication.java (55%)
 rename dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/model/KVResponse.java => demo/demo-cse-v2/provider/src/main/java/org/apache/servicecomb/samples/ProviderController.java (58%)
 create mode 100644 demo/demo-cse-v2/provider/src/main/resources/application.yml
 create mode 100644 demo/demo-cse-v2/provider/src/main/resources/log4j2.xml
 copy {dynamic-config/config-kie => demo/demo-cse-v2/test-client}/pom.xml (51%)
 copy dynamic-config/config-cc/src/main/java/org/apache/servicecomb/config/client/ConnFailEvent.java => demo/demo-cse-v2/test-client/src/main/java/org/apache/servicecomb/samples/Config.java (75%)
 create mode 100644 demo/demo-cse-v2/test-client/src/main/java/org/apache/servicecomb/samples/ConsumerConfigIT.java
 rename dynamic-config/config-cc/src/main/java/org/apache/servicecomb/config/client/ConnFailEvent.java => demo/demo-cse-v2/test-client/src/main/java/org/apache/servicecomb/samples/HelloWorldIT.java (56%)
 create mode 100644 demo/demo-cse-v2/test-client/src/main/java/org/apache/servicecomb/samples/TestClientApplication.java
 create mode 100644 demo/demo-cse-v2/test-client/src/main/resources/application.yml
 create mode 100644 demo/demo-cse-v2/test-client/src/main/resources/log4j2.xml
 rename dynamic-config/config-cc/src/main/java/org/apache/servicecomb/config/{client => }/ConfigCenterConfig.java (85%)
 create mode 100644 dynamic-config/config-cc/src/main/java/org/apache/servicecomb/config/ConfigCenterConfigurationSourceImpl.java
 create mode 100644 dynamic-config/config-cc/src/main/java/org/apache/servicecomb/config/TransportUtils.java
 delete mode 100644 dynamic-config/config-cc/src/main/java/org/apache/servicecomb/config/archaius/sources/ConfigCenterConfigurationSourceImpl.java
 delete mode 100644 dynamic-config/config-cc/src/main/java/org/apache/servicecomb/config/client/ConfigCenterClient.java
 delete mode 100644 dynamic-config/config-cc/src/main/java/org/apache/servicecomb/config/client/ConfigCenterHttpClientOptionsSPI.java
 delete mode 100644 dynamic-config/config-cc/src/main/java/org/apache/servicecomb/config/client/MemberDiscovery.java
 delete mode 100644 dynamic-config/config-cc/src/main/java/org/apache/servicecomb/config/client/ParseConfigUtils.java
 delete mode 100644 dynamic-config/config-cc/src/main/java/org/apache/servicecomb/config/client/URIConst.java
 delete mode 100644 dynamic-config/config-cc/src/test/java/org/apache/servicecomb/config/archaius/sources/TestConfigCenterConfigurationSource.java
 delete mode 100644 dynamic-config/config-cc/src/test/java/org/apache/servicecomb/config/client/TestConfigCenterClient.java
 delete mode 100644 dynamic-config/config-cc/src/test/java/org/apache/servicecomb/config/client/TestConfigCenterConfig.java
 delete mode 100644 dynamic-config/config-cc/src/test/java/org/apache/servicecomb/config/client/TestMemberDiscovery.java
 delete mode 100644 dynamic-config/config-cc/src/test/java/org/apache/servicecomb/config/client/TestParseConfigUtils.java
 delete mode 100644 dynamic-config/config-cc/src/test/java/org/apache/servicecomb/config/client/TestURIConst.java
 rename dynamic-config/config-cc/src/test/java/org/apache/servicecomb/config/collect/{TestConfigCenterDefaultDeploymentProvder.java => TestConfigCenterDefaultDeploymentProvider.java} (98%)
 rename dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/{client => }/KieConfig.java (66%)
 create mode 100644 dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/KieConfigurationSourceImpl.java
 create mode 100644 dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/TransportUtils.java
 delete mode 100644 dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/archaius/sources/KieConfigurationSourceImpl.java
 delete mode 100644 dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/client/ConfigKieHttpClientOptionsSPI.java
 delete mode 100644 dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/client/KieClient.java
 delete mode 100644 dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/client/KieUtil.java
 delete mode 100644 dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/client/KieWatcher.java
 delete mode 100644 dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/model/KVBody.java
 delete mode 100644 dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/model/KVDoc.java
 delete mode 100644 dynamic-config/config-kie/src/test/java/org/apache/servicecomb/config/kie/client/TestKieClient.java
 delete mode 100644 dynamic-config/config-kie/src/test/java/org/apache/servicecomb/config/kie/client/TestKieConfig.java
 delete mode 100644 dynamic-config/config-kie/src/test/java/org/apache/servicecomb/config/kie/client/TestKieUtil.java
 delete mode 100644 dynamic-config/config-kie/src/test/java/org/apache/servicecomb/config/kie/client/TestKieWatcher.java
 delete mode 100644 dynamic-config/config-kie/src/test/java/org/apache/servicecomb/config/kie/sources/TestKieConfigurationSource.java
 copy {demo => integration-tests}/README.md (60%)

[servicecomb-java-chassis] 02/03: [SCB-2273]support kie latest layered configuration. Part2: config center implementation

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

liubao pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/servicecomb-java-chassis.git

commit 23e0feb9b882cc6c34b299f47b2aaea1d4b2b6dc
Author: liubao68 <bi...@qq.com>
AuthorDate: Wed Jun 2 18:07:48 2021 +0800

    [SCB-2273]support kie latest layered configuration. Part2: config center implementation
---
 dynamic-config/config-cc/pom.xml                   |   4 +
 .../config/{client => }/ConfigCenterConfig.java    |  45 +--
 .../ConfigCenterConfigurationSourceImpl.java       | 177 +++++++++
 .../apache/servicecomb/config/TransportUtils.java  | 118 ++++++
 .../ConfigCenterConfigurationSourceImpl.java       | 171 ---------
 .../config/client/ConfigCenterClient.java          | 427 ---------------------
 .../client/ConfigCenterHttpClientOptionsSPI.java   | 177 ---------
 .../servicecomb/config/client/ConnFailEvent.java   |  35 --
 .../servicecomb/config/client/ConnSuccEvent.java   |  22 --
 .../servicecomb/config/client/MemberDiscovery.java |  90 -----
 .../config/client/ParseConfigUtils.java            | 183 ---------
 .../apache/servicecomb/config/client/URIConst.java |  42 --
 ...comb.config.spi.ConfigCenterConfigurationSource |   2 +-
 .../TestConfigCenterConfigurationSource.java       | 124 ------
 .../config/client/TestConfigCenterClient.java      | 353 -----------------
 .../config/client/TestConfigCenterConfig.java      |  56 ---
 .../config/client/TestMemberDiscovery.java         |  84 ----
 .../config/client/TestParseConfigUtils.java        | 122 ------
 .../servicecomb/config/client/TestURIConst.java    |  60 ---
 ...TestConfigCenterDefaultDeploymentProvider.java} |   2 +-
 20 files changed, 316 insertions(+), 1978 deletions(-)

diff --git a/dynamic-config/config-cc/pom.xml b/dynamic-config/config-cc/pom.xml
index 1ab6d3f..2ebea1e 100644
--- a/dynamic-config/config-cc/pom.xml
+++ b/dynamic-config/config-cc/pom.xml
@@ -59,6 +59,10 @@
       <artifactId>foundation-test-scaffolding</artifactId>
       <scope>test</scope>
     </dependency>
+    <dependency>
+      <groupId>org.apache.servicecomb</groupId>
+      <artifactId>config-center-client</artifactId>
+    </dependency>
   </dependencies>
 
 </project>
\ No newline at end of file
diff --git a/dynamic-config/config-cc/src/main/java/org/apache/servicecomb/config/client/ConfigCenterConfig.java b/dynamic-config/config-cc/src/main/java/org/apache/servicecomb/config/ConfigCenterConfig.java
similarity index 85%
rename from dynamic-config/config-cc/src/main/java/org/apache/servicecomb/config/client/ConfigCenterConfig.java
rename to dynamic-config/config-cc/src/main/java/org/apache/servicecomb/config/ConfigCenterConfig.java
index 219329b..f65d12e 100644
--- a/dynamic-config/config-cc/src/main/java/org/apache/servicecomb/config/client/ConfigCenterConfig.java
+++ b/dynamic-config/config-cc/src/main/java/org/apache/servicecomb/config/ConfigCenterConfig.java
@@ -15,18 +15,17 @@
  * limitations under the License.
  */
 
-package org.apache.servicecomb.config.client;
+package org.apache.servicecomb.config;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
 
-import com.google.common.base.Joiner;
-import com.netflix.config.ConcurrentCompositeConfiguration;
-import org.apache.servicecomb.config.BootStrapProperties;
 import org.apache.servicecomb.config.collect.ConfigCenterDefaultDeploymentProvider;
 import org.apache.servicecomb.deployment.Deployment;
 import org.apache.servicecomb.foundation.vertx.VertxConst;
 
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
+import com.netflix.config.ConcurrentCompositeConfiguration;
 
 public final class ConfigCenterConfig {
   public static final ConfigCenterConfig INSTANCE = new ConfigCenterConfig();
@@ -146,35 +145,21 @@ public final class ConfigCenterConfig {
     return finalConfig.getString(VertxConst.PROXY_PASSWD, null);
   }
 
-  @SuppressWarnings("unchecked")
   public String getServiceName() {
-    String service = BootStrapProperties.readServiceName(finalConfig);
-    String appName = BootStrapProperties.readApplication(finalConfig);
-    String tags;
-    if (appName != null) {
-      service = service + "@" + appName;
-    }
+    return BootStrapProperties.readServiceName(finalConfig);
+  }
 
-    String serviceVersion = BootStrapProperties.readServiceVersion(finalConfig);
-    if (serviceVersion != null) {
-      service = service + "#" + serviceVersion;
-    }
+  public String getAppName() {
+    return BootStrapProperties.readApplication(finalConfig);
+  }
 
-    Object o = BootStrapProperties.readServiceInstanceTags(finalConfig);
-    if (o == null) {
-      return service;
-    }
-    if (o instanceof List) {
-      tags = Joiner.on(",").join((List<String>) o);
-    } else {
-      tags = o.toString();
-    }
-    service += "!" + tags;
-    return service;
+  public String getServiceVersion() {
+    return BootStrapProperties.readServiceVersion(finalConfig);
   }
 
   public List<String> getServerUri() {
-    return Deployment.getSystemBootStrapInfo(ConfigCenterDefaultDeploymentProvider.SYSTEM_KEY_CONFIG_CENTER).getAccessURL();
+    return Deployment.getSystemBootStrapInfo(ConfigCenterDefaultDeploymentProvider.SYSTEM_KEY_CONFIG_CENTER)
+        .getAccessURL();
   }
 
   public boolean getAutoDiscoveryEnabled() {
diff --git a/dynamic-config/config-cc/src/main/java/org/apache/servicecomb/config/ConfigCenterConfigurationSourceImpl.java b/dynamic-config/config-cc/src/main/java/org/apache/servicecomb/config/ConfigCenterConfigurationSourceImpl.java
new file mode 100644
index 0000000..d471e08
--- /dev/null
+++ b/dynamic-config/config-cc/src/main/java/org/apache/servicecomb/config/ConfigCenterConfigurationSourceImpl.java
@@ -0,0 +1,177 @@
+/*
+ * 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.servicecomb.config;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+import org.apache.commons.configuration.Configuration;
+import org.apache.http.client.config.RequestConfig;
+import org.apache.servicecomb.config.center.client.AddressManager;
+import org.apache.servicecomb.config.center.client.ConfigCenterClient;
+import org.apache.servicecomb.config.center.client.ConfigCenterManager;
+import org.apache.servicecomb.config.center.client.model.QueryConfigurationsRequest;
+import org.apache.servicecomb.config.center.client.model.QueryConfigurationsResponse;
+import org.apache.servicecomb.config.collect.ConfigCenterDefaultDeploymentProvider;
+import org.apache.servicecomb.config.common.ConfigConverter;
+import org.apache.servicecomb.config.common.ConfigurationChangedEvent;
+import org.apache.servicecomb.config.spi.ConfigCenterConfigurationSource;
+import org.apache.servicecomb.deployment.Deployment;
+import org.apache.servicecomb.deployment.SystemBootstrapInfo;
+import org.apache.servicecomb.foundation.auth.AuthHeaderProvider;
+import org.apache.servicecomb.foundation.common.event.EventManager;
+import org.apache.servicecomb.foundation.common.utils.SPIServiceUtils;
+import org.apache.servicecomb.http.client.auth.RequestAuthHeaderProvider;
+import org.apache.servicecomb.http.client.common.HttpTransport;
+import org.apache.servicecomb.http.client.common.HttpTransportFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.eventbus.Subscribe;
+import com.netflix.config.ConcurrentCompositeConfiguration;
+import com.netflix.config.WatchedUpdateListener;
+import com.netflix.config.WatchedUpdateResult;
+
+public class ConfigCenterConfigurationSourceImpl implements ConfigCenterConfigurationSource {
+  private static final Logger LOGGER = LoggerFactory.getLogger(ConfigCenterConfigurationSourceImpl.class);
+
+  private List<WatchedUpdateListener> listeners = new CopyOnWriteArrayList<>();
+
+  private ConfigCenterManager configCenterManager;
+
+  private ConfigConverter configConverter = new ConfigConverter(null);
+
+  @Override
+  public int getOrder() {
+    return ORDER_BASE * 2;
+  }
+
+  @Override
+  public boolean isValidSource(Configuration localConfiguration) {
+    ConfigCenterConfig.setConcurrentCompositeConfiguration((ConcurrentCompositeConfiguration) localConfiguration);
+    SystemBootstrapInfo address = Deployment
+        .getSystemBootStrapInfo(ConfigCenterDefaultDeploymentProvider.SYSTEM_KEY_CONFIG_CENTER);
+
+    if (address == null) {
+      LOGGER.info("config center server is not configured.");
+      return false;
+    }
+    return true;
+  }
+
+  @Override
+  public void init(Configuration localConfiguration) {
+    AddressManager kieAddressManager = configKieAddressManager();
+
+    RequestConfig.Builder requestBuilder = HttpTransportFactory.defaultRequestConfig();
+
+    HttpTransport httpTransport = createHttpTransport(requestBuilder.build(), localConfiguration);
+    ConfigCenterClient configCenterClient = new ConfigCenterClient(kieAddressManager, httpTransport);
+    EventManager.register(this);
+
+    QueryConfigurationsRequest queryConfigurationsRequest = createQueryConfigurationsRequest();
+    QueryConfigurationsResponse response = configCenterClient
+        .queryConfigurations(queryConfigurationsRequest);
+    if (response.isChanged()) {
+      configConverter.updateData(response.getConfigurations());
+      updateConfiguration(WatchedUpdateResult.createIncremental(configConverter.getCurrentData(), null, null));
+    }
+    queryConfigurationsRequest.setRevision(response.getRevision());
+
+    configCenterManager = new ConfigCenterManager(configCenterClient, EventManager.getEventBus(),
+        configConverter);
+    configCenterManager.setQueryConfigurationsRequest(queryConfigurationsRequest);
+    configCenterManager.startConfigCenterManager();
+  }
+
+  @Subscribe
+  public void onConfigurationChangedEvent(ConfigurationChangedEvent event) {
+    updateConfiguration(
+        WatchedUpdateResult.createIncremental(event.getAdded(), event.getUpdated(), event.getDeleted()));
+  }
+
+  private QueryConfigurationsRequest createQueryConfigurationsRequest() {
+    QueryConfigurationsRequest request = new QueryConfigurationsRequest();
+    request.setApplication(ConfigCenterConfig.INSTANCE.getAppName());
+    request.setServiceName(ConfigCenterConfig.INSTANCE.getServiceName());
+    request.setVersion(ConfigCenterConfig.INSTANCE.getServiceVersion());
+    request.setEnvironment(ConfigCenterConfig.INSTANCE.getEnvironment());
+    // 需要设置为 null, 并且 query 参数为 revision=null 才会返回 revision 信息。 revision = 是不行的。
+    request.setRevision(null);
+    return request;
+  }
+
+  private HttpTransport createHttpTransport(RequestConfig requestConfig, Configuration localConfiguration) {
+    List<AuthHeaderProvider> authHeaderProviders = SPIServiceUtils.getOrLoadSortedService(AuthHeaderProvider.class);
+
+    return HttpTransportFactory
+        .createHttpTransport(
+            TransportUtils.createSSLProperties(localConfiguration, "kie"),
+            getRequestAuthHeaderProvider(authHeaderProviders), requestConfig);
+  }
+
+  private static RequestAuthHeaderProvider getRequestAuthHeaderProvider(List<AuthHeaderProvider> authHeaderProviders) {
+    return signRequest -> {
+      Map<String, String> headers = new HashMap<>();
+      authHeaderProviders.forEach(provider -> headers.putAll(provider.authHeaders()));
+      return headers;
+    };
+  }
+
+  private AddressManager configKieAddressManager() {
+    AddressManager kieAddressManager = new AddressManager(ConfigCenterConfig.INSTANCE.getDomainName(),
+        Deployment
+            .getSystemBootStrapInfo(ConfigCenterDefaultDeploymentProvider.SYSTEM_KEY_CONFIG_CENTER).getAccessURL());
+    return kieAddressManager;
+  }
+
+  private void updateConfiguration(WatchedUpdateResult result) {
+    for (WatchedUpdateListener l : listeners) {
+      try {
+        l.updateConfiguration(result);
+      } catch (Throwable ex) {
+        LOGGER.error("Error in invoking WatchedUpdateListener", ex);
+      }
+    }
+  }
+
+  @Override
+  public void destroy() {
+    if (configCenterManager == null) {
+      return;
+    }
+    configCenterManager.stop();
+  }
+
+  @Override
+  public void addUpdateListener(WatchedUpdateListener watchedUpdateListener) {
+    listeners.add(watchedUpdateListener);
+  }
+
+  @Override
+  public void removeUpdateListener(WatchedUpdateListener watchedUpdateListener) {
+    listeners.remove(watchedUpdateListener);
+  }
+
+  @Override
+  public Map<String, Object> getCurrentData() throws Exception {
+    return configConverter.getCurrentData();
+  }
+}
diff --git a/dynamic-config/config-cc/src/main/java/org/apache/servicecomb/config/TransportUtils.java b/dynamic-config/config-cc/src/main/java/org/apache/servicecomb/config/TransportUtils.java
new file mode 100644
index 0000000..e6c8b48
--- /dev/null
+++ b/dynamic-config/config-cc/src/main/java/org/apache/servicecomb/config/TransportUtils.java
@@ -0,0 +1,118 @@
+/*
+ * 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.servicecomb.config;
+
+import static org.apache.servicecomb.foundation.ssl.SSLOption.DEFAULT_OPTION;
+
+import org.apache.commons.configuration.Configuration;
+import org.apache.servicecomb.foundation.ssl.SSLCustom;
+import org.apache.servicecomb.foundation.ssl.SSLOption;
+import org.apache.servicecomb.http.client.common.HttpConfiguration.SSLProperties;
+
+public class TransportUtils {
+  public static SSLProperties createSSLProperties(Configuration configuration, String tag) {
+    SSLProperties sslProperties = new SSLProperties();
+
+    SSLOption option = new SSLOption();
+    option.setEngine(getStringProperty(configuration,
+        DEFAULT_OPTION.getEngine(),
+        "ssl." + tag + ".engine",
+        "ssl.engine"));
+    option.setProtocols(
+        getStringProperty(configuration,
+            DEFAULT_OPTION.getProtocols(),
+            "ssl." + tag + ".protocols",
+            "ssl.protocols"));
+    option.setCiphers(
+        getStringProperty(configuration, DEFAULT_OPTION.getCiphers(), "ssl." + tag + ".ciphers", "ssl.ciphers"));
+    option.setAuthPeer(
+        getBooleanProperty(configuration, DEFAULT_OPTION.isAuthPeer(), "ssl." + tag + ".authPeer", "ssl.authPeer"));
+    option.setCheckCNHost(
+        getBooleanProperty(configuration,
+            DEFAULT_OPTION.isCheckCNHost(),
+            "ssl." + tag + ".checkCN.host",
+            "ssl.checkCN.host"));
+    option.setCheckCNWhite(
+        getBooleanProperty(configuration,
+            DEFAULT_OPTION.isCheckCNWhite(),
+            "ssl." + tag + ".checkCN.white",
+            "ssl.checkCN.white"));
+    option.setCheckCNWhiteFile(getStringProperty(configuration,
+        DEFAULT_OPTION.getCiphers(),
+        "ssl." + tag + ".checkCN.white.file",
+        "ssl.checkCN.white.file"));
+    option.setAllowRenegociate(getBooleanProperty(configuration,
+        DEFAULT_OPTION.isAllowRenegociate(),
+        "ssl." + tag + ".allowRenegociate",
+        "ssl.allowRenegociate"));
+    option.setStorePath(
+        getStringProperty(configuration,
+            DEFAULT_OPTION.getStorePath(),
+            "ssl." + tag + ".storePath",
+            "ssl.storePath"));
+    option.setTrustStore(
+        getStringProperty(configuration,
+            DEFAULT_OPTION.getTrustStore(),
+            "ssl." + tag + ".trustStore",
+            "ssl.trustStore"));
+    option.setTrustStoreType(getStringProperty(configuration,
+        DEFAULT_OPTION.getTrustStoreType(),
+        "ssl." + tag + ".trustStoreType",
+        "ssl.trustStoreType"));
+    option.setTrustStoreValue(getStringProperty(configuration,
+        DEFAULT_OPTION.getTrustStoreValue(),
+        "ssl." + tag + ".trustStoreValue",
+        "ssl.trustStoreValue"));
+    option.setKeyStore(
+        getStringProperty(configuration, DEFAULT_OPTION.getKeyStore(), "ssl." + tag + ".keyStore", "ssl.keyStore"));
+    option.setKeyStoreType(
+        getStringProperty(configuration,
+            DEFAULT_OPTION.getKeyStoreType(),
+            "ssl." + tag + ".keyStoreType",
+            "ssl.keyStoreType"));
+    option.setKeyStoreValue(getStringProperty(configuration,
+        DEFAULT_OPTION.getKeyStoreValue(),
+        "ssl." + tag + ".keyStoreValue",
+        "ssl.keyStoreValue"));
+    option.setCrl(getStringProperty(configuration, DEFAULT_OPTION.getCrl(), "ssl." + tag + ".crl", "ssl.crl"));
+    option.setSslCustomClass(
+        getStringProperty(configuration, null, "ssl." + tag + ".sslCustomClass", "ssl.sslCustomClass"));
+
+    sslProperties.setSslOption(option);
+    sslProperties.setSslCustom(SSLCustom.createSSLCustom(option.getSslCustomClass()));
+    return sslProperties;
+  }
+
+  private static String getStringProperty(Configuration configuration, String defaultValue, String... keys) {
+    for (String key : keys) {
+      if (configuration.containsKey(key)) {
+        return configuration.getString(key);
+      }
+    }
+    return defaultValue;
+  }
+
+  private static boolean getBooleanProperty(Configuration configuration, boolean defaultValue, String... keys) {
+    for (String key : keys) {
+      if (configuration.containsKey(key)) {
+        return configuration.getBoolean(key);
+      }
+    }
+    return defaultValue;
+  }
+}
diff --git a/dynamic-config/config-cc/src/main/java/org/apache/servicecomb/config/archaius/sources/ConfigCenterConfigurationSourceImpl.java b/dynamic-config/config-cc/src/main/java/org/apache/servicecomb/config/archaius/sources/ConfigCenterConfigurationSourceImpl.java
deleted file mode 100644
index 04b53a7..0000000
--- a/dynamic-config/config-cc/src/main/java/org/apache/servicecomb/config/archaius/sources/ConfigCenterConfigurationSourceImpl.java
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * 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.servicecomb.config.archaius.sources;
-
-import static com.netflix.config.WatchedUpdateResult.createIncremental;
-
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.CopyOnWriteArrayList;
-
-import org.apache.commons.configuration.Configuration;
-import org.apache.servicecomb.config.ConfigMapping;
-import org.apache.servicecomb.config.YAMLUtil;
-import org.apache.servicecomb.config.client.ConfigCenterClient;
-import org.apache.servicecomb.config.client.ConfigCenterConfig;
-import org.apache.servicecomb.config.collect.ConfigCenterDefaultDeploymentProvider;
-import org.apache.servicecomb.config.spi.ConfigCenterConfigurationSource;
-import org.apache.servicecomb.deployment.Deployment;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Maps;
-import com.netflix.config.ConcurrentCompositeConfiguration;
-import com.netflix.config.WatchedUpdateListener;
-import com.netflix.config.WatchedUpdateResult;
-
-/**
- * Created by on 2017/1/9.
- */
-public class ConfigCenterConfigurationSourceImpl implements ConfigCenterConfigurationSource {
-  private static final Logger LOGGER = LoggerFactory.getLogger(ConfigCenterConfigurationSourceImpl.class);
-
-  private final Map<String, Object> valueCache = Maps.newConcurrentMap();
-
-  private final List<WatchedUpdateListener> listeners = new CopyOnWriteArrayList<>();
-
-  private UpdateHandler updateHandler = new UpdateHandler();
-
-  private ConfigCenterClient configCenterClient;
-
-  public ConfigCenterConfigurationSourceImpl() {
-  }
-
-  @Override
-  public int getOrder() {
-    return ORDER_BASE * 1;
-  }
-
-  @Override
-  public boolean isValidSource(Configuration localConfiguration) {
-    return Deployment.getSystemBootStrapInfo(ConfigCenterDefaultDeploymentProvider.SYSTEM_KEY_CONFIG_CENTER) != null;
-  }
-
-  private void init() {
-    configCenterClient = new ConfigCenterClient(updateHandler);
-    configCenterClient.connectServer();
-  }
-
-  @Override
-  public void init(Configuration localConfiguration) {
-    ConfigCenterConfig.setConcurrentCompositeConfiguration((ConcurrentCompositeConfiguration) localConfiguration);
-    init();
-  }
-
-  @Override
-  public void destroy() {
-    if (configCenterClient == null) {
-      return;
-    }
-
-    configCenterClient.destroy();
-  }
-
-  public void addUpdateListener(WatchedUpdateListener watchedUpdateListener) {
-    if (watchedUpdateListener != null) {
-      listeners.add(watchedUpdateListener);
-    }
-  }
-
-  public void removeUpdateListener(WatchedUpdateListener watchedUpdateListener) {
-    if (watchedUpdateListener != null) {
-      listeners.remove(watchedUpdateListener);
-    }
-  }
-
-  private void updateConfiguration(WatchedUpdateResult result) {
-    for (WatchedUpdateListener l : listeners) {
-      try {
-        l.updateConfiguration(result);
-      } catch (Throwable ex) {
-        LOGGER.error("Error in invoking WatchedUpdateListener", ex);
-      }
-    }
-  }
-
-  public Map<String, Object> getCurrentData()
-      throws Exception {
-    return valueCache;
-  }
-
-  public List<WatchedUpdateListener> getCurrentListeners() {
-    return listeners;
-  }
-
-  public class UpdateHandler {
-
-    public void handle(String action, Map<String, Object> parseConfigs) {
-      if (parseConfigs == null || parseConfigs.isEmpty()) {
-        return;
-      }
-
-      Map<String, Object> configuration = ConfigMapping.getConvertedMap(parseConfigs);
-      if (configCenterClient != null) {
-        List<String> fileSourceList = configCenterClient.getFileSources();
-        if (fileSourceList != null) {
-          fileSourceList.forEach(fileName -> {
-            if (configuration.containsKey(fileName)) {
-              replaceConfig(configuration, fileName);
-            }
-          });
-        }
-      }
-
-      if ("create".equals(action)) {
-        valueCache.putAll(configuration);
-        updateConfiguration(createIncremental(ImmutableMap.<String, Object>copyOf(configuration),
-            null,
-            null));
-      } else if ("set".equals(action)) {
-        valueCache.putAll(configuration);
-        updateConfiguration(createIncremental(null, ImmutableMap.<String, Object>copyOf(configuration),
-            null));
-      } else if ("delete".equals(action)) {
-        configuration.keySet().forEach(valueCache::remove);
-        updateConfiguration(createIncremental(null,
-            null,
-            ImmutableMap.<String, Object>copyOf(configuration)));
-      } else {
-        LOGGER.error("action: {} is invalid.", action);
-        return;
-      }
-      LOGGER.info("Config value cache changed: action:{}; item:{}", action, configuration.keySet());
-    }
-
-    private void replaceConfig(Map<String, Object> configuration, String fileName) {
-      Object tempConfig = configuration.get(fileName);
-      try {
-        Map<String, Object> properties = YAMLUtil.yaml2Properties(tempConfig.toString());
-        configuration.putAll(properties);
-      } catch (Exception e) {
-        LOGGER.warn("yaml file has incorrect format", e);
-      }
-    }
-  }
-}
diff --git a/dynamic-config/config-cc/src/main/java/org/apache/servicecomb/config/client/ConfigCenterClient.java b/dynamic-config/config-cc/src/main/java/org/apache/servicecomb/config/client/ConfigCenterClient.java
deleted file mode 100644
index 290a6d4..0000000
--- a/dynamic-config/config-cc/src/main/java/org/apache/servicecomb/config/client/ConfigCenterClient.java
+++ /dev/null
@@ -1,427 +0,0 @@
-/*
- * 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.servicecomb.config.client;
-
-import com.fasterxml.jackson.core.type.TypeReference;
-import io.netty.handler.codec.http.HttpResponseStatus;
-import io.vertx.core.MultiMap;
-import io.vertx.core.buffer.Buffer;
-import io.vertx.core.http.HttpClientRequest;
-import io.vertx.core.http.WebSocket;
-import io.vertx.core.http.WebSocketConnectOptions;
-import io.vertx.core.http.impl.FrameType;
-import io.vertx.core.http.impl.ws.WebSocketFrameImpl;
-import org.apache.commons.lang.StringUtils;
-import org.apache.servicecomb.config.archaius.sources.ConfigCenterConfigurationSourceImpl;
-import org.apache.servicecomb.foundation.auth.AuthHeaderLoader;
-import org.apache.servicecomb.foundation.auth.SignRequest;
-import org.apache.servicecomb.foundation.common.event.EventManager;
-import org.apache.servicecomb.foundation.common.net.IpPort;
-import org.apache.servicecomb.foundation.common.net.NetUtils;
-import org.apache.servicecomb.foundation.common.utils.JsonUtils;
-import org.apache.servicecomb.foundation.vertx.client.http.HttpClientWithContext;
-import org.apache.servicecomb.foundation.vertx.client.http.HttpClients;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.UnsupportedEncodingException;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.net.URLEncoder;
-import java.net.UnknownHostException;
-import java.nio.charset.StandardCharsets;
-import java.util.*;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.TimeUnit;
-
-public class ConfigCenterClient {
-
-  private static final Logger LOGGER = LoggerFactory.getLogger(ConfigCenterClient.class);
-
-  private static final ConfigCenterConfig CONFIG_CENTER_CONFIG = ConfigCenterConfig.INSTANCE;
-
-  private static final long HEARTBEAT_INTERVAL = 30000;
-
-  private static final long BOOTUP_WAIT_TIME = 10;
-
-  private ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
-
-  private ScheduledExecutorService heartbeatTask = null;
-
-  private int refreshMode = CONFIG_CENTER_CONFIG.getRefreshMode();
-
-  private int refreshInterval = CONFIG_CENTER_CONFIG.getRefreshInterval();
-
-  private int firstRefreshInterval = CONFIG_CENTER_CONFIG.getFirstRefreshInterval();
-
-  private int refreshPort = CONFIG_CENTER_CONFIG.getRefreshPort();
-
-  private String tenantName = CONFIG_CENTER_CONFIG.getTenantName();
-
-  private String serviceName = CONFIG_CENTER_CONFIG.getServiceName();
-
-  private String environment = CONFIG_CENTER_CONFIG.getEnvironment();
-  
-  private List<String> fileSources = CONFIG_CENTER_CONFIG.getFileSources();
-  
-  public List<String> getFileSources() {
-    return fileSources;
-  }
-
-  private MemberDiscovery memberDiscovery = new MemberDiscovery(CONFIG_CENTER_CONFIG.getServerUri());
-
-  private ConfigCenterConfigurationSourceImpl.UpdateHandler updateHandler;
-
-  private boolean isWatching = false;
-
-  private URIConst uriConst = new URIConst();
-
-  public ConfigCenterClient(ConfigCenterConfigurationSourceImpl.UpdateHandler updateHandler) {
-    HttpClients.addNewClientPoolManager(new ConfigCenterHttpClientOptionsSPI());
-    this.updateHandler = updateHandler;
-  }
-
-  public void connectServer() {
-    if (refreshMode != 0 && refreshMode != 1) {
-      LOGGER.error("refreshMode must be 0 or 1.");
-      return;
-    }
-    ParseConfigUtils.getInstance().initWithUpdateHandler(updateHandler);
-    refreshMembers(memberDiscovery);
-    ConfigRefresh refreshTask = new ConfigRefresh(ParseConfigUtils.getInstance(), memberDiscovery);
-    refreshTask.run(true);
-    executor.scheduleWithFixedDelay(refreshTask,
-        firstRefreshInterval,
-        refreshInterval,
-        TimeUnit.MILLISECONDS);
-  }
-
-  public void destroy() {
-    if (executor != null) {
-      executor.shutdown();
-      executor = null;
-    }
-
-    if (heartbeatTask != null) {
-      heartbeatTask.shutdown();
-      heartbeatTask = null;
-    }
-  }
-
-  private void refreshMembers(MemberDiscovery memberDiscovery) {
-    if (CONFIG_CENTER_CONFIG.getAutoDiscoveryEnabled()) {
-      String configCenter = memberDiscovery.getConfigServer();
-      IpPort ipPort = NetUtils.parseIpPortFromURI(configCenter);
-      HttpClients.getClient(ConfigCenterHttpClientOptionsSPI.CLIENT_NAME).runOnContext(client -> {
-        @SuppressWarnings("deprecation")
-        HttpClientRequest request =
-            client.get(ipPort.getPort(), ipPort.getHostOrIp(), uriConst.MEMBERS, rsp -> {
-              if (rsp.statusCode() == HttpResponseStatus.OK.code()) {
-                rsp.bodyHandler(buf -> {
-                  memberDiscovery.refreshMembers(buf.toJsonObject());
-                });
-              }
-            });
-        SignRequest signReq = createSignRequest(request.method().toString(),
-            configCenter + uriConst.MEMBERS,
-            new HashMap<>(),
-            null);
-        if (ConfigCenterConfig.INSTANCE.getToken() != null) {
-          request.headers().add("X-Auth-Token", ConfigCenterConfig.INSTANCE.getToken());
-        }
-        request.headers()
-            .addAll(AuthHeaderLoader.getInstance().loadAuthHeaders(signReq));
-        request.exceptionHandler(e -> {
-          LOGGER.error("Fetch member from {} failed. Error message is [{}].", configCenter, e.getMessage());
-          logIfDnsFailed(e);
-        });
-        request.end();
-      });
-    }
-  }
-
-  class ConfigRefresh implements Runnable {
-    private ParseConfigUtils parseConfigUtils;
-
-    private MemberDiscovery memberdis;
-
-    ConfigRefresh(ParseConfigUtils parseConfigUtils, MemberDiscovery memberdis) {
-      this.parseConfigUtils = parseConfigUtils;
-      this.memberdis = memberdis;
-    }
-
-    public void run(boolean wait) {
-      try {
-        String configCenter = memberdis.getConfigServer();
-        if (refreshMode == 1) {
-          //make sure that revision is updated timely,wait sub thread to finish it's pull task
-          refreshConfig(configCenter, true);
-        } else if (!isWatching) {
-          // 重新监听时需要先加载,避免在断开期间丢失变更
-          //we do not need worry about that the revision may not be updated timely, because we do not need
-          //revision info in the push mode. the config-center will push the changing to us
-          refreshConfig(configCenter, wait);
-          doWatch(configCenter);
-        }
-      } catch (Throwable e) {
-        LOGGER.error("client refresh thread exception", e);
-      }
-    }
-
-    // 具体动作
-    @Override
-    public void run() {
-      run(false);
-    }
-
-    // create watch and wait for done
-    public void doWatch(String configCenter)
-        throws UnsupportedEncodingException, InterruptedException {
-      CountDownLatch waiter = new CountDownLatch(1);
-      IpPort ipPort = NetUtils.parseIpPortFromURI(configCenter);
-      String url = uriConst.REFRESH_ITEMS + "?dimensionsInfo="
-          + StringUtils.deleteWhitespace(URLEncoder.encode(serviceName, "UTF-8"));
-      Map<String, String> headers = new HashMap<>();
-      headers.put("x-domain-name", tenantName);
-      if (ConfigCenterConfig.INSTANCE.getToken() != null) {
-        headers.put("X-Auth-Token", ConfigCenterConfig.INSTANCE.getToken());
-      }
-      headers.put("x-environment", environment);
-
-      HttpClientWithContext vertxHttpClient = HttpClients.getClient(ConfigCenterHttpClientOptionsSPI.CLIENT_NAME);
-
-      vertxHttpClient.runOnContext(client -> {
-        Map<String, String> authHeaders = new HashMap<>();
-        authHeaders.putAll(AuthHeaderLoader.getInstance().loadAuthHeaders((
-            createSignRequest(null, configCenter + url, headers, null))));
-        WebSocketConnectOptions options = new WebSocketConnectOptions();
-        options.setHost(ipPort.getHostOrIp()).setPort(refreshPort).setURI(url)
-            .setHeaders(MultiMap.caseInsensitiveMultiMap().addAll(headers)
-                .addAll(authHeaders));
-        client.webSocket(options, asyncResult -> {
-          if (asyncResult.failed()) {
-            LOGGER.error(
-                "watcher connect to config center {} refresh port {} failed. Error message is [{}]",
-                configCenter,
-                refreshPort,
-                asyncResult.cause().getMessage());
-            waiter.countDown();
-          } else {
-            {
-              asyncResult.result().exceptionHandler(e -> {
-                LOGGER.error("watch config read fail", e);
-                stopHeartBeatThread();
-                isWatching = false;
-              });
-              asyncResult.result().closeHandler(v -> {
-                LOGGER.warn("watching config connection is closed accidentally");
-                stopHeartBeatThread();
-                isWatching = false;
-              });
-
-              asyncResult.result().pongHandler(pong -> {
-                // ignore, just prevent NPE.
-              });
-              asyncResult.result().frameHandler(frame -> {
-                if (frame.isText() || frame.isBinary()) {
-                  Buffer action = frame.binaryData();
-                  LOGGER.debug("watching config received {}", action);
-                  Map<String, Object> mAction = null;
-
-                  try {
-                    mAction = action.toJsonObject().getMap();
-                  } catch (Exception e) {
-                    LOGGER.error("parse config item failed.", e);
-                    return;
-                  }
-
-                  if ("CREATE".equals(mAction.get("action"))) {
-                    //event loop can not be blocked,we just keep nothing changed in push mode
-                    refreshConfig(configCenter, false);
-                  } else if ("MEMBER_CHANGE".equals(mAction.get("action"))) {
-                    refreshMembers(memberdis);
-                  } else {
-                    parseConfigUtils.refreshConfigItemsIncremental(mAction);
-                  }
-                }
-              });
-              startHeartBeatThread(asyncResult.result());
-              isWatching = true;
-              waiter.countDown();
-            }
-          }
-        });
-      });
-      waiter.await();
-    }
-
-    private void startHeartBeatThread(WebSocket ws) {
-      heartbeatTask = Executors.newScheduledThreadPool(1);
-      heartbeatTask.scheduleWithFixedDelay(() -> sendHeartbeat(ws),
-          HEARTBEAT_INTERVAL,
-          HEARTBEAT_INTERVAL,
-          TimeUnit.MILLISECONDS);
-    }
-
-    private void stopHeartBeatThread() {
-      if (heartbeatTask != null) {
-        heartbeatTask.shutdownNow();
-      }
-    }
-
-    private void sendHeartbeat(WebSocket ws) {
-      try {
-        ws.writeFrame(new WebSocketFrameImpl(FrameType.PING));
-        EventManager.post(new ConnSuccEvent());
-      } catch (IllegalStateException e) {
-        EventManager.post(new ConnFailEvent("heartbeat fail, " + e.getMessage()));
-        LOGGER.error("heartbeat fail", e);
-      }
-    }
-
-    public void refreshConfig(String configcenter, boolean wait) {
-      CountDownLatch latch = new CountDownLatch(1);
-      String encodeServiceName = "";
-      try {
-        encodeServiceName =
-            URLEncoder.encode(StringUtils.deleteWhitespace(serviceName), StandardCharsets.UTF_8.name());
-      } catch (UnsupportedEncodingException e) {
-        LOGGER.error("encode failed. Error message: {}", e.getMessage());
-        encodeServiceName = StringUtils.deleteWhitespace(serviceName);
-      }
-      //just log in the debug level
-      if (LOGGER.isDebugEnabled()) {
-        LOGGER.debug("Updating remote config...");
-      }
-      String path = uriConst.ITEMS + "?dimensionsInfo=" + encodeServiceName + "&revision="
-          + ParseConfigUtils.getInstance().getCurrentVersionInfo();
-      HttpClients.getClient(ConfigCenterHttpClientOptionsSPI.CLIENT_NAME).runOnContext(client -> {
-        IpPort ipPort = NetUtils.parseIpPortFromURI(configcenter);
-        @SuppressWarnings("deprecation")
-        HttpClientRequest request = client.get(ipPort.getPort(), ipPort.getHostOrIp(), path, rsp -> {
-          if (rsp.statusCode() == HttpResponseStatus.OK.code()) {
-            rsp.bodyHandler(buf -> {
-              try {
-                parseConfigUtils
-                    .refreshConfigItems(JsonUtils.OBJ_MAPPER.readValue(buf.toString(),
-                        new TypeReference<LinkedHashMap<String, Map<String, Object>>>() {
-                        }));
-                EventManager.post(new ConnSuccEvent());
-              } catch (IOException e) {
-                EventManager.post(new ConnFailEvent(
-                    "config update result parse fail " + e.getMessage()));
-                LOGGER.error("Config update from {} failed. Error message is [{}].",
-                    configcenter,
-                    e.getMessage());
-              }
-              latch.countDown();
-            });
-          } else if (rsp.statusCode() == HttpResponseStatus.NOT_MODIFIED.code()) {
-            //nothing changed
-            EventManager.post(new ConnSuccEvent());
-            if (LOGGER.isDebugEnabled()) {
-              LOGGER.debug("Updating remote config is done. the revision {} has no change",
-                  ParseConfigUtils.getInstance().getCurrentVersionInfo());
-            }
-            latch.countDown();
-          } else {
-            rsp.bodyHandler(buf -> {
-              LOGGER.error("Server error message is [{}].", buf);
-              latch.countDown();
-            });
-            EventManager.post(new ConnFailEvent("fetch config fail"));
-            LOGGER.error("Config update from {} failed.", configcenter);
-          }
-        }).setTimeout((BOOTUP_WAIT_TIME - 1) * 1000);
-        Map<String, String> headers = new HashMap<>();
-        headers.put("x-domain-name", tenantName);
-        if (ConfigCenterConfig.INSTANCE.getToken() != null) {
-          headers.put("X-Auth-Token", ConfigCenterConfig.INSTANCE.getToken());
-        }
-        headers.put("x-environment", environment);
-        request.headers().addAll(headers);
-        request.headers()
-            .addAll(AuthHeaderLoader.getInstance().loadAuthHeaders(createSignRequest(request.method().toString(),
-                configcenter + path,
-                headers,
-                null)));
-        request.exceptionHandler(e -> {
-          EventManager.post(new ConnFailEvent("fetch config fail"));
-          LOGGER.error("Config update from {} failed. Error message is [{}].",
-              configcenter,
-              e.getMessage());
-          logIfDnsFailed(e);
-          latch.countDown();
-        });
-        request.end();
-      });
-      if (wait) {
-        try {
-          latch.await(BOOTUP_WAIT_TIME, TimeUnit.SECONDS);
-        } catch (InterruptedException e) {
-          LOGGER.warn(e.getMessage());
-        }
-      }
-    }
-  }
-
-  public static SignRequest createSignRequest(String method, String endpoint, Map<String, String> headers,
-      InputStream content) {
-    SignRequest signReq = new SignRequest();
-    try {
-      signReq.setEndpoint(new URI(endpoint));
-    } catch (URISyntaxException e) {
-      LOGGER.warn("set uri failed, uri is {}, message: {}", endpoint, e.getMessage());
-    }
-
-    Map<String, String[]> queryParams = new HashMap<>();
-    if (endpoint.contains("?")) {
-      String parameters = endpoint.substring(endpoint.indexOf("?") + 1);
-      if (null != parameters && !"".equals(parameters)) {
-        String[] parameterarray = parameters.split("&");
-        for (String p : parameterarray) {
-          String key = p.split("=")[0];
-          String value = p.split("=")[1];
-          if (!queryParams.containsKey(key)) {
-            queryParams.put(key, new String[] {value});
-          } else {
-            List<String> vals = new ArrayList<>(Arrays.asList(queryParams.get(key)));
-            vals.add(value);
-            queryParams.put(key, vals.toArray(new String[vals.size()]));
-          }
-        }
-      }
-    }
-    signReq.setQueryParams(queryParams);
-
-    signReq.setHeaders(headers);
-    signReq.setHttpMethod(method);
-    signReq.setContent(content);
-    return signReq;
-  }
-
-  private void logIfDnsFailed(Throwable e) {
-    if (e instanceof UnknownHostException) {
-      LOGGER.error("DNS resolve failed!", e);
-    }
-  }
-}
diff --git a/dynamic-config/config-cc/src/main/java/org/apache/servicecomb/config/client/ConfigCenterHttpClientOptionsSPI.java b/dynamic-config/config-cc/src/main/java/org/apache/servicecomb/config/client/ConfigCenterHttpClientOptionsSPI.java
deleted file mode 100644
index e9980f2..0000000
--- a/dynamic-config/config-cc/src/main/java/org/apache/servicecomb/config/client/ConfigCenterHttpClientOptionsSPI.java
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * 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.servicecomb.config.client;
-
-import org.apache.servicecomb.config.collect.ConfigCenterDefaultDeploymentProvider;
-import org.apache.servicecomb.deployment.Deployment;
-import org.apache.servicecomb.foundation.vertx.client.http.HttpClientOptionsSPI;
-
-import com.netflix.config.ConcurrentCompositeConfiguration;
-
-import io.vertx.core.VertxOptions;
-import io.vertx.core.http.HttpClientOptions;
-import io.vertx.core.http.HttpVersion;
-
-public class ConfigCenterHttpClientOptionsSPI implements HttpClientOptionsSPI {
-  public static final String CLIENT_NAME = "config-center";
-
-  @Override
-  public String clientName() {
-    return CLIENT_NAME;
-  }
-
-  @Override
-  public int getOrder() {
-    return -100;
-  }
-
-  @Override
-  public boolean enabled() {
-    return Deployment.getSystemBootStrapInfo(ConfigCenterDefaultDeploymentProvider.SYSTEM_KEY_CONFIG_CENTER) != null;
-  }
-
-  @Override
-  public String getConfigTag() {
-    return "cc.consumer";
-  }
-
-  @Override
-  public ConcurrentCompositeConfiguration getConfigReader() {
-    return ConfigCenterConfig.getConcurrentCompositeConfiguration();
-  }
-
-  @Override
-  public int getEventLoopPoolSize() {
-    return ConfigCenterConfig.INSTANCE.getEventLoopSize();
-  }
-
-  @Override
-  public boolean useSharedVertx() {
-    return false;
-  }
-
-  @Override
-  public int getInstanceCount() {
-    return ConfigCenterConfig.INSTANCE.getVerticalInstanceCount();
-  }
-
-  @Override
-  public boolean isWorker() {
-    return false;
-  }
-
-  @Override
-  public String getWorkerPoolName() {
-    return "pool-worker-config-center-client";
-  }
-
-  @Override
-  public int getWorkerPoolSize() {
-    return VertxOptions.DEFAULT_WORKER_POOL_SIZE;
-  }
-
-  @Override
-  public HttpVersion getHttpVersion() {
-    return HttpVersion.HTTP_1_1;
-  }
-
-  @Override
-  public int getConnectTimeoutInMillis() {
-    return ConfigCenterConfig.INSTANCE.getConnectionTimeout();
-  }
-
-  @Override
-  public int getIdleTimeoutInSeconds() {
-    return ConfigCenterConfig.INSTANCE.getIdleTimeoutInSeconds();
-  }
-
-  @Override
-  public boolean isTryUseCompression() {
-    return HttpClientOptions.DEFAULT_TRY_USE_COMPRESSION;
-  }
-
-  @Override
-  public int getMaxWaitQueueSize() {
-    return HttpClientOptions.DEFAULT_MAX_WAIT_QUEUE_SIZE;
-  }
-
-  @Override
-  public int getMaxPoolSize() {
-    return HttpClientOptions.DEFAULT_MAX_POOL_SIZE;
-  }
-
-  @Override
-  public boolean isKeepAlive() {
-    return HttpClientOptions.DEFAULT_KEEP_ALIVE;
-  }
-
-  @Override
-  public int getMaxHeaderSize() {
-    return HttpClientOptions.DEFAULT_MAX_HEADER_SIZE;
-  }
-
-  @Override
-  public int getKeepAliveTimeout() {
-    return HttpClientOptions.DEFAULT_KEEP_ALIVE_TIMEOUT;
-  }
-
-  @Override
-  public int getHttp2MultiplexingLimit() {
-    return HttpClientOptions.DEFAULT_HTTP2_MULTIPLEXING_LIMIT;
-  }
-
-  @Override
-  public int getHttp2MaxPoolSize() {
-    return HttpClientOptions.DEFAULT_HTTP2_MAX_POOL_SIZE;
-  }
-
-  @Override
-  public boolean isUseAlpn() {
-    return HttpClientOptions.DEFAULT_USE_ALPN;
-  }
-
-  @Override
-  public boolean isProxyEnable() {
-    return ConfigCenterConfig.INSTANCE.isProxyEnable();
-  }
-
-  @Override
-  public String getProxyHost() {
-    return ConfigCenterConfig.INSTANCE.getProxyHost();
-  }
-
-  @Override
-  public int getProxyPort() {
-    return ConfigCenterConfig.INSTANCE.getProxyPort();
-  }
-
-  @Override
-  public String getProxyUsername() {
-    return ConfigCenterConfig.INSTANCE.getProxyUsername();
-  }
-
-  @Override
-  public String getProxyPassword() {
-    return ConfigCenterConfig.INSTANCE.getProxyPasswd();
-  }
-
-  @Override
-  public boolean isSsl() {
-    return ConfigCenterConfig.INSTANCE.getServerUri().get(0).startsWith("https");
-  }
-}
diff --git a/dynamic-config/config-cc/src/main/java/org/apache/servicecomb/config/client/ConnFailEvent.java b/dynamic-config/config-cc/src/main/java/org/apache/servicecomb/config/client/ConnFailEvent.java
deleted file mode 100644
index b608fae..0000000
--- a/dynamic-config/config-cc/src/main/java/org/apache/servicecomb/config/client/ConnFailEvent.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * 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.servicecomb.config.client;
-
-public class ConnFailEvent {
-
-  private String msg;
-
-  public ConnFailEvent(String msg) {
-    this.msg = msg;
-  }
-
-  public String getMsg() {
-    return msg;
-  }
-
-  public void setMsg(String msg) {
-    this.msg = msg;
-  }
-}
diff --git a/dynamic-config/config-cc/src/main/java/org/apache/servicecomb/config/client/ConnSuccEvent.java b/dynamic-config/config-cc/src/main/java/org/apache/servicecomb/config/client/ConnSuccEvent.java
deleted file mode 100644
index 54239ab..0000000
--- a/dynamic-config/config-cc/src/main/java/org/apache/servicecomb/config/client/ConnSuccEvent.java
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * 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.servicecomb.config.client;
-
-public class ConnSuccEvent {
-
-}
diff --git a/dynamic-config/config-cc/src/main/java/org/apache/servicecomb/config/client/MemberDiscovery.java b/dynamic-config/config-cc/src/main/java/org/apache/servicecomb/config/client/MemberDiscovery.java
deleted file mode 100644
index cee4c04..0000000
--- a/dynamic-config/config-cc/src/main/java/org/apache/servicecomb/config/client/MemberDiscovery.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * 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.servicecomb.config.client;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.concurrent.atomic.AtomicInteger;
-
-import org.apache.servicecomb.foundation.common.event.EventManager;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.eventbus.Subscribe;
-
-import io.vertx.core.json.JsonObject;
-
-/**
- * Created by on 2016/11/19.
- */
-public class MemberDiscovery {
-
-  private static final Logger LOGGER = LoggerFactory.getLogger(MemberDiscovery.class);
-
-  private static final String SCHEMA_SEPRATOR = "://";
-
-  private List<String> configServerAddresses = new ArrayList<>();
-
-  private Object lock = new Object();
-
-  private AtomicInteger counter = new AtomicInteger(0);
-
-  public MemberDiscovery(List<String> configCenterUri) {
-    if (configCenterUri != null && !configCenterUri.isEmpty()) {
-      configServerAddresses.addAll(configCenterUri);
-    }
-    Collections.shuffle(configServerAddresses);
-    EventManager.register(this);
-  }
-
-  public String getConfigServer() {
-    synchronized (lock) {
-      if (configServerAddresses.isEmpty()) {
-        throw new IllegalStateException("Config center address is not available.");
-      }
-      int index = Math.abs(counter.get() % configServerAddresses.size());
-      return configServerAddresses.get(index);
-    }
-  }
-
-  @Subscribe
-  public void onConnFailEvent(ConnFailEvent e) {
-    counter.incrementAndGet();
-  }
-
-  public void refreshMembers(JsonObject members) {
-    List<String> newServerAddresses = new ArrayList<>();
-    members.getJsonArray("instances").forEach(m -> {
-      JsonObject instance = (JsonObject) m;
-      if ("UP".equals(instance.getString("status", "UP"))) {
-        String endpoint = instance.getJsonArray("endpoints").getString(0);
-        String scheme = instance.getBoolean("isHttps", false) ? "https" : "http";
-        newServerAddresses.add(scheme + SCHEMA_SEPRATOR
-            + endpoint.substring(endpoint.indexOf(SCHEMA_SEPRATOR) + SCHEMA_SEPRATOR.length()));
-      }
-    });
-
-    synchronized (lock) {
-      this.configServerAddresses.clear();
-      this.configServerAddresses.addAll(newServerAddresses);
-      Collections.shuffle(this.configServerAddresses);
-    }
-    LOGGER.info("New config center members: {}", this.configServerAddresses);
-  }
-}
diff --git a/dynamic-config/config-cc/src/main/java/org/apache/servicecomb/config/client/ParseConfigUtils.java b/dynamic-config/config-cc/src/main/java/org/apache/servicecomb/config/client/ParseConfigUtils.java
deleted file mode 100644
index b20262a..0000000
--- a/dynamic-config/config-cc/src/main/java/org/apache/servicecomb/config/client/ParseConfigUtils.java
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
- * 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.servicecomb.config.client;
-
-import java.io.IOException;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.LinkedHashMap;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeSet;
-import java.util.concurrent.locks.Lock;
-import java.util.concurrent.locks.ReentrantLock;
-
-import org.apache.servicecomb.config.archaius.sources.ConfigCenterConfigurationSourceImpl.UpdateHandler;
-import org.apache.servicecomb.foundation.common.utils.JsonUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.fasterxml.jackson.core.type.TypeReference;
-
-/**
- * Created by on 2017/1/5.
- */
-public class ParseConfigUtils {
-
-  private static final Logger LOGGER = LoggerFactory.getLogger(ParseConfigUtils.class);
-
-  private static final ParseConfigUtils INSTANCE = new ParseConfigUtils();
-
-  private LinkedHashMap<String, Map<String, Object>> multiDimensionItems = new LinkedHashMap<>();
-
-  //it's dangerous to make flatItems public
-  private final Map<String, Object> flatItems = new HashMap<>();
-
-  private String currentVersionInfo = "default";
-
-  private UpdateHandler updateHandler;
-
-  private Lock configLock = new ReentrantLock();
-
-  //for compatibility with other modules and JunitTest
-  public ParseConfigUtils(UpdateHandler updateHandler) {
-    this.updateHandler = updateHandler;
-  }
-
-  private ParseConfigUtils() {
-  }
-
-  public void initWithUpdateHandler(UpdateHandler updateHandler) {
-    if (updateHandler == null) {
-      LOGGER.error("when init ParseConfigUtils, updateHandler can not be null");
-    }
-    this.updateHandler = updateHandler;
-  }
-
-  /*
-      as the data is returned, we can block the thread at a short time. consider that if the multiple verticles were deployed
-      and if we use pull mode and push mode at the same time , we must share a common lock with all methods which would
-      change the config setting
-     */
-  public void refreshConfigItems(Map<String, Map<String, Object>> remoteItems) {
-    try {
-      configLock.lock();
-      String oldRevision = currentVersionInfo;
-      currentVersionInfo =
-          remoteItems.getOrDefault("revision", new HashMap<>()).getOrDefault("version", "default").toString();
-      //make sure the currentVersionInfo != ""
-      currentVersionInfo = currentVersionInfo.equals("") ? "default" : currentVersionInfo;
-      //the key revision is not the config setting
-      boolean newVersion = (remoteItems.remove("revision") != null);
-      multiDimensionItems.clear();
-      multiDimensionItems.putAll(remoteItems);
-      doRefreshItems();
-      if (newVersion) {
-        LOGGER.info("Updating remote config is done. revision has changed from {} to {}", oldRevision,
-            currentVersionInfo);
-      }
-    } finally {
-      configLock.unlock();
-    }
-  }
-
-  public static ParseConfigUtils getInstance() {
-    return INSTANCE;
-  }
-
-  public String getCurrentVersionInfo() {
-    return this.currentVersionInfo;
-  }
-
-  public void refreshConfigItemsIncremental(Map<String, Object> action) {
-    try {
-      configLock.lock();
-      if ("UPDATE".equals(action.get("action"))) {
-        try {
-          multiDimensionItems.put((String) action.get("key"), JsonUtils.OBJ_MAPPER
-              .readValue(action.get("value").toString(), new TypeReference<Map<String, Object>>() {
-              }));
-        } catch (IOException e) {
-          LOGGER.error("parse config change action fail");
-        }
-        doRefreshItems();
-      } else if ("DELETE".equals(action.get("action"))) {
-        multiDimensionItems.remove(action.get("key"));
-        doRefreshItems();
-      }
-    } finally {
-      configLock.unlock();
-    }
-  }
-
-  private void doRefreshItems() {
-    Map<String, Object> freshFlatItems = mergeDimensionItems(multiDimensionItems);
-    notifyItemsChangedNeedRefresh(flatItems, freshFlatItems);
-    flatItems.clear();
-    flatItems.putAll(freshFlatItems);
-  }
-
-  private Map<String, Object> mergeDimensionItems(Map<String, Map<String, Object>> items) {
-    Map<String, Object> flatMap = new HashMap<>();
-    Set<String> keySet = items.keySet();
-    if (keySet.contains("application")) {
-      flatMap.putAll(items.get("application"));
-      keySet.remove("application");
-    }
-    if (!keySet.isEmpty()) {
-      TreeSet<String> sortedKeys = new TreeSet<String>(new Comparator<String>() {
-        @Override
-        public int compare(String o1, String o2) {
-          return o1.length() - o2.length();
-        }
-      });
-      sortedKeys.addAll(keySet);
-      sortedKeys.forEach(key -> flatMap.putAll(items.get(key)));
-    }
-    return flatMap;
-  }
-
-  private void notifyItemsChangedNeedRefresh(Map<String, Object> before, Map<String, Object> after) {
-    Map<String, Object> itemsCreated = new HashMap<>();
-    Map<String, Object> itemsDeleted = new HashMap<>();
-    Map<String, Object> itemsModified = new HashMap<>();
-    if (before == null || before.isEmpty()) {
-      updateHandler.handle("create", after);
-      return;
-    }
-    if (after == null || after.isEmpty()) {
-      updateHandler.handle("delete", before);
-      return;
-    }
-    for (String itemKey : after.keySet()) {
-      if (!before.containsKey(itemKey)) {
-        itemsCreated.put(itemKey, after.get(itemKey));
-      } else if (!after.get(itemKey).equals(before.get(itemKey))) {
-        itemsModified.put(itemKey, after.get(itemKey));
-      }
-    }
-    for (String itemKey : before.keySet()) {
-      if (!after.containsKey(itemKey)) {
-        itemsDeleted.put(itemKey, "");
-      }
-    }
-    updateHandler.handle("create", itemsCreated);
-    updateHandler.handle("set", itemsModified);
-    updateHandler.handle("delete", itemsDeleted);
-  }
-}
diff --git a/dynamic-config/config-cc/src/main/java/org/apache/servicecomb/config/client/URIConst.java b/dynamic-config/config-cc/src/main/java/org/apache/servicecomb/config/client/URIConst.java
deleted file mode 100644
index 14be671..0000000
--- a/dynamic-config/config-cc/src/main/java/org/apache/servicecomb/config/client/URIConst.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * 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.servicecomb.config.client;
-
-public class URIConst {
-  private final String DOMAIN_NAME = ConfigCenterConfig.INSTANCE.getDomainName();
-
-  private final String CURRENT_VERSION = ConfigCenterConfig.INSTANCE.getApiVersion();
-
-  private final String VERSION_V2 = "v2";
-
-  private final String PREFIX_V2 = "/configuration/v2";
-
-  private final String PREFIX_V3 = String.format("/v3/%s/configuration", DOMAIN_NAME);
-
-  private final boolean isV2 = VERSION_V2.equals(CURRENT_VERSION);
-
-  private final String CURRENT_PREFIX = isV2 ? PREFIX_V2 : PREFIX_V3;
-
-  // v2 no prefix
-  public final String MEMBERS = isV2 ? "/members" : PREFIX_V3 + "/members";
-
-  // v2 has prefix
-  public final String REFRESH_ITEMS = CURRENT_PREFIX + "/refresh/items";
-
-  public final String ITEMS = CURRENT_PREFIX + "/items";
-}
diff --git a/dynamic-config/config-cc/src/main/resources/META-INF/services/org.apache.servicecomb.config.spi.ConfigCenterConfigurationSource b/dynamic-config/config-cc/src/main/resources/META-INF/services/org.apache.servicecomb.config.spi.ConfigCenterConfigurationSource
index 10d2b83..d38ec07 100644
--- a/dynamic-config/config-cc/src/main/resources/META-INF/services/org.apache.servicecomb.config.spi.ConfigCenterConfigurationSource
+++ b/dynamic-config/config-cc/src/main/resources/META-INF/services/org.apache.servicecomb.config.spi.ConfigCenterConfigurationSource
@@ -15,4 +15,4 @@
 # limitations under the License.
 #
 
-org.apache.servicecomb.config.archaius.sources.ConfigCenterConfigurationSourceImpl
\ No newline at end of file
+org.apache.servicecomb.config.ConfigCenterConfigurationSourceImpl
\ No newline at end of file
diff --git a/dynamic-config/config-cc/src/test/java/org/apache/servicecomb/config/archaius/sources/TestConfigCenterConfigurationSource.java b/dynamic-config/config-cc/src/test/java/org/apache/servicecomb/config/archaius/sources/TestConfigCenterConfigurationSource.java
deleted file mode 100644
index ec45127..0000000
--- a/dynamic-config/config-cc/src/test/java/org/apache/servicecomb/config/archaius/sources/TestConfigCenterConfigurationSource.java
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * 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.servicecomb.config.archaius.sources;
-
-import java.util.HashMap;
-import java.util.Map;
-import java.util.concurrent.atomic.AtomicInteger;
-
-import org.apache.commons.lang.reflect.FieldUtils;
-import org.apache.servicecomb.config.archaius.sources.ConfigCenterConfigurationSourceImpl.UpdateHandler;
-import org.apache.servicecomb.config.client.ConfigCenterClient;
-import org.junit.Assert;
-import org.junit.Test;
-import org.mockito.Mockito;
-
-import com.netflix.config.WatchedUpdateListener;
-import com.netflix.config.WatchedUpdateResult;
-
-import mockit.Deencapsulation;
-import mockit.Mock;
-import mockit.MockUp;
-
-/**
- * Created by on 2017/1/12.
- */
-public class TestConfigCenterConfigurationSource {
-  @Test
-  public void testCreate() throws Exception {
-
-    ConfigCenterConfigurationSourceImpl configCenterSource = new ConfigCenterConfigurationSourceImpl();
-    configCenterSource.addUpdateListener(new WatchedUpdateListener() {
-      @Override
-      public void updateConfiguration(WatchedUpdateResult result) {
-        Assert.assertTrue(!result.getAdded().isEmpty());
-      }
-    });
-    UpdateHandler udateHandler = Deencapsulation.getField(configCenterSource, UpdateHandler.class);
-    Map<String, Object> addedItems = new HashMap<>();
-    addedItems.put("testKey", "testValue");
-    udateHandler.handle("create", addedItems);
-  }
-
-  @Test
-  public void testUpdate() throws Exception {
-
-    ConfigCenterConfigurationSourceImpl configCenterSource = new ConfigCenterConfigurationSourceImpl();
-    configCenterSource.addUpdateListener(new WatchedUpdateListener() {
-      @Override
-      public void updateConfiguration(WatchedUpdateResult result) {
-        Assert.assertTrue(!result.getChanged().isEmpty());
-      }
-    });
-    UpdateHandler udateHandler = Deencapsulation.getField(configCenterSource, UpdateHandler.class);
-    Map<String, Object> addedItems = new HashMap<>();
-    addedItems.put("testKey", "testValue");
-    udateHandler.handle("set", addedItems);
-  }
-
-  @Test
-  public void testDelete() throws Exception {
-    ConfigCenterConfigurationSourceImpl configCenterSource = new ConfigCenterConfigurationSourceImpl();
-    configCenterSource.addUpdateListener(new WatchedUpdateListener() {
-      @Override
-      public void updateConfiguration(WatchedUpdateResult result) {
-        Assert.assertTrue(!result.getDeleted().isEmpty());
-      }
-    });
-    UpdateHandler udateHandler = Deencapsulation.getField(configCenterSource, UpdateHandler.class);
-    Map<String, Object> addedItems = new HashMap<>();
-    addedItems.put("testKey", "testValue");
-
-    configCenterSource.getCurrentData().put("testKey", "testValue");
-    udateHandler.handle("delete", addedItems);
-    Assert.assertTrue(configCenterSource.getCurrentData().isEmpty());
-  }
-
-  @Test
-  public void testRemoveUpdateListener() {
-    ConfigCenterConfigurationSourceImpl configCenterSource = new ConfigCenterConfigurationSourceImpl();
-    WatchedUpdateListener watchedUpdateListener = Mockito.mock(WatchedUpdateListener.class);
-    configCenterSource.addUpdateListener(watchedUpdateListener);
-    configCenterSource.removeUpdateListener(watchedUpdateListener);
-    Assert.assertTrue(configCenterSource.getCurrentListeners().isEmpty());
-  }
-
-  @Test
-  public void destroy_notInit() {
-    ConfigCenterConfigurationSourceImpl configCenterSource = new ConfigCenterConfigurationSourceImpl();
-
-    // need not throw exception
-    configCenterSource.destroy();
-  }
-
-  @Test
-  public void destroy_inited() throws IllegalAccessException {
-    AtomicInteger count = new AtomicInteger();
-    ConfigCenterClient configCenterClient = new MockUp<ConfigCenterClient>() {
-      @Mock
-      void destroy() {
-        count.incrementAndGet();
-      }
-    }.getMockInstance();
-    ConfigCenterConfigurationSourceImpl configCenterSource = new ConfigCenterConfigurationSourceImpl();
-    FieldUtils.writeDeclaredField(configCenterSource, "configCenterClient", configCenterClient, true);
-
-    configCenterSource.destroy();
-
-    Assert.assertEquals(1, count.get());
-  }
-}
diff --git a/dynamic-config/config-cc/src/test/java/org/apache/servicecomb/config/client/TestConfigCenterClient.java b/dynamic-config/config-cc/src/test/java/org/apache/servicecomb/config/client/TestConfigCenterClient.java
deleted file mode 100644
index efbd2d3..0000000
--- a/dynamic-config/config-cc/src/test/java/org/apache/servicecomb/config/client/TestConfigCenterClient.java
+++ /dev/null
@@ -1,353 +0,0 @@
-/*
- * 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.servicecomb.config.client;
-
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ScheduledExecutorService;
-
-import org.apache.servicecomb.config.ConfigUtil;
-import org.apache.servicecomb.config.archaius.sources.ConfigCenterConfigurationSourceImpl;
-import org.apache.servicecomb.config.archaius.sources.ConfigCenterConfigurationSourceImpl.UpdateHandler;
-import org.apache.servicecomb.config.client.ConfigCenterClient.ConfigRefresh;
-import org.apache.servicecomb.foundation.common.event.EventManager;
-import org.apache.servicecomb.foundation.vertx.client.ClientPoolManager;
-import org.apache.servicecomb.foundation.vertx.client.http.HttpClientWithContext;
-import org.apache.servicecomb.foundation.vertx.client.http.HttpClientWithContext.RunHandler;
-import org.apache.servicecomb.foundation.vertx.client.http.HttpClients;
-import org.junit.Assert;
-import org.junit.BeforeClass;
-import org.junit.Test;
-import org.mockito.Mockito;
-
-import com.google.common.eventbus.Subscribe;
-
-import io.vertx.core.Handler;
-import io.vertx.core.MultiMap;
-import io.vertx.core.buffer.Buffer;
-import io.vertx.core.http.HttpClient;
-import io.vertx.core.http.HttpClientRequest;
-import io.vertx.core.http.HttpClientResponse;
-import io.vertx.core.http.HttpMethod;
-import io.vertx.core.http.WebSocket;
-import io.vertx.core.json.JsonObject;
-import mockit.Deencapsulation;
-import mockit.Expectations;
-import mockit.Mock;
-import mockit.MockUp;
-import mockit.Mocked;
-
-@SuppressWarnings("deprecation")
-public class TestConfigCenterClient {
-  @BeforeClass
-  public static void setUpClass() {
-    ConfigCenterConfig.setConcurrentCompositeConfiguration(ConfigUtil.createLocalConfig());
-  }
-
-  @SuppressWarnings("unchecked")
-  @Test
-  public void testConnectServer(@Mocked ClientPoolManager<HttpClientWithContext> clientMgr) {
-    HttpClients.mockClientPoolManager("config-center", clientMgr);
-
-    HttpClientRequest request = Mockito.mock(HttpClientRequest.class);
-    Mockito.when(request.method()).thenReturn(HttpMethod.GET);
-    Mockito.when(request.headers()).thenReturn(MultiMap.caseInsensitiveMultiMap());
-    Buffer rsp = Mockito.mock(Buffer.class);
-    Mockito.when(rsp.toJsonObject()).thenReturn(new JsonObject(
-        "{\"instances\":[{\"status\":\"UP\",\"endpoints\":[\"rest:0.0.0.0:30103\"],\"hostName\":\"125292-0.0.0.0\",\"serviceName\":\"configServer\",\"https\":false}]}"));
-    HttpClientResponse event = Mockito.mock(HttpClientResponse.class);
-    Mockito.when(event.bodyHandler(Mockito.any(Handler.class))).then(invocation -> {
-      Handler<Buffer> handler = invocation.getArgumentAt(0, Handler.class);
-      handler.handle(rsp);
-      return null;
-    });
-    Mockito.when(event.statusCode()).thenReturn(200);
-    HttpClient httpClient = Mockito.mock(HttpClient.class);
-    Mockito.when(
-        httpClient.get(Mockito.anyInt(), Mockito.anyString(), Mockito.anyString(), Mockito.any(Handler.class)))
-        .then(invocation -> {
-          Handler<HttpClientResponse> handler = invocation.getArgumentAt(3, Handler.class);
-          handler.handle(event);
-          return request;
-        });
-    new MockUp<HttpClientWithContext>() {
-      @Mock
-      public void runOnContext(RunHandler handler) {
-        handler.run(httpClient);
-      }
-    };
-    new MockUp<MemberDiscovery>() {
-      @Mock
-      public void refreshMembers(JsonObject members) {
-        Assert.assertTrue(members.size() == 1);
-      }
-    };
-    UpdateHandler updateHandler = new ConfigCenterConfigurationSourceImpl().new UpdateHandler();
-    ConfigCenterClient cc = new ConfigCenterClient(updateHandler);
-    cc.connectServer();
-  }
-
-  @Test
-  public void testConnectRefreshModeTwo() {
-    ConfigCenterClient cc2 = new ConfigCenterClient(null);
-    boolean status = false;
-    try {
-      Deencapsulation.setField(cc2, "refreshMode", 2);
-      cc2.connectServer();
-    } catch (Exception e) {
-      status = true;
-    }
-    Assert.assertFalse(status);
-  }
-
-  @SuppressWarnings({"unchecked", "rawtypes"})
-  @Test
-  public void testConfigRefreshModeOne(@Mocked ClientPoolManager clientMgr) {
-    String version1 = refreshAndGetCurrentRevision(clientMgr, 200, "huawei");
-    //test the sdk get and change the latestRevision
-    Assert.assertEquals("huawei", version1);
-    String version2 = refreshAndGetCurrentRevision(clientMgr, 304, "rkd");
-    //test that when return code is 304, the sdk do not change the latestRevision
-    Assert.assertNotEquals("rkd", version2);
-    String version3 = refreshAndGetCurrentRevision(clientMgr, 200, "");
-    //make sure the current version is not ""
-    Assert.assertNotEquals("", version3);
-  }
-
-  @SuppressWarnings({"unchecked", "rawtypes"})
-  private String refreshAndGetCurrentRevision(ClientPoolManager clientMgr, int statusCode, String version) {
-
-    ConfigCenterConfigurationSourceImpl impl = new ConfigCenterConfigurationSourceImpl();
-    UpdateHandler updateHandler = impl.new UpdateHandler();
-    HttpClientRequest request = Mockito.mock(HttpClientRequest.class);
-    Mockito.when(request.headers()).thenReturn(MultiMap.caseInsensitiveMultiMap());
-    Buffer rsp = Mockito.mock(Buffer.class);
-    Mockito.when(rsp.toString())
-        .thenReturn(String.format(
-            "{\"application\":{\"3\":\"2\",\"aa\":\"1\"},\"vmalledge\":{\"aa\":\"3\"},\"revision\": { \"version\": \"%s\"} }",
-            version));
-
-    HttpClientResponse httpClientResponse = Mockito.mock(HttpClientResponse.class);
-    Mockito.when(httpClientResponse.bodyHandler(Mockito.any(Handler.class))).then(invocation -> {
-      Handler<Buffer> handler = invocation.getArgumentAt(0, Handler.class);
-      handler.handle(rsp);
-      return null;
-    });
-    Mockito.when(httpClientResponse.statusCode()).thenReturn(statusCode);
-
-    HttpClient httpClient = Mockito.mock(HttpClient.class);
-    Mockito.when(
-        httpClient.get(Mockito.anyInt(), Mockito.anyString(), Mockito.anyString(), Mockito.any(Handler.class)))
-        .then(invocation -> {
-          Handler<HttpClientResponse> handler = invocation.getArgumentAt(3, Handler.class);
-          handler.handle(httpClientResponse);
-          return request;
-        });
-
-    HttpClientWithContext httpClientWithContext = new MockUp<HttpClientWithContext>() {
-      @Mock
-      public void runOnContext(RunHandler handler) {
-        handler.run(httpClient);
-      }
-    }.getMockInstance();
-
-    HttpClients.mockClientPoolManager("config-center", clientMgr);
-
-    new Expectations() {
-      {
-        clientMgr.findThreadBindClientPool();
-        result = httpClientWithContext;
-      }
-    };
-
-    ConfigCenterClient cc = new ConfigCenterClient(updateHandler);
-    ParseConfigUtils parseConfigUtils = new ParseConfigUtils(updateHandler);
-    MemberDiscovery memberdis = new MemberDiscovery(Arrays.asList("http://configcentertest:30103"));
-    ConfigRefresh refresh = cc.new ConfigRefresh(parseConfigUtils, memberdis);
-    Deencapsulation.setField(cc, "refreshMode", 1);
-    refresh.run();
-    String currentVersionInfo = Deencapsulation.getField(parseConfigUtils, "currentVersionInfo").toString();
-    return currentVersionInfo;
-  }
-
-  @SuppressWarnings({"unchecked", "rawtypes"})
-  @Test
-  public void testConfigRefreshModeZero(@Mocked ClientPoolManager clientMgr) {
-    ConfigCenterConfigurationSourceImpl impl = new ConfigCenterConfigurationSourceImpl();
-    UpdateHandler updateHandler = impl.new UpdateHandler();
-    HttpClientRequest request = Mockito.mock(HttpClientRequest.class);
-    Mockito.when(request.headers()).thenReturn(MultiMap.caseInsensitiveMultiMap());
-    Buffer rsp = Mockito.mock(Buffer.class);
-    Mockito.when(rsp.toString())
-        .thenReturn("{\"application\":{\"2\":\"2\",\"aa\":\"1\"},\"vmalledge\":{\"aa\":\"3\"}}");
-
-    HttpClientResponse httpClientResponse = Mockito.mock(HttpClientResponse.class);
-    Mockito.when(httpClientResponse.bodyHandler(Mockito.any(Handler.class))).then(invocation -> {
-      Handler<Buffer> handler = invocation.getArgumentAt(0, Handler.class);
-      handler.handle(rsp);
-      return null;
-    });
-    Mockito.when(httpClientResponse.statusCode()).thenReturn(200);
-
-    Buffer buf = Mockito.mock(Buffer.class);
-    Mockito.when(buf.toJsonObject()).thenReturn(new JsonObject(
-        "{\"action\":\"UPDATE\",\"key\":\"vmalledge\",\"value\":\"{\\\"aa\\\":\\\"3\\\"}\"}"));
-    WebSocket websocket = Mockito.mock(WebSocket.class);
-    Mockito.when(websocket.handler(Mockito.any(Handler.class))).then(invocation -> {
-      Handler<Buffer> handler = invocation.getArgumentAt(0, Handler.class);
-      handler.handle(buf);
-      return websocket;
-    });
-    HttpClient httpClient = Mockito.mock(HttpClient.class);
-    Mockito.when(
-        httpClient.get(Mockito.anyInt(), Mockito.anyString(), Mockito.anyString(), Mockito.any(Handler.class)))
-        .then(invocation -> {
-          Handler<HttpClientResponse> handler = invocation.getArgumentAt(3, Handler.class);
-          handler.handle(httpClientResponse);
-          return request;
-        });
-    Mockito.when(httpClient.websocket(Mockito.anyInt(),
-        Mockito.anyString(),
-        Mockito.anyString(),
-        Mockito.any(MultiMap.class),
-        Mockito.any(Handler.class),
-        Mockito.any(Handler.class)))
-        .then(invocation -> {
-          Handler<WebSocket> handler = invocation.getArgumentAt(4, Handler.class);
-          handler.handle(websocket);
-          return null;
-        });
-
-    HttpClientWithContext httpClientWithContext = new MockUp<HttpClientWithContext>() {
-      @Mock
-      public void runOnContext(RunHandler handler) {
-        handler.run(httpClient);
-      }
-    }.getMockInstance();
-
-    HttpClients.mockClientPoolManager("config-center", clientMgr);
-
-    new Expectations() {
-      {
-        clientMgr.findThreadBindClientPool();
-        result = httpClientWithContext;
-      }
-    };
-
-    ConfigCenterClient cc = new ConfigCenterClient(updateHandler);
-    ParseConfigUtils parseConfigUtils = new ParseConfigUtils(updateHandler);
-    MemberDiscovery memberdis = new MemberDiscovery(Arrays.asList("http://configcentertest:30103"));
-    ConfigRefresh refresh = cc.new ConfigRefresh(parseConfigUtils, memberdis);
-    refresh.run();
-    Map<String, Object> flatItems = Deencapsulation.getField(parseConfigUtils, "flatItems");
-    Assert.assertEquals(2, flatItems.size());
-    Deencapsulation.setField(cc, "refreshMode", 0);
-    refresh.run();
-  }
-
-  public static class ConfigRefreshExceptionEvent {
-    Map<String, String> map;
-
-    public ConfigRefreshExceptionEvent(Map<String, String> map) {
-      this.map = map;
-    }
-
-    @Subscribe
-    public void testMsg(Object event) {
-      if (event instanceof ConnFailEvent) {
-        map.put("result", "Fail event trigger");
-      }
-      if (event instanceof ConnSuccEvent) {
-        map.put("result", "Succ event trigger");
-      }
-    }
-  }
-
-  @SuppressWarnings("unchecked")
-  @Test
-  public void testConfigRefreshException(@Mocked ClientPoolManager<HttpClientWithContext> clientMgr,
-      @Mocked HttpClientWithContext httpClientWithContext) {
-    ConfigCenterConfigurationSourceImpl impl = new ConfigCenterConfigurationSourceImpl();
-    Map<String, String> map = new HashMap<>();
-    EventManager.register(new ConfigRefreshExceptionEvent(map));
-    UpdateHandler updateHandler = impl.new UpdateHandler();
-    HttpClientRequest request = Mockito.mock(HttpClientRequest.class);
-    Mockito.when(request.headers()).thenReturn(MultiMap.caseInsensitiveMultiMap());
-    Buffer rsp = Mockito.mock(Buffer.class);
-    Mockito.when(rsp.toString())
-        .thenReturn("{\"application\":{\"2\":\"2\",\"aa\":\"1\"},\"vmalledge\":{\"aa\":\"3\"}}");
-
-    HttpClientResponse event = Mockito.mock(HttpClientResponse.class);
-    Mockito.when(event.bodyHandler(Mockito.any(Handler.class))).then(invocation -> {
-      Handler<Buffer> handler = invocation.getArgumentAt(0, Handler.class);
-      handler.handle(rsp);
-      return null;
-    });
-    Mockito.when(event.statusCode()).thenReturn(400);
-    Buffer buf = Mockito.mock(Buffer.class);
-    Mockito.when(buf.toJsonObject()).thenReturn(new JsonObject(
-        "{\"action\":\"UPDATE\",\"key\":\"vmalledge\",\"value\":\"{\\\"aa\\\":\\\"3\\\"}\"}"));
-    HttpClient httpClient = Mockito.mock(HttpClient.class);
-    Mockito.when(
-        httpClient.get(Mockito.anyInt(), Mockito.anyString(), Mockito.anyString(), Mockito.any(Handler.class)))
-        .then(invocation -> {
-          Handler<HttpClientResponse> handler = invocation.getArgumentAt(3, Handler.class);
-          handler.handle(event);
-          return request;
-        });
-    new MockUp<HttpClientWithContext>() {
-      @Mock
-      public void runOnContext(RunHandler handler) {
-        handler.run(httpClient);
-      }
-    };
-    new Expectations() {
-      {
-        clientMgr.findThreadBindClientPool();
-        result = httpClientWithContext;
-      }
-    };
-    ConfigCenterClient cc = new ConfigCenterClient(updateHandler);
-    HttpClients.mockClientPoolManager("config-center", clientMgr);
-    ParseConfigUtils parseConfigUtils = new ParseConfigUtils(updateHandler);
-    MemberDiscovery memberdis = new MemberDiscovery(Arrays.asList("http://configcentertest:30103"));
-    ConfigRefresh refresh = cc.new ConfigRefresh(parseConfigUtils, memberdis);
-    refresh.run();
-    Assert.assertEquals("Fail event trigger", map.get("result"));
-    Mockito.when(event.statusCode()).thenReturn(200);
-    refresh.run();
-    Assert.assertEquals("Succ event trigger", map.get("result"));
-  }
-
-  @Test
-  public void destroy() {
-    ConfigCenterClient configCenterClient = new ConfigCenterClient(null);
-    ScheduledExecutorService executor = Deencapsulation.getField(configCenterClient, "executor");
-    ScheduledExecutorService heartbeatTask = Executors.newScheduledThreadPool(1);
-    Deencapsulation.setField(configCenterClient, "heartbeatTask", heartbeatTask);
-
-    Assert.assertFalse(executor.isShutdown());
-
-    configCenterClient.destroy();
-
-    Assert.assertTrue(executor.isShutdown());
-    Assert.assertTrue(heartbeatTask.isShutdown());
-  }
-}
diff --git a/dynamic-config/config-cc/src/test/java/org/apache/servicecomb/config/client/TestConfigCenterConfig.java b/dynamic-config/config-cc/src/test/java/org/apache/servicecomb/config/client/TestConfigCenterConfig.java
deleted file mode 100644
index dda2a21..0000000
--- a/dynamic-config/config-cc/src/test/java/org/apache/servicecomb/config/client/TestConfigCenterConfig.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * 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.servicecomb.config.client;
-
-import java.util.List;
-
-import org.apache.servicecomb.config.ConfigUtil;
-import org.junit.Assert;
-import org.junit.BeforeClass;
-import org.junit.Test;
-
-public class TestConfigCenterConfig {
-  @BeforeClass
-  public static void setUpClass() {
-    ConfigCenterConfig.setConcurrentCompositeConfiguration(ConfigUtil.createLocalConfig());
-  }
-
-  @Test
-  public void getServerUri() {
-    List<String> servers = ConfigCenterConfig.INSTANCE.getServerUri();
-    Assert.assertEquals("https://172.16.8.7:30103", servers.get(0));
-    Assert.assertEquals("https://172.16.8.7:30103", servers.get(1));
-  }
-
-  @Test
-  public void getEnvironment() {
-    Assert.assertEquals("testing", ConfigCenterConfig.INSTANCE.getEnvironment());
-    System.setProperty("SERVICECOMB_ENV", "development");
-    ConfigCenterConfig.setConcurrentCompositeConfiguration(ConfigUtil.createLocalConfig());
-    Assert.assertEquals("development", ConfigCenterConfig.INSTANCE.getEnvironment());
-  }
-
-  @Test
-  public void getProxyConfig() {
-    Assert.assertFalse(ConfigCenterConfig.INSTANCE.isProxyEnable());
-    Assert.assertEquals("127.0.0.1", ConfigCenterConfig.INSTANCE.getProxyHost());
-    Assert.assertEquals(8080, ConfigCenterConfig.INSTANCE.getProxyPort());
-    Assert.assertNull(ConfigCenterConfig.INSTANCE.getProxyUsername());
-    Assert.assertNull(ConfigCenterConfig.INSTANCE.getProxyPasswd());
-  }
-}
diff --git a/dynamic-config/config-cc/src/test/java/org/apache/servicecomb/config/client/TestMemberDiscovery.java b/dynamic-config/config-cc/src/test/java/org/apache/servicecomb/config/client/TestMemberDiscovery.java
deleted file mode 100644
index 2362902..0000000
--- a/dynamic-config/config-cc/src/test/java/org/apache/servicecomb/config/client/TestMemberDiscovery.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * 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.servicecomb.config.client;
-
-import static org.junit.Assert.assertNotNull;
-
-import java.util.Arrays;
-
-import org.apache.servicecomb.config.ConfigUtil;
-import org.apache.servicecomb.foundation.common.event.EventManager;
-import org.junit.Assert;
-import org.junit.BeforeClass;
-import org.junit.Test;
-
-import io.vertx.core.json.JsonObject;
-
-public class TestMemberDiscovery {
-  @BeforeClass
-  public static void setUpClass() {
-    ConfigCenterConfig.setConcurrentCompositeConfiguration(ConfigUtil.createLocalConfig());
-  }
-
-  @Test
-  public void testGetConfigServerURIs() {
-    MemberDiscovery dc = new MemberDiscovery(ConfigCenterConfig.INSTANCE.getServerUri());
-    assertNotNull(dc.getConfigServer());
-  }
-
-  @Test
-  public void testServerChange() {
-    MemberDiscovery dc = new MemberDiscovery(Arrays.asList("http://127.0.0.1:30103", "http://127.0.0.1:30104"));
-    String server1 = dc.getConfigServer();
-    EventManager.post(new ConnFailEvent("connect failed."));
-    String server2 = dc.getConfigServer();
-    Assert.assertNotEquals(server1, server2);
-    EventManager.post(new ConnFailEvent("connect failed."));
-    server2 = dc.getConfigServer();
-    Assert.assertEquals(server1, server2);
-
-    dc.refreshMembers(new JsonObject(
-        "{\"instances\":"
-            + "[{\"status\":\"UP\",\"endpoints\":[\"rest://0.0.0.0:30109\"],\"hostName\":\"125292-0.0.0.0\",\"serviceName\":\"configServer\",\"isHttps\":false}"
-            + ",{\"status\":\"UP\",\"endpoints\":[\"rest://0.0.0.0:30108\"],\"hostName\":\"125293-0.0.0.0\",\"serviceName\":\"configServer\",\"isHttps\":false}"
-            + "]}"));
-    server1 = dc.getConfigServer();
-    EventManager.post(new ConnFailEvent("connect failed."));
-    server2 = dc.getConfigServer();
-    Assert.assertNotEquals(server1, server2);
-    EventManager.post(new ConnFailEvent("connect failed."));
-    server2 = dc.getConfigServer();
-    Assert.assertEquals(server1, server2);
-  }
-
-  @Test
-  public void testDiscoverywithHttp() {
-    MemberDiscovery discoveryClient1 = new MemberDiscovery(null);
-    discoveryClient1.refreshMembers(new JsonObject(
-        "{\"instances\":[{\"status\":\"UP\",\"endpoints\":[\"rest://0.0.0.0:30103\"],\"hostName\":\"125292-0.0.0.0\",\"serviceName\":\"configServer\",\"isHttps\":false}]}"));
-    Assert.assertEquals("http://0.0.0.0:30103", discoveryClient1.getConfigServer());
-  }
-
-  @Test
-  public void testDiscoverywithHttps() {
-    MemberDiscovery discoveryClient1 = new MemberDiscovery(null);
-    discoveryClient1.refreshMembers(new JsonObject(
-        "{\"instances\":[{\"status\":\"UP\",\"endpoints\":[\"rest://0.0.0.0:30103\"],\"hostName\":\"125292-0.0.0.0\",\"serviceName\":\"configServer\",\"isHttps\":true}]}"));
-    Assert.assertEquals("https://0.0.0.0:30103", discoveryClient1.getConfigServer());
-  }
-}
diff --git a/dynamic-config/config-cc/src/test/java/org/apache/servicecomb/config/client/TestParseConfigUtils.java b/dynamic-config/config-cc/src/test/java/org/apache/servicecomb/config/client/TestParseConfigUtils.java
deleted file mode 100644
index 9c12cb1..0000000
--- a/dynamic-config/config-cc/src/test/java/org/apache/servicecomb/config/client/TestParseConfigUtils.java
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * 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.servicecomb.config.client;
-
-import java.util.HashMap;
-import java.util.LinkedHashMap;
-import java.util.Map;
-
-import org.apache.servicecomb.config.archaius.sources.ConfigCenterConfigurationSourceImpl;
-import org.apache.servicecomb.config.archaius.sources.ConfigCenterConfigurationSourceImpl.UpdateHandler;
-import org.junit.Assert;
-import org.junit.Test;
-
-import mockit.Deencapsulation;
-
-/**
- * @author
- */
-public class TestParseConfigUtils {
-
-  private ConfigCenterConfigurationSourceImpl configCenterSource = new ConfigCenterConfigurationSourceImpl();
-
-  private UpdateHandler uh = configCenterSource.new UpdateHandler();
-
-  private ParseConfigUtils pc = new ParseConfigUtils(uh);
-
-  @Test
-  public void testNotifyItemsChangedNeedRefresh() {
-
-    boolean status = true;
-    Map<String, Object> before = new HashMap<>();
-    Map<String, Object> after = new HashMap<>();
-    try {
-      Deencapsulation.invoke(pc, "notifyItemsChangedNeedRefresh", before, after);
-    } catch (Exception e) {
-      status = false;
-    }
-    Assert.assertTrue(status);
-
-    // Check with valid before object
-    status = true;
-    before.put("test", "testValue");
-    try {
-      Deencapsulation.invoke(pc, "notifyItemsChangedNeedRefresh", before, after);
-    } catch (Exception e) {
-      status = false;
-    }
-    Assert.assertTrue(status);
-
-    // Check with valid after object
-    status = true;
-    after.put("test", "testValue2");
-    try {
-      Deencapsulation.invoke(pc, "notifyItemsChangedNeedRefresh", before, after);
-    } catch (Exception e) {
-      status = false;
-    }
-    Assert.assertTrue(status);
-
-    // Check with valid localItems object
-    status = true;
-    try {
-      Deencapsulation.invoke(pc, "notifyItemsChangedNeedRefresh", before, after);
-    } catch (Exception e) {
-      status = false;
-    }
-    Assert.assertTrue(status);
-  }
-  
-  @Test
-  public void testMergeDimensionItems() {
-
-    boolean status = true;
-    Map<String, Object> application = new HashMap<>();
-    application.put("key1", "application1");
-    application.put("key2", "application2");
-    application.put("key3", "application3");
-    application.put("key4", "application4");
-    Map<String, Object> service = new HashMap<>();
-    service.put("key1", "service1");
-    service.put("key2", "service2");
-    service.put("key3", "service3");
-    Map<String, Object> version = new HashMap<>();
-    version.put("key1", "version1");
-    version.put("key2", "version1");
-    Map<String, Object> tag = new HashMap<>();
-    tag.put("key1", "tag1");
-
-    Map<String, Map<String, Object>> items = new LinkedHashMap<String, Map<String, Object>>();
-    items.put("application", application);
-    items.put("service@app", service);
-    items.put("service@app#version", version);
-    items.put("service@app#version!tag", tag);
-
-    Map<String, Object> result = null;
-    try {
-      result = Deencapsulation.invoke(pc, "mergeDimensionItems", items);
-    } catch (Exception e) {
-      status = false;
-    }
-    Assert.assertTrue(status);
-    Assert.assertEquals(application.get("key4"), result.get("key4"));
-    Assert.assertEquals(service.get("key3"), result.get("key3"));
-    Assert.assertEquals(version.get("key2"), result.get("key2"));
-    Assert.assertEquals(tag.get("key1"), result.get("key1"));
-  }
-}
diff --git a/dynamic-config/config-cc/src/test/java/org/apache/servicecomb/config/client/TestURIConst.java b/dynamic-config/config-cc/src/test/java/org/apache/servicecomb/config/client/TestURIConst.java
deleted file mode 100644
index 8877624..0000000
--- a/dynamic-config/config-cc/src/test/java/org/apache/servicecomb/config/client/TestURIConst.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * 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.servicecomb.config.client;
-
-import org.junit.Assert;
-import org.junit.Test;
-
-import mockit.Expectations;
-import mockit.Mocked;
-
-public class TestURIConst {
-  @Test
-  public void testURI_v2(final @Mocked ConfigCenterConfig config) {
-    new Expectations() {
-      {
-        config.getDomainName();
-        result = "mytenant";
-        config.getApiVersion();
-        result = "v2";
-      }
-    };
-
-    URIConst uriConst = new URIConst();
-    Assert.assertEquals("/members", uriConst.MEMBERS);
-    Assert.assertEquals("/configuration/v2/refresh/items", uriConst.REFRESH_ITEMS);
-    Assert.assertEquals("/configuration/v2/items", uriConst.ITEMS);
-  }
-
-  @Test
-  public void testURI_v3(final @Mocked ConfigCenterConfig config) {
-    new Expectations() {
-      {
-        config.getDomainName();
-        result = "mytenant";
-        config.getApiVersion();
-        result = "v3";
-      }
-    };
-
-    URIConst uriConst = new URIConst();
-    Assert.assertEquals("/v3/mytenant/configuration/members", uriConst.MEMBERS);
-    Assert.assertEquals("/v3/mytenant/configuration/refresh/items", uriConst.REFRESH_ITEMS);
-    Assert.assertEquals("/v3/mytenant/configuration/items", uriConst.ITEMS);
-  }
-}
diff --git a/dynamic-config/config-cc/src/test/java/org/apache/servicecomb/config/collect/TestConfigCenterDefaultDeploymentProvder.java b/dynamic-config/config-cc/src/test/java/org/apache/servicecomb/config/collect/TestConfigCenterDefaultDeploymentProvider.java
similarity index 98%
rename from dynamic-config/config-cc/src/test/java/org/apache/servicecomb/config/collect/TestConfigCenterDefaultDeploymentProvder.java
rename to dynamic-config/config-cc/src/test/java/org/apache/servicecomb/config/collect/TestConfigCenterDefaultDeploymentProvider.java
index 486cade..597c31f 100644
--- a/dynamic-config/config-cc/src/test/java/org/apache/servicecomb/config/collect/TestConfigCenterDefaultDeploymentProvder.java
+++ b/dynamic-config/config-cc/src/test/java/org/apache/servicecomb/config/collect/TestConfigCenterDefaultDeploymentProvider.java
@@ -26,7 +26,7 @@ import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
 
-public class TestConfigCenterDefaultDeploymentProvder {
+public class TestConfigCenterDefaultDeploymentProvider {
   @Before
   public void start() {
     ArchaiusUtils.resetConfig();

[servicecomb-java-chassis] 01/03: [SCB-2273]support kie latest layered configuration. Part1: kie implementation

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

liubao pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/servicecomb-java-chassis.git

commit b74bcd79b50a808f46eb2ad80ff63ded6e519e7f
Author: liubao68 <bi...@qq.com>
AuthorDate: Wed Jun 2 17:09:27 2021 +0800

    [SCB-2273]support kie latest layered configuration. Part1: kie implementation
---
 .../config/center/client/AddressManager.java       |   4 +
 .../config/center/client/ConfigCenterManager.java  |  20 +--
 .../servicecomb/config/common/ConfigConverter.java |  92 ++++++++++
 .../servicecomb/config/kie/client/KieClient.java   | 148 ++++-----------
 .../config/kie/client/KieConfigManager.java        |  87 +++++++--
 .../kie/client/model/ConfigurationsRequest.java    |  61 ++++---
 .../client/model/ConfigurationsRequestFactory.java |  94 ++++++++++
 .../config/kie/client/model/KieAddressManager.java |  19 +-
 .../config/kie/client/model/KieConfiguration.java  | 152 ++++++++++++++++
 .../servicecomb/http/client/task/AbstractTask.java |  27 ++-
 .../center/client/ServiceCenterConfiguration.java  |  32 ----
 .../center/client/ServiceCenterDiscovery.java      |  35 +++-
 .../center/client/ServiceCenterRegistration.java   |  38 ++--
 .../client/model/ServiceCenterConfiguration.java   |  24 +--
 .../RegistryClientTest.java                        |   5 +-
 dynamic-config/config-kie/pom.xml                  |   4 +
 .../config/kie/{client => }/KieConfig.java         |  50 +++++-
 .../config/kie/KieConfigurationSourceImpl.java     | 172 ++++++++++++++++++
 .../servicecomb/config/kie/TransportUtils.java     | 118 ++++++++++++
 .../sources/KieConfigurationSourceImpl.java        | 138 --------------
 .../kie/client/ConfigKieHttpClientOptionsSPI.java  | 175 ------------------
 .../config/kie/client/ConnSuccEvent.java           |  22 ---
 .../servicecomb/config/kie/client/KieClient.java   | 176 ------------------
 .../servicecomb/config/kie/client/KieUtil.java     | 154 ----------------
 .../servicecomb/config/kie/client/KieWatcher.java  |  86 ---------
 .../servicecomb/config/kie/model/KVBody.java       |  65 -------
 .../apache/servicecomb/config/kie/model/KVDoc.java | 127 -------------
 .../servicecomb/config/kie/model/KVResponse.java   |  53 ------
 .../config/kie/model/LabelDocResponse.java         |  46 -----
 .../servicecomb/config/kie/model/ValueType.java    |  27 ---
 ...comb.config.spi.ConfigCenterConfigurationSource |   2 +-
 .../config/kie/client/TestKieClient.java           | 200 ---------------------
 .../config/kie/client/TestKieConfig.java           |  46 -----
 .../servicecomb/config/kie/client/TestKieUtil.java |  62 -------
 .../config/kie/client/TestKieWatcher.java          |  54 ------
 .../kie/sources/TestKieConfigurationSource.java    |  96 ----------
 36 files changed, 939 insertions(+), 1772 deletions(-)

diff --git a/clients/config-center-client/src/main/java/org/apache/servicecomb/config/center/client/AddressManager.java b/clients/config-center-client/src/main/java/org/apache/servicecomb/config/center/client/AddressManager.java
index fb4e7ef..cc073ff 100644
--- a/clients/config-center-client/src/main/java/org/apache/servicecomb/config/center/client/AddressManager.java
+++ b/clients/config-center-client/src/main/java/org/apache/servicecomb/config/center/client/AddressManager.java
@@ -63,4 +63,8 @@ public class AddressManager {
       return addresses.get(index);
     }
   }
+
+  public boolean sslEnabled() {
+    return address().startsWith("https://");
+  }
 }
diff --git a/clients/config-center-client/src/main/java/org/apache/servicecomb/config/center/client/ConfigCenterManager.java b/clients/config-center-client/src/main/java/org/apache/servicecomb/config/center/client/ConfigCenterManager.java
index ab63198..054d565 100644
--- a/clients/config-center-client/src/main/java/org/apache/servicecomb/config/center/client/ConfigCenterManager.java
+++ b/clients/config-center-client/src/main/java/org/apache/servicecomb/config/center/client/ConfigCenterManager.java
@@ -17,11 +17,9 @@
 
 package org.apache.servicecomb.config.center.client;
 
-import java.util.Collections;
-import java.util.Map;
-
 import org.apache.servicecomb.config.center.client.model.QueryConfigurationsRequest;
 import org.apache.servicecomb.config.center.client.model.QueryConfigurationsResponse;
+import org.apache.servicecomb.config.common.ConfigConverter;
 import org.apache.servicecomb.config.common.ConfigurationChangedEvent;
 import org.apache.servicecomb.http.client.task.AbstractTask;
 import org.apache.servicecomb.http.client.task.Task;
@@ -42,18 +40,14 @@ public class ConfigCenterManager extends AbstractTask {
 
   private QueryConfigurationsRequest queryConfigurationsRequest;
 
-  private Map<String, Object> lastConfiguration;
-
-  public ConfigCenterManager(ConfigCenterClient configCenterClient, EventBus eventBus) {
-    this(configCenterClient, eventBus, Collections.emptyMap());
-  }
+  private ConfigConverter configConverter;
 
   public ConfigCenterManager(ConfigCenterClient configCenterClient, EventBus eventBus,
-      Map<String, Object> lastConfiguration) {
+      ConfigConverter configConverter) {
     super("config-center-configuration-task");
     this.configCenterClient = configCenterClient;
     this.eventBus = eventBus;
-    this.lastConfiguration = lastConfiguration;
+    this.configConverter = configConverter;
   }
 
   public void setQueryConfigurationsRequest(QueryConfigurationsRequest queryConfigurationsRequest) {
@@ -77,8 +71,10 @@ public class ConfigCenterManager extends AbstractTask {
         QueryConfigurationsResponse response = configCenterClient.queryConfigurations(queryConfigurationsRequest);
         if (response.isChanged()) {
           queryConfigurationsRequest.setRevision(response.getRevision());
-          eventBus.post(ConfigurationChangedEvent.createIncremental(response.getConfigurations(), lastConfiguration));
-          lastConfiguration = response.getConfigurations();
+          ConfigurationChangedEvent event = ConfigurationChangedEvent
+              .createIncremental(response.getConfigurations(), configConverter.getLastRawData());
+          configConverter.updateData(response.getConfigurations());
+          eventBus.post(event);
         }
         startTask(new BackOffSleepTask(POLL_INTERVAL, new PollConfigurationTask(0)));
       } catch (Exception e) {
diff --git a/clients/config-common/src/main/java/org/apache/servicecomb/config/common/ConfigConverter.java b/clients/config-common/src/main/java/org/apache/servicecomb/config/common/ConfigConverter.java
new file mode 100644
index 0000000..5f55f99
--- /dev/null
+++ b/clients/config-common/src/main/java/org/apache/servicecomb/config/common/ConfigConverter.java
@@ -0,0 +1,92 @@
+/*
+ * 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.servicecomb.config.common;
+
+import java.nio.charset.Charset;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+import org.springframework.beans.factory.config.YamlPropertiesFactoryBean;
+import org.springframework.core.io.ByteArrayResource;
+import org.springframework.util.CollectionUtils;
+
+public class ConfigConverter {
+  private Map<String, Object> currentData = Collections.emptyMap();
+
+  private Map<String, Object> lastRawData;
+
+  private final List<String> fileSources;
+
+  public ConfigConverter(List<String> fileSources) {
+    this.fileSources = fileSources;
+  }
+
+  public Map<String, Object> getLastRawData() {
+    return this.lastRawData;
+  }
+
+  public Map<String, Object> getCurrentData() {
+    return this.currentData;
+  }
+
+  public void updateData(Map<String, Object> rawData) {
+    this.lastRawData = rawData;
+
+    if (CollectionUtils.isEmpty(fileSources)) {
+      this.currentData = rawData;
+      return;
+    }
+
+    Map<String, Object> fileProperties = new HashMap<>();
+    fileSources.forEach(source -> {
+      if (rawData.get(source) != null) {
+        fileProperties.put(source, rawData.get(source));
+      }
+    });
+
+    Map<String, Object> result = new HashMap<>(rawData.size());
+    result.putAll(rawData);
+    fileProperties.forEach((k, v) -> result.putAll(createFileSource(v)));
+    this.currentData = result;
+  }
+
+  private Map<String, Object> createFileSource(Object v) {
+    YamlPropertiesFactoryBean yamlFactory = new YamlPropertiesFactoryBean();
+    yamlFactory.setResources(new ByteArrayResource(v.toString().getBytes(Charset.forName("UTF-8"))));
+    return propertiesToMap(yamlFactory.getObject());
+  }
+
+  @SuppressWarnings("unchecked")
+  private Map<String, Object> propertiesToMap(Properties properties) {
+    if (properties == null) {
+      return Collections.emptyMap();
+    }
+    Map<String, Object> result = new HashMap<>();
+    Enumeration<String> keys = (Enumeration<String>) properties.propertyNames();
+    while (keys.hasMoreElements()) {
+      String key = keys.nextElement();
+      Object value = properties.getProperty(key);
+      result.put(key, value);
+    }
+    return result;
+  }
+}
diff --git a/clients/config-kie-client/src/main/java/org/apache/servicecomb/config/kie/client/KieClient.java b/clients/config-kie-client/src/main/java/org/apache/servicecomb/config/kie/client/KieClient.java
index 6b24969..4a1fdb6 100644
--- a/clients/config-kie-client/src/main/java/org/apache/servicecomb/config/kie/client/KieClient.java
+++ b/clients/config-kie-client/src/main/java/org/apache/servicecomb/config/kie/client/KieClient.java
@@ -17,7 +17,14 @@
 
 package org.apache.servicecomb.config.kie.client;
 
-import org.apache.commons.lang3.StringUtils;
+import java.io.StringReader;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+import java.util.stream.Collectors;
+
 import org.apache.http.HttpStatus;
 import org.apache.servicecomb.config.kie.client.exception.OperationException;
 import org.apache.servicecomb.config.kie.client.model.ConfigConstants;
@@ -26,6 +33,7 @@ import org.apache.servicecomb.config.kie.client.model.ConfigurationsResponse;
 import org.apache.servicecomb.config.kie.client.model.KVDoc;
 import org.apache.servicecomb.config.kie.client.model.KVResponse;
 import org.apache.servicecomb.config.kie.client.model.KieAddressManager;
+import org.apache.servicecomb.config.kie.client.model.KieConfiguration;
 import org.apache.servicecomb.config.kie.client.model.ValueType;
 import org.apache.servicecomb.http.client.common.HttpRequest;
 import org.apache.servicecomb.http.client.common.HttpResponse;
@@ -36,76 +44,52 @@ import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.config.YamlPropertiesFactoryBean;
 import org.springframework.core.io.ByteArrayResource;
 
-import java.io.StringReader;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Properties;
-import java.util.concurrent.atomic.AtomicBoolean;
-
 public class KieClient implements KieConfigOperation {
 
   private static final Logger LOGGER = LoggerFactory.getLogger(KieClient.class);
 
-  private AtomicBoolean isFirst = new AtomicBoolean(true);
-
   protected HttpTransport httpTransport;
 
   protected String revision = "0";
 
-  private String url;
+  private final KieAddressManager addressManager;
 
-  private HttpResponse httpResponse = null;
-
-  private KieAddressManager addressManager;
-
-  private Map<String, String> labelsMap;
+  private final KieConfiguration kieConfiguration;
 
   public static final String DEFAULT_KIE_API_VERSION = "v1";
 
-  public KieClient(KieAddressManager addressManager, HttpTransport httpTransport) {
+  public KieClient(KieAddressManager addressManager, HttpTransport httpTransport, KieConfiguration kieConfiguration) {
     this.httpTransport = httpTransport;
     this.addressManager = addressManager;
+    this.kieConfiguration = kieConfiguration;
   }
 
   @Override
   public ConfigurationsResponse queryConfigurations(ConfigurationsRequest request) {
-    boolean isWatch = false;
-    if (Boolean.valueOf(getPropertiesValue(getConfigKeyValue(ConfigConstants.KEY_ENABLELONGPOLLING)))) {
-      isWatch = true;
-    }
     try {
-      url = addressManager.address()
+      String url = addressManager.address()
           + "/"
           + DEFAULT_KIE_API_VERSION
           + "/"
-          + getPropertiesValue(getConfigKeyValue(ConfigConstants.KEY_PROJECT))
-          + "/kie/kv?label=app:"
-          //app 名称作为筛选条件
-          + request.getApplication()
+          + kieConfiguration.getProject()
+          + "/kie/kv?"
+          + request.getLabelsQuery()
           + "&revision="
-          + revision;
+          + request.getRevision()
+          + "&withExact="
+          + request.isWithExact();
 
-      if (isWatch && !isFirst.get()) {
-        url +=
-            "&wait=" + getPropertiesValue(getConfigKeyValue(ConfigConstants.KEY_POLLINGWAITSEC)) + "s";
-      }
-      isFirst.compareAndSet(true, false);
-      Map<String, String> headers = new HashMap<>();
-      headers.put("environment", request.getEnvironment());
-      HttpRequest httpRequest = new HttpRequest(url, headers, null, HttpRequest.GET);
-      httpResponse = httpTransport.doRequest(httpRequest);
-      if (httpResponse == null) {
-        return null;
+      if (kieConfiguration.isEnableLongPolling()) {
+        url += "&wait=" + kieConfiguration.getPollingWaitInSeconds() + "s";
       }
+
+      HttpRequest httpRequest = new HttpRequest(url, null, null, HttpRequest.GET);
+      HttpResponse httpResponse = httpTransport.doRequest(httpRequest);
       ConfigurationsResponse configurationsResponse = new ConfigurationsResponse();
       if (httpResponse.getStatusCode() == HttpStatus.SC_OK) {
         revision = httpResponse.getHeader("X-Kie-Revision");
         KVResponse allConfigList = HttpUtils.deserialize(httpResponse.getContent(), KVResponse.class);
-        Map<String, Object> configurations = getConfigByLabel(allConfigList, request);
+        Map<String, Object> configurations = getConfigByLabel(allConfigList);
         configurationsResponse.setConfigurations(configurations);
         configurationsResponse.setChanged(true);
         configurationsResponse.setRevision(revision);
@@ -121,80 +105,41 @@ public class KieClient implements KieConfigOperation {
       throw new OperationException(
           "read response failed. status:" + httpResponse.getStatusCode() + "; message:" +
               httpResponse.getMessage() + "; content:" + httpResponse.getContent());
-
     } catch (Exception e) {
       addressManager.nextAddress();
       throw new OperationException("read response failed. ", e);
     }
   }
 
-  private Map<String, Object> getConfigByLabel(KVResponse resp, ConfigurationsRequest request) {
+  private Map<String, Object> getConfigByLabel(KVResponse resp) {
     Map<String, Object> resultMap = new HashMap<>();
-    List<KVDoc> appList = new ArrayList<>();
-    List<KVDoc> serviceList = new ArrayList<>();
-    List<KVDoc> versionList = new ArrayList<>();
-    for (KVDoc kvDoc : resp.getData()) {
-      if (!StringUtils.isEmpty(kvDoc.getStatus()) && !kvDoc.getStatus()
-          .equals(ConfigConstants.STATUS_ENABLED)) {
-        continue;
-      }
-      labelsMap = kvDoc.getLabels();
-      boolean checkApplication = checkValue(ConfigConstants.LABEL_APP, request.getApplication());
-      boolean checkEnvironment = checkValue(ConfigConstants.LABEL_ENV, request.getEnvironment());
-      boolean checkServer = checkValue(ConfigConstants.LABEL_SERVICE, request.getServiceName());
-      boolean checkVersion = checkValue(ConfigConstants.LABEL_VERSION, request.getVersion());
-      if (checkApplication && checkEnvironment && !labelsMap.containsKey(ConfigConstants.LABEL_SERVICE)) {
-          appList.add(kvDoc);
-      }
-      if (checkApplication && checkEnvironment && checkServer && !kvDoc.getLabels().containsKey(ConfigConstants.LABEL_VERSION)) {
-        serviceList.add(kvDoc);
-      }
-      if (checkApplication && checkEnvironment && checkServer && checkVersion) {
-        versionList.add(kvDoc);
-      }
-    }
-    //kv is priority
-    for (KVDoc kvDoc : appList) {
-      resultMap.putAll(processValueType(kvDoc));
-    }
-    for (KVDoc kvDoc : serviceList) {
-      resultMap.putAll(processValueType(kvDoc));
-    }
-    for (KVDoc kvDoc : versionList) {
-      resultMap.putAll(processValueType(kvDoc));
-    }
+    resp.getData().stream()
+        .filter(doc -> doc.getStatus() == null || ConfigConstants.STATUS_ENABLED.equalsIgnoreCase(doc.getStatus()))
+        .map(this::processValueType)
+        .collect(Collectors.toList())
+        .forEach(resultMap::putAll);
     return resultMap;
   }
 
-  private boolean checkValue(String key, String propertyName) {
-    if (!labelsMap.containsKey(key)) {
-      return false;
-    }
-    if (!labelsMap.get(key).equals(propertyName)) {
-      return false;
-    }
-    return true;
-  }
-
   private Map<String, Object> processValueType(KVDoc kvDoc) {
-    ValueType vtype;
+    ValueType valueType;
     try {
-      vtype = ValueType.valueOf(kvDoc.getValueType());
+      valueType = ValueType.valueOf(kvDoc.getValueType());
     } catch (IllegalArgumentException e) {
       throw new OperationException("value type not support");
     }
     Properties properties = new Properties();
     Map<String, Object> kvMap = new HashMap<>();
     try {
-      switch (vtype) {
+      switch (valueType) {
         case yml:
         case yaml:
           YamlPropertiesFactoryBean yamlFactory = new YamlPropertiesFactoryBean();
           yamlFactory.setResources(new ByteArrayResource(kvDoc.getValue().getBytes()));
-          return toMap(kvDoc.getKey(), yamlFactory.getObject());
+          return toMap(yamlFactory.getObject());
         case properties:
           properties.load(new StringReader(kvDoc.getValue()));
-          return toMap(kvDoc.getKey(), properties);
+          return toMap(properties);
         case text:
         case string:
         default:
@@ -208,7 +153,7 @@ public class KieClient implements KieConfigOperation {
   }
 
   @SuppressWarnings("unchecked")
-  private Map<String, Object> toMap(String prefix, Properties properties) {
+  private Map<String, Object> toMap(Properties properties) {
     if (properties == null) {
       return Collections.emptyMap();
     }
@@ -217,23 +162,8 @@ public class KieClient implements KieConfigOperation {
     while (keys.hasMoreElements()) {
       String key = keys.nextElement();
       Object value = properties.getProperty(key);
-      if (!StringUtils.isEmpty(prefix)) {
-        key = prefix + "." + key;
-      }
-      if (value != null) {
-        result.put(key, value);
-      } else {
-        result.put(key, null);
-      }
+      result.put(key, value);
     }
     return result;
   }
-
-  private String getPropertiesValue(String key) {
-    return this.addressManager.getProperties().getProperty(key);
-  }
-
-  private String getConfigKeyValue(String key) {
-    return this.addressManager.getConfigKey().get(key);
-  }
 }
diff --git a/clients/config-kie-client/src/main/java/org/apache/servicecomb/config/kie/client/KieConfigManager.java b/clients/config-kie-client/src/main/java/org/apache/servicecomb/config/kie/client/KieConfigManager.java
index f636ffe..567e8fa 100644
--- a/clients/config-kie-client/src/main/java/org/apache/servicecomb/config/kie/client/KieConfigManager.java
+++ b/clients/config-kie-client/src/main/java/org/apache/servicecomb/config/kie/client/KieConfigManager.java
@@ -17,12 +17,17 @@
 
 package org.apache.servicecomb.config.kie.client;
 
-import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
+import java.util.concurrent.Executors;
 
+import org.apache.servicecomb.config.common.ConfigConverter;
 import org.apache.servicecomb.config.common.ConfigurationChangedEvent;
 import org.apache.servicecomb.config.kie.client.model.ConfigurationsRequest;
+import org.apache.servicecomb.config.kie.client.model.ConfigurationsRequestFactory;
 import org.apache.servicecomb.config.kie.client.model.ConfigurationsResponse;
+import org.apache.servicecomb.config.kie.client.model.KieConfiguration;
 import org.apache.servicecomb.http.client.task.AbstractTask;
 import org.apache.servicecomb.http.client.task.Task;
 import org.slf4j.Logger;
@@ -40,35 +45,77 @@ public class KieConfigManager extends AbstractTask {
 
   private final EventBus eventBus;
 
-  private ConfigurationsRequest configurationsRequest;
+  private ConfigConverter configConverter;
 
-  private Map<String, Object> lastConfiguration;
+  private List<ConfigurationsRequest> configurationsRequests;
 
-  public KieConfigManager(KieConfigOperation configKieClient, EventBus eventBus) {
-    this(configKieClient, eventBus, Collections.emptyMap());
-  }
+  private KieConfiguration kieConfiguration;
 
   public KieConfigManager(KieConfigOperation configKieClient, EventBus eventBus,
-      Map<String, Object> lastConfiguration) {
+      KieConfiguration kieConfiguration,
+      ConfigConverter configConverter) {
     super("config-center-configuration-task");
+    this.configurationsRequests = ConfigurationsRequestFactory.buildConfigurationRequests(kieConfiguration);
+    this.configurationsRequests.sort(ConfigurationsRequest::compareTo);
     this.configKieClient = configKieClient;
     this.eventBus = eventBus;
-    this.lastConfiguration = lastConfiguration;
+    this.configConverter = configConverter;
+    this.kieConfiguration = kieConfiguration;
+  }
+
+  public void firstPull() {
+    try {
+      Map<String, Object> data = new HashMap<>();
+      this.configurationsRequests.forEach(r -> {
+        r.setRevision(ConfigurationsRequest.INITIAL_REVISION);
+        ConfigurationsResponse response = configKieClient.queryConfigurations(r);
+        if (response.isChanged()) {
+          r.setRevision(response.getRevision());
+          r.setLastRawData(response.getConfigurations());
+          data.putAll(response.getConfigurations());
+        } else {
+          throw new IllegalStateException("can not fetch config data.");
+        }
+      });
+      this.configConverter.updateData(data);
+    } catch (RuntimeException e) {
+      if (this.kieConfiguration.isFirstPullRequired()) {
+        throw e;
+      } else {
+        LOGGER.warn("first pull failed, and ignore {}", e.getMessage());
+      }
+    }
+  }
+
+  private void onDataChanged() {
+    Map<String, Object> lastData = new HashMap<>();
+    this.configurationsRequests.forEach(r -> lastData.putAll(r.getLastRawData()));
+
+    ConfigurationChangedEvent event = ConfigurationChangedEvent
+        .createIncremental(lastData, configConverter.getLastRawData());
+    configConverter.updateData(lastData);
+    eventBus.post(event);
   }
 
-  public void setConfigurationsRequest(ConfigurationsRequest configurationsRequest) {
-    this.configurationsRequest = configurationsRequest;
+  @Override
+  protected void initTaskPool(String taskName) {
+    this.taskPool = Executors.newFixedThreadPool(3, (task) ->
+        new Thread(task, taskName));
   }
 
   public void startConfigKieManager() {
-    this.startTask(new PollConfigurationTask(0));
+    this.configurationsRequests.forEach((t) ->
+        this.startTask(new PollConfigurationTask(0, t)));
   }
 
   class PollConfigurationTask implements Task {
-    int failCount = 0;
+    final int failCount;
+
+    ConfigurationsRequest configurationsRequest;
 
-    public PollConfigurationTask(int failCount) {
+    public PollConfigurationTask(int failCount, ConfigurationsRequest configurationsRequest) {
       this.failCount = failCount;
+      this.configurationsRequest = configurationsRequest;
     }
 
     @Override
@@ -76,15 +123,19 @@ public class KieConfigManager extends AbstractTask {
       try {
         ConfigurationsResponse response = configKieClient.queryConfigurations(configurationsRequest);
         if (response.isChanged()) {
-          LOGGER.info("The configurations are change, will refresh local configurations.");
           configurationsRequest.setRevision(response.getRevision());
-          eventBus.post(ConfigurationChangedEvent.createIncremental(response.getConfigurations(), lastConfiguration));
-          lastConfiguration = response.getConfigurations();
+          configurationsRequest.setLastRawData(response.getConfigurations());
+          onDataChanged();
+        }
+        if (KieConfigManager.this.kieConfiguration.isEnableLongPolling()) {
+          startTask(new BackOffSleepTask(POLL_INTERVAL, new PollConfigurationTask(0, this.configurationsRequest)));
+        } else {
+          startTask(new PollConfigurationTask(0, this.configurationsRequest));
         }
-        startTask(new BackOffSleepTask(POLL_INTERVAL, new PollConfigurationTask(0)));
       } catch (Exception e) {
         LOGGER.error("get configurations from KieConfigCenter failed, and will try again.", e);
-        startTask(new BackOffSleepTask(failCount + 1, new PollConfigurationTask(failCount + 1)));
+        startTask(
+            new BackOffSleepTask(failCount + 1, new PollConfigurationTask(failCount + 1, this.configurationsRequest)));
       }
     }
   }
diff --git a/clients/config-kie-client/src/main/java/org/apache/servicecomb/config/kie/client/model/ConfigurationsRequest.java b/clients/config-kie-client/src/main/java/org/apache/servicecomb/config/kie/client/model/ConfigurationsRequest.java
index 1523334..cbf9647 100644
--- a/clients/config-kie-client/src/main/java/org/apache/servicecomb/config/kie/client/model/ConfigurationsRequest.java
+++ b/clients/config-kie-client/src/main/java/org/apache/servicecomb/config/kie/client/model/ConfigurationsRequest.java
@@ -17,59 +17,68 @@
 
 package org.apache.servicecomb.config.kie.client.model;
 
-public class ConfigurationsRequest {
-  private String environment;
+import java.util.Map;
 
-  private String application;
+public class ConfigurationsRequest implements Comparable<ConfigurationsRequest> {
+  public static final String INITIAL_REVISION = "0";
 
-  private String serviceName;
+  private int order;
 
-  private String version;
+  private String revision = INITIAL_REVISION;
 
-  private String revision;
+  private boolean withExact;
 
-  public String getEnvironment() {
-    return environment;
+  private String labelsQuery;
+
+  private Map<String, Object> lastRawData;
+
+  public int getOrder() {
+    return order;
   }
 
-  public ConfigurationsRequest setEnvironment(String environment) {
-    this.environment = environment;
+  public ConfigurationsRequest setOrder(int order) {
+    this.order = order;
     return this;
   }
 
-  public String getApplication() {
-    return application;
+  public String getRevision() {
+    return revision;
   }
 
-  public ConfigurationsRequest setApplication(String application) {
-    this.application = application;
+  public ConfigurationsRequest setRevision(String revision) {
+    this.revision = revision;
     return this;
   }
 
-  public String getServiceName() {
-    return serviceName;
+  public boolean isWithExact() {
+    return withExact;
   }
 
-  public ConfigurationsRequest setServiceName(String serviceName) {
-    this.serviceName = serviceName;
+  public ConfigurationsRequest setWithExact(boolean withExact) {
+    this.withExact = withExact;
     return this;
   }
 
-  public String getVersion() {
-    return version;
+  public String getLabelsQuery() {
+    return labelsQuery;
   }
 
-  public ConfigurationsRequest setVersion(String version) {
-    this.version = version;
+  public ConfigurationsRequest setLabelsQuery(String labelsQuery) {
+    this.labelsQuery = labelsQuery;
     return this;
   }
 
-  public String getRevision() {
-    return revision;
+  public Map<String, Object> getLastRawData() {
+    return lastRawData;
   }
 
-  public ConfigurationsRequest setRevision(String revision) {
-    this.revision = revision;
+  public ConfigurationsRequest setLastRawData(Map<String, Object> lastRawData) {
+    this.lastRawData = lastRawData;
     return this;
   }
+
+  @Override
+  public int compareTo(ConfigurationsRequest o) {
+    return o.getOrder() - this.order;
+  }
 }
diff --git a/clients/config-kie-client/src/main/java/org/apache/servicecomb/config/kie/client/model/ConfigurationsRequestFactory.java b/clients/config-kie-client/src/main/java/org/apache/servicecomb/config/kie/client/model/ConfigurationsRequestFactory.java
new file mode 100644
index 0000000..dd766aa
--- /dev/null
+++ b/clients/config-kie-client/src/main/java/org/apache/servicecomb/config/kie/client/model/ConfigurationsRequestFactory.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.servicecomb.config.kie.client.model;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.servicecomb.http.client.common.HttpUtils;
+
+public class ConfigurationsRequestFactory {
+  private static final String KEY_APP = "app";
+
+  private static final String KEY_ENVIRONMENT = "environment";
+
+  private static final String KEY_SERVICE = "service";
+
+  private static final int SERVICE_ORDER = 100;
+
+  private static final int APP_ORDER = 200;
+
+  private static final int CUSTOM_ORDER = 300;
+
+  public static List<ConfigurationsRequest> buildConfigurationRequests(KieConfiguration configuration) {
+    List<ConfigurationsRequest> result = new ArrayList<>();
+    if (configuration.isEnableAppConfig()) {
+      result.add(createAppConfigurationsRequest(configuration));
+    }
+    if (configuration.isEnableServiceConfig()) {
+      result.add(createServiceConfigurationsRequest(configuration));
+    }
+    if (configuration.isEnableCustomConfig()) {
+      result.add(createCustomConfigurationsRequest(configuration));
+    }
+    return result;
+  }
+
+  private static ConfigurationsRequest createAppConfigurationsRequest(KieConfiguration configuration) {
+    return new ConfigurationsRequest()
+        .setOrder(APP_ORDER)
+        .setWithExact(true)
+        .setLabelsQuery(buildLabelQuery(buildLabelQueryItem(KEY_APP, configuration.getAppName()),
+            buildLabelQueryItem(KEY_ENVIRONMENT, configuration.getEnvironment())));
+  }
+
+  private static ConfigurationsRequest createServiceConfigurationsRequest(KieConfiguration configuration) {
+    return new ConfigurationsRequest()
+        .setOrder(SERVICE_ORDER)
+        .setWithExact(true)
+        .setLabelsQuery(buildLabelQuery(buildLabelQueryItem(KEY_APP, configuration.getAppName()),
+            buildLabelQueryItem(KEY_SERVICE, configuration.getServiceName()),
+            buildLabelQueryItem(KEY_ENVIRONMENT, configuration.getEnvironment())));
+  }
+
+  private static ConfigurationsRequest createCustomConfigurationsRequest(KieConfiguration configuration) {
+    return new ConfigurationsRequest()
+        .setOrder(CUSTOM_ORDER)
+        .setWithExact(false)
+        .setLabelsQuery(
+            buildLabelQuery(buildLabelQueryItem(configuration.getCustomLabel(), configuration.getCustomLabelValue())));
+  }
+
+  private static String buildLabelQuery(String... labels) {
+    StringBuilder result = new StringBuilder();
+    for (String label : labels) {
+      result.append(label);
+      result.append("&");
+    }
+    return result.toString();
+  }
+
+  private static String buildLabelQueryItem(String key, String value) {
+    try {
+      return "label=" + HttpUtils.encodeURLParam(key + ":" + value);
+    } catch (IOException e) {
+      throw new IllegalArgumentException("unexpected param", e);
+    }
+  }
+}
diff --git a/clients/config-kie-client/src/main/java/org/apache/servicecomb/config/kie/client/model/KieAddressManager.java b/clients/config-kie-client/src/main/java/org/apache/servicecomb/config/kie/client/model/KieAddressManager.java
index 1b32be6..de21237 100644
--- a/clients/config-kie-client/src/main/java/org/apache/servicecomb/config/kie/client/model/KieAddressManager.java
+++ b/clients/config-kie-client/src/main/java/org/apache/servicecomb/config/kie/client/model/KieAddressManager.java
@@ -19,24 +19,15 @@ package org.apache.servicecomb.config.kie.client.model;
 
 import java.util.ArrayList;
 import java.util.List;
-import java.util.Map;
-import java.util.Properties;
 import java.util.Random;
 
 public class KieAddressManager {
-
-  private final Properties properties;
-
   private final List<String> addresses;
 
-  private final Map<String, String> configKey;
-
   private int index;
 
-  public KieAddressManager(Properties properties, List<String> addresses, Map<String, String> configKey) {
-    this.properties = properties;
+  public KieAddressManager(List<String> addresses) {
     this.addresses = new ArrayList<>(addresses.size());
-    this.configKey = configKey;
     addresses.forEach((address -> this.addresses.add(address)));
     this.index = new Random().nextInt(addresses.size());
   }
@@ -57,11 +48,7 @@ public class KieAddressManager {
     }
   }
 
-  public Properties getProperties() {
-    return properties;
-  }
-
-  public Map<String, String> getConfigKey() {
-    return configKey;
+  public boolean sslEnabled() {
+    return address().startsWith("https://");
   }
 }
diff --git a/clients/config-kie-client/src/main/java/org/apache/servicecomb/config/kie/client/model/KieConfiguration.java b/clients/config-kie-client/src/main/java/org/apache/servicecomb/config/kie/client/model/KieConfiguration.java
new file mode 100644
index 0000000..8bf93c1
--- /dev/null
+++ b/clients/config-kie-client/src/main/java/org/apache/servicecomb/config/kie/client/model/KieConfiguration.java
@@ -0,0 +1,152 @@
+/*
+ * 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.servicecomb.config.kie.client.model;
+
+public class KieConfiguration {
+  private boolean enableLongPolling;
+
+  private int pollingWaitInSeconds;
+
+  private String project;
+
+  private String appName;
+
+  private String serviceName;
+
+  private String environment;
+
+  private boolean enableAppConfig;
+
+  private boolean enableServiceConfig;
+
+  private boolean enableCustomConfig;
+
+  private String customLabelValue;
+
+  private String customLabel;
+
+  private boolean firstPullRequired;
+
+  public String getAppName() {
+    return appName;
+  }
+
+  public KieConfiguration setAppName(String appName) {
+    this.appName = appName;
+    return this;
+  }
+
+  public String getServiceName() {
+    return serviceName;
+  }
+
+  public KieConfiguration setServiceName(String serviceName) {
+    this.serviceName = serviceName;
+    return this;
+  }
+
+  public String getEnvironment() {
+    return environment;
+  }
+
+  public KieConfiguration setEnvironment(String environment) {
+    this.environment = environment;
+    return this;
+  }
+
+  public String getCustomLabelValue() {
+    return customLabelValue;
+  }
+
+  public KieConfiguration setCustomLabelValue(String customLabelValue) {
+    this.customLabelValue = customLabelValue;
+    return this;
+  }
+
+  public boolean isEnableAppConfig() {
+    return enableAppConfig;
+  }
+
+  public KieConfiguration setEnableAppConfig(boolean enableAppConfig) {
+    this.enableAppConfig = enableAppConfig;
+    return this;
+  }
+
+  public boolean isEnableServiceConfig() {
+    return enableServiceConfig;
+  }
+
+  public KieConfiguration setEnableServiceConfig(boolean enableServiceConfig) {
+    this.enableServiceConfig = enableServiceConfig;
+    return this;
+  }
+
+  public boolean isEnableCustomConfig() {
+    return enableCustomConfig;
+  }
+
+  public KieConfiguration setEnableCustomConfig(boolean enableCustomConfig) {
+    this.enableCustomConfig = enableCustomConfig;
+    return this;
+  }
+
+  public String getCustomLabel() {
+    return customLabel;
+  }
+
+  public KieConfiguration setCustomLabel(String customLabel) {
+    this.customLabel = customLabel;
+    return this;
+  }
+
+  public boolean isEnableLongPolling() {
+    return enableLongPolling;
+  }
+
+  public KieConfiguration setEnableLongPolling(boolean enableLongPolling) {
+    this.enableLongPolling = enableLongPolling;
+    return this;
+  }
+
+  public int getPollingWaitInSeconds() {
+    return pollingWaitInSeconds;
+  }
+
+  public KieConfiguration setPollingWaitInSeconds(int pollingWaitInSeconds) {
+    this.pollingWaitInSeconds = pollingWaitInSeconds;
+    return this;
+  }
+
+  public String getProject() {
+    return project;
+  }
+
+  public KieConfiguration setProject(String project) {
+    this.project = project;
+    return this;
+  }
+
+  public boolean isFirstPullRequired() {
+    return firstPullRequired;
+  }
+
+  public KieConfiguration setFirstPullRequired(boolean firstPullRequired) {
+    this.firstPullRequired = firstPullRequired;
+    return this;
+  }
+}
diff --git a/clients/http-client-common/src/main/java/org/apache/servicecomb/http/client/task/AbstractTask.java b/clients/http-client-common/src/main/java/org/apache/servicecomb/http/client/task/AbstractTask.java
index e05eef2..c33c04a 100644
--- a/clients/http-client-common/src/main/java/org/apache/servicecomb/http/client/task/AbstractTask.java
+++ b/clients/http-client-common/src/main/java/org/apache/servicecomb/http/client/task/AbstractTask.java
@@ -20,6 +20,7 @@ package org.apache.servicecomb.http.client.task;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 import java.util.concurrent.RejectedExecutionException;
+import java.util.concurrent.TimeUnit;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -58,14 +59,30 @@ public class AbstractTask {
 
   private static final Logger LOGGER = LoggerFactory.getLogger(AbstractTask.class);
 
-  private final ExecutorService taskPool;
+  protected ExecutorService taskPool;
+
+  private volatile boolean running = true;
 
   protected AbstractTask(String taskName) {
+    initTaskPool(taskName);
+    Runtime.getRuntime().addShutdownHook(new Thread(taskName + "-shutdown-hook") {
+      @Override
+      public void run() {
+        AbstractTask.this.stop();
+      }
+    });
+  }
+
+  protected void initTaskPool(String taskName) {
     this.taskPool = Executors.newSingleThreadExecutor((task) ->
         new Thread(task, taskName));
   }
 
   protected void startTask(Task task) {
+    if (!running) {
+      return;
+    }
+
     try {
       this.taskPool.execute(() -> {
         try {
@@ -80,6 +97,12 @@ public class AbstractTask {
   }
 
   public void stop() {
-    this.taskPool.shutdownNow();
+    try {
+      running = false;
+      this.taskPool.shutdown();
+      this.taskPool.awaitTermination(10, TimeUnit.SECONDS);
+    } catch (InterruptedException e) {
+      LOGGER.warn("tasks not shutdown in time {}", e.getMessage());
+    }
   }
 }
diff --git a/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/ServiceCenterConfiguration.java b/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/ServiceCenterConfiguration.java
deleted file mode 100644
index 794b976..0000000
--- a/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/ServiceCenterConfiguration.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * 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.servicecomb.service.center.client;
-
-public interface ServiceCenterConfiguration {
-  class AddressProperties {
-    private boolean address;
-
-    public boolean isAddress() {
-      return address;
-    }
-
-    public void setAddress(boolean address) {
-      this.address = address;
-    }
-  }
-}
diff --git a/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/ServiceCenterDiscovery.java b/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/ServiceCenterDiscovery.java
index 1b63035..0e2df3b 100644
--- a/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/ServiceCenterDiscovery.java
+++ b/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/ServiceCenterDiscovery.java
@@ -17,6 +17,7 @@
 
 package org.apache.servicecomb.service.center.client;
 
+import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
@@ -27,6 +28,7 @@ import org.apache.servicecomb.http.client.task.Task;
 import org.apache.servicecomb.service.center.client.DiscoveryEvents.InstanceChangedEvent;
 import org.apache.servicecomb.service.center.client.DiscoveryEvents.PullInstanceEvent;
 import org.apache.servicecomb.service.center.client.model.FindMicroserviceInstancesResponse;
+import org.apache.servicecomb.service.center.client.model.Microservice;
 import org.apache.servicecomb.service.center.client.model.MicroserviceInstance;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -86,6 +88,8 @@ public class ServiceCenterDiscovery extends AbstractTask {
 
   private final Map<SubscriptionKey, SubscriptionValue> instancesCache = new ConcurrentHashMap<>();
 
+  private final Map<String, Microservice> microserviceCache = new ConcurrentHashMap<>();
+
   public ServiceCenterDiscovery(ServiceCenterClient serviceCenterClient, EventBus eventBus) {
     super("service-center-discovery-task");
     this.serviceCenterClient = serviceCenterClient;
@@ -123,32 +127,53 @@ public class ServiceCenterDiscovery extends AbstractTask {
   }
 
   private void pullInstance(SubscriptionKey k, SubscriptionValue v) {
+    if (myselfServiceId == null) {
+      // registration not ready
+      return;
+    }
     try {
       FindMicroserviceInstancesResponse instancesResponse = serviceCenterClient
           .findMicroserviceInstance(myselfServiceId, k.appId, k.serviceName, ALL_VERSION, v.revision);
       if (instancesResponse.isModified()) {
-        // java chassis 实现了空实例保护,这里暂时不实现。
+        List<MicroserviceInstance> instances = instancesResponse.getMicroserviceInstancesResponse().getInstances()
+            == null ? Collections.emptyList() : instancesResponse.getMicroserviceInstancesResponse().getInstances();
+        setMicroserviceInfo(instances);
         LOGGER.info("Instance changed event, "
                 + "current: revision={}, instances={}; "
                 + "origin: revision={}, instances={}; "
                 + "appId={}, serviceName={}",
             instancesResponse.getRevision(),
-            instanceToString(instancesResponse.getMicroserviceInstancesResponse().getInstances()),
+            instanceToString(instances),
             v.revision,
             instanceToString(v.instancesCache),
             k.appId,
             k.serviceName
         );
-        v.instancesCache = instancesResponse.getMicroserviceInstancesResponse().getInstances();
+        v.instancesCache = instances;
         v.revision = instancesResponse.getRevision();
         eventBus.post(new InstanceChangedEvent(k.appId, k.serviceName,
             v.instancesCache));
       }
     } catch (Exception e) {
-      LOGGER.error("find service instance failed.", e);
+      LOGGER.error("find service {}#{} instance failed.", k.appId, k.serviceName, e);
     }
   }
 
+  private void setMicroserviceInfo(List<MicroserviceInstance> instances) {
+    instances.forEach(instance -> {
+      Microservice microservice = microserviceCache
+          .computeIfAbsent(instance.getServiceId(), id -> {
+            try {
+              return serviceCenterClient.getMicroserviceByServiceId(id);
+            } catch (Exception e) {
+              LOGGER.error("Find microservice by id={} failed", id, e);
+              throw e;
+            }
+          });
+      instance.setMicroservice(microservice);
+    });
+  }
+
   class PullInstanceTask implements Task {
     @Override
     public void execute() {
@@ -175,6 +200,8 @@ public class ServiceCenterDiscovery extends AbstractTask {
         sb.append(endpoint.length() > 64 ? endpoint.substring(0, 64) : endpoint);
         sb.append("|");
       }
+      sb.append(instance.getServiceName());
+      sb.append("|");
     }
     sb.append("#");
     return sb.toString();
diff --git a/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/ServiceCenterRegistration.java b/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/ServiceCenterRegistration.java
index a9d8fbf..a10f7e6 100644
--- a/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/ServiceCenterRegistration.java
+++ b/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/ServiceCenterRegistration.java
@@ -32,6 +32,7 @@ import org.apache.servicecomb.service.center.client.model.MicroserviceInstance;
 import org.apache.servicecomb.service.center.client.model.RegisteredMicroserviceInstanceResponse;
 import org.apache.servicecomb.service.center.client.model.RegisteredMicroserviceResponse;
 import org.apache.servicecomb.service.center.client.model.SchemaInfo;
+import org.apache.servicecomb.service.center.client.model.ServiceCenterConfiguration;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -50,9 +51,13 @@ public class ServiceCenterRegistration extends AbstractTask {
 
   private List<SchemaInfo> schemaInfos;
 
-  public ServiceCenterRegistration(ServiceCenterClient serviceCenterClient, EventBus eventBus) {
+  private ServiceCenterConfiguration serviceCenterConfiguration;
+
+  public ServiceCenterRegistration(ServiceCenterClient serviceCenterClient, ServiceCenterConfiguration
+      serviceCenterConfiguration, EventBus eventBus) {
     super("service-center-registration-task");
     this.serviceCenterClient = serviceCenterClient;
+    this.serviceCenterConfiguration = serviceCenterConfiguration;
     this.eventBus = eventBus;
   }
 
@@ -89,20 +94,16 @@ public class ServiceCenterRegistration extends AbstractTask {
             LOGGER.error("register microservice failed, and will try again.");
             eventBus.post(new MicroserviceRegistrationEvent(false));
             startTask(new BackOffSleepTask(failedCount + 1, new RegisterMicroserviceTask(failedCount + 1)));
-          } else {
-            microservice.setServiceId(response.getServiceId());
-            microserviceInstance.setServiceId(response.getServiceId());
-            microserviceInstance.setMicroservice(microservice);
-            eventBus.post(new MicroserviceRegistrationEvent(true));
-            startTask(new RegisterSchemaTask(0));
+            return;
           }
-          return;
+          microservice.setServiceId(response.getServiceId());
+          microserviceInstance.setServiceId(response.getServiceId());
+          microserviceInstance.setMicroservice(microservice);
+          eventBus.post(new MicroserviceRegistrationEvent(true));
+          startTask(new RegisterSchemaTask(0));
         } else {
           Microservice newMicroservice = serviceCenterClient.getMicroserviceByServiceId(serviceResponse.getServiceId());
-          if (!isListEquals(newMicroservice.getSchemas(), microservice.getSchemas())) {
-            throw new IllegalStateException("Service has already registered, but schema ids not equal, stop register. "
-                + "Change the microservice version or delete the old microservice info and try again.");
-          }
+          dealIsSwaggerDifferent(newMicroservice);
           microservice.setServiceId(serviceResponse.getServiceId());
           microserviceInstance.setServiceId(serviceResponse.getServiceId());
           microserviceInstance.setMicroservice(microservice);
@@ -120,6 +121,19 @@ public class ServiceCenterRegistration extends AbstractTask {
     }
   }
 
+  private void dealIsSwaggerDifferent(Microservice newMicroservice) {
+    if (isListEquals(newMicroservice.getSchemas(), microservice.getSchemas())) {
+      return;
+    }
+    if (!serviceCenterConfiguration.isIgnoreSwaggerDifferent()) {
+      throw new IllegalStateException("Service has already registered, but schema ids not equal, stop register. "
+          + "Change the microservice version or delete the old microservice info and try again.");
+    }
+    LOGGER.warn("Service has already registered, but schema ids not equal. However, it will continue to register. "
+        + "If you want to eliminate this warning. you can Change the microservice version or delete the old " +
+        "microservice info and try again. eg: version:1.0.0 -> 1.0.1");
+  }
+
   private boolean isListEquals(List<String> one, List<String> two) {
     return one.size() == two.size() && one.containsAll(two) && two.containsAll(one);
   }
diff --git a/dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/client/ConnFailEvent.java b/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/model/ServiceCenterConfiguration.java
similarity index 55%
rename from dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/client/ConnFailEvent.java
rename to clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/model/ServiceCenterConfiguration.java
index 1e34810..a452259 100644
--- a/dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/client/ConnFailEvent.java
+++ b/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/model/ServiceCenterConfiguration.java
@@ -15,21 +15,23 @@
  * limitations under the License.
  */
 
-package org.apache.servicecomb.config.kie.client;
+package org.apache.servicecomb.service.center.client.model;
 
-public class ConnFailEvent {
+public class ServiceCenterConfiguration {
 
-  private String msg;
+  /**
+   * for registration service
+   * when swagger is different between local with remote serviceCenter. if ignoreSwaggerDifferent is true.
+   * it will ignore the different and continue the program. otherwise, the program will be stop.
+   */
+  private Boolean ignoreSwaggerDifferent;
 
-  public ConnFailEvent(String msg) {
-    this.msg = msg;
+  public Boolean isIgnoreSwaggerDifferent() {
+    return ignoreSwaggerDifferent;
   }
 
-  public String getMsg() {
-    return msg;
-  }
-
-  public void setMsg(String msg) {
-    this.msg = msg;
+  public ServiceCenterConfiguration setIgnoreSwaggerDifferent(Boolean ignoreSwaggerDifferent) {
+    this.ignoreSwaggerDifferent = ignoreSwaggerDifferent;
+    return this;
   }
 }
diff --git a/demo/demo-multi-service-center/demo-multi-service-center-client/src/main/java/org/apache/servicecomb/demo/multiServiceCenterClient/RegistryClientTest.java b/demo/demo-multi-service-center/demo-multi-service-center-client/src/main/java/org/apache/servicecomb/demo/multiServiceCenterClient/RegistryClientTest.java
index 87ec262..d64dc24 100644
--- a/demo/demo-multi-service-center/demo-multi-service-center-client/src/main/java/org/apache/servicecomb/demo/multiServiceCenterClient/RegistryClientTest.java
+++ b/demo/demo-multi-service-center/demo-multi-service-center-client/src/main/java/org/apache/servicecomb/demo/multiServiceCenterClient/RegistryClientTest.java
@@ -42,6 +42,7 @@ import org.apache.servicecomb.service.center.client.ServiceCenterRegistration;
 import org.apache.servicecomb.service.center.client.model.Microservice;
 import org.apache.servicecomb.service.center.client.model.MicroserviceInstance;
 import org.apache.servicecomb.service.center.client.model.SchemaInfo;
+import org.apache.servicecomb.service.center.client.model.ServiceCenterConfiguration;
 import org.springframework.stereotype.Component;
 
 import com.google.common.base.Charsets;
@@ -70,7 +71,9 @@ public class RegistryClientTest implements CategorizedTestCase {
     ServiceCenterClient serviceCenterClient = new ServiceCenterClient(addressManager, sslProperties,
         new DefaultRequestAuthHeaderProvider(), "default", null);
     EventBus eventBus = new SimpleEventBus();
-    ServiceCenterRegistration serviceCenterRegistration = new ServiceCenterRegistration(serviceCenterClient, eventBus);
+    ServiceCenterConfiguration serviceCenterConfiguration = new ServiceCenterConfiguration();
+    ServiceCenterRegistration serviceCenterRegistration = new ServiceCenterRegistration(serviceCenterClient,
+        serviceCenterConfiguration, eventBus);
     Microservice microservice = new Microservice();
     microservice.setAppId("app_registry");
     microservice.setServiceName("name_registry");
diff --git a/dynamic-config/config-kie/pom.xml b/dynamic-config/config-kie/pom.xml
index 7a6c3b5..7e89420 100644
--- a/dynamic-config/config-kie/pom.xml
+++ b/dynamic-config/config-kie/pom.xml
@@ -61,5 +61,9 @@
       <artifactId>foundation-test-scaffolding</artifactId>
       <scope>test</scope>
     </dependency>
+    <dependency>
+      <groupId>org.apache.servicecomb</groupId>
+      <artifactId>config-kie-client</artifactId>
+    </dependency>
   </dependencies>
 </project>
\ No newline at end of file
diff --git a/dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/client/KieConfig.java b/dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/KieConfig.java
similarity index 73%
rename from dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/client/KieConfig.java
rename to dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/KieConfig.java
index 38c68bf..ac43c86 100644
--- a/dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/client/KieConfig.java
+++ b/dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/KieConfig.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.servicecomb.config.kie.client;
+package org.apache.servicecomb.config.kie;
 
 import org.apache.servicecomb.config.BootStrapProperties;
 import org.apache.servicecomb.foundation.vertx.VertxConst;
@@ -38,6 +38,20 @@ public class KieConfig {
 
   private static final String ENABLE_LONG_POLLING = "servicecomb.kie.enableLongPolling";
 
+  private static final String POLLING_WAIT_TIME = "servicecomb.kie.pollingWaitTime";
+
+  private static final String FIRST_PULL_REQUIRED = "servicecomb.kie.firstPullRequired";
+
+  private static final String CUSTOM_LABEL = "servicecomb.kie.customLabel";
+
+  private static final String CUSTOM_LABEL_VALUE = "servicecomb.kie.customLabelValue";
+
+  private static final String ENABLE_APP_CONFIG = "servicecomb.kie.enableAppConfig";
+
+  private static final String ENABLE_SERVICE_CONFIG = "servicecomb.kie.enableServiceConfig";
+
+  private static final String ENABLE_CUSTOM_CONFIG = "servicecomb.kie.enableCustomConfig";
+
   public static final String CONNECTION_TIME_OUT = "servicecomb.kie.client.timeout.connection";
 
   public static final String EVENT_LOOP_SIZE = "servicecomb.kie.client.eventLoopSize";
@@ -48,10 +62,16 @@ public class KieConfig {
 
   private static final int DEFAULT_REFRESH_INTERVAL = 3000;
 
+  private static final int DEFAULT_POLLING_WAIT_TIME = 10;
+
   private static final int DEFAULT_FIRST_REFRESH_INTERVAL = 0;
 
   private static final boolean DEFAULT_ENABLE_LONG_POLLING = true;
 
+  private static final String CUSTOM_LABEL_DEFAULT = "public";
+
+  private static final String CUSTOM_LABEL_VALUE_DEFAULT = "";
+
   private KieConfig() {
   }
 
@@ -115,10 +135,38 @@ public class KieConfig {
     return finalConfig.getInt(FIRST_REFRESH_INTERVAL, DEFAULT_FIRST_REFRESH_INTERVAL);
   }
 
+  public boolean enableAppConfig() {
+    return finalConfig.getBoolean(ENABLE_APP_CONFIG, true);
+  }
+
+  public boolean enableServiceConfig() {
+    return finalConfig.getBoolean(ENABLE_SERVICE_CONFIG, true);
+  }
+
+  public boolean enableCustomConfig() {
+    return finalConfig.getBoolean(ENABLE_CUSTOM_CONFIG, true);
+  }
+
   public boolean enableLongPolling() {
     return finalConfig.getBoolean(ENABLE_LONG_POLLING, DEFAULT_ENABLE_LONG_POLLING);
   }
 
+  public int getPollingWaitTime() {
+    return finalConfig.getInt(POLLING_WAIT_TIME, DEFAULT_POLLING_WAIT_TIME);
+  }
+
+  public boolean firstPullRequired() {
+    return finalConfig.getBoolean(FIRST_PULL_REQUIRED, false);
+  }
+
+  public String getCustomLabel() {
+    return finalConfig.getString(CUSTOM_LABEL, CUSTOM_LABEL_DEFAULT);
+  }
+
+  public String getCustomLabelValue() {
+    return finalConfig.getString(CUSTOM_LABEL_VALUE, CUSTOM_LABEL_VALUE_DEFAULT);
+  }
+
   public Boolean isProxyEnable() {
     return finalConfig.getBoolean(VertxConst.PROXY_ENABLE, false);
   }
diff --git a/dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/KieConfigurationSourceImpl.java b/dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/KieConfigurationSourceImpl.java
new file mode 100644
index 0000000..18d3fb4
--- /dev/null
+++ b/dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/KieConfigurationSourceImpl.java
@@ -0,0 +1,172 @@
+/*
+ * 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.servicecomb.config.kie;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+import org.apache.commons.configuration.Configuration;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.http.client.config.RequestConfig;
+import org.apache.servicecomb.config.common.ConfigConverter;
+import org.apache.servicecomb.config.common.ConfigurationChangedEvent;
+import org.apache.servicecomb.config.kie.client.KieClient;
+import org.apache.servicecomb.config.kie.client.KieConfigManager;
+import org.apache.servicecomb.config.kie.client.model.KieAddressManager;
+import org.apache.servicecomb.config.kie.client.model.KieConfiguration;
+import org.apache.servicecomb.config.spi.ConfigCenterConfigurationSource;
+import org.apache.servicecomb.foundation.auth.AuthHeaderProvider;
+import org.apache.servicecomb.foundation.common.event.EventManager;
+import org.apache.servicecomb.foundation.common.utils.SPIServiceUtils;
+import org.apache.servicecomb.http.client.auth.RequestAuthHeaderProvider;
+import org.apache.servicecomb.http.client.common.HttpTransport;
+import org.apache.servicecomb.http.client.common.HttpTransportFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.eventbus.Subscribe;
+import com.netflix.config.ConcurrentCompositeConfiguration;
+import com.netflix.config.WatchedUpdateListener;
+import com.netflix.config.WatchedUpdateResult;
+
+public class KieConfigurationSourceImpl implements ConfigCenterConfigurationSource {
+
+  private static final Logger LOGGER = LoggerFactory.getLogger(KieConfigurationSourceImpl.class);
+
+  private List<WatchedUpdateListener> listeners = new CopyOnWriteArrayList<>();
+
+  private KieConfigManager kieConfigManager;
+
+  private ConfigConverter configConverter = new ConfigConverter(null);
+
+  @Override
+  public int getOrder() {
+    return ORDER_BASE * 2;
+  }
+
+  @Override
+  public boolean isValidSource(Configuration localConfiguration) {
+    KieConfig.setFinalConfig((ConcurrentCompositeConfiguration) localConfiguration);
+
+    if (StringUtils.isEmpty(KieConfig.INSTANCE.getServerUri())) {
+      LOGGER.info("Kie server is not configured.");
+      return false;
+    }
+    return true;
+  }
+
+  @Override
+  public void init(Configuration localConfiguration) {
+    KieAddressManager kieAddressManager = configKieAddressManager();
+
+    RequestConfig.Builder requestBuilder = HttpTransportFactory.defaultRequestConfig();
+    if (KieConfig.INSTANCE.enableLongPolling()
+        && KieConfig.INSTANCE.getPollingWaitTime() >= 0) {
+      requestBuilder.setConnectionRequestTimeout(KieConfig.INSTANCE.getPollingWaitTime() * 2 * 1000);
+      requestBuilder.setSocketTimeout(KieConfig.INSTANCE.getPollingWaitTime() * 2 * 1000);
+    }
+    HttpTransport httpTransport = createHttpTransport(requestBuilder.build(), localConfiguration);
+    KieConfiguration kieConfiguration = createKieConfiguration();
+    KieClient kieClient = new KieClient(kieAddressManager, httpTransport, kieConfiguration);
+    EventManager.register(this);
+    kieConfigManager = new KieConfigManager(kieClient, EventManager.getEventBus(), kieConfiguration, configConverter);
+    kieConfigManager.firstPull();
+    kieConfigManager.startConfigKieManager();
+    updateConfiguration(WatchedUpdateResult.createIncremental(configConverter.getCurrentData(), null, null));
+  }
+
+  @Subscribe
+  public void onConfigurationChangedEvent(ConfigurationChangedEvent event) {
+    updateConfiguration(
+        WatchedUpdateResult.createIncremental(event.getAdded(), event.getUpdated(), event.getDeleted()));
+  }
+
+  private KieConfiguration createKieConfiguration() {
+    return new KieConfiguration().setAppName(KieConfig.INSTANCE.getAppName())
+        .setFirstPullRequired(KieConfig.INSTANCE.firstPullRequired())
+        .setCustomLabel(KieConfig.INSTANCE.getCustomLabel())
+        .setCustomLabelValue(KieConfig.INSTANCE.getCustomLabelValue())
+        .setEnableAppConfig(KieConfig.INSTANCE.enableAppConfig())
+        .setEnableCustomConfig(KieConfig.INSTANCE.enableCustomConfig())
+        .setEnableLongPolling(KieConfig.INSTANCE.enableLongPolling())
+        .setEnableServiceConfig(KieConfig.INSTANCE.enableServiceConfig())
+        .setEnvironment(KieConfig.INSTANCE.getEnvironment())
+        .setPollingWaitInSeconds(KieConfig.INSTANCE.getPollingWaitTime())
+        .setProject(KieConfig.INSTANCE.getDomainName())
+        .setServiceName(KieConfig.INSTANCE.getServiceName());
+  }
+
+  private HttpTransport createHttpTransport(RequestConfig requestConfig, Configuration localConfiguration) {
+    List<AuthHeaderProvider> authHeaderProviders = SPIServiceUtils.getOrLoadSortedService(AuthHeaderProvider.class);
+
+    return HttpTransportFactory
+        .createHttpTransport(
+            TransportUtils.createSSLProperties(localConfiguration, "kie"),
+            getRequestAuthHeaderProvider(authHeaderProviders), requestConfig);
+  }
+
+  private static RequestAuthHeaderProvider getRequestAuthHeaderProvider(List<AuthHeaderProvider> authHeaderProviders) {
+    return signRequest -> {
+      Map<String, String> headers = new HashMap<>();
+      authHeaderProviders.forEach(provider -> headers.putAll(provider.authHeaders()));
+      return headers;
+    };
+  }
+
+  private KieAddressManager configKieAddressManager() {
+    KieAddressManager kieAddressManager = new KieAddressManager(
+        Arrays.asList(KieConfig.INSTANCE.getServerUri().split(",")));
+    return kieAddressManager;
+  }
+
+  private void updateConfiguration(WatchedUpdateResult result) {
+    for (WatchedUpdateListener l : listeners) {
+      try {
+        l.updateConfiguration(result);
+      } catch (Throwable ex) {
+        LOGGER.error("Error in invoking WatchedUpdateListener", ex);
+      }
+    }
+  }
+
+  @Override
+  public void destroy() {
+    if (kieConfigManager == null) {
+      return;
+    }
+    kieConfigManager.stop();
+  }
+
+  @Override
+  public void addUpdateListener(WatchedUpdateListener watchedUpdateListener) {
+    listeners.add(watchedUpdateListener);
+  }
+
+  @Override
+  public void removeUpdateListener(WatchedUpdateListener watchedUpdateListener) {
+    listeners.remove(watchedUpdateListener);
+  }
+
+  @Override
+  public Map<String, Object> getCurrentData() throws Exception {
+    return configConverter.getCurrentData();
+  }
+}
diff --git a/dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/TransportUtils.java b/dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/TransportUtils.java
new file mode 100644
index 0000000..d335fd5
--- /dev/null
+++ b/dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/TransportUtils.java
@@ -0,0 +1,118 @@
+/*
+ * 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.servicecomb.config.kie;
+
+import static org.apache.servicecomb.foundation.ssl.SSLOption.DEFAULT_OPTION;
+
+import org.apache.commons.configuration.Configuration;
+import org.apache.servicecomb.foundation.ssl.SSLCustom;
+import org.apache.servicecomb.foundation.ssl.SSLOption;
+import org.apache.servicecomb.http.client.common.HttpConfiguration.SSLProperties;
+
+public class TransportUtils {
+  public static SSLProperties createSSLProperties(Configuration configuration, String tag) {
+    SSLProperties sslProperties = new SSLProperties();
+
+    SSLOption option = new SSLOption();
+    option.setEngine(getStringProperty(configuration,
+        DEFAULT_OPTION.getEngine(),
+        "ssl." + tag + ".engine",
+        "ssl.engine"));
+    option.setProtocols(
+        getStringProperty(configuration,
+            DEFAULT_OPTION.getProtocols(),
+            "ssl." + tag + ".protocols",
+            "ssl.protocols"));
+    option.setCiphers(
+        getStringProperty(configuration, DEFAULT_OPTION.getCiphers(), "ssl." + tag + ".ciphers", "ssl.ciphers"));
+    option.setAuthPeer(
+        getBooleanProperty(configuration, DEFAULT_OPTION.isAuthPeer(), "ssl." + tag + ".authPeer", "ssl.authPeer"));
+    option.setCheckCNHost(
+        getBooleanProperty(configuration,
+            DEFAULT_OPTION.isCheckCNHost(),
+            "ssl." + tag + ".checkCN.host",
+            "ssl.checkCN.host"));
+    option.setCheckCNWhite(
+        getBooleanProperty(configuration,
+            DEFAULT_OPTION.isCheckCNWhite(),
+            "ssl." + tag + ".checkCN.white",
+            "ssl.checkCN.white"));
+    option.setCheckCNWhiteFile(getStringProperty(configuration,
+        DEFAULT_OPTION.getCiphers(),
+        "ssl." + tag + ".checkCN.white.file",
+        "ssl.checkCN.white.file"));
+    option.setAllowRenegociate(getBooleanProperty(configuration,
+        DEFAULT_OPTION.isAllowRenegociate(),
+        "ssl." + tag + ".allowRenegociate",
+        "ssl.allowRenegociate"));
+    option.setStorePath(
+        getStringProperty(configuration,
+            DEFAULT_OPTION.getStorePath(),
+            "ssl." + tag + ".storePath",
+            "ssl.storePath"));
+    option.setTrustStore(
+        getStringProperty(configuration,
+            DEFAULT_OPTION.getTrustStore(),
+            "ssl." + tag + ".trustStore",
+            "ssl.trustStore"));
+    option.setTrustStoreType(getStringProperty(configuration,
+        DEFAULT_OPTION.getTrustStoreType(),
+        "ssl." + tag + ".trustStoreType",
+        "ssl.trustStoreType"));
+    option.setTrustStoreValue(getStringProperty(configuration,
+        DEFAULT_OPTION.getTrustStoreValue(),
+        "ssl." + tag + ".trustStoreValue",
+        "ssl.trustStoreValue"));
+    option.setKeyStore(
+        getStringProperty(configuration, DEFAULT_OPTION.getKeyStore(), "ssl." + tag + ".keyStore", "ssl.keyStore"));
+    option.setKeyStoreType(
+        getStringProperty(configuration,
+            DEFAULT_OPTION.getKeyStoreType(),
+            "ssl." + tag + ".keyStoreType",
+            "ssl.keyStoreType"));
+    option.setKeyStoreValue(getStringProperty(configuration,
+        DEFAULT_OPTION.getKeyStoreValue(),
+        "ssl." + tag + ".keyStoreValue",
+        "ssl.keyStoreValue"));
+    option.setCrl(getStringProperty(configuration, DEFAULT_OPTION.getCrl(), "ssl." + tag + ".crl", "ssl.crl"));
+    option.setSslCustomClass(
+        getStringProperty(configuration, null, "ssl." + tag + ".sslCustomClass", "ssl.sslCustomClass"));
+
+    sslProperties.setSslOption(option);
+    sslProperties.setSslCustom(SSLCustom.createSSLCustom(option.getSslCustomClass()));
+    return sslProperties;
+  }
+
+  private static String getStringProperty(Configuration configuration, String defaultValue, String... keys) {
+    for (String key : keys) {
+      if (configuration.containsKey(key)) {
+        return configuration.getString(key);
+      }
+    }
+    return defaultValue;
+  }
+
+  private static boolean getBooleanProperty(Configuration configuration, boolean defaultValue, String... keys) {
+    for (String key : keys) {
+      if (configuration.containsKey(key)) {
+        return configuration.getBoolean(key);
+      }
+    }
+    return defaultValue;
+  }
+}
diff --git a/dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/archaius/sources/KieConfigurationSourceImpl.java b/dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/archaius/sources/KieConfigurationSourceImpl.java
deleted file mode 100644
index 7b0b764..0000000
--- a/dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/archaius/sources/KieConfigurationSourceImpl.java
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * 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.servicecomb.config.kie.archaius.sources;
-
-import static com.netflix.config.WatchedUpdateResult.createIncremental;
-
-import com.google.common.collect.ImmutableMap;
-import com.netflix.config.ConcurrentCompositeConfiguration;
-import com.netflix.config.WatchedUpdateListener;
-import com.netflix.config.WatchedUpdateResult;
-
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.CopyOnWriteArrayList;
-
-import org.apache.commons.configuration.Configuration;
-import org.apache.servicecomb.config.ConfigMapping;
-import org.apache.servicecomb.config.kie.client.KieClient;
-import org.apache.servicecomb.config.kie.client.KieConfig;
-import org.apache.servicecomb.config.spi.ConfigCenterConfigurationSource;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class KieConfigurationSourceImpl implements ConfigCenterConfigurationSource {
-
-  private static final Logger LOGGER = LoggerFactory.getLogger(KieConfigurationSourceImpl.class);
-
-  private static final String KIE_CONFIG_URL_KEY = "servicecomb.kie.serverUri";
-
-  private final Map<String, Object> valueCache = new ConcurrentHashMap<>();
-
-  private List<WatchedUpdateListener> listeners = new CopyOnWriteArrayList<>();
-
-  private UpdateHandler updateHandler = new UpdateHandler();
-
-  private KieClient kieClient;
-
-  @Override
-  public int getOrder() {
-    return ORDER_BASE * 2;
-  }
-
-  @Override
-  public boolean isValidSource(Configuration localConfiguration) {
-    if (localConfiguration.getProperty(KIE_CONFIG_URL_KEY) == null) {
-      LOGGER.warn("Kie configuration source is not configured!");
-      return false;
-    }
-    return true;
-  }
-
-  @Override
-  public void init(Configuration localConfiguration) {
-    KieConfig.setFinalConfig((ConcurrentCompositeConfiguration) localConfiguration);
-    kieClient = new KieClient(updateHandler);
-    kieClient.refreshKieConfig();
-  }
-
-  @Override
-  public void destroy() {
-    if (kieClient == null) {
-      return;
-    }
-    kieClient.destroy();
-  }
-
-  @Override
-  public void addUpdateListener(WatchedUpdateListener watchedUpdateListener) {
-    listeners.add(watchedUpdateListener);
-  }
-
-  @Override
-  public void removeUpdateListener(WatchedUpdateListener watchedUpdateListener) {
-    listeners.remove(watchedUpdateListener);
-  }
-
-  @Override
-  public Map<String, Object> getCurrentData() throws Exception {
-    return valueCache;
-  }
-
-
-  private void updateConfiguration(WatchedUpdateResult result) {
-    for (WatchedUpdateListener l : listeners) {
-      try {
-        l.updateConfiguration(result);
-      } catch (Throwable ex) {
-        LOGGER.error("Error in invoking WatchedUpdateListener", ex);
-      }
-    }
-  }
-
-  public class UpdateHandler {
-
-    public void handle(String action, Map<String, Object> parseConfigs) {
-      if (parseConfigs == null || parseConfigs.isEmpty()) {
-        return;
-      }
-      Map<String, Object> configuration = ConfigMapping.getConvertedMap(parseConfigs);
-      if ("create".equals(action)) {
-        valueCache.putAll(configuration);
-        updateConfiguration(createIncremental(ImmutableMap.<String, Object>copyOf(configuration),
-            null,
-            null));
-      } else if ("set".equals(action)) {
-        valueCache.putAll(configuration);
-        updateConfiguration(
-            createIncremental(null, ImmutableMap.<String, Object>copyOf(configuration),
-                null));
-      } else if ("delete".equals(action)) {
-        configuration.keySet().forEach(valueCache::remove);
-        updateConfiguration(createIncremental(null,
-            null,
-            ImmutableMap.<String, Object>copyOf(configuration)));
-      } else {
-        LOGGER.error("action: {} is invalid.", action);
-        return;
-      }
-      LOGGER.warn("Config value cache changed: action:{}; item:{}", action, configuration.keySet());
-    }
-  }
-}
diff --git a/dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/client/ConfigKieHttpClientOptionsSPI.java b/dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/client/ConfigKieHttpClientOptionsSPI.java
deleted file mode 100644
index 7b46738..0000000
--- a/dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/client/ConfigKieHttpClientOptionsSPI.java
+++ /dev/null
@@ -1,175 +0,0 @@
-/*
- * 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.servicecomb.config.kie.client;
-
-import org.apache.servicecomb.foundation.vertx.client.http.HttpClientOptionsSPI;
-
-import com.netflix.config.ConcurrentCompositeConfiguration;
-
-import io.vertx.core.VertxOptions;
-import io.vertx.core.http.HttpClientOptions;
-import io.vertx.core.http.HttpVersion;
-
-public class ConfigKieHttpClientOptionsSPI implements HttpClientOptionsSPI {
-  public static final String CLIENT_NAME = "config-kie";
-
-  @Override
-  public String clientName() {
-    return CLIENT_NAME;
-  }
-
-  @Override
-  public int getOrder() {
-    return -200;
-  }
-
-  @Override
-  public boolean enabled() {
-    return KieConfig.INSTANCE.getServerUri() != null;
-  }
-
-  @Override
-  public String getConfigTag() {
-    return "kie.consumer";
-  }
-
-  @Override
-  public ConcurrentCompositeConfiguration getConfigReader() {
-    return KieConfig.getFinalConfig();
-  }
-
-  @Override
-  public int getEventLoopPoolSize() {
-    return KieConfig.INSTANCE.getEventLoopSize();
-  }
-
-  @Override
-  public boolean useSharedVertx() {
-    return false;
-  }
-
-  @Override
-  public int getInstanceCount() {
-    return KieConfig.INSTANCE.getVerticalInstanceCount();
-  }
-
-  @Override
-  public boolean isWorker() {
-    return false;
-  }
-
-  @Override
-  public String getWorkerPoolName() {
-    return "pool-worker-kie-client";
-  }
-
-  @Override
-  public int getWorkerPoolSize() {
-    return VertxOptions.DEFAULT_WORKER_POOL_SIZE;
-  }
-
-  @Override
-  public HttpVersion getHttpVersion() {
-    return HttpVersion.HTTP_1_1;
-  }
-
-  @Override
-  public int getConnectTimeoutInMillis() {
-    return KieConfig.INSTANCE.getConnectionTimeOut();
-  }
-
-  @Override
-  public int getIdleTimeoutInSeconds() {
-    return KieConfig.INSTANCE.getIdleTimeoutInSeconds();
-  }
-
-  @Override
-  public boolean isTryUseCompression() {
-    return HttpClientOptions.DEFAULT_TRY_USE_COMPRESSION;
-  }
-
-  @Override
-  public int getMaxWaitQueueSize() {
-    return HttpClientOptions.DEFAULT_MAX_WAIT_QUEUE_SIZE;
-  }
-
-  @Override
-  public int getMaxPoolSize() {
-    return HttpClientOptions.DEFAULT_MAX_POOL_SIZE;
-  }
-
-  @Override
-  public boolean isKeepAlive() {
-    return HttpClientOptions.DEFAULT_KEEP_ALIVE;
-  }
-
-  @Override
-  public int getMaxHeaderSize() {
-    return HttpClientOptions.DEFAULT_MAX_HEADER_SIZE;
-  }
-
-  @Override
-  public int getKeepAliveTimeout() {
-    return HttpClientOptions.DEFAULT_KEEP_ALIVE_TIMEOUT;
-  }
-
-  @Override
-  public int getHttp2MultiplexingLimit() {
-    return HttpClientOptions.DEFAULT_HTTP2_MULTIPLEXING_LIMIT;
-  }
-
-  @Override
-  public int getHttp2MaxPoolSize() {
-    return HttpClientOptions.DEFAULT_HTTP2_MAX_POOL_SIZE;
-  }
-
-  @Override
-  public boolean isUseAlpn() {
-    return HttpClientOptions.DEFAULT_USE_ALPN;
-  }
-
-  @Override
-  public boolean isProxyEnable() {
-    return KieConfig.INSTANCE.isProxyEnable();
-  }
-
-  @Override
-  public String getProxyHost() {
-    return KieConfig.INSTANCE.getProxyHost();
-  }
-
-  @Override
-  public int getProxyPort() {
-    return KieConfig.INSTANCE.getProxyPort();
-  }
-
-  @Override
-  public String getProxyUsername() {
-    return KieConfig.INSTANCE.getProxyUsername();
-  }
-
-  @Override
-  public String getProxyPassword() {
-    return KieConfig.INSTANCE.getProxyPasswd();
-  }
-
-  @Override
-  public boolean isSsl() {
-    return KieConfig.INSTANCE.getServerUri() != null && KieConfig.INSTANCE.getServerUri().startsWith("https");
-  }
-}
diff --git a/dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/client/ConnSuccEvent.java b/dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/client/ConnSuccEvent.java
deleted file mode 100644
index 95d9758..0000000
--- a/dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/client/ConnSuccEvent.java
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * 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.servicecomb.config.kie.client;
-
-public class ConnSuccEvent {
-
-}
diff --git a/dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/client/KieClient.java b/dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/client/KieClient.java
deleted file mode 100644
index e130bee..0000000
--- a/dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/client/KieClient.java
+++ /dev/null
@@ -1,176 +0,0 @@
-/*
- * 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.servicecomb.config.kie.client;
-
-import java.io.IOException;
-import java.util.Map;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-import org.apache.http.HttpStatus;
-import org.apache.servicecomb.config.kie.archaius.sources.KieConfigurationSourceImpl.UpdateHandler;
-import org.apache.servicecomb.config.kie.model.KVResponse;
-import org.apache.servicecomb.foundation.common.event.EventManager;
-import org.apache.servicecomb.foundation.common.net.IpPort;
-import org.apache.servicecomb.foundation.common.net.NetUtils;
-import org.apache.servicecomb.foundation.common.utils.JsonUtils;
-import org.apache.servicecomb.foundation.vertx.client.http.HttpClients;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import io.vertx.core.http.HttpClientRequest;
-
-public class KieClient {
-
-  private static final Logger LOGGER = LoggerFactory.getLogger(KieClient.class);
-
-  private ScheduledExecutorService EXECUTOR = Executors.newScheduledThreadPool(1, (r) -> {
-    Thread thread = new Thread(r);
-    thread.setName("org.apache.servicecomb.config.kie");
-    thread.setDaemon(true);
-    return thread;
-  });
-
-  private static final long PULL_REQUEST_TIME_OUT_IN_MILLIS = 10000;
-
-  private static final long LONG_POLLING_REQUEST_TIME_OUT_IN_MILLIS = 60000;
-
-  private static AtomicBoolean IS_FIRST_PULL = new AtomicBoolean(true);
-
-  private static final int LONG_POLLING_WAIT_TIME_IN_SECONDS = 30;
-
-  private static String revision = "0";
-
-  private static final KieConfig KIE_CONFIG = KieConfig.INSTANCE;
-
-  private final int refreshInterval = KIE_CONFIG.getRefreshInterval();
-
-  private final int firstRefreshInterval = KIE_CONFIG.getFirstRefreshInterval();
-
-  private final boolean enableLongPolling = KIE_CONFIG.enableLongPolling();
-
-  private final String serviceUri = KIE_CONFIG.getServerUri();
-
-  public KieClient(UpdateHandler updateHandler) {
-    HttpClients.addNewClientPoolManager(new ConfigKieHttpClientOptionsSPI());
-    KieWatcher.INSTANCE.setUpdateHandler(updateHandler);
-  }
-
-  public void refreshKieConfig() {
-    if (enableLongPolling) {
-      EXECUTOR.execute(new ConfigRefresh(serviceUri));
-    } else {
-      EXECUTOR.scheduleWithFixedDelay(new ConfigRefresh(serviceUri), firstRefreshInterval,
-          refreshInterval, TimeUnit.MILLISECONDS);
-    }
-  }
-
-  public void destroy() {
-    if (EXECUTOR != null) {
-      EXECUTOR.shutdown();
-      EXECUTOR = null;
-    }
-  }
-
-  class ConfigRefresh implements Runnable {
-
-    private final String serviceUri;
-
-    ConfigRefresh(String serviceUris) {
-      this.serviceUri = serviceUris;
-    }
-
-    @Override
-    public void run() {
-      try {
-        CountDownLatch latch = new CountDownLatch(1);
-        refreshConfig(latch);
-        latch.await();
-      } catch (Throwable e) {
-        LOGGER.error("client refresh thread exception ", e);
-      }
-      if (enableLongPolling) {
-        EXECUTOR.execute(this);
-      }
-    }
-
-    @SuppressWarnings("deprecation")
-    void refreshConfig(CountDownLatch latch) {
-      String path = "/v1/"
-          + KieConfig.INSTANCE.getDomainName()
-          + "/kie/kv?label=app:"
-          + KieConfig.INSTANCE.getAppName()
-          + "&revision=" + revision;
-      long timeout;
-      if (enableLongPolling && !IS_FIRST_PULL.get()) {
-        path += "&wait=" + LONG_POLLING_WAIT_TIME_IN_SECONDS + "s";
-        timeout = LONG_POLLING_REQUEST_TIME_OUT_IN_MILLIS;
-      } else {
-        IS_FIRST_PULL.compareAndSet(true, false);
-        timeout = PULL_REQUEST_TIME_OUT_IN_MILLIS;
-      }
-      String finalPath = path;
-      HttpClients.getClient(ConfigKieHttpClientOptionsSPI.CLIENT_NAME).runOnContext(client -> {
-        IpPort ipPort = NetUtils.parseIpPortFromURI(serviceUri);
-        HttpClientRequest request = client
-            .get(ipPort.getPort(), ipPort.getHostOrIp(), finalPath, rsp -> {
-              if (rsp.statusCode() == HttpStatus.SC_OK) {
-                revision = rsp.getHeader("X-Kie-Revision");
-                rsp.bodyHandler(buf -> {
-                  try {
-                    Map<String, Object> resMap = KieUtil.getConfigByLabel(JsonUtils.OBJ_MAPPER
-                        .readValue(buf.toString(), KVResponse.class));
-                    KieWatcher.INSTANCE.refreshConfigItems(resMap);
-                    EventManager.post(new ConnSuccEvent());
-                  } catch (IOException e) {
-                    EventManager.post(new ConnFailEvent(
-                        "config update result parse fail " + e.getMessage()));
-                    LOGGER.error("Config update from {} failed. Error message is [{}].",
-                        serviceUri,
-                        e.getMessage());
-                  }
-                  latch.countDown();
-                });
-              } else if (rsp.statusCode() == HttpStatus.SC_NOT_MODIFIED) {
-                EventManager.post(new ConnSuccEvent());
-                latch.countDown();
-              } else {
-                EventManager.post(new ConnFailEvent("fetch config fail"));
-                LOGGER.error("Config update from {} failed. Error code is {}, error message is [{}].",
-                    serviceUri,
-                    rsp.statusCode(),
-                    rsp.statusMessage());
-                latch.countDown();
-              }
-            }).setTimeout(timeout);
-
-        request.exceptionHandler(e -> {
-          EventManager.post(new ConnFailEvent("fetch config fail"));
-          LOGGER.error("Config update from {} failed. Error message is [{}].",
-              serviceUri,
-              e.getMessage());
-          latch.countDown();
-        });
-        request.end();
-      });
-    }
-  }
-}
diff --git a/dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/client/KieUtil.java b/dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/client/KieUtil.java
deleted file mode 100644
index 63ebefa..0000000
--- a/dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/client/KieUtil.java
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * 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.servicecomb.config.kie.client;
-
-import java.math.BigInteger;
-import java.nio.charset.StandardCharsets;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import java.util.ArrayList;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Properties;
-
-import org.apache.commons.lang3.StringUtils;
-import org.apache.servicecomb.config.kie.model.KVDoc;
-import org.apache.servicecomb.config.kie.model.KVResponse;
-import org.apache.servicecomb.config.kie.model.ValueType;
-import org.apache.servicecomb.config.parser.Parser;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class KieUtil {
-
-  private static final Logger LOGGER = LoggerFactory.getLogger(KieUtil.class);
-
-  private static final String LABEL_ENV = "environment";
-
-  private static final String LABEL_APP = "app";
-
-  private static final String LABEL_SERVICE = "service";
-
-  private static final String LABEL_VERSION = "version";
-
-  private static final String STATUS_ENABLED = "enabled";
-
-  public static String encrypt(String dataStr) {
-    MessageDigest messageDigest = null;
-    String result = "";
-    try {
-      messageDigest = MessageDigest.getInstance("MD5");
-      messageDigest.update(dataStr.getBytes(StandardCharsets.UTF_8));
-      result = new BigInteger(1, messageDigest.digest(dataStr.getBytes(StandardCharsets.UTF_8)))
-          .toString(16);
-    } catch (NoSuchAlgorithmException e) {
-      LOGGER.error("Failed to generate MD5 . ", e);
-    }
-    return result;
-  }
-
-  public static Map<String, Object> getConfigByLabel(KVResponse resp) {
-    Map<String, Object> resultMap = new HashMap<>();
-    List<KVDoc> appList = new ArrayList<>();
-    List<KVDoc> serviceList = new ArrayList<>();
-    List<KVDoc> versionList = new ArrayList<>();
-    for (KVDoc kvDoc : resp.getData()) {
-      if (!StringUtils.isEmpty(kvDoc.getStatus()) && !kvDoc.getStatus().equals(STATUS_ENABLED)) {
-        continue;
-      }
-      Map<String, String> labelsMap = kvDoc.getLabels();
-      if (labelsMap.containsKey(LABEL_APP) && labelsMap.get(LABEL_APP)
-          .equals(KieConfig.INSTANCE.getAppName())
-          && labelsMap.containsKey(LABEL_ENV) && labelsMap.get(LABEL_ENV)
-          .equals(KieConfig.INSTANCE.getEnvironment())) {
-        if (!labelsMap.containsKey(LABEL_SERVICE)) {
-          appList.add(kvDoc);
-        }
-        if (labelsMap.containsKey(LABEL_SERVICE) && labelsMap.get(LABEL_SERVICE)
-            .equals(KieConfig.INSTANCE.getServiceName())) {
-          if (!kvDoc.getLabels().containsKey(LABEL_VERSION)) {
-            serviceList.add(kvDoc);
-          }
-          if (labelsMap.containsKey(LABEL_VERSION) && labelsMap.get(LABEL_VERSION)
-              .equals(KieConfig.INSTANCE.getVersion())) {
-            versionList.add(kvDoc);
-          }
-        }
-      }
-    }
-    //kv is priority
-    for (KVDoc kvDoc : appList) {
-      resultMap.putAll(processValueType(kvDoc));
-    }
-    for (KVDoc kvDoc : serviceList) {
-      resultMap.putAll(processValueType(kvDoc));
-    }
-    for (KVDoc kvDoc : versionList) {
-      resultMap.putAll(processValueType(kvDoc));
-    }
-    return resultMap;
-  }
-
-  public static Map<String, Object> processValueType(KVDoc kvDoc) {
-    ValueType valueType = parseValueType(kvDoc.getValueType());
-    if (valueType == (ValueType.YAML) || valueType == (ValueType.YML)) {
-      return Parser.findParser(Parser.CONTENT_TYPE_YAML).parse(kvDoc.getValue(), kvDoc.getKey(), true);
-    } else if (valueType == (ValueType.PROPERTIES)) {
-      return Parser.findParser(Parser.CONTENT_TYPE_PROPERTIES).parse(kvDoc.getValue(), kvDoc.getKey(), true);
-    } else {
-      return Parser.findParser(Parser.CONTENT_TYPE_RAW).parse(kvDoc.getValue(), kvDoc.getKey(), true);
-    }
-  }
-
-  private static ValueType parseValueType(String valueType) {
-    if (StringUtils.isEmpty(valueType)) {
-      return ValueType.STRING;
-    }
-
-    try {
-      return ValueType.valueOf(valueType.toUpperCase());
-    } catch (IllegalArgumentException e) {
-      LOGGER.warn("read unrecognized value type {}", valueType);
-      return ValueType.STRING;
-    }
-  }
-
-
-  @SuppressWarnings("unchecked")
-  private static Map<String, String> toMap(String prefix, Properties properties) {
-    Map<String, String> result = new HashMap<>();
-    Enumeration<String> keys = (Enumeration<String>) properties.propertyNames();
-    while (keys.hasMoreElements()) {
-      String key = keys.nextElement();
-      Object value = properties.getProperty(key);
-
-      if (!StringUtils.isEmpty(prefix)) {
-        key = prefix + "." + key;
-      }
-
-      if (value != null) {
-        result.put(key, ((String) value).trim());
-      } else {
-        result.put(key, null);
-      }
-    }
-    return result;
-  }
-}
diff --git a/dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/client/KieWatcher.java b/dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/client/KieWatcher.java
deleted file mode 100644
index 0d7ba32..0000000
--- a/dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/client/KieWatcher.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * 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.servicecomb.config.kie.client;
-
-import java.util.HashMap;
-import java.util.Map;
-import org.apache.servicecomb.config.kie.archaius.sources.KieConfigurationSourceImpl.UpdateHandler;
-import org.springframework.util.CollectionUtils;
-import org.springframework.util.StringUtils;
-
-public class KieWatcher {
-
-  public static final KieWatcher INSTANCE = new KieWatcher();
-
-  private UpdateHandler updateHandler;
-
-  private String refreshRecord;
-
-  Map<String, Object> lastTimeData;
-
-  private KieWatcher() {
-  }
-
-  public void setUpdateHandler(UpdateHandler updateHandler) {
-    this.updateHandler = updateHandler;
-  }
-
-  public void refreshConfigItems(Map<String, Object> remoteItems) {
-    String md5Vaule = KieUtil.encrypt(remoteItems.toString());
-    if (CollectionUtils.isEmpty(remoteItems)) {
-      updateHandler.handle("delete", lastTimeData);
-      lastTimeData = remoteItems;
-      return;
-    }
-    if (StringUtils.isEmpty(refreshRecord)) {
-      refreshRecord = md5Vaule;
-      updateHandler.handle("create", remoteItems);
-      lastTimeData = remoteItems;
-      return;
-    }
-    if (md5Vaule.equals(refreshRecord)) {
-      return;
-    }
-    refreshRecord = md5Vaule;
-    doRefresh(remoteItems);
-    lastTimeData = remoteItems;
-  }
-
-
-  private void doRefresh(Map<String, Object> remoteItems) {
-    Map<String, Object> itemsCreated = new HashMap<>();
-    Map<String, Object> itemsDeleted = new HashMap<>();
-    Map<String, Object> itemsModified = new HashMap<>();
-    for (String itemKey : remoteItems.keySet()) {
-      if (!lastTimeData.containsKey(itemKey)) {
-        itemsCreated.put(itemKey, remoteItems.get(itemKey));
-      } else if (!remoteItems.get(itemKey).equals(lastTimeData.get(itemKey))) {
-        itemsModified.put(itemKey, remoteItems.get(itemKey));
-      }
-    }
-    for (String itemKey : lastTimeData.keySet()) {
-      if (!remoteItems.containsKey(itemKey)) {
-        itemsDeleted.put(itemKey, "");
-      }
-    }
-    updateHandler.handle("create", itemsCreated);
-    updateHandler.handle("set", itemsModified);
-    updateHandler.handle("delete", itemsDeleted);
-  }
-
-}
diff --git a/dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/model/KVBody.java b/dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/model/KVBody.java
deleted file mode 100644
index b7deee0..0000000
--- a/dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/model/KVBody.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * 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.servicecomb.config.kie.model;
-
-import com.fasterxml.jackson.annotation.JsonAlias;
-import java.util.HashMap;
-import java.util.Map;
-import org.apache.servicecomb.config.kie.client.KieConfig;
-
-public class KVBody {
-
-  private Map<String, String> labels = new HashMap<String, String>();
-
-  private String value;
-
-  @JsonAlias("value_type")
-  private String valueType;
-
-  public Map<String, String> getLabels() {
-    return labels;
-  }
-
-  public void setLabels(Map<String, String> labels) {
-    this.labels = labels;
-  }
-
-  public void initLabels() {
-    labels.put("env", KieConfig.INSTANCE.getEnvironment());
-    labels.put("app", KieConfig.INSTANCE.getAppName());
-    labels.put("service", KieConfig.INSTANCE.getServiceName());
-    labels.put("version", KieConfig.INSTANCE.getVersion());
-    labels.put("tags", KieConfig.INSTANCE.getTags());
-  }
-
-  public String getValue() {
-    return value;
-  }
-
-  public void setValue(String value) {
-    this.value = value;
-  }
-
-  public String getValueType() {
-    return valueType;
-  }
-
-  public void setValueType(String valueType) {
-    this.valueType = valueType;
-  }
-}
diff --git a/dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/model/KVDoc.java b/dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/model/KVDoc.java
deleted file mode 100644
index e969442..0000000
--- a/dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/model/KVDoc.java
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * 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.servicecomb.config.kie.model;
-
-import com.fasterxml.jackson.annotation.JsonAlias;
-import java.util.HashMap;
-import java.util.Map;
-
-public class KVDoc {
-
-  private String id;
-
-  private String check;
-
-  private String domain;
-
-  private String key;
-
-  @JsonAlias("label_id")
-  private String labelId;
-
-  private Map<String, String> labels = new HashMap<String, String>();
-
-  private Integer revision;
-
-  private String value;
-
-  @JsonAlias("value_type")
-  private String valueType;
-
-  private String status;
-
-  public String getStatus() {
-    return status;
-  }
-
-  public void setStatus(String status) {
-    this.status = status;
-  }
-
-  public String getId() {
-    return id;
-  }
-
-  public void setId(String id) {
-    this.id = id;
-  }
-
-  public String getKey() {
-    return key;
-  }
-
-  public void setKey(String key) {
-    this.key = key;
-  }
-
-  public String getCheck() {
-    return check;
-  }
-
-  public String getDomain() {
-    return domain;
-  }
-
-  public String getLabelId() {
-    return labelId;
-  }
-
-  public Map<String, String> getLabels() {
-    return labels;
-  }
-
-  public Integer getRevision() {
-    return revision;
-  }
-
-  public String getValue() {
-    return value;
-  }
-
-  public void setCheck(String check) {
-    this.check = check;
-  }
-
-  public void setDomain(String domain) {
-    this.domain = domain;
-  }
-
-  public void setLabelId(String labelId) {
-    this.labelId = labelId;
-  }
-
-  public void setLabels(Map<String, String> labels) {
-    this.labels = labels;
-  }
-
-  public void setRevision(Integer revision) {
-    this.revision = revision;
-  }
-
-  public void setValueType(String valueType) {
-    this.valueType = valueType;
-  }
-
-  public void setValue(String value) {
-    this.value = value;
-  }
-
-  public String getValueType() {
-    return valueType;
-  }
-}
diff --git a/dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/model/KVResponse.java b/dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/model/KVResponse.java
deleted file mode 100644
index f67fa00..0000000
--- a/dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/model/KVResponse.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * 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.servicecomb.config.kie.model;
-
-import java.util.List;
-
-public class KVResponse {
-
-  private List<KVDoc> data;
-
-  private LabelDocResponse label;
-
-  private Integer total;
-
-  public Integer getTotal() {
-    return total;
-  }
-
-  public void setTotal(Integer total) {
-    this.total = total;
-  }
-
-  public List<KVDoc> getData() {
-    return data;
-  }
-
-  public LabelDocResponse getLabel() {
-    return label;
-  }
-
-  public void setData(List<KVDoc> data) {
-    this.data = data;
-  }
-
-  public void setLabel(LabelDocResponse label) {
-    this.label = label;
-  }
-}
diff --git a/dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/model/LabelDocResponse.java b/dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/model/LabelDocResponse.java
deleted file mode 100644
index fb2b541..0000000
--- a/dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/model/LabelDocResponse.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * 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.servicecomb.config.kie.model;
-
-import com.fasterxml.jackson.annotation.JsonAlias;
-import java.util.HashMap;
-import java.util.Map;
-
-public class LabelDocResponse {
-
-  @JsonAlias("label_id")
-  private String labelId;
-
-  private Map<String, String> labels = new HashMap<String, String>();
-
-  public String getLabelId() {
-    return labelId;
-  }
-
-  public Map<String, String> getLabels() {
-    return labels;
-  }
-
-  public void setLabelId(String labelId) {
-    this.labelId = labelId;
-  }
-
-  public void setLabels(Map<String, String> labels) {
-    this.labels = labels;
-  }
-}
diff --git a/dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/model/ValueType.java b/dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/model/ValueType.java
deleted file mode 100644
index 8190878..0000000
--- a/dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/model/ValueType.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * 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.servicecomb.config.kie.model;
-
-public enum ValueType {
-  YML,
-  YAML,
-  STRING,
-  TEXT,
-  JSON,
-  PROPERTIES
-}
diff --git a/dynamic-config/config-kie/src/main/resources/META-INF/services/org.apache.servicecomb.config.spi.ConfigCenterConfigurationSource b/dynamic-config/config-kie/src/main/resources/META-INF/services/org.apache.servicecomb.config.spi.ConfigCenterConfigurationSource
index c696fa9..67520d4 100644
--- a/dynamic-config/config-kie/src/main/resources/META-INF/services/org.apache.servicecomb.config.spi.ConfigCenterConfigurationSource
+++ b/dynamic-config/config-kie/src/main/resources/META-INF/services/org.apache.servicecomb.config.spi.ConfigCenterConfigurationSource
@@ -15,4 +15,4 @@
 # limitations under the License.
 #
 
-org.apache.servicecomb.config.kie.archaius.sources.KieConfigurationSourceImpl
\ No newline at end of file
+org.apache.servicecomb.config.kie.KieConfigurationSourceImpl
\ No newline at end of file
diff --git a/dynamic-config/config-kie/src/test/java/org/apache/servicecomb/config/kie/client/TestKieClient.java b/dynamic-config/config-kie/src/test/java/org/apache/servicecomb/config/kie/client/TestKieClient.java
deleted file mode 100644
index 4b73db2..0000000
--- a/dynamic-config/config-kie/src/test/java/org/apache/servicecomb/config/kie/client/TestKieClient.java
+++ /dev/null
@@ -1,200 +0,0 @@
-/*
- * 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.servicecomb.config.kie.client;
-
-import com.google.common.eventbus.Subscribe;
-import io.vertx.core.Handler;
-import io.vertx.core.MultiMap;
-import io.vertx.core.buffer.Buffer;
-import io.vertx.core.http.HttpClient;
-import io.vertx.core.http.HttpClientRequest;
-import io.vertx.core.http.HttpClientResponse;
-import io.vertx.core.http.HttpMethod;
-import io.vertx.core.json.JsonObject;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.concurrent.ScheduledExecutorService;
-import mockit.Deencapsulation;
-import mockit.Expectations;
-import mockit.Mock;
-import mockit.MockUp;
-import mockit.Mocked;
-import org.apache.servicecomb.config.ConfigUtil;
-import org.apache.servicecomb.config.kie.archaius.sources.KieConfigurationSourceImpl;
-import org.apache.servicecomb.config.kie.archaius.sources.KieConfigurationSourceImpl.UpdateHandler;
-import org.apache.servicecomb.config.kie.client.KieClient.ConfigRefresh;
-import org.apache.servicecomb.foundation.common.event.EventManager;
-import org.apache.servicecomb.foundation.vertx.client.ClientPoolManager;
-import org.apache.servicecomb.foundation.vertx.client.http.HttpClientWithContext;
-import org.apache.servicecomb.foundation.vertx.client.http.HttpClientWithContext.RunHandler;
-import org.junit.Assert;
-import org.junit.BeforeClass;
-import org.junit.Test;
-import org.mockito.Mockito;
-
-@SuppressWarnings("deprecation")
-public class TestKieClient {
-
-  String mockKvResponse = "{\n"
-      + "  \"data\": [\n"
-      + "    {\n"
-      + "      \"id\": \"string\",\n"
-      + "      \"check\": \"string\",\n"
-      + "      \"domain\": \"string\",\n"
-      + "      \"key\": \"string\",\n"
-      + "      \"label_id\": \"string\",\n"
-      + "      \"labels\": {\n"
-      + "        \"additionalProp1\": \"string\",\n"
-      + "        \"additionalProp2\": \"string\",\n"
-      + "        \"additionalProp3\": \"string\"\n"
-      + "      },\n"
-      + "      \"project\": \"string\",\n"
-      + "      \"revision\": 0,\n"
-      + "      \"value\": \"string\",\n"
-      + "      \"value_type\": \"string\"\n"
-      + "    }\n"
-      + "  ],\n"
-      + "  \"label\": {\n"
-      + "    \"label_id\": \"string\",\n"
-      + "    \"labels\": {\n"
-      + "      \"additionalProp1\": \"string\",\n"
-      + "      \"additionalProp2\": \"string\",\n"
-      + "      \"additionalProp3\": \"string\"\n"
-      + "    }\n"
-      + "  },\n"
-      + "  \"num\": 0,\n"
-      + "  \"size\": 0,\n"
-      + "  \"total\": 0\n"
-      + "}";
-
-  @BeforeClass
-  public static void setUpClass() {
-    KieConfig.setFinalConfig(ConfigUtil.createLocalConfig());
-  }
-
-  @SuppressWarnings("unchecked")
-  @Test
-  public void testRefreshKieConfig() {
-    HttpClientRequest request = Mockito.mock(HttpClientRequest.class);
-    Mockito.when(request.method()).thenReturn(HttpMethod.GET);
-    Mockito.when(request.headers()).thenReturn(MultiMap.caseInsensitiveMultiMap());
-    Buffer rsp = Mockito.mock(Buffer.class);
-    Mockito.when(rsp.toJsonObject()).thenReturn(new JsonObject(mockKvResponse));
-    HttpClientResponse event = Mockito.mock(HttpClientResponse.class);
-    Mockito.when(event.bodyHandler(Mockito.any(Handler.class))).then(invocation -> {
-      Handler<Buffer> handler = invocation.getArgumentAt(0, Handler.class);
-      handler.handle(rsp);
-      return null;
-    });
-    Mockito.when(event.statusCode()).thenReturn(200);
-    HttpClient httpClient = Mockito.mock(HttpClient.class);
-    Mockito.when(
-        httpClient.get(Mockito.anyInt(), Mockito.anyString(), Mockito.anyString(),
-            Mockito.any(Handler.class)))
-        .then(invocation -> {
-          Handler<HttpClientResponse> handler = invocation.getArgumentAt(3, Handler.class);
-          handler.handle(event);
-          return request;
-        });
-    new MockUp<HttpClientWithContext>() {
-      @Mock
-      public void runOnContext(RunHandler handler) {
-        handler.run(httpClient);
-      }
-    };
-    UpdateHandler updateHandler = new KieConfigurationSourceImpl().new UpdateHandler();
-    KieClient kie = new KieClient(updateHandler);
-    kie.refreshKieConfig();
-  }
-
-
-  public static class ConfigRefreshExceptionEvent {
-    Map<String, String> map;
-
-    public ConfigRefreshExceptionEvent(Map<String, String> map) {
-      this.map = map;
-    }
-
-    @Subscribe
-    public void testMsg(Object event) {
-      if (event instanceof ConnFailEvent) {
-        map.put("result", "Fail event trigger");
-      }
-      if (event instanceof ConnSuccEvent) {
-        map.put("result", "Succ event trigger");
-      }
-    }
-  }
-
-  @SuppressWarnings("unchecked")
-  @Test
-  public void testConfigRefreshException(@Mocked ClientPoolManager<HttpClientWithContext> clientMgr,
-      @Mocked HttpClientWithContext httpClientWithContext) {
-    KieConfigurationSourceImpl impl = new KieConfigurationSourceImpl();
-    Map<String, String> map = new HashMap<>();
-    EventManager.register(new ConfigRefreshExceptionEvent(map));
-    UpdateHandler updateHandler = impl.new UpdateHandler();
-    HttpClientRequest request = Mockito.mock(HttpClientRequest.class);
-    Mockito.when(request.headers()).thenReturn(MultiMap.caseInsensitiveMultiMap());
-    Buffer rsp = Mockito.mock(Buffer.class);
-    Mockito.when(rsp.toString()).thenReturn(mockKvResponse);
-
-    HttpClientResponse event = Mockito.mock(HttpClientResponse.class);
-    Mockito.when(event.bodyHandler(Mockito.any(Handler.class))).then(invocation -> {
-      Handler<Buffer> handler = invocation.getArgumentAt(0, Handler.class);
-      handler.handle(rsp);
-      return null;
-    });
-    Mockito.when(event.statusCode()).thenReturn(400);
-    Buffer buf = Mockito.mock(Buffer.class);
-    Mockito.when(buf.toJsonObject()).thenReturn(new JsonObject(mockKvResponse));
-    HttpClient httpClient = Mockito.mock(HttpClient.class);
-    Mockito.when(
-        httpClient.get(Mockito.anyInt(), Mockito.anyString(), Mockito.anyString(),
-            Mockito.any(Handler.class)))
-        .then(invocation -> {
-          Handler<HttpClientResponse> handler = invocation.getArgumentAt(3, Handler.class);
-          handler.handle(event);
-          return request;
-        });
-    new MockUp<HttpClientWithContext>() {
-      @Mock
-      public void runOnContext(RunHandler handler) {
-        handler.run(httpClient);
-      }
-    };
-
-    KieClient kie = new KieClient(updateHandler);
-
-    ConfigRefresh refresh = kie.new ConfigRefresh("http://configcentertest:30110");
-    refresh.run();
-    Assert.assertEquals("Fail event trigger", map.get("result"));
-    Mockito.when(event.statusCode()).thenReturn(200);
-    refresh.run();
-    Assert.assertEquals("Succ event trigger", map.get("result"));
-  }
-
-  @Test
-  public void destroy() {
-    KieClient kieClient = new KieClient(null);
-    ScheduledExecutorService executor = Deencapsulation.getField(kieClient, "EXECUTOR");
-    Assert.assertFalse(executor.isShutdown());
-    executor.shutdown();
-    Assert.assertTrue(executor.isShutdown());
-  }
-}
diff --git a/dynamic-config/config-kie/src/test/java/org/apache/servicecomb/config/kie/client/TestKieConfig.java b/dynamic-config/config-kie/src/test/java/org/apache/servicecomb/config/kie/client/TestKieConfig.java
deleted file mode 100644
index 1f8e6d2..0000000
--- a/dynamic-config/config-kie/src/test/java/org/apache/servicecomb/config/kie/client/TestKieConfig.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * 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.servicecomb.config.kie.client;
-
-import org.apache.servicecomb.config.ConfigUtil;
-import org.junit.Assert;
-import org.junit.BeforeClass;
-import org.junit.Test;
-
-public class TestKieConfig {
-
-  @BeforeClass
-  public static void setUpClass() {
-    KieConfig.setFinalConfig(ConfigUtil.createLocalConfig());
-  }
-
-  @Test
-  public void getServerUri() {
-    String servers = KieConfig.INSTANCE.getServerUri();
-    Assert.assertEquals("https://172.16.8.7:30110", servers);
-  }
-
-  @Test
-  public void getEnvironment() {
-    Assert.assertEquals("testing", KieConfig.INSTANCE.getEnvironment());
-    System.setProperty("SERVICECOMB_ENV", "development");
-    KieConfig.setFinalConfig(ConfigUtil.createLocalConfig());
-    Assert.assertEquals("development", KieConfig.INSTANCE.getEnvironment());
-  }
-
-}
diff --git a/dynamic-config/config-kie/src/test/java/org/apache/servicecomb/config/kie/client/TestKieUtil.java b/dynamic-config/config-kie/src/test/java/org/apache/servicecomb/config/kie/client/TestKieUtil.java
deleted file mode 100644
index 55e991e..0000000
--- a/dynamic-config/config-kie/src/test/java/org/apache/servicecomb/config/kie/client/TestKieUtil.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * 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.servicecomb.config.kie.client;
-
-import java.util.Map;
-
-import org.apache.servicecomb.config.kie.model.KVDoc;
-import org.junit.Assert;
-import org.junit.Test;
-
-public class TestKieUtil {
-  @Test
-  public void test_processValueType() {
-    KVDoc kvDoc = new KVDoc();
-    kvDoc.setKey("hello");
-    kvDoc.setValue("world");
-    Map<String, Object> result = KieUtil.processValueType(kvDoc);
-    Assert.assertEquals("world", result.get("hello"));
-
-    kvDoc.setValueType("text");
-    result = KieUtil.processValueType(kvDoc);
-    Assert.assertEquals("world", result.get("hello"));
-
-    kvDoc.setValueType("string");
-    result = KieUtil.processValueType(kvDoc);
-    Assert.assertEquals("world", result.get("hello"));
-
-    kvDoc.setValueType("json");
-    result = KieUtil.processValueType(kvDoc);
-    Assert.assertEquals("world", result.get("hello"));
-
-    kvDoc.setValueType("yml");
-    kvDoc.setValue("hello: world");
-    result = KieUtil.processValueType(kvDoc);
-    Assert.assertEquals("world", result.get("hello.hello"));
-
-    kvDoc.setValueType("yaml");
-    kvDoc.setValue("hello: world");
-    result = KieUtil.processValueType(kvDoc);
-    Assert.assertEquals("world", result.get("hello.hello"));
-
-    kvDoc.setValueType("properties");
-    kvDoc.setValue("hello=world");
-    result = KieUtil.processValueType(kvDoc);
-    Assert.assertEquals("world", result.get("hello.hello"));
-  }
-}
diff --git a/dynamic-config/config-kie/src/test/java/org/apache/servicecomb/config/kie/client/TestKieWatcher.java b/dynamic-config/config-kie/src/test/java/org/apache/servicecomb/config/kie/client/TestKieWatcher.java
deleted file mode 100644
index 126107e..0000000
--- a/dynamic-config/config-kie/src/test/java/org/apache/servicecomb/config/kie/client/TestKieWatcher.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * 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.servicecomb.config.kie.client;
-
-import java.util.HashMap;
-import java.util.Map;
-import mockit.Deencapsulation;
-import org.apache.servicecomb.config.kie.archaius.sources.KieConfigurationSourceImpl;
-import org.apache.servicecomb.config.kie.archaius.sources.KieConfigurationSourceImpl.UpdateHandler;
-import org.junit.Assert;
-import org.junit.Test;
-
-public class TestKieWatcher {
-
-  private KieConfigurationSourceImpl kieSource = new KieConfigurationSourceImpl();
-
-  private UpdateHandler uh = kieSource.new UpdateHandler();
-
-  {
-    KieWatcher.INSTANCE.setUpdateHandler(uh);
-  }
-
-  @Test
-  public void testRefreshConfigItems() {
-    boolean status = true;
-    Map<String, Object> configMap = new HashMap<>();
-    configMap.put("key1", "application1");
-    configMap.put("key2", "application2");
-    configMap.put("key3", "application3");
-    configMap.put("key4", "application4");
-    Map<String, Object> result = null;
-    try {
-      result = Deencapsulation.invoke(KieWatcher.INSTANCE, "refreshConfigItems", configMap);
-    } catch (Exception e) {
-      status = false;
-    }
-    Assert.assertTrue(status);
-  }
-}
diff --git a/dynamic-config/config-kie/src/test/java/org/apache/servicecomb/config/kie/sources/TestKieConfigurationSource.java b/dynamic-config/config-kie/src/test/java/org/apache/servicecomb/config/kie/sources/TestKieConfigurationSource.java
deleted file mode 100644
index 73cfae5..0000000
--- a/dynamic-config/config-kie/src/test/java/org/apache/servicecomb/config/kie/sources/TestKieConfigurationSource.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * 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.servicecomb.config.kie.sources;
-
-import com.netflix.config.WatchedUpdateListener;
-import com.netflix.config.WatchedUpdateResult;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.concurrent.atomic.AtomicInteger;
-import mockit.Deencapsulation;
-import mockit.Mock;
-import mockit.MockUp;
-import org.apache.commons.lang.reflect.FieldUtils;
-import org.apache.servicecomb.config.kie.archaius.sources.KieConfigurationSourceImpl;
-import org.apache.servicecomb.config.kie.archaius.sources.KieConfigurationSourceImpl.UpdateHandler;
-import org.apache.servicecomb.config.kie.client.KieClient;
-import org.junit.Assert;
-import org.junit.Test;
-
-public class TestKieConfigurationSource {
-
-  @Test
-  public void testCreate() {
-
-    KieConfigurationSourceImpl kieSource = new KieConfigurationSourceImpl();
-    kieSource.addUpdateListener(result -> Assert.assertTrue(!result.getAdded().isEmpty()));
-    UpdateHandler udateHandler = Deencapsulation.getField(kieSource, UpdateHandler.class);
-    Map<String, Object> addedItems = new HashMap<>();
-    addedItems.put("testKey", "testValue");
-    udateHandler.handle("create", addedItems);
-  }
-
-  @Test
-  public void testUpdate() {
-
-    KieConfigurationSourceImpl kieSource = new KieConfigurationSourceImpl();
-    kieSource.addUpdateListener(result -> Assert.assertTrue(!result.getChanged().isEmpty()));
-    UpdateHandler udateHandler = Deencapsulation.getField(kieSource, UpdateHandler.class);
-    Map<String, Object> addedItems = new HashMap<>();
-    addedItems.put("testKey", "testValue");
-    udateHandler.handle("set", addedItems);
-  }
-
-  @Test
-  public void testDelete() throws Exception {
-    KieConfigurationSourceImpl kieSource = new KieConfigurationSourceImpl();
-    kieSource.addUpdateListener(result -> Assert.assertTrue(!result.getDeleted().isEmpty()));
-    UpdateHandler udateHandler = Deencapsulation.getField(kieSource, UpdateHandler.class);
-    Map<String, Object> addedItems = new HashMap<>();
-    addedItems.put("testKey", "testValue");
-
-    kieSource.getCurrentData().put("testKey", "testValue");
-    udateHandler.handle("delete", addedItems);
-    Assert.assertTrue(kieSource.getCurrentData().isEmpty());
-  }
-
-  @Test
-  public void destroy_notInit() {
-    KieConfigurationSourceImpl kieSource = new KieConfigurationSourceImpl();
-
-    // need not throw exception
-    kieSource.destroy();
-  }
-
-  @Test
-  public void destroy_inited() throws IllegalAccessException {
-    AtomicInteger count = new AtomicInteger();
-    KieClient kieClient = new MockUp<KieClient>() {
-      @Mock
-      void destroy() {
-        count.incrementAndGet();
-      }
-    }.getMockInstance();
-    KieConfigurationSourceImpl kieSource = new KieConfigurationSourceImpl();
-    FieldUtils
-        .writeDeclaredField(kieSource, "kieClient", kieClient, true);
-
-    kieSource.destroy();
-
-    Assert.assertEquals(1, count.get());
-  }
-}

[servicecomb-java-chassis] 03/03: [SCB-2273]support kie latest layered configuration. Part3: add integration tests and fix all problems found

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

liubao pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/servicecomb-java-chassis.git

commit d66630946f450a7c0815c4a2482143d193559bcc
Author: liubao68 <bi...@qq.com>
AuthorDate: Fri Jun 4 12:02:14 2021 +0800

    [SCB-2273]support kie latest layered configuration. Part3: add integration tests and fix all problems found
---
 .../core/ConfigurationSpringInitializer.java       | 34 ++++++++-
 demo/README.md                                     |  6 +-
 demo/demo-cse-v1/README.md                         | 18 +++++
 demo/demo-cse-v1/consumer/pom.xml                  | 47 +++++++++++++
 .../servicecomb/samples/ConsumerApplication.java   | 36 ++++++++++
 .../samples/ConsumerConfigController.java          | 50 +++++++++++++
 .../samples/ConsumerConfigurationProperties.java   | 45 ++++++++++++
 .../servicecomb/samples/ConsumerController.java    | 37 ++++++++++
 .../servicecomb/samples/ProviderService.java       | 22 ++++++
 .../consumer/src/main/resources/application.yml    | 45 ++++++++++++
 .../consumer/src/main/resources/log4j2.xml         | 45 ++++++++++++
 demo/demo-cse-v1/gateway/pom.xml                   | 50 +++++++++++++
 .../servicecomb/samples/GatewayApplication.java    | 35 ++++++++++
 .../gateway/src/main/resources/application.yml     | 59 ++++++++++++++++
 .../gateway/src/main/resources/log4j2.xml          | 45 ++++++++++++
 demo/demo-cse-v1/pom.xml                           | 53 ++++++++++++++
 demo/demo-cse-v1/provider/pom.xml                  | 51 ++++++++++++++
 .../servicecomb/samples/ProviderApplication.java   | 36 ++++++++++
 .../servicecomb/samples/ProviderController.java    | 33 +++++++++
 .../provider/src/main/resources/application.yml    | 47 +++++++++++++
 .../provider/src/main/resources/log4j2.xml         | 45 ++++++++++++
 demo/demo-cse-v1/test-client/pom.xml               | 55 +++++++++++++++
 .../org/apache/servicecomb/samples/Config.java     | 22 ++++++
 .../servicecomb/samples/ConsumerConfigIT.java      | 48 +++++++++++++
 .../apache/servicecomb/samples/HelloWorldIT.java   | 39 +++++++++++
 .../servicecomb/samples/TestClientApplication.java | 47 +++++++++++++
 .../test-client/src/main/resources/application.yml | 47 +++++++++++++
 .../test-client/src/main/resources/log4j2.xml      | 45 ++++++++++++
 demo/demo-cse-v2/README.md                         | 81 ++++++++++++++++++++++
 demo/demo-cse-v2/consumer/pom.xml                  | 47 +++++++++++++
 .../servicecomb/samples/ConsumerApplication.java   | 36 ++++++++++
 .../samples/ConsumerConfigController.java          | 60 ++++++++++++++++
 .../samples/ConsumerConfigurationProperties.java   | 65 +++++++++++++++++
 .../servicecomb/samples/ConsumerController.java    | 37 ++++++++++
 .../servicecomb/samples/ProviderService.java       | 22 ++++++
 .../consumer/src/main/resources/application.yml    | 38 ++++++++++
 .../consumer/src/main/resources/log4j2.xml         | 45 ++++++++++++
 demo/demo-cse-v2/gateway/pom.xml                   | 50 +++++++++++++
 .../servicecomb/samples/GatewayApplication.java    | 35 ++++++++++
 .../gateway/src/main/resources/application.yml     | 59 ++++++++++++++++
 .../gateway/src/main/resources/log4j2.xml          | 45 ++++++++++++
 demo/demo-cse-v2/pom.xml                           | 53 ++++++++++++++
 demo/demo-cse-v2/provider/pom.xml                  | 51 ++++++++++++++
 .../servicecomb/samples/ProviderApplication.java   | 36 ++++++++++
 .../servicecomb/samples/ProviderController.java    | 33 +++++++++
 .../provider/src/main/resources/application.yml    | 40 +++++++++++
 .../provider/src/main/resources/log4j2.xml         | 45 ++++++++++++
 demo/demo-cse-v2/test-client/pom.xml               | 55 +++++++++++++++
 .../org/apache/servicecomb/samples/Config.java     | 22 ++++++
 .../servicecomb/samples/ConsumerConfigIT.java      | 56 +++++++++++++++
 .../apache/servicecomb/samples/HelloWorldIT.java   | 39 +++++++++++
 .../servicecomb/samples/TestClientApplication.java | 47 +++++++++++++
 .../test-client/src/main/resources/application.yml | 47 +++++++++++++
 .../test-client/src/main/resources/log4j2.xml      | 45 ++++++++++++
 .../demo/springmvc/client/SpringmvcClient.java     |  2 -
 demo/pom.xml                                       |  2 +
 .../servicecomb/config/ConfigCenterConfig.java     |  8 +++
 .../ConfigCenterConfigurationSourceImpl.java       | 50 +++++++++----
 .../apache/servicecomb/config/TransportUtils.java  |  7 +-
 .../apache/servicecomb/config/kie/KieConfig.java   | 22 ++++++
 .../config/kie/KieConfigurationSourceImpl.java     | 20 ++++--
 .../servicecomb/config/kie/TransportUtils.java     |  7 +-
 .../org/apache/servicecomb/config/ConfigUtil.java  |  7 +-
 {demo => integration-tests}/README.md              |  6 +-
 .../client/http/ServiceRegistryClientImpl.java     |  4 +-
 .../task/ServiceCenterTaskMonitor.java             |  2 +-
 solutions/solution-basic/pom.xml                   |  5 +-
 67 files changed, 2439 insertions(+), 34 deletions(-)

diff --git a/core/src/main/java/org/apache/servicecomb/core/ConfigurationSpringInitializer.java b/core/src/main/java/org/apache/servicecomb/core/ConfigurationSpringInitializer.java
index 2fb562a..52e2b2b 100644
--- a/core/src/main/java/org/apache/servicecomb/core/ConfigurationSpringInitializer.java
+++ b/core/src/main/java/org/apache/servicecomb/core/ConfigurationSpringInitializer.java
@@ -23,6 +23,7 @@ import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Properties;
+import java.util.concurrent.ConcurrentHashMap;
 import java.util.stream.Collectors;
 
 import org.apache.commons.configuration.AbstractConfiguration;
@@ -30,8 +31,10 @@ import org.apache.servicecomb.config.ConfigMapping;
 import org.apache.servicecomb.config.ConfigUtil;
 import org.apache.servicecomb.config.YAMLUtil;
 import org.apache.servicecomb.config.archaius.sources.MicroserviceConfigLoader;
+import org.apache.servicecomb.config.event.ConfigurationChangedEvent;
 import org.apache.servicecomb.config.spi.ConfigCenterConfigurationSource;
 import org.apache.servicecomb.foundation.bootstrap.BootStrapService;
+import org.apache.servicecomb.foundation.common.event.EventManager;
 import org.apache.servicecomb.foundation.common.utils.SPIServiceUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -48,7 +51,9 @@ import org.springframework.core.env.MutablePropertySources;
 import org.springframework.core.env.PropertySource;
 import org.springframework.util.StringUtils;
 
+import com.google.common.eventbus.Subscribe;
 import com.netflix.config.ConfigurationManager;
+import com.netflix.config.WatchedUpdateResult;
 
 /**
  *  Adapt spring PropertySource and Archaius Configuration
@@ -86,6 +91,10 @@ public class ConfigurationSpringInitializer extends PropertySourcesPlaceholderCo
 
   private final List<BootStrapService> bootStrapServices = SPIServiceUtils.getSortedService(BootStrapService.class);
 
+  private final Map<String, Object> dynamicData = new ConcurrentHashMap<>();
+
+  private ConfigCenterConfigurationSource configCenterConfigurationSource;
+
   public ConfigurationSpringInitializer() {
     setOrder(Ordered.LOWEST_PRECEDENCE / 2);
     setIgnoreUnresolvablePlaceholders(true);
@@ -106,10 +115,31 @@ public class ConfigurationSpringInitializer extends PropertySourcesPlaceholderCo
     syncToSpring(environment);
 
     startupBootStrapService(environment);
-    ConfigCenterConfigurationSource configCenterConfigurationSource = ConfigUtil.installDynamicConfig();
+
+    // watch configuration changes
+    EventManager.register(this);
+    configCenterConfigurationSource = ConfigUtil.installDynamicConfig();
     addDynamicConfigurationToSpring(environment, configCenterConfigurationSource);
   }
 
+  @Subscribe
+  public void onConfigurationDataChanged(ConfigurationChangedEvent event) {
+    try {
+      WatchedUpdateResult data = event.getEvent();
+      if (data.getDeleted() != null) {
+        data.getDeleted().forEach((k, v) -> dynamicData.remove(k));
+      }
+      if (data.getAdded() != null) {
+        dynamicData.putAll(data.getAdded());
+      }
+      if (data.getChanged() != null) {
+        dynamicData.putAll(data.getChanged());
+      }
+    } catch (Exception e) {
+      LOGGER.error("", e);
+    }
+  }
+
   private void syncFromSpring(Environment environment) {
     String environmentName = generateNameForEnvironment(environment);
     LOGGER.info("Environment received, will get configurations from [{}].", environmentName);
@@ -204,7 +234,7 @@ public class ConfigurationSpringInitializer extends PropertySourcesPlaceholderCo
       if (configCenterConfigurationSource != null) {
         try {
           ce.getPropertySources()
-              .addFirst(new MapPropertySource("dynamic-source", configCenterConfigurationSource.getCurrentData()));
+              .addFirst(new MapPropertySource("dynamic-source", dynamicData));
         } catch (Exception e) {
           LOGGER.warn("set up spring property source failed. msg: {}", e.getMessage());
         }
diff --git a/demo/README.md b/demo/README.md
index e8c2880..02ebd23 100644
--- a/demo/README.md
+++ b/demo/README.md
@@ -1,4 +1,8 @@
-This module contains integrated test cases. 
+This module contains integrated test cases. Running these test cases, should include profile 
+
+```shell script
+-Pdocker -Pdemo-run-release
+```
 
 [java-chassis-samples][java-chassis-samples] project provides a lot of samples.
  
diff --git a/demo/demo-cse-v1/README.md b/demo/demo-cse-v1/README.md
new file mode 100644
index 0000000..29049b2
--- /dev/null
+++ b/demo/demo-cse-v1/README.md
@@ -0,0 +1,18 @@
+# 使用微服务引擎专业版的测试用例
+
+* 首先登陆华为云华南区,获取 AK/SK。 测试机器设置环境变量: CREDENTIALS_AK、CREDENTIALS_SK。
+* 在配置中心增加如下配置:
+  * consumer.yaml
+
+```yaml
+cse:
+  v1:
+    test:
+      foo: foo
+```
+
+* 依次启动 provider、consumer、gateway
+* 在配置中心增加如下配置:
+  * cse.v1.test.bar: bar
+
+* 执行 tests-client 里面的集成测试用例
diff --git a/demo/demo-cse-v1/consumer/pom.xml b/demo/demo-cse-v1/consumer/pom.xml
new file mode 100644
index 0000000..935f516
--- /dev/null
+++ b/demo/demo-cse-v1/consumer/pom.xml
@@ -0,0 +1,47 @@
+<!--
+  ~ 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.
+  -->
+
+<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">
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.apache.servicecomb.demo</groupId>
+    <artifactId>demo-cse-v1</artifactId>
+    <version>2.3.0-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>cse-v1-consumer</artifactId>
+  <name>Java Chassis::Demo::CSE-V1::CONSUMER</name>
+  <packaging>jar</packaging>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.servicecomb</groupId>
+      <artifactId>java-chassis-spring-boot-starter-standalone</artifactId>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.springframework.boot</groupId>
+        <artifactId>spring-boot-maven-plugin</artifactId>
+      </plugin>
+    </plugins>
+  </build>
+</project>
\ No newline at end of file
diff --git a/demo/demo-cse-v1/consumer/src/main/java/org/apache/servicecomb/samples/ConsumerApplication.java b/demo/demo-cse-v1/consumer/src/main/java/org/apache/servicecomb/samples/ConsumerApplication.java
new file mode 100644
index 0000000..0010f13
--- /dev/null
+++ b/demo/demo-cse-v1/consumer/src/main/java/org/apache/servicecomb/samples/ConsumerApplication.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.servicecomb.samples;
+
+import org.apache.servicecomb.springboot2.starter.EnableServiceComb;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.WebApplicationType;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.builder.SpringApplicationBuilder;
+
+@SpringBootApplication
+@EnableServiceComb
+public class ConsumerApplication {
+  public static void main(String[] args) throws Exception {
+    try {
+      new SpringApplicationBuilder().web(WebApplicationType.NONE).sources(ConsumerApplication.class).run(args);
+    } catch (Exception e) {
+      e.printStackTrace();
+    }
+  }
+}
diff --git a/demo/demo-cse-v1/consumer/src/main/java/org/apache/servicecomb/samples/ConsumerConfigController.java b/demo/demo-cse-v1/consumer/src/main/java/org/apache/servicecomb/samples/ConsumerConfigController.java
new file mode 100644
index 0000000..4018e11
--- /dev/null
+++ b/demo/demo-cse-v1/consumer/src/main/java/org/apache/servicecomb/samples/ConsumerConfigController.java
@@ -0,0 +1,50 @@
+/*
+ * 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.servicecomb.samples;
+
+import org.apache.servicecomb.provider.rest.common.RestSchema;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.env.Environment;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+
+@RestSchema(schemaId = "ConsumerConfigController")
+@RequestMapping(path = "/")
+public class ConsumerConfigController {
+  @Autowired
+  private Environment environment;
+
+  @Autowired
+  private ConsumerConfigurationProperties consumerConfigurationProperties;
+
+  @GetMapping("/config")
+  public String config(@RequestParam("key") String key) {
+    return environment.getProperty(key);
+  }
+
+  @GetMapping("/foo")
+  public String foo() {
+    return consumerConfigurationProperties.getFoo();
+  }
+
+  @GetMapping("/bar")
+  public String bar() {
+    return consumerConfigurationProperties.getBar();
+  }
+}
diff --git a/demo/demo-cse-v1/consumer/src/main/java/org/apache/servicecomb/samples/ConsumerConfigurationProperties.java b/demo/demo-cse-v1/consumer/src/main/java/org/apache/servicecomb/samples/ConsumerConfigurationProperties.java
new file mode 100644
index 0000000..c21ba63
--- /dev/null
+++ b/demo/demo-cse-v1/consumer/src/main/java/org/apache/servicecomb/samples/ConsumerConfigurationProperties.java
@@ -0,0 +1,45 @@
+/*
+ * 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.servicecomb.samples;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+@ConfigurationProperties("cse.v1.test")
+@Component
+public class ConsumerConfigurationProperties {
+  private String foo;
+
+  private String bar;
+
+  public String getFoo() {
+    return foo;
+  }
+
+  public void setFoo(String foo) {
+    this.foo = foo;
+  }
+
+  public String getBar() {
+    return bar;
+  }
+
+  public void setBar(String bar) {
+    this.bar = bar;
+  }
+}
diff --git a/demo/demo-cse-v1/consumer/src/main/java/org/apache/servicecomb/samples/ConsumerController.java b/demo/demo-cse-v1/consumer/src/main/java/org/apache/servicecomb/samples/ConsumerController.java
new file mode 100644
index 0000000..4ed0ecd
--- /dev/null
+++ b/demo/demo-cse-v1/consumer/src/main/java/org/apache/servicecomb/samples/ConsumerController.java
@@ -0,0 +1,37 @@
+/*
+ * 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.servicecomb.samples;
+
+import org.apache.servicecomb.provider.pojo.RpcReference;
+import org.apache.servicecomb.provider.rest.common.RestSchema;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+
+@RestSchema(schemaId = "ConsumerController")
+@RequestMapping(path = "/")
+public class ConsumerController {
+  @RpcReference(schemaId = "ProviderController", microserviceName = "provider")
+  private ProviderService providerService;
+
+  // consumer service which delegate the implementation to provider service.
+  @GetMapping("/sayHello")
+  public String sayHello(@RequestParam("name") String name) {
+    return providerService.sayHello(name);
+  }
+}
diff --git a/demo/demo-cse-v1/consumer/src/main/java/org/apache/servicecomb/samples/ProviderService.java b/demo/demo-cse-v1/consumer/src/main/java/org/apache/servicecomb/samples/ProviderService.java
new file mode 100644
index 0000000..f327412
--- /dev/null
+++ b/demo/demo-cse-v1/consumer/src/main/java/org/apache/servicecomb/samples/ProviderService.java
@@ -0,0 +1,22 @@
+/*
+ * 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.servicecomb.samples;
+
+public interface ProviderService {
+  String sayHello(String name);
+}
diff --git a/demo/demo-cse-v1/consumer/src/main/resources/application.yml b/demo/demo-cse-v1/consumer/src/main/resources/application.yml
new file mode 100644
index 0000000..d61d76b
--- /dev/null
+++ b/demo/demo-cse-v1/consumer/src/main/resources/application.yml
@@ -0,0 +1,45 @@
+#
+## ---------------------------------------------------------------------------
+## 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.
+## ---------------------------------------------------------------------------
+
+# override common configurations in common module
+servicecomb-config-order: 10
+
+servicecomb:
+  service:
+    application: demo-cse-v1
+    name: consumer
+    version: 0.0.1
+    registry:
+      address: https://cse.cn-south-1.myhuaweicloud.com
+      instance:
+        watch: false
+  config:
+    client:
+      serverUri: https://cse.cn-south-1.myhuaweicloud.com
+      fileSource: consumer.yaml
+
+  rest:
+    address: 0.0.0.0:9092  # should be same with server.port to use web container
+
+  # Configure AK/SK credentials if needed. Default not enabled.
+  credentials:
+    akskEnabled: true
+    accessKey: ${CREDENTIALS_AK}
+    secretKey: ${CREDENTIALS_SK}
+    akskCustomCipher: default
+    project: cn-south-1
diff --git a/demo/demo-cse-v1/consumer/src/main/resources/log4j2.xml b/demo/demo-cse-v1/consumer/src/main/resources/log4j2.xml
new file mode 100644
index 0000000..313d1fc
--- /dev/null
+++ b/demo/demo-cse-v1/consumer/src/main/resources/log4j2.xml
@@ -0,0 +1,45 @@
+<?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.
+  -->
+
+<!--this is sample configuration, please modify as your wish -->
+
+<configuration>
+  <Properties>
+    <Property name="log_path">./file/log/</Property>
+  </Properties>
+
+  <Appenders>
+    <Console name="Console" target="SYSTEM_OUT">
+      <PatternLayout pattern="[%d][%t][%p][%c:%L] %m%n" />
+    </Console>
+    <RollingFile name="DailyRollingFile" fileName="${log_path}/output.log"
+      filePattern="${log_path}/zcrTest%d{yyyy-MM-dd}.log">
+      <PatternLayout pattern="[%d][%t][%p][%c:%L] %m%n" />
+      <Policies>
+        <TimeBasedTriggeringPolicy interval="1" />
+        <SizeBasedTriggeringPolicy size="10 MB" />
+      </Policies>
+    </RollingFile>
+  </Appenders>
+  <Loggers>
+    <Root level="info">
+      <AppenderRef ref="Console" />
+      <AppenderRef ref="DailyRollingFile" />
+    </Root>
+  </Loggers>
+</configuration>
\ No newline at end of file
diff --git a/demo/demo-cse-v1/gateway/pom.xml b/demo/demo-cse-v1/gateway/pom.xml
new file mode 100644
index 0000000..d8d5f73
--- /dev/null
+++ b/demo/demo-cse-v1/gateway/pom.xml
@@ -0,0 +1,50 @@
+<!--
+  ~ 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.
+  -->
+
+<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">
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.apache.servicecomb.demo</groupId>
+    <artifactId>demo-cse-v1</artifactId>
+    <version>2.3.0-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>cse-v1-gateway</artifactId>
+  <name>Java Chassis::Demo::CSE-V1::GATEWAY</name>
+  <packaging>jar</packaging>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.servicecomb</groupId>
+      <artifactId>java-chassis-spring-boot-starter-standalone</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.servicecomb</groupId>
+      <artifactId>edge-core</artifactId>
+    </dependency>
+  </dependencies>
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.springframework.boot</groupId>
+        <artifactId>spring-boot-maven-plugin</artifactId>
+      </plugin>
+    </plugins>
+  </build>
+</project>
\ No newline at end of file
diff --git a/demo/demo-cse-v1/gateway/src/main/java/org/apache/servicecomb/samples/GatewayApplication.java b/demo/demo-cse-v1/gateway/src/main/java/org/apache/servicecomb/samples/GatewayApplication.java
new file mode 100644
index 0000000..f2e086b
--- /dev/null
+++ b/demo/demo-cse-v1/gateway/src/main/java/org/apache/servicecomb/samples/GatewayApplication.java
@@ -0,0 +1,35 @@
+/*
+ * 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.servicecomb.samples;
+
+import org.apache.servicecomb.springboot2.starter.EnableServiceComb;
+import org.springframework.boot.WebApplicationType;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.builder.SpringApplicationBuilder;
+
+@SpringBootApplication
+@EnableServiceComb
+public class GatewayApplication {
+  public static void main(String[] args) throws Exception {
+    try {
+      new SpringApplicationBuilder().web(WebApplicationType.NONE).sources(GatewayApplication.class).run(args);
+    } catch (Exception e) {
+      e.printStackTrace();
+    }
+  }
+}
diff --git a/demo/demo-cse-v1/gateway/src/main/resources/application.yml b/demo/demo-cse-v1/gateway/src/main/resources/application.yml
new file mode 100644
index 0000000..a64212b
--- /dev/null
+++ b/demo/demo-cse-v1/gateway/src/main/resources/application.yml
@@ -0,0 +1,59 @@
+#
+## ---------------------------------------------------------------------------
+## 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.
+## ---------------------------------------------------------------------------
+
+# override common configurations in common module
+servicecomb-config-order: 100
+
+servicecomb:
+  service:
+    application: demo-cse-v1
+    name: gateway
+    version: 0.0.1
+    registry:
+      address: https://cse.cn-south-1.myhuaweicloud.com
+      instance:
+        watch: false
+  config:
+    client:
+      serverUri: https://cse.cn-south-1.myhuaweicloud.com
+
+  rest:
+    address: 0.0.0.0:9090?sslEnabled=false
+
+  http:
+    dispatcher:
+      edge:
+        default:
+          enabled: false
+        url:
+          enabled: true
+          pattern: /(.*)
+          mappings:
+            consumer:
+              prefixSegmentCount: 0
+              path: "/.*"
+              microserviceName: consumer
+              versionRule: 0.0.0+
+
+  # Configure AK/SK credentials if needed. Default not enabled.
+  credentials:
+    akskEnabled: true
+    accessKey: ${CREDENTIALS_AK}
+    secretKey: ${CREDENTIALS_SK}
+    akskCustomCipher: default
+    project: cn-south-1
\ No newline at end of file
diff --git a/demo/demo-cse-v1/gateway/src/main/resources/log4j2.xml b/demo/demo-cse-v1/gateway/src/main/resources/log4j2.xml
new file mode 100644
index 0000000..e9bb265
--- /dev/null
+++ b/demo/demo-cse-v1/gateway/src/main/resources/log4j2.xml
@@ -0,0 +1,45 @@
+<?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.
+  -->
+
+<!--this is sample configuration, please modify as your wish -->
+
+<configuration>
+  <Properties>
+    <Property name="log_path">./gateway/log/</Property>
+  </Properties>
+
+  <Appenders>
+    <Console name="Console" target="SYSTEM_OUT">
+      <PatternLayout pattern="[%d][%t][%p][%c:%L] %m%n" />
+    </Console>
+    <RollingFile name="DailyRollingFile" fileName="${log_path}/output.log"
+      filePattern="${log_path}/zcrTest%d{yyyy-MM-dd}.log">
+      <PatternLayout pattern="[%d][%t][%p][%c:%L] %m%n" />
+      <Policies>
+        <TimeBasedTriggeringPolicy interval="1" />
+        <SizeBasedTriggeringPolicy size="10 MB" />
+      </Policies>
+    </RollingFile>
+  </Appenders>
+  <Loggers>
+    <Root level="info">
+      <AppenderRef ref="Console" />
+      <AppenderRef ref="DailyRollingFile" />
+    </Root>
+  </Loggers>
+</configuration>
\ No newline at end of file
diff --git a/demo/demo-cse-v1/pom.xml b/demo/demo-cse-v1/pom.xml
new file mode 100644
index 0000000..aff6149
--- /dev/null
+++ b/demo/demo-cse-v1/pom.xml
@@ -0,0 +1,53 @@
+<?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.
+  -->
+
+<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">
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.apache.servicecomb.demo</groupId>
+    <artifactId>demo-parent</artifactId>
+    <version>2.3.0-SNAPSHOT</version>
+  </parent>
+  <artifactId>demo-cse-v1</artifactId>
+  <name>Java Chassis::Demo::CSE-V1</name>
+  <packaging>pom</packaging>
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.servicecomb</groupId>
+      <artifactId>solution-basic</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.servicecomb</groupId>
+      <artifactId>registry-service-center</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.servicecomb</groupId>
+      <artifactId>servicestage-environment</artifactId>
+    </dependency>
+  </dependencies>
+
+  <modules>
+    <module>provider</module>
+    <module>consumer</module>
+    <module>gateway</module>
+    <module>test-client</module>
+  </modules>
+
+</project>
\ No newline at end of file
diff --git a/demo/demo-cse-v1/provider/pom.xml b/demo/demo-cse-v1/provider/pom.xml
new file mode 100644
index 0000000..b0be2d4
--- /dev/null
+++ b/demo/demo-cse-v1/provider/pom.xml
@@ -0,0 +1,51 @@
+<?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.
+  -->
+
+<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">
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.apache.servicecomb.demo</groupId>
+    <artifactId>demo-cse-v1</artifactId>
+    <version>2.3.0-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>cse-v1-provider</artifactId>
+  <name>Java Chassis::Demo::CSE-V1::PROVIDER</name>
+  <packaging>jar</packaging>
+
+  <properties>
+  </properties>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.servicecomb</groupId>
+      <artifactId>java-chassis-spring-boot-starter-standalone</artifactId>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.springframework.boot</groupId>
+        <artifactId>spring-boot-maven-plugin</artifactId>
+      </plugin>
+    </plugins>
+  </build>
+</project>
\ No newline at end of file
diff --git a/demo/demo-cse-v1/provider/src/main/java/org/apache/servicecomb/samples/ProviderApplication.java b/demo/demo-cse-v1/provider/src/main/java/org/apache/servicecomb/samples/ProviderApplication.java
new file mode 100644
index 0000000..6542bce
--- /dev/null
+++ b/demo/demo-cse-v1/provider/src/main/java/org/apache/servicecomb/samples/ProviderApplication.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.servicecomb.samples;
+
+import org.apache.servicecomb.springboot2.starter.EnableServiceComb;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.WebApplicationType;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.builder.SpringApplicationBuilder;
+
+@SpringBootApplication
+@EnableServiceComb
+public class ProviderApplication {
+  public static void main(String[] args) throws Exception {
+    try {
+      new SpringApplicationBuilder().web(WebApplicationType.NONE).sources(ProviderApplication.class).run(args);
+    } catch (Exception e) {
+      e.printStackTrace();
+    }
+  }
+}
diff --git a/demo/demo-cse-v1/provider/src/main/java/org/apache/servicecomb/samples/ProviderController.java b/demo/demo-cse-v1/provider/src/main/java/org/apache/servicecomb/samples/ProviderController.java
new file mode 100644
index 0000000..6eea777
--- /dev/null
+++ b/demo/demo-cse-v1/provider/src/main/java/org/apache/servicecomb/samples/ProviderController.java
@@ -0,0 +1,33 @@
+/*
+ * 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.servicecomb.samples;
+
+import org.apache.servicecomb.provider.rest.common.RestSchema;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+
+@RestSchema(schemaId = "ProviderController")
+@RequestMapping(path = "/")
+public class ProviderController {
+  // a very simple service to echo the request parameter
+  @GetMapping("/sayHello")
+  public String sayHello(@RequestParam("name") String name) {
+    return "Hello " + name;
+  }
+}
diff --git a/demo/demo-cse-v1/provider/src/main/resources/application.yml b/demo/demo-cse-v1/provider/src/main/resources/application.yml
new file mode 100644
index 0000000..cddd84e
--- /dev/null
+++ b/demo/demo-cse-v1/provider/src/main/resources/application.yml
@@ -0,0 +1,47 @@
+#
+## ---------------------------------------------------------------------------
+## 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.
+## ---------------------------------------------------------------------------
+# spring boot configurations
+server:
+  port: 9093  # should be same with servicecomb.rest.address to use web container
+
+# override common configurations in common module
+servicecomb-config-order: 10
+
+servicecomb:
+  service:
+    application: demo-cse-v1
+    name: provider
+    version: 0.0.1
+    registry:
+      address: https://cse.cn-south-1.myhuaweicloud.com
+      instance:
+        watch: false
+  config:
+    client:
+      serverUri: https://cse.cn-south-1.myhuaweicloud.com
+
+  rest:
+    address: 0.0.0.0:9093 # should be same with server.port to use web container
+
+# Configure AK/SK credentials if needed. Default not enabled.
+  credentials:
+    akskEnabled: true
+    accessKey: ${CREDENTIALS_AK}
+    secretKey: ${CREDENTIALS_SK}
+    akskCustomCipher: default
+    project: cn-south-1
diff --git a/demo/demo-cse-v1/provider/src/main/resources/log4j2.xml b/demo/demo-cse-v1/provider/src/main/resources/log4j2.xml
new file mode 100644
index 0000000..56fc9a0
--- /dev/null
+++ b/demo/demo-cse-v1/provider/src/main/resources/log4j2.xml
@@ -0,0 +1,45 @@
+<?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.
+  -->
+
+<!--this is sample configuration, please modify as your wish -->
+
+<configuration>
+  <Properties>
+    <Property name="log_path">./user/log/</Property>
+  </Properties>
+
+  <Appenders>
+    <Console name="Console" target="SYSTEM_OUT">
+      <PatternLayout pattern="[%d][%t][%p][%c:%L] %m%n" />
+    </Console>
+    <RollingFile name="DailyRollingFile" fileName="${log_path}/output.log"
+      filePattern="${log_path}/zcrTest%d{yyyy-MM-dd}.log">
+      <PatternLayout pattern="[%d][%t][%p][%c:%L] %m%n" />
+      <Policies>
+        <TimeBasedTriggeringPolicy interval="1" />
+        <SizeBasedTriggeringPolicy size="10MB" />
+      </Policies>
+    </RollingFile>
+  </Appenders>
+  <Loggers>
+    <Root level="info">
+      <AppenderRef ref="Console" />
+      <AppenderRef ref="DailyRollingFile" />
+    </Root>
+  </Loggers>
+</configuration>
\ No newline at end of file
diff --git a/demo/demo-cse-v1/test-client/pom.xml b/demo/demo-cse-v1/test-client/pom.xml
new file mode 100644
index 0000000..32c87cf
--- /dev/null
+++ b/demo/demo-cse-v1/test-client/pom.xml
@@ -0,0 +1,55 @@
+<?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.
+  -->
+
+<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">
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.apache.servicecomb.demo</groupId>
+    <artifactId>demo-cse-v1</artifactId>
+    <version>2.3.0-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>cse-v1-test-client</artifactId>
+  <name>Java Chassis::Demo::CSE-V1::TEST-CLIENT</name>
+  <packaging>jar</packaging>
+
+  <properties>
+  </properties>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.servicecomb</groupId>
+      <artifactId>java-chassis-spring-boot-starter-standalone</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.servicecomb.demo</groupId>
+      <artifactId>demo-schema</artifactId>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.springframework.boot</groupId>
+        <artifactId>spring-boot-maven-plugin</artifactId>
+      </plugin>
+    </plugins>
+  </build>
+</project>
\ No newline at end of file
diff --git a/demo/demo-cse-v1/test-client/src/main/java/org/apache/servicecomb/samples/Config.java b/demo/demo-cse-v1/test-client/src/main/java/org/apache/servicecomb/samples/Config.java
new file mode 100644
index 0000000..2e9105c
--- /dev/null
+++ b/demo/demo-cse-v1/test-client/src/main/java/org/apache/servicecomb/samples/Config.java
@@ -0,0 +1,22 @@
+/*
+ * 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.servicecomb.samples;
+
+public interface Config {
+  String GATEWAY_URL = "http://localhost:9090";
+}
diff --git a/demo/demo-cse-v1/test-client/src/main/java/org/apache/servicecomb/samples/ConsumerConfigIT.java b/demo/demo-cse-v1/test-client/src/main/java/org/apache/servicecomb/samples/ConsumerConfigIT.java
new file mode 100644
index 0000000..ff03a44
--- /dev/null
+++ b/demo/demo-cse-v1/test-client/src/main/java/org/apache/servicecomb/samples/ConsumerConfigIT.java
@@ -0,0 +1,48 @@
+/*
+ * 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.servicecomb.samples;
+
+import org.apache.servicecomb.demo.CategorizedTestCase;
+import org.apache.servicecomb.demo.TestMgr;
+import org.springframework.stereotype.Component;
+import org.springframework.web.client.RestTemplate;
+
+@Component
+public class ConsumerConfigIT implements CategorizedTestCase {
+  RestTemplate template = new RestTemplate();
+
+  @Override
+  public void testRestTransport() throws Exception {
+    testConfig();
+    testFooBar();
+  }
+
+  private void testConfig() {
+    String result = template.getForObject(Config.GATEWAY_URL + "/config?key=cse.v1.test.foo", String.class);
+    TestMgr.check("\"foo\"", result);
+    result = template.getForObject(Config.GATEWAY_URL + "/config?key=cse.v1.test.bar", String.class);
+    TestMgr.check("\"bar\"", result);
+  }
+
+  private void testFooBar() {
+    String result = template.getForObject(Config.GATEWAY_URL + "/foo", String.class);
+    TestMgr.check("\"foo\"", result);
+    result = template.getForObject(Config.GATEWAY_URL + "/bar", String.class);
+    TestMgr.check("\"bar\"", result);
+  }
+}
diff --git a/demo/demo-cse-v1/test-client/src/main/java/org/apache/servicecomb/samples/HelloWorldIT.java b/demo/demo-cse-v1/test-client/src/main/java/org/apache/servicecomb/samples/HelloWorldIT.java
new file mode 100644
index 0000000..bce1456
--- /dev/null
+++ b/demo/demo-cse-v1/test-client/src/main/java/org/apache/servicecomb/samples/HelloWorldIT.java
@@ -0,0 +1,39 @@
+/*
+ * 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.servicecomb.samples;
+
+import org.apache.servicecomb.demo.CategorizedTestCase;
+import org.apache.servicecomb.demo.TestMgr;
+import org.springframework.stereotype.Component;
+import org.springframework.web.client.RestTemplate;
+
+@Component
+public class HelloWorldIT implements CategorizedTestCase {
+  RestTemplate template = new RestTemplate();
+
+  @Override
+  public void testRestTransport() throws Exception {
+    testHelloWorld();
+  }
+
+  private void testHelloWorld() {
+    String result = template
+        .getForObject(Config.GATEWAY_URL + "/sayHello?name=World", String.class);
+    TestMgr.check("\"Hello World\"", result);
+  }
+}
diff --git a/demo/demo-cse-v1/test-client/src/main/java/org/apache/servicecomb/samples/TestClientApplication.java b/demo/demo-cse-v1/test-client/src/main/java/org/apache/servicecomb/samples/TestClientApplication.java
new file mode 100644
index 0000000..f2a67a3
--- /dev/null
+++ b/demo/demo-cse-v1/test-client/src/main/java/org/apache/servicecomb/samples/TestClientApplication.java
@@ -0,0 +1,47 @@
+/*
+ * 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.servicecomb.samples;
+
+import org.apache.servicecomb.demo.CategorizedTestCaseRunner;
+import org.apache.servicecomb.demo.TestMgr;
+import org.apache.servicecomb.springboot2.starter.EnableServiceComb;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.boot.WebApplicationType;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.builder.SpringApplicationBuilder;
+
+@SpringBootApplication
+@EnableServiceComb
+public class TestClientApplication {
+  private static final Logger LOGGER = LoggerFactory.getLogger(TestClientApplication.class);
+
+  public static void main(String[] args) throws Exception {
+    try {
+      new SpringApplicationBuilder().web(WebApplicationType.NONE).sources(TestClientApplication.class).run(args);
+
+      CategorizedTestCaseRunner.runCategorizedTestCase("consumer");
+    } catch (Exception e) {
+      TestMgr.failed("test case run failed", e);
+      LOGGER.error("-------------- test failed -------------");
+      LOGGER.error("", e);
+      LOGGER.error("-------------- test failed -------------");
+    }
+    TestMgr.summary();
+  }
+}
diff --git a/demo/demo-cse-v1/test-client/src/main/resources/application.yml b/demo/demo-cse-v1/test-client/src/main/resources/application.yml
new file mode 100644
index 0000000..746ae32
--- /dev/null
+++ b/demo/demo-cse-v1/test-client/src/main/resources/application.yml
@@ -0,0 +1,47 @@
+#
+## ---------------------------------------------------------------------------
+## 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.
+## ---------------------------------------------------------------------------
+# spring boot configurations
+server:
+  port: 9093  # should be same with servicecomb.rest.address to use web container
+
+# override common configurations in common module
+servicecomb-config-order: 10
+
+servicecomb:
+  service:
+    application: demo-cse-v1
+    name: test-client
+    version: 0.0.1
+    registry:
+      address: https://cse.cn-south-1.myhuaweicloud.com
+      instance:
+        watch: false
+  config:
+    client:
+      serverUri: https://cse.cn-south-1.myhuaweicloud.com
+
+  rest:
+    address: 0.0.0.0:9097 # should be same with server.port to use web container
+
+  # Configure AK/SK credentials if needed. Default not enabled.
+  credentials:
+    akskEnabled: true
+    accessKey: ${CREDENTIALS_AK}
+    secretKey: ${CREDENTIALS_SK}
+    akskCustomCipher: default
+    project: cn-south-1
\ No newline at end of file
diff --git a/demo/demo-cse-v1/test-client/src/main/resources/log4j2.xml b/demo/demo-cse-v1/test-client/src/main/resources/log4j2.xml
new file mode 100644
index 0000000..56fc9a0
--- /dev/null
+++ b/demo/demo-cse-v1/test-client/src/main/resources/log4j2.xml
@@ -0,0 +1,45 @@
+<?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.
+  -->
+
+<!--this is sample configuration, please modify as your wish -->
+
+<configuration>
+  <Properties>
+    <Property name="log_path">./user/log/</Property>
+  </Properties>
+
+  <Appenders>
+    <Console name="Console" target="SYSTEM_OUT">
+      <PatternLayout pattern="[%d][%t][%p][%c:%L] %m%n" />
+    </Console>
+    <RollingFile name="DailyRollingFile" fileName="${log_path}/output.log"
+      filePattern="${log_path}/zcrTest%d{yyyy-MM-dd}.log">
+      <PatternLayout pattern="[%d][%t][%p][%c:%L] %m%n" />
+      <Policies>
+        <TimeBasedTriggeringPolicy interval="1" />
+        <SizeBasedTriggeringPolicy size="10MB" />
+      </Policies>
+    </RollingFile>
+  </Appenders>
+  <Loggers>
+    <Root level="info">
+      <AppenderRef ref="Console" />
+      <AppenderRef ref="DailyRollingFile" />
+    </Root>
+  </Loggers>
+</configuration>
\ No newline at end of file
diff --git a/demo/demo-cse-v2/README.md b/demo/demo-cse-v2/README.md
new file mode 100644
index 0000000..4593ad6
--- /dev/null
+++ b/demo/demo-cse-v2/README.md
@@ -0,0 +1,81 @@
+# 使用微服务引擎2.0的测试用例
+
+* 参考:https://github.com/apache/servicecomb-service-center/tree/master/ux 安装微服务引擎2.0
+
+* 设置环境变量:
+  * CSE_V2_SC: 注册中心的地址
+  * CSE_V2_CC: 配置中心的地址
+
+* 依次启动 provider、consumer、gateway
+
+* 在配置中心增加如下配置:
+  * 应用级配置:consumer.yaml。类型为 yaml。 
+
+```yaml
+cse:
+  v2:
+    test:
+      foo: foo
+```
+
+  * 自定义配置:priority1.yaml。label信息: public=default 。类型为 yaml。 
+```yaml
+cse:
+  v2:
+    test:
+      priority: v2
+      common: common
+```
+
+  * 应用级配置:priority2.yaml。类型为 yaml。 
+```yaml
+cse:
+  v2:
+    test:
+      priority: v2
+```
+
+  * 服务级配置:priority3.yaml,微服务性选择consumer。类型为 yaml。 
+```yaml
+cse:
+  v2:
+    test:
+      priority: v3
+```
+
+  * 应用级配置: cse.v2.test.bar: bar 。 类型为 text。 
+  
+* 执行 tests-client 里面的集成测试用例 (成功)
+
+* 修改
+  * priority1.yaml。label信息: public=default 。类型为 yaml。 
+```yaml
+cse:
+  v2:
+    test:
+      priority: v4
+```
+
+* 执行 tests-client 里面的集成测试用例 (成功) 
+
+* 修改
+  * priority3.yaml。label信息: app=cse-v2-test-application,service=basic-consumer,environment=production 。类型为 yaml。 
+```yaml
+cse:
+  v2:
+    test:
+      priority: v5
+```
+
+* 执行 tests-client 里面的集成测试用例 (失败) 
+
+* 修改
+  * priority3.yaml。label信息: app=cse-v2-test-application,service=basic-consumer,environment=production 。类型为 yaml。 
+```yaml
+cse:
+  v2:
+    test:
+      priority: v3
+```
+
+* 执行 tests-client 里面的集成测试用例 (成功) 
\ No newline at end of file
diff --git a/demo/demo-cse-v2/consumer/pom.xml b/demo/demo-cse-v2/consumer/pom.xml
new file mode 100644
index 0000000..56a9e60
--- /dev/null
+++ b/demo/demo-cse-v2/consumer/pom.xml
@@ -0,0 +1,47 @@
+<!--
+  ~ 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.
+  -->
+
+<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">
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.apache.servicecomb.demo</groupId>
+    <artifactId>demo-cse-v2</artifactId>
+    <version>2.3.0-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>cse-v2-consumer</artifactId>
+  <name>Java Chassis::Demo::CSE-V2::CONSUMER</name>
+  <packaging>jar</packaging>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.servicecomb</groupId>
+      <artifactId>java-chassis-spring-boot-starter-standalone</artifactId>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.springframework.boot</groupId>
+        <artifactId>spring-boot-maven-plugin</artifactId>
+      </plugin>
+    </plugins>
+  </build>
+</project>
\ No newline at end of file
diff --git a/demo/demo-cse-v2/consumer/src/main/java/org/apache/servicecomb/samples/ConsumerApplication.java b/demo/demo-cse-v2/consumer/src/main/java/org/apache/servicecomb/samples/ConsumerApplication.java
new file mode 100644
index 0000000..0010f13
--- /dev/null
+++ b/demo/demo-cse-v2/consumer/src/main/java/org/apache/servicecomb/samples/ConsumerApplication.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.servicecomb.samples;
+
+import org.apache.servicecomb.springboot2.starter.EnableServiceComb;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.WebApplicationType;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.builder.SpringApplicationBuilder;
+
+@SpringBootApplication
+@EnableServiceComb
+public class ConsumerApplication {
+  public static void main(String[] args) throws Exception {
+    try {
+      new SpringApplicationBuilder().web(WebApplicationType.NONE).sources(ConsumerApplication.class).run(args);
+    } catch (Exception e) {
+      e.printStackTrace();
+    }
+  }
+}
diff --git a/demo/demo-cse-v2/consumer/src/main/java/org/apache/servicecomb/samples/ConsumerConfigController.java b/demo/demo-cse-v2/consumer/src/main/java/org/apache/servicecomb/samples/ConsumerConfigController.java
new file mode 100644
index 0000000..d0d1c2b
--- /dev/null
+++ b/demo/demo-cse-v2/consumer/src/main/java/org/apache/servicecomb/samples/ConsumerConfigController.java
@@ -0,0 +1,60 @@
+/*
+ * 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.servicecomb.samples;
+
+import org.apache.servicecomb.provider.rest.common.RestSchema;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.env.Environment;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+
+@RestSchema(schemaId = "ConsumerConfigController")
+@RequestMapping(path = "/")
+public class ConsumerConfigController {
+  @Autowired
+  private Environment environment;
+
+  @Autowired
+  private ConsumerConfigurationProperties consumerConfigurationProperties;
+
+  @GetMapping("/config")
+  public String config(@RequestParam("key") String key) {
+    return environment.getProperty(key);
+  }
+
+  @GetMapping("/foo")
+  public String foo() {
+    return consumerConfigurationProperties.getFoo();
+  }
+
+  @GetMapping("/bar")
+  public String bar() {
+    return consumerConfigurationProperties.getBar();
+  }
+
+  @GetMapping("/priority")
+  public String priority() {
+    return consumerConfigurationProperties.getPriority();
+  }
+
+  @GetMapping("/common")
+  public String common() {
+    return consumerConfigurationProperties.getCommon();
+  }
+}
diff --git a/demo/demo-cse-v2/consumer/src/main/java/org/apache/servicecomb/samples/ConsumerConfigurationProperties.java b/demo/demo-cse-v2/consumer/src/main/java/org/apache/servicecomb/samples/ConsumerConfigurationProperties.java
new file mode 100644
index 0000000..3571a71
--- /dev/null
+++ b/demo/demo-cse-v2/consumer/src/main/java/org/apache/servicecomb/samples/ConsumerConfigurationProperties.java
@@ -0,0 +1,65 @@
+/*
+ * 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.servicecomb.samples;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+@ConfigurationProperties("cse.v2.test")
+@Component
+public class ConsumerConfigurationProperties {
+  private String foo;
+
+  private String bar;
+
+  private String priority;
+
+  private String common;
+
+  public String getFoo() {
+    return foo;
+  }
+
+  public void setFoo(String foo) {
+    this.foo = foo;
+  }
+
+  public String getBar() {
+    return bar;
+  }
+
+  public void setBar(String bar) {
+    this.bar = bar;
+  }
+
+  public String getPriority() {
+    return priority;
+  }
+
+  public void setPriority(String priority) {
+    this.priority = priority;
+  }
+
+  public String getCommon() {
+    return common;
+  }
+
+  public void setCommon(String common) {
+    this.common = common;
+  }
+}
diff --git a/demo/demo-cse-v2/consumer/src/main/java/org/apache/servicecomb/samples/ConsumerController.java b/demo/demo-cse-v2/consumer/src/main/java/org/apache/servicecomb/samples/ConsumerController.java
new file mode 100644
index 0000000..4ed0ecd
--- /dev/null
+++ b/demo/demo-cse-v2/consumer/src/main/java/org/apache/servicecomb/samples/ConsumerController.java
@@ -0,0 +1,37 @@
+/*
+ * 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.servicecomb.samples;
+
+import org.apache.servicecomb.provider.pojo.RpcReference;
+import org.apache.servicecomb.provider.rest.common.RestSchema;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+
+@RestSchema(schemaId = "ConsumerController")
+@RequestMapping(path = "/")
+public class ConsumerController {
+  @RpcReference(schemaId = "ProviderController", microserviceName = "provider")
+  private ProviderService providerService;
+
+  // consumer service which delegate the implementation to provider service.
+  @GetMapping("/sayHello")
+  public String sayHello(@RequestParam("name") String name) {
+    return providerService.sayHello(name);
+  }
+}
diff --git a/demo/demo-cse-v2/consumer/src/main/java/org/apache/servicecomb/samples/ProviderService.java b/demo/demo-cse-v2/consumer/src/main/java/org/apache/servicecomb/samples/ProviderService.java
new file mode 100644
index 0000000..f327412
--- /dev/null
+++ b/demo/demo-cse-v2/consumer/src/main/java/org/apache/servicecomb/samples/ProviderService.java
@@ -0,0 +1,22 @@
+/*
+ * 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.servicecomb.samples;
+
+public interface ProviderService {
+  String sayHello(String name);
+}
diff --git a/demo/demo-cse-v2/consumer/src/main/resources/application.yml b/demo/demo-cse-v2/consumer/src/main/resources/application.yml
new file mode 100644
index 0000000..707a5a1
--- /dev/null
+++ b/demo/demo-cse-v2/consumer/src/main/resources/application.yml
@@ -0,0 +1,38 @@
+#
+## ---------------------------------------------------------------------------
+## 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.
+## ---------------------------------------------------------------------------
+
+# override common configurations in common module
+servicecomb-config-order: 10
+
+servicecomb:
+  service:
+    application: demo-cse-v2
+    name: consumer
+    version: 0.0.1
+    registry:
+      address: ${CSE_V2_SC}
+      instance:
+        watch: false
+  kie:
+    serverUri: ${CSE_V2_CC}
+    customLabel: public
+    customLabelValue: default
+
+  rest:
+    address: 0.0.0.0:9092  # should be same with server.port to use web container
+
diff --git a/demo/demo-cse-v2/consumer/src/main/resources/log4j2.xml b/demo/demo-cse-v2/consumer/src/main/resources/log4j2.xml
new file mode 100644
index 0000000..313d1fc
--- /dev/null
+++ b/demo/demo-cse-v2/consumer/src/main/resources/log4j2.xml
@@ -0,0 +1,45 @@
+<?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.
+  -->
+
+<!--this is sample configuration, please modify as your wish -->
+
+<configuration>
+  <Properties>
+    <Property name="log_path">./file/log/</Property>
+  </Properties>
+
+  <Appenders>
+    <Console name="Console" target="SYSTEM_OUT">
+      <PatternLayout pattern="[%d][%t][%p][%c:%L] %m%n" />
+    </Console>
+    <RollingFile name="DailyRollingFile" fileName="${log_path}/output.log"
+      filePattern="${log_path}/zcrTest%d{yyyy-MM-dd}.log">
+      <PatternLayout pattern="[%d][%t][%p][%c:%L] %m%n" />
+      <Policies>
+        <TimeBasedTriggeringPolicy interval="1" />
+        <SizeBasedTriggeringPolicy size="10 MB" />
+      </Policies>
+    </RollingFile>
+  </Appenders>
+  <Loggers>
+    <Root level="info">
+      <AppenderRef ref="Console" />
+      <AppenderRef ref="DailyRollingFile" />
+    </Root>
+  </Loggers>
+</configuration>
\ No newline at end of file
diff --git a/demo/demo-cse-v2/gateway/pom.xml b/demo/demo-cse-v2/gateway/pom.xml
new file mode 100644
index 0000000..acdc9fa
--- /dev/null
+++ b/demo/demo-cse-v2/gateway/pom.xml
@@ -0,0 +1,50 @@
+<!--
+  ~ 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.
+  -->
+
+<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">
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.apache.servicecomb.demo</groupId>
+    <artifactId>demo-cse-v2</artifactId>
+    <version>2.3.0-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>cse-v2-gateway</artifactId>
+  <name>Java Chassis::Demo::CSE-V2::GATEWAY</name>
+  <packaging>jar</packaging>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.servicecomb</groupId>
+      <artifactId>java-chassis-spring-boot-starter-standalone</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.servicecomb</groupId>
+      <artifactId>edge-core</artifactId>
+    </dependency>
+  </dependencies>
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.springframework.boot</groupId>
+        <artifactId>spring-boot-maven-plugin</artifactId>
+      </plugin>
+    </plugins>
+  </build>
+</project>
\ No newline at end of file
diff --git a/demo/demo-cse-v2/gateway/src/main/java/org/apache/servicecomb/samples/GatewayApplication.java b/demo/demo-cse-v2/gateway/src/main/java/org/apache/servicecomb/samples/GatewayApplication.java
new file mode 100644
index 0000000..f2e086b
--- /dev/null
+++ b/demo/demo-cse-v2/gateway/src/main/java/org/apache/servicecomb/samples/GatewayApplication.java
@@ -0,0 +1,35 @@
+/*
+ * 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.servicecomb.samples;
+
+import org.apache.servicecomb.springboot2.starter.EnableServiceComb;
+import org.springframework.boot.WebApplicationType;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.builder.SpringApplicationBuilder;
+
+@SpringBootApplication
+@EnableServiceComb
+public class GatewayApplication {
+  public static void main(String[] args) throws Exception {
+    try {
+      new SpringApplicationBuilder().web(WebApplicationType.NONE).sources(GatewayApplication.class).run(args);
+    } catch (Exception e) {
+      e.printStackTrace();
+    }
+  }
+}
diff --git a/demo/demo-cse-v2/gateway/src/main/resources/application.yml b/demo/demo-cse-v2/gateway/src/main/resources/application.yml
new file mode 100644
index 0000000..0cc3123
--- /dev/null
+++ b/demo/demo-cse-v2/gateway/src/main/resources/application.yml
@@ -0,0 +1,59 @@
+#
+## ---------------------------------------------------------------------------
+## 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.
+## ---------------------------------------------------------------------------
+
+# override common configurations in common module
+servicecomb-config-order: 100
+
+servicecomb:
+  service:
+    application: demo-cse-v2
+    name: gateway
+    version: 0.0.1
+    registry:
+      address: ${CSE_V2_SC}
+      instance:
+        watch: false
+  kie:
+    serverUri: ${CSE_V2_CC}
+    customLabel: public
+
+  rest:
+    address: 0.0.0.0:9090?sslEnabled=false
+
+  http:
+    dispatcher:
+      edge:
+        default:
+          enabled: false
+        url:
+          enabled: true
+          pattern: /(.*)
+          mappings:
+            consumer:
+              prefixSegmentCount: 0
+              path: "/.*"
+              microserviceName: consumer
+              versionRule: 0.0.0+
+
+  # Configure AK/SK credentials if needed. Default not enabled.
+  credentials:
+    akskEnabled: true
+    accessKey: ${CREDENTIALS_AK}
+    secretKey: ${CREDENTIALS_SK}
+    akskCustomCipher: default
+    project: cn-south-1
\ No newline at end of file
diff --git a/demo/demo-cse-v2/gateway/src/main/resources/log4j2.xml b/demo/demo-cse-v2/gateway/src/main/resources/log4j2.xml
new file mode 100644
index 0000000..e9bb265
--- /dev/null
+++ b/demo/demo-cse-v2/gateway/src/main/resources/log4j2.xml
@@ -0,0 +1,45 @@
+<?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.
+  -->
+
+<!--this is sample configuration, please modify as your wish -->
+
+<configuration>
+  <Properties>
+    <Property name="log_path">./gateway/log/</Property>
+  </Properties>
+
+  <Appenders>
+    <Console name="Console" target="SYSTEM_OUT">
+      <PatternLayout pattern="[%d][%t][%p][%c:%L] %m%n" />
+    </Console>
+    <RollingFile name="DailyRollingFile" fileName="${log_path}/output.log"
+      filePattern="${log_path}/zcrTest%d{yyyy-MM-dd}.log">
+      <PatternLayout pattern="[%d][%t][%p][%c:%L] %m%n" />
+      <Policies>
+        <TimeBasedTriggeringPolicy interval="1" />
+        <SizeBasedTriggeringPolicy size="10 MB" />
+      </Policies>
+    </RollingFile>
+  </Appenders>
+  <Loggers>
+    <Root level="info">
+      <AppenderRef ref="Console" />
+      <AppenderRef ref="DailyRollingFile" />
+    </Root>
+  </Loggers>
+</configuration>
\ No newline at end of file
diff --git a/demo/demo-cse-v2/pom.xml b/demo/demo-cse-v2/pom.xml
new file mode 100644
index 0000000..0a9edea
--- /dev/null
+++ b/demo/demo-cse-v2/pom.xml
@@ -0,0 +1,53 @@
+<?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.
+  -->
+
+<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">
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.apache.servicecomb.demo</groupId>
+    <artifactId>demo-parent</artifactId>
+    <version>2.3.0-SNAPSHOT</version>
+  </parent>
+  <artifactId>demo-cse-v2</artifactId>
+  <name>Java Chassis::Demo::CSE-V2</name>
+  <packaging>pom</packaging>
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.servicecomb</groupId>
+      <artifactId>solution-basic</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.servicecomb</groupId>
+      <artifactId>registry-service-center</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.servicecomb</groupId>
+      <artifactId>servicestage-environment</artifactId>
+    </dependency>
+  </dependencies>
+
+  <modules>
+    <module>provider</module>
+    <module>consumer</module>
+    <module>gateway</module>
+    <module>test-client</module>
+  </modules>
+
+</project>
\ No newline at end of file
diff --git a/demo/demo-cse-v2/provider/pom.xml b/demo/demo-cse-v2/provider/pom.xml
new file mode 100644
index 0000000..3fdebd9
--- /dev/null
+++ b/demo/demo-cse-v2/provider/pom.xml
@@ -0,0 +1,51 @@
+<?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.
+  -->
+
+<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">
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.apache.servicecomb.demo</groupId>
+    <artifactId>demo-cse-v2</artifactId>
+    <version>2.3.0-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>cse-v2-provider</artifactId>
+  <name>Java Chassis::Demo::CSE-V2::PROVIDER</name>
+  <packaging>jar</packaging>
+
+  <properties>
+  </properties>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.servicecomb</groupId>
+      <artifactId>java-chassis-spring-boot-starter-standalone</artifactId>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.springframework.boot</groupId>
+        <artifactId>spring-boot-maven-plugin</artifactId>
+      </plugin>
+    </plugins>
+  </build>
+</project>
\ No newline at end of file
diff --git a/demo/demo-cse-v2/provider/src/main/java/org/apache/servicecomb/samples/ProviderApplication.java b/demo/demo-cse-v2/provider/src/main/java/org/apache/servicecomb/samples/ProviderApplication.java
new file mode 100644
index 0000000..6542bce
--- /dev/null
+++ b/demo/demo-cse-v2/provider/src/main/java/org/apache/servicecomb/samples/ProviderApplication.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.servicecomb.samples;
+
+import org.apache.servicecomb.springboot2.starter.EnableServiceComb;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.WebApplicationType;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.builder.SpringApplicationBuilder;
+
+@SpringBootApplication
+@EnableServiceComb
+public class ProviderApplication {
+  public static void main(String[] args) throws Exception {
+    try {
+      new SpringApplicationBuilder().web(WebApplicationType.NONE).sources(ProviderApplication.class).run(args);
+    } catch (Exception e) {
+      e.printStackTrace();
+    }
+  }
+}
diff --git a/demo/demo-cse-v2/provider/src/main/java/org/apache/servicecomb/samples/ProviderController.java b/demo/demo-cse-v2/provider/src/main/java/org/apache/servicecomb/samples/ProviderController.java
new file mode 100644
index 0000000..6eea777
--- /dev/null
+++ b/demo/demo-cse-v2/provider/src/main/java/org/apache/servicecomb/samples/ProviderController.java
@@ -0,0 +1,33 @@
+/*
+ * 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.servicecomb.samples;
+
+import org.apache.servicecomb.provider.rest.common.RestSchema;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+
+@RestSchema(schemaId = "ProviderController")
+@RequestMapping(path = "/")
+public class ProviderController {
+  // a very simple service to echo the request parameter
+  @GetMapping("/sayHello")
+  public String sayHello(@RequestParam("name") String name) {
+    return "Hello " + name;
+  }
+}
diff --git a/demo/demo-cse-v2/provider/src/main/resources/application.yml b/demo/demo-cse-v2/provider/src/main/resources/application.yml
new file mode 100644
index 0000000..d1abed7
--- /dev/null
+++ b/demo/demo-cse-v2/provider/src/main/resources/application.yml
@@ -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.
+## ---------------------------------------------------------------------------
+# spring boot configurations
+server:
+  port: 9093  # should be same with servicecomb.rest.address to use web container
+
+# override common configurations in common module
+servicecomb-config-order: 10
+
+servicecomb:
+  service:
+    application: demo-cse-v2
+    name: provider
+    version: 0.0.1
+    registry:
+      address: ${CSE_V2_SC}
+      instance:
+        watch: false
+  kie:
+    serverUri: ${CSE_V2_CC}
+    customLabel: public
+
+  rest:
+    address: 0.0.0.0:9093 # should be same with server.port to use web container
+
diff --git a/demo/demo-cse-v2/provider/src/main/resources/log4j2.xml b/demo/demo-cse-v2/provider/src/main/resources/log4j2.xml
new file mode 100644
index 0000000..56fc9a0
--- /dev/null
+++ b/demo/demo-cse-v2/provider/src/main/resources/log4j2.xml
@@ -0,0 +1,45 @@
+<?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.
+  -->
+
+<!--this is sample configuration, please modify as your wish -->
+
+<configuration>
+  <Properties>
+    <Property name="log_path">./user/log/</Property>
+  </Properties>
+
+  <Appenders>
+    <Console name="Console" target="SYSTEM_OUT">
+      <PatternLayout pattern="[%d][%t][%p][%c:%L] %m%n" />
+    </Console>
+    <RollingFile name="DailyRollingFile" fileName="${log_path}/output.log"
+      filePattern="${log_path}/zcrTest%d{yyyy-MM-dd}.log">
+      <PatternLayout pattern="[%d][%t][%p][%c:%L] %m%n" />
+      <Policies>
+        <TimeBasedTriggeringPolicy interval="1" />
+        <SizeBasedTriggeringPolicy size="10MB" />
+      </Policies>
+    </RollingFile>
+  </Appenders>
+  <Loggers>
+    <Root level="info">
+      <AppenderRef ref="Console" />
+      <AppenderRef ref="DailyRollingFile" />
+    </Root>
+  </Loggers>
+</configuration>
\ No newline at end of file
diff --git a/demo/demo-cse-v2/test-client/pom.xml b/demo/demo-cse-v2/test-client/pom.xml
new file mode 100644
index 0000000..ab36136
--- /dev/null
+++ b/demo/demo-cse-v2/test-client/pom.xml
@@ -0,0 +1,55 @@
+<?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.
+  -->
+
+<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">
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.apache.servicecomb.demo</groupId>
+    <artifactId>demo-cse-v2</artifactId>
+    <version>2.3.0-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>cse-v2-test-client</artifactId>
+  <name>Java Chassis::Demo::CSE-V2::TEST-CLIENT</name>
+  <packaging>jar</packaging>
+
+  <properties>
+  </properties>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.servicecomb</groupId>
+      <artifactId>java-chassis-spring-boot-starter-standalone</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.servicecomb.demo</groupId>
+      <artifactId>demo-schema</artifactId>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.springframework.boot</groupId>
+        <artifactId>spring-boot-maven-plugin</artifactId>
+      </plugin>
+    </plugins>
+  </build>
+</project>
\ No newline at end of file
diff --git a/demo/demo-cse-v2/test-client/src/main/java/org/apache/servicecomb/samples/Config.java b/demo/demo-cse-v2/test-client/src/main/java/org/apache/servicecomb/samples/Config.java
new file mode 100644
index 0000000..2e9105c
--- /dev/null
+++ b/demo/demo-cse-v2/test-client/src/main/java/org/apache/servicecomb/samples/Config.java
@@ -0,0 +1,22 @@
+/*
+ * 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.servicecomb.samples;
+
+public interface Config {
+  String GATEWAY_URL = "http://localhost:9090";
+}
diff --git a/demo/demo-cse-v2/test-client/src/main/java/org/apache/servicecomb/samples/ConsumerConfigIT.java b/demo/demo-cse-v2/test-client/src/main/java/org/apache/servicecomb/samples/ConsumerConfigIT.java
new file mode 100644
index 0000000..18eb86a
--- /dev/null
+++ b/demo/demo-cse-v2/test-client/src/main/java/org/apache/servicecomb/samples/ConsumerConfigIT.java
@@ -0,0 +1,56 @@
+/*
+ * 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.servicecomb.samples;
+
+import org.apache.servicecomb.demo.CategorizedTestCase;
+import org.apache.servicecomb.demo.TestMgr;
+import org.springframework.stereotype.Component;
+import org.springframework.web.client.RestTemplate;
+
+@Component
+public class ConsumerConfigIT implements CategorizedTestCase {
+  RestTemplate template = new RestTemplate();
+
+  @Override
+  public void testRestTransport() throws Exception {
+    testConfig();
+    testFooBar();
+  }
+
+  private void testConfig() {
+    String result = template.getForObject(Config.GATEWAY_URL + "/config?key=cse.v2.test.foo", String.class);
+    TestMgr.check("\"foo\"", result);
+    result = template.getForObject(Config.GATEWAY_URL + "/config?key=cse.v2.test.bar", String.class);
+    TestMgr.check("\"bar\"", result);
+    result = template.getForObject(Config.GATEWAY_URL + "/config?key=cse.v2.test.priority", String.class);
+    TestMgr.check("\"v3\"", result);
+    result = template.getForObject(Config.GATEWAY_URL + "/config?key=cse.v2.test.common", String.class);
+    TestMgr.check("\"common\"", result);
+  }
+
+  private void testFooBar() {
+    String result = template.getForObject(Config.GATEWAY_URL + "/bar", String.class);
+    TestMgr.check("\"bar\"", result);
+    result = template.getForObject(Config.GATEWAY_URL + "/foo", String.class);
+    TestMgr.check("\"foo\"", result);
+    result = template.getForObject(Config.GATEWAY_URL + "/priority", String.class);
+    TestMgr.check("\"v3\"", result);
+    result = template.getForObject(Config.GATEWAY_URL + "/common", String.class);
+    TestMgr.check("\"common\"", result);
+  }
+}
diff --git a/demo/demo-cse-v2/test-client/src/main/java/org/apache/servicecomb/samples/HelloWorldIT.java b/demo/demo-cse-v2/test-client/src/main/java/org/apache/servicecomb/samples/HelloWorldIT.java
new file mode 100644
index 0000000..bce1456
--- /dev/null
+++ b/demo/demo-cse-v2/test-client/src/main/java/org/apache/servicecomb/samples/HelloWorldIT.java
@@ -0,0 +1,39 @@
+/*
+ * 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.servicecomb.samples;
+
+import org.apache.servicecomb.demo.CategorizedTestCase;
+import org.apache.servicecomb.demo.TestMgr;
+import org.springframework.stereotype.Component;
+import org.springframework.web.client.RestTemplate;
+
+@Component
+public class HelloWorldIT implements CategorizedTestCase {
+  RestTemplate template = new RestTemplate();
+
+  @Override
+  public void testRestTransport() throws Exception {
+    testHelloWorld();
+  }
+
+  private void testHelloWorld() {
+    String result = template
+        .getForObject(Config.GATEWAY_URL + "/sayHello?name=World", String.class);
+    TestMgr.check("\"Hello World\"", result);
+  }
+}
diff --git a/demo/demo-cse-v2/test-client/src/main/java/org/apache/servicecomb/samples/TestClientApplication.java b/demo/demo-cse-v2/test-client/src/main/java/org/apache/servicecomb/samples/TestClientApplication.java
new file mode 100644
index 0000000..f2a67a3
--- /dev/null
+++ b/demo/demo-cse-v2/test-client/src/main/java/org/apache/servicecomb/samples/TestClientApplication.java
@@ -0,0 +1,47 @@
+/*
+ * 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.servicecomb.samples;
+
+import org.apache.servicecomb.demo.CategorizedTestCaseRunner;
+import org.apache.servicecomb.demo.TestMgr;
+import org.apache.servicecomb.springboot2.starter.EnableServiceComb;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.boot.WebApplicationType;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.builder.SpringApplicationBuilder;
+
+@SpringBootApplication
+@EnableServiceComb
+public class TestClientApplication {
+  private static final Logger LOGGER = LoggerFactory.getLogger(TestClientApplication.class);
+
+  public static void main(String[] args) throws Exception {
+    try {
+      new SpringApplicationBuilder().web(WebApplicationType.NONE).sources(TestClientApplication.class).run(args);
+
+      CategorizedTestCaseRunner.runCategorizedTestCase("consumer");
+    } catch (Exception e) {
+      TestMgr.failed("test case run failed", e);
+      LOGGER.error("-------------- test failed -------------");
+      LOGGER.error("", e);
+      LOGGER.error("-------------- test failed -------------");
+    }
+    TestMgr.summary();
+  }
+}
diff --git a/demo/demo-cse-v2/test-client/src/main/resources/application.yml b/demo/demo-cse-v2/test-client/src/main/resources/application.yml
new file mode 100644
index 0000000..e1f950b
--- /dev/null
+++ b/demo/demo-cse-v2/test-client/src/main/resources/application.yml
@@ -0,0 +1,47 @@
+#
+## ---------------------------------------------------------------------------
+## 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.
+## ---------------------------------------------------------------------------
+# spring boot configurations
+server:
+  port: 9093  # should be same with servicecomb.rest.address to use web container
+
+# override common configurations in common module
+servicecomb-config-order: 10
+
+servicecomb:
+  service:
+    application: demo-cse-v2
+    name: test-client
+    version: 0.0.1
+    registry:
+      address: https://cse.cn-south-1.myhuaweicloud.com
+      instance:
+        watch: false
+  config:
+    client:
+      serverUri: https://cse.cn-south-1.myhuaweicloud.com
+
+  rest:
+    address: 0.0.0.0:9097 # should be same with server.port to use web container
+
+  # Configure AK/SK credentials if needed. Default not enabled.
+  credentials:
+    akskEnabled: true
+    accessKey: ${CREDENTIALS_AK}
+    secretKey: ${CREDENTIALS_SK}
+    akskCustomCipher: default
+    project: cn-south-1
\ No newline at end of file
diff --git a/demo/demo-cse-v2/test-client/src/main/resources/log4j2.xml b/demo/demo-cse-v2/test-client/src/main/resources/log4j2.xml
new file mode 100644
index 0000000..56fc9a0
--- /dev/null
+++ b/demo/demo-cse-v2/test-client/src/main/resources/log4j2.xml
@@ -0,0 +1,45 @@
+<?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.
+  -->
+
+<!--this is sample configuration, please modify as your wish -->
+
+<configuration>
+  <Properties>
+    <Property name="log_path">./user/log/</Property>
+  </Properties>
+
+  <Appenders>
+    <Console name="Console" target="SYSTEM_OUT">
+      <PatternLayout pattern="[%d][%t][%p][%c:%L] %m%n" />
+    </Console>
+    <RollingFile name="DailyRollingFile" fileName="${log_path}/output.log"
+      filePattern="${log_path}/zcrTest%d{yyyy-MM-dd}.log">
+      <PatternLayout pattern="[%d][%t][%p][%c:%L] %m%n" />
+      <Policies>
+        <TimeBasedTriggeringPolicy interval="1" />
+        <SizeBasedTriggeringPolicy size="10MB" />
+      </Policies>
+    </RollingFile>
+  </Appenders>
+  <Loggers>
+    <Root level="info">
+      <AppenderRef ref="Console" />
+      <AppenderRef ref="DailyRollingFile" />
+    </Root>
+  </Loggers>
+</configuration>
\ No newline at end of file
diff --git a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/SpringmvcClient.java b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/SpringmvcClient.java
index c44c3e1..7b37deb 100644
--- a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/SpringmvcClient.java
+++ b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/SpringmvcClient.java
@@ -114,13 +114,11 @@ public class SpringmvcClient {
   private static void testHttpClientsIsOk() {
     TestMgr.check(HttpClients.getClient("registry") != null, true);
     TestMgr.check(HttpClients.getClient("registry-watch") != null, true);
-    TestMgr.check(HttpClients.getClient("config-center") != null, true);
     TestMgr.check(HttpClients.getClient("http-transport-client") != null, true);
     TestMgr.check(HttpClients.getClient("http2-transport-client") != null, true);
 
     TestMgr.check(HttpClients.getClient("registry", false) != null, true);
     TestMgr.check(HttpClients.getClient("registry-watch", false) != null, true);
-    TestMgr.check(HttpClients.getClient("config-center", false) != null, true);
     TestMgr.check(HttpClients.getClient("http-transport-client", false) != null, true);
     TestMgr.check(HttpClients.getClient("http2-transport-client", false) != null, true);
   }
diff --git a/demo/pom.xml b/demo/pom.xml
index 1951416..67d8b12 100644
--- a/demo/pom.xml
+++ b/demo/pom.xml
@@ -50,6 +50,8 @@
     <module>demo-multiple</module>
     <module>demo-multi-service-center</module>
     <module>demo-signature</module>
+    <module>demo-cse-v1</module>
+    <module>demo-cse-v2</module>
   </modules>
 
   <dependencyManagement>
diff --git a/dynamic-config/config-cc/src/main/java/org/apache/servicecomb/config/ConfigCenterConfig.java b/dynamic-config/config-cc/src/main/java/org/apache/servicecomb/config/ConfigCenterConfig.java
index f65d12e..3c0a582 100644
--- a/dynamic-config/config-cc/src/main/java/org/apache/servicecomb/config/ConfigCenterConfig.java
+++ b/dynamic-config/config-cc/src/main/java/org/apache/servicecomb/config/ConfigCenterConfig.java
@@ -30,6 +30,8 @@ import com.netflix.config.ConcurrentCompositeConfiguration;
 public final class ConfigCenterConfig {
   public static final ConfigCenterConfig INSTANCE = new ConfigCenterConfig();
 
+  public static final String SSL_TAG = "cc.consumer";
+
   private static ConcurrentCompositeConfiguration finalConfig;
 
   private static final String AUTO_DISCOVERY_ENABLED = "servicecomb.service.registry.autodiscovery";
@@ -50,6 +52,8 @@ public final class ConfigCenterConfig {
 
   private static final String FIRST_REFRESH_INTERVAL = "servicecomb.config.client.first_refresh_interval";
 
+  private static final String FIRST_PULL_REQUIRED = "servicecomb.config.client.firstPullRequired";
+
   public static final String CONNECTION_TIME_OUT = "servicecomb.config.client.timeout.connection";
 
   public static final String EVENT_LOOP_SIZE = "servicecomb.config.client.eventLoopSize";
@@ -103,6 +107,10 @@ public final class ConfigCenterConfig {
     return finalConfig.getString(URI_API_VERSION, "v3");
   }
 
+  public boolean firstPullRequired() {
+    return finalConfig.getBoolean(FIRST_PULL_REQUIRED, false);
+  }
+
   @SuppressWarnings("unchecked")
   public List<String> getFileSources() {
     Object property = finalConfig.getProperty(FILE_SOURCE);
diff --git a/dynamic-config/config-cc/src/main/java/org/apache/servicecomb/config/ConfigCenterConfigurationSourceImpl.java b/dynamic-config/config-cc/src/main/java/org/apache/servicecomb/config/ConfigCenterConfigurationSourceImpl.java
index d471e08..4be4fe7 100644
--- a/dynamic-config/config-cc/src/main/java/org/apache/servicecomb/config/ConfigCenterConfigurationSourceImpl.java
+++ b/dynamic-config/config-cc/src/main/java/org/apache/servicecomb/config/ConfigCenterConfigurationSourceImpl.java
@@ -17,6 +17,7 @@
 
 package org.apache.servicecomb.config;
 
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -56,7 +57,7 @@ public class ConfigCenterConfigurationSourceImpl implements ConfigCenterConfigur
 
   private ConfigCenterManager configCenterManager;
 
-  private ConfigConverter configConverter = new ConfigConverter(null);
+  private ConfigConverter configConverter;
 
   @Override
   public int getOrder() {
@@ -78,22 +79,18 @@ public class ConfigCenterConfigurationSourceImpl implements ConfigCenterConfigur
 
   @Override
   public void init(Configuration localConfiguration) {
+    configConverter = new ConfigConverter(ConfigCenterConfig.INSTANCE.getFileSources());
+
     AddressManager kieAddressManager = configKieAddressManager();
 
     RequestConfig.Builder requestBuilder = HttpTransportFactory.defaultRequestConfig();
 
-    HttpTransport httpTransport = createHttpTransport(requestBuilder.build(), localConfiguration);
+    HttpTransport httpTransport = createHttpTransport(kieAddressManager.sslEnabled(), requestBuilder.build(),
+        localConfiguration);
     ConfigCenterClient configCenterClient = new ConfigCenterClient(kieAddressManager, httpTransport);
     EventManager.register(this);
 
-    QueryConfigurationsRequest queryConfigurationsRequest = createQueryConfigurationsRequest();
-    QueryConfigurationsResponse response = configCenterClient
-        .queryConfigurations(queryConfigurationsRequest);
-    if (response.isChanged()) {
-      configConverter.updateData(response.getConfigurations());
-      updateConfiguration(WatchedUpdateResult.createIncremental(configConverter.getCurrentData(), null, null));
-    }
-    queryConfigurationsRequest.setRevision(response.getRevision());
+    QueryConfigurationsRequest queryConfigurationsRequest = firstPull(configCenterClient);
 
     configCenterManager = new ConfigCenterManager(configCenterClient, EventManager.getEventBus(),
         configConverter);
@@ -101,6 +98,27 @@ public class ConfigCenterConfigurationSourceImpl implements ConfigCenterConfigur
     configCenterManager.startConfigCenterManager();
   }
 
+  private QueryConfigurationsRequest firstPull(ConfigCenterClient configCenterClient) {
+    QueryConfigurationsRequest queryConfigurationsRequest = createQueryConfigurationsRequest();
+    try {
+      QueryConfigurationsResponse response = configCenterClient
+          .queryConfigurations(queryConfigurationsRequest);
+      if (response.isChanged()) {
+        configConverter.updateData(response.getConfigurations());
+        updateConfiguration(WatchedUpdateResult.createIncremental(configConverter.getCurrentData(), null, null));
+      } else {
+        throw new IllegalStateException("can not fetch config data.");
+      }
+      queryConfigurationsRequest.setRevision(response.getRevision());
+    } catch (Exception e) {
+      if (ConfigCenterConfig.INSTANCE.firstPullRequired()) {
+        throw e;
+      }
+      LOGGER.warn("first pull failed, and ignore {}", e.getMessage());
+    }
+    return queryConfigurationsRequest;
+  }
+
   @Subscribe
   public void onConfigurationChangedEvent(ConfigurationChangedEvent event) {
     updateConfiguration(
@@ -118,12 +136,13 @@ public class ConfigCenterConfigurationSourceImpl implements ConfigCenterConfigur
     return request;
   }
 
-  private HttpTransport createHttpTransport(RequestConfig requestConfig, Configuration localConfiguration) {
+  private HttpTransport createHttpTransport(boolean sslEnabled, RequestConfig requestConfig,
+      Configuration localConfiguration) {
     List<AuthHeaderProvider> authHeaderProviders = SPIServiceUtils.getOrLoadSortedService(AuthHeaderProvider.class);
 
     return HttpTransportFactory
         .createHttpTransport(
-            TransportUtils.createSSLProperties(localConfiguration, "kie"),
+            TransportUtils.createSSLProperties(sslEnabled, localConfiguration, ConfigCenterConfig.SSL_TAG),
             getRequestAuthHeaderProvider(authHeaderProviders), requestConfig);
   }
 
@@ -143,6 +162,10 @@ public class ConfigCenterConfigurationSourceImpl implements ConfigCenterConfigur
   }
 
   private void updateConfiguration(WatchedUpdateResult result) {
+    LOGGER.info("configuration updated keys, added=[{}], updated=[{}], deleted=[{}]",
+        result.getAdded() == null ? "" : result.getAdded().keySet(),
+        result.getChanged() == null ? "" : result.getChanged().keySet(),
+        result.getDeleted() == null ? "" : result.getDeleted().keySet());
     for (WatchedUpdateListener l : listeners) {
       try {
         l.updateConfiguration(result);
@@ -172,6 +195,7 @@ public class ConfigCenterConfigurationSourceImpl implements ConfigCenterConfigur
 
   @Override
   public Map<String, Object> getCurrentData() throws Exception {
-    return configConverter.getCurrentData();
+    // data will updated by first pull, set empty to DynamicWatchedConfiguration first.
+    return Collections.emptyMap();
   }
 }
diff --git a/dynamic-config/config-cc/src/main/java/org/apache/servicecomb/config/TransportUtils.java b/dynamic-config/config-cc/src/main/java/org/apache/servicecomb/config/TransportUtils.java
index e6c8b48..bbfdb72 100644
--- a/dynamic-config/config-cc/src/main/java/org/apache/servicecomb/config/TransportUtils.java
+++ b/dynamic-config/config-cc/src/main/java/org/apache/servicecomb/config/TransportUtils.java
@@ -25,8 +25,13 @@ import org.apache.servicecomb.foundation.ssl.SSLOption;
 import org.apache.servicecomb.http.client.common.HttpConfiguration.SSLProperties;
 
 public class TransportUtils {
-  public static SSLProperties createSSLProperties(Configuration configuration, String tag) {
+  public static SSLProperties createSSLProperties(boolean sslEnabled, Configuration configuration, String tag) {
     SSLProperties sslProperties = new SSLProperties();
+    sslProperties.setEnabled(sslEnabled);
+
+    if (!sslEnabled) {
+      return sslProperties;
+    }
 
     SSLOption option = new SSLOption();
     option.setEngine(getStringProperty(configuration,
diff --git a/dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/KieConfig.java b/dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/KieConfig.java
index ac43c86..4bd8d04 100644
--- a/dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/KieConfig.java
+++ b/dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/KieConfig.java
@@ -17,6 +17,10 @@
 
 package org.apache.servicecomb.config.kie;
 
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
 import org.apache.servicecomb.config.BootStrapProperties;
 import org.apache.servicecomb.foundation.vertx.VertxConst;
 
@@ -28,6 +32,8 @@ public class KieConfig {
 
   private static ConcurrentCompositeConfiguration finalConfig;
 
+  public static final String SSL_TAG = "kie.consumer";
+
   private static final String SERVER_URL_KEY = "servicecomb.kie.serverUri";
 
   private static final String REFRESH_INTERVAL = "servicecomb.kie.refreshInterval";
@@ -52,6 +58,8 @@ public class KieConfig {
 
   private static final String ENABLE_CUSTOM_CONFIG = "servicecomb.kie.enableCustomConfig";
 
+  public static final String FILE_SOURCE = "servicecomb.config.client.fileSource";
+
   public static final String CONNECTION_TIME_OUT = "servicecomb.kie.client.timeout.connection";
 
   public static final String EVENT_LOOP_SIZE = "servicecomb.kie.client.eventLoopSize";
@@ -83,6 +91,20 @@ public class KieConfig {
     KieConfig.finalConfig = finalConfig;
   }
 
+  @SuppressWarnings("unchecked")
+  public List<String> getFileSources() {
+    Object property = finalConfig.getProperty(FILE_SOURCE);
+    if (property instanceof String) {
+      List<String> result = new ArrayList<>();
+      result.add((String) property);
+      return result;
+    }
+    if (property instanceof List) {
+      return (List<String>) property;
+    }
+    return Collections.EMPTY_LIST;
+  }
+
   public int getConnectionTimeOut() {
     return finalConfig.getInt(CONNECTION_TIME_OUT, 1000);
   }
diff --git a/dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/KieConfigurationSourceImpl.java b/dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/KieConfigurationSourceImpl.java
index 18d3fb4..6910822 100644
--- a/dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/KieConfigurationSourceImpl.java
+++ b/dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/KieConfigurationSourceImpl.java
@@ -18,6 +18,7 @@
 package org.apache.servicecomb.config.kie;
 
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -55,7 +56,7 @@ public class KieConfigurationSourceImpl implements ConfigCenterConfigurationSour
 
   private KieConfigManager kieConfigManager;
 
-  private ConfigConverter configConverter = new ConfigConverter(null);
+  private ConfigConverter configConverter;
 
   @Override
   public int getOrder() {
@@ -75,6 +76,7 @@ public class KieConfigurationSourceImpl implements ConfigCenterConfigurationSour
 
   @Override
   public void init(Configuration localConfiguration) {
+    configConverter = new ConfigConverter(KieConfig.INSTANCE.getFileSources());
     KieAddressManager kieAddressManager = configKieAddressManager();
 
     RequestConfig.Builder requestBuilder = HttpTransportFactory.defaultRequestConfig();
@@ -83,7 +85,8 @@ public class KieConfigurationSourceImpl implements ConfigCenterConfigurationSour
       requestBuilder.setConnectionRequestTimeout(KieConfig.INSTANCE.getPollingWaitTime() * 2 * 1000);
       requestBuilder.setSocketTimeout(KieConfig.INSTANCE.getPollingWaitTime() * 2 * 1000);
     }
-    HttpTransport httpTransport = createHttpTransport(requestBuilder.build(), localConfiguration);
+    HttpTransport httpTransport = createHttpTransport(kieAddressManager.sslEnabled(), requestBuilder.build(),
+        localConfiguration);
     KieConfiguration kieConfiguration = createKieConfiguration();
     KieClient kieClient = new KieClient(kieAddressManager, httpTransport, kieConfiguration);
     EventManager.register(this);
@@ -114,12 +117,13 @@ public class KieConfigurationSourceImpl implements ConfigCenterConfigurationSour
         .setServiceName(KieConfig.INSTANCE.getServiceName());
   }
 
-  private HttpTransport createHttpTransport(RequestConfig requestConfig, Configuration localConfiguration) {
+  private HttpTransport createHttpTransport(boolean sslEnabled, RequestConfig requestConfig,
+      Configuration localConfiguration) {
     List<AuthHeaderProvider> authHeaderProviders = SPIServiceUtils.getOrLoadSortedService(AuthHeaderProvider.class);
 
     return HttpTransportFactory
         .createHttpTransport(
-            TransportUtils.createSSLProperties(localConfiguration, "kie"),
+            TransportUtils.createSSLProperties(sslEnabled, localConfiguration, KieConfig.SSL_TAG),
             getRequestAuthHeaderProvider(authHeaderProviders), requestConfig);
   }
 
@@ -138,6 +142,11 @@ public class KieConfigurationSourceImpl implements ConfigCenterConfigurationSour
   }
 
   private void updateConfiguration(WatchedUpdateResult result) {
+    LOGGER.info("configuration updated keys, added=[{}], updated=[{}], deleted=[{}]",
+        result.getAdded() == null ? "" : result.getAdded().keySet(),
+        result.getChanged() == null ? "" : result.getChanged().keySet(),
+        result.getDeleted() == null ? "" : result.getDeleted().keySet());
+
     for (WatchedUpdateListener l : listeners) {
       try {
         l.updateConfiguration(result);
@@ -167,6 +176,7 @@ public class KieConfigurationSourceImpl implements ConfigCenterConfigurationSour
 
   @Override
   public Map<String, Object> getCurrentData() throws Exception {
-    return configConverter.getCurrentData();
+    // data will updated by first pull, set empty to DynamicWatchedConfiguration first.
+    return Collections.emptyMap();
   }
 }
diff --git a/dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/TransportUtils.java b/dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/TransportUtils.java
index d335fd5..42959b7 100644
--- a/dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/TransportUtils.java
+++ b/dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/TransportUtils.java
@@ -25,8 +25,13 @@ import org.apache.servicecomb.foundation.ssl.SSLOption;
 import org.apache.servicecomb.http.client.common.HttpConfiguration.SSLProperties;
 
 public class TransportUtils {
-  public static SSLProperties createSSLProperties(Configuration configuration, String tag) {
+  public static SSLProperties createSSLProperties(boolean sslEnabled, Configuration configuration, String tag) {
     SSLProperties sslProperties = new SSLProperties();
+    sslProperties.setEnabled(sslEnabled);
+
+    if (!sslEnabled) {
+      return sslProperties;
+    }
 
     SSLOption option = new SSLOption();
     option.setEngine(getStringProperty(configuration,
diff --git a/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/ConfigUtil.java b/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/ConfigUtil.java
index 2b288d4..564b699 100644
--- a/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/ConfigUtil.java
+++ b/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/ConfigUtil.java
@@ -247,15 +247,14 @@ public final class ConfigUtil {
     ConfigCenterConfigurationSource configCenterConfigurationSource =
         createConfigCenterConfigurationSource(compositeConfig);
     if (configCenterConfigurationSource != null) {
+      // add listeners
       createDynamicWatchedConfiguration(compositeConfig, configCenterConfigurationSource);
+      // then init data
+      configCenterConfigurationSource.init(compositeConfig);
     }
 
     ConfigurationManager.install(compositeConfig);
 
-    if (configCenterConfigurationSource != null) {
-      configCenterConfigurationSource.init(compositeConfig);
-    }
-
     return configCenterConfigurationSource;
   }
 
diff --git a/demo/README.md b/integration-tests/README.md
similarity index 60%
copy from demo/README.md
copy to integration-tests/README.md
index e8c2880..5568c7b 100644
--- a/demo/README.md
+++ b/integration-tests/README.md
@@ -1,4 +1,8 @@
-This module contains integrated test cases. 
+This module contains integrated test cases. Running these test cases, should include profile 
+
+```shell script
+-Pit
+```
 
 [java-chassis-samples][java-chassis-samples] project provides a lot of samples.
  
diff --git a/service-registry/registry-service-center/src/main/java/org/apache/servicecomb/serviceregistry/client/http/ServiceRegistryClientImpl.java b/service-registry/registry-service-center/src/main/java/org/apache/servicecomb/serviceregistry/client/http/ServiceRegistryClientImpl.java
index 9b38300..2f0f41c 100644
--- a/service-registry/registry-service-center/src/main/java/org/apache/servicecomb/serviceregistry/client/http/ServiceRegistryClientImpl.java
+++ b/service-registry/registry-service-center/src/main/java/org/apache/servicecomb/serviceregistry/client/http/ServiceRegistryClientImpl.java
@@ -120,9 +120,9 @@ public final class ServiceRegistryClientImpl implements ServiceRegistryClient {
   }
 
   private void retry(RequestContext requestContext, Handler<RestResponse> responseHandler) {
-    String oldUri = requestContext.getUri();
+    String oldUri = requestContext.getIpPort().toString();
     requestContext.setIpPort(ipPortManager.getAvailableAddress());
-    String newUri = requestContext.getUri();
+    String newUri = requestContext.getIpPort().toString();
     LOGGER.warn("invoke service [{}] failed, retry address [{}].", oldUri, newUri);
     requestContext.incrementRetryTimes();
     restClientUtil.httpDo(requestContext, responseHandler);
diff --git a/service-registry/registry-service-center/src/main/java/org/apache/servicecomb/serviceregistry/task/ServiceCenterTaskMonitor.java b/service-registry/registry-service-center/src/main/java/org/apache/servicecomb/serviceregistry/task/ServiceCenterTaskMonitor.java
index 7faa91e..daba2a0 100644
--- a/service-registry/registry-service-center/src/main/java/org/apache/servicecomb/serviceregistry/task/ServiceCenterTaskMonitor.java
+++ b/service-registry/registry-service-center/src/main/java/org/apache/servicecomb/serviceregistry/task/ServiceCenterTaskMonitor.java
@@ -25,7 +25,7 @@ import org.slf4j.LoggerFactory;
 public class ServiceCenterTaskMonitor {
   private static final Logger LOGGER = LoggerFactory.getLogger(ServiceCenterTaskMonitor.class);
 
-  private static final long MAX_TIME_TAKEN = 1000;
+  private static final long MAX_TIME_TAKEN = 3000;
 
   private long beginTime = 0;
 
diff --git a/solutions/solution-basic/pom.xml b/solutions/solution-basic/pom.xml
index 0bf8b07..6490845 100644
--- a/solutions/solution-basic/pom.xml
+++ b/solutions/solution-basic/pom.xml
@@ -109,7 +109,10 @@
       <groupId>org.apache.servicecomb</groupId>
       <artifactId>config-cc</artifactId>
     </dependency>
-
+    <dependency>
+      <groupId>org.apache.servicecomb</groupId>
+      <artifactId>config-kie</artifactId>
+    </dependency>
   </dependencies>
 
 </project>