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 2018/08/09 00:59:30 UTC

[incubator-servicecomb-java-chassis] branch master updated (7abb7b1 -> 424bd02)

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/incubator-servicecomb-java-chassis.git.


    from 7abb7b1  [SCB-788] public key black/white choose server by microservice field and properties
     new fbad3da  [SCB-782]support revision check when use pull mode with config center
     new fb32c3c  add post event
     new 6c942b2  consider multipul verticle is deployed, pull and push config at the same time
     new 53453e6  make currentVersionInfo and flatItems private
     new 424bd02  make ParseConfigUtils singleton

The 5 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/client/ConfigCenterClient.java          | 54 +++++++++-----
 .../config/client/ParseConfigUtils.java            | 82 +++++++++++++++++-----
 .../config/client/TestConfigCenterClient.java      | 72 ++++++++++++++++++-
 3 files changed, 171 insertions(+), 37 deletions(-)


[incubator-servicecomb-java-chassis] 05/05: make ParseConfigUtils singleton

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/incubator-servicecomb-java-chassis.git

commit 424bd022e03ba06fcbd9eb90ae8bb3a71f6ecf86
Author: heyile <he...@huawei.com>
AuthorDate: Tue Aug 7 19:46:11 2018 +0800

    make ParseConfigUtils singleton
---
 .../config/client/ConfigCenterClient.java          |  6 ++--
 .../config/client/ParseConfigUtils.java            | 38 ++++++++++++++++------
 2 files changed, 31 insertions(+), 13 deletions(-)

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
index e7aa18f..09d26c4 100644
--- 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
@@ -128,14 +128,14 @@ public class ConfigCenterClient {
       LOGGER.error("refreshMode must be 0 or 1.");
       return;
     }
-    ParseConfigUtils parseConfigUtils = new ParseConfigUtils(updateHandler);
+    ParseConfigUtils.getInstance().initWithUpdateHandler(updateHandler);
     try {
       deployConfigClient();
     } catch (InterruptedException e) {
       throw new IllegalStateException(e);
     }
     refreshMembers(memberDiscovery);
-    ConfigRefresh refreshTask = new ConfigRefresh(parseConfigUtils, memberDiscovery);
+    ConfigRefresh refreshTask = new ConfigRefresh(ParseConfigUtils.getInstance(), memberDiscovery);
     refreshTask.run(true);
     executor.scheduleWithFixedDelay(refreshTask,
         firstRefreshInterval,
@@ -364,7 +364,7 @@ public class ConfigCenterClient {
         encodeServiceName = StringUtils.deleteWhitespace(serviceName);
       }
       String path = uriConst.ITEMS + "?dimensionsInfo=" + encodeServiceName + "&revision="
-          + ParseConfigUtils.getCurrentVersionInfo();
+          + ParseConfigUtils.getInstance().getCurrentVersionInfo();
       clientMgr.findThreadBindClientPool().runOnContext(client -> {
         IpPort ipPort = NetUtils.parseIpPortFromURI(configcenter);
         HttpClientRequest request = client.get(ipPort.getPort(), ipPort.getHostOrIp(), path, rsp -> {
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
index 79366dc..3dd95c8 100644
--- 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
@@ -38,25 +38,39 @@ public class ParseConfigUtils {
 
   private static final Logger LOGGER = LoggerFactory.getLogger(ParseConfigUtils.class);
 
-  private static LinkedHashMap<String, Map<String, Object>> multiDimensionItems = new LinkedHashMap<>();
-  //it's dangerous that makes flatItems public
-  private static final Map<String, Object> flatItems = new HashMap<>();
+  private static final ParseConfigUtils INSTANCE = new ParseConfigUtils();
 
-  private static String currentVersionInfo = "default";
+  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 verticle is 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
-   */
+      as the data is returned, we can block the thread at a short time. consider that if the multiple verticle is 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();
@@ -74,8 +88,12 @@ public class ParseConfigUtils {
     }
   }
 
-  public static String getCurrentVersionInfo() {
-    return currentVersionInfo;
+  public static ParseConfigUtils getInstance() {
+    return INSTANCE;
+  }
+
+  public String getCurrentVersionInfo() {
+    return this.currentVersionInfo;
   }
 
   public void refreshConfigItemsIncremental(Map<String, Object> action) {


[incubator-servicecomb-java-chassis] 02/05: add post event

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/incubator-servicecomb-java-chassis.git

commit fb32c3c4e9b90f203b68a64da60178c7cab27b4c
Author: heyile <he...@huawei.com>
AuthorDate: Thu Aug 2 10:14:16 2018 +0800

    add post event
---
 .../java/org/apache/servicecomb/config/client/ConfigCenterClient.java    | 1 +
 1 file changed, 1 insertion(+)

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
index 1925aa4..3f78b20 100644
--- 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
@@ -387,6 +387,7 @@ public class ConfigCenterClient {
             });
           } else if (rsp.statusCode() == HttpResponseStatus.NOT_MODIFIED.code()) {
             //nothing changed
+            EventManager.post(new ConnSuccEvent());
             latch.countDown();
           } else {
             rsp.bodyHandler(buf -> {


[incubator-servicecomb-java-chassis] 04/05: make currentVersionInfo and flatItems private

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/incubator-servicecomb-java-chassis.git

commit 53453e65b1f9b313147c3da18e7517512a0d93ad
Author: heyile <he...@huawei.com>
AuthorDate: Mon Aug 6 14:27:30 2018 +0800

    make currentVersionInfo and flatItems private
---
 .../servicecomb/config/client/ConfigCenterClient.java    |  2 +-
 .../servicecomb/config/client/ParseConfigUtils.java      | 16 ++++++++++------
 .../config/client/TestConfigCenterClient.java            |  2 +-
 3 files changed, 12 insertions(+), 8 deletions(-)

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
index 3f78b20..e7aa18f 100644
--- 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
@@ -364,7 +364,7 @@ public class ConfigCenterClient {
         encodeServiceName = StringUtils.deleteWhitespace(serviceName);
       }
       String path = uriConst.ITEMS + "?dimensionsInfo=" + encodeServiceName + "&revision="
-          + ParseConfigUtils.CURRENT_VERSION_INFO;
+          + ParseConfigUtils.getCurrentVersionInfo();
       clientMgr.findThreadBindClientPool().runOnContext(client -> {
         IpPort ipPort = NetUtils.parseIpPortFromURI(configcenter);
         HttpClientRequest request = client.get(ipPort.getPort(), ipPort.getHostOrIp(), path, rsp -> {
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
index b9e517e..79366dc 100644
--- 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
@@ -39,10 +39,10 @@ public class ParseConfigUtils {
   private static final Logger LOGGER = LoggerFactory.getLogger(ParseConfigUtils.class);
 
   private static LinkedHashMap<String, Map<String, Object>> multiDimensionItems = new LinkedHashMap<>();
+  //it's dangerous that makes flatItems public
+  private static final Map<String, Object> flatItems = new HashMap<>();
 
-  public static final Map<String, Object> flatItems = new HashMap<>();
-
-  public static String CURRENT_VERSION_INFO = "default";
+  private static String currentVersionInfo = "default";
 
   private UpdateHandler updateHandler;
 
@@ -60,10 +60,10 @@ public class ParseConfigUtils {
   public void refreshConfigItems(Map<String, Map<String, Object>> remoteItems) {
     try {
       configLock.lock();
-      CURRENT_VERSION_INFO =
+      currentVersionInfo =
           remoteItems.getOrDefault("revision", new HashMap<>()).getOrDefault("version", "default").toString();
-      //make sure the CURRENT_VERSION_INFO != ""
-      CURRENT_VERSION_INFO = CURRENT_VERSION_INFO.equals("") ? "default" : CURRENT_VERSION_INFO;
+      //make sure the currentVersionInfo != ""
+      currentVersionInfo = currentVersionInfo.equals("") ? "default" : currentVersionInfo;
       remoteItems.remove("revision");//the key revision is not the config setting
       multiDimensionItems.clear();
       multiDimensionItems.putAll(remoteItems);
@@ -74,6 +74,10 @@ public class ParseConfigUtils {
     }
   }
 
+  public static String getCurrentVersionInfo() {
+    return currentVersionInfo;
+  }
+
   public void refreshConfigItemsIncremental(Map<String, Object> action) {
     try {
       configLock.lock();
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
index 58d76af..f672d9e 100644
--- 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
@@ -179,7 +179,7 @@ public class TestConfigCenterClient {
     ConfigRefresh refresh = cc.new ConfigRefresh(parseConfigUtils, memberdis);
     Deencapsulation.setField(cc, "refreshMode", 1);
     refresh.run();
-    String currentVersionInfo = Deencapsulation.getField(parseConfigUtils, "CURRENT_VERSION_INFO").toString();
+    String currentVersionInfo = Deencapsulation.getField(parseConfigUtils, "currentVersionInfo").toString();
     return currentVersionInfo;
   }
 


[incubator-servicecomb-java-chassis] 03/05: consider multipul verticle is deployed, pull and push config at the same time

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/incubator-servicecomb-java-chassis.git

commit 6c942b2aa3815bb45c0134d2f7e9c3242d377053
Author: heyile <he...@huawei.com>
AuthorDate: Thu Aug 2 10:51:13 2018 +0800

    consider multipul verticle is deployed, pull and push config at the same time
---
 .../config/client/ParseConfigUtils.java            | 59 ++++++++++++++--------
 1 file changed, 39 insertions(+), 20 deletions(-)

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
index 0ced4fd..b9e517e 100644
--- 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
@@ -21,6 +21,8 @@ import java.io.IOException;
 import java.util.HashMap;
 import java.util.LinkedHashMap;
 import java.util.Map;
+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;
@@ -44,35 +46,52 @@ public class ParseConfigUtils {
 
   private UpdateHandler updateHandler;
 
+  private Lock configLock = new ReentrantLock();
+
   public ParseConfigUtils(UpdateHandler updateHandler) {
     this.updateHandler = updateHandler;
   }
 
+  /*
+    as the data is returned, we can block the thread at a short time. consider that if the multiple verticle is 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) {
-    CURRENT_VERSION_INFO =
-        remoteItems.getOrDefault("revision", new HashMap<>()).getOrDefault("version", "default").toString();
-    //make sure the CURRENT_VERSION_INFO != ""
-    CURRENT_VERSION_INFO = CURRENT_VERSION_INFO.equals("") ? "default" : CURRENT_VERSION_INFO;
-    remoteItems.remove("revision");//the key revision is not the config setting
-    multiDimensionItems.clear();
-    multiDimensionItems.putAll(remoteItems);
-    doRefreshItems();
-    LOGGER.debug("refresh config success");
+    try {
+      configLock.lock();
+      CURRENT_VERSION_INFO =
+          remoteItems.getOrDefault("revision", new HashMap<>()).getOrDefault("version", "default").toString();
+      //make sure the CURRENT_VERSION_INFO != ""
+      CURRENT_VERSION_INFO = CURRENT_VERSION_INFO.equals("") ? "default" : CURRENT_VERSION_INFO;
+      remoteItems.remove("revision");//the key revision is not the config setting
+      multiDimensionItems.clear();
+      multiDimensionItems.putAll(remoteItems);
+      doRefreshItems();
+      LOGGER.debug("refresh config success");
+    } finally {
+      configLock.unlock();
+    }
   }
 
   public void refreshConfigItemsIncremental(Map<String, Object> action) {
-    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");
+    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();
       }
-      doRefreshItems();
-    } else if ("DELETE".equals(action.get("action"))) {
-      multiDimensionItems.remove(action.get("key"));
-      doRefreshItems();
+    } finally {
+      configLock.unlock();
     }
   }
 


[incubator-servicecomb-java-chassis] 01/05: [SCB-782]support revision check when use pull mode with config center

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/incubator-servicecomb-java-chassis.git

commit fbad3da4b31f5040fdb9d1b8788d5dfb58cde893
Author: heyile <he...@huawei.com>
AuthorDate: Wed Aug 1 20:25:30 2018 +0800

    [SCB-782]support revision check when use pull mode with config center
---
 .../config/client/ConfigCenterClient.java          | 49 ++++++++++-----
 .../config/client/ParseConfigUtils.java            |  7 +++
 .../config/client/TestConfigCenterClient.java      | 72 +++++++++++++++++++++-
 3 files changed, 110 insertions(+), 18 deletions(-)

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
index a58de4d..1925aa4 100644
--- 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
@@ -160,13 +160,14 @@ public class ConfigCenterClient {
       String configCenter = memberDiscovery.getConfigServer();
       IpPort ipPort = NetUtils.parseIpPortFromURI(configCenter);
       clientMgr.findThreadBindClientPool().runOnContext(client -> {
-        HttpClientRequest request = client.get(ipPort.getPort(), ipPort.getHostOrIp(), uriConst.MEMBERS, rsp -> {
-          if (rsp.statusCode() == HttpResponseStatus.OK.code()) {
-            rsp.bodyHandler(buf -> {
-              memberDiscovery.refreshMembers(buf.toJsonObject());
+        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<>(),
@@ -174,7 +175,8 @@ public class ConfigCenterClient {
         if (ConfigCenterConfig.INSTANCE.getToken() != null) {
           request.headers().add("X-Auth-Token", ConfigCenterConfig.INSTANCE.getToken());
         }
-        authHeaderProviders.forEach(provider -> request.headers().addAll(provider.getSignAuthHeaders(signReq)));
+        authHeaderProviders.forEach(provider -> request.headers()
+            .addAll(provider.getSignAuthHeaders(signReq)));
         request.exceptionHandler(e -> {
           LOGGER.error("Fetch member from {} failed. Error message is [{}].", configCenter, e.getMessage());
         });
@@ -235,14 +237,15 @@ public class ConfigCenterClient {
     }
 
     public void run(boolean wait) {
-      // this will be single threaded, so we don't care about concurrent
-      // staffs
       try {
         String configCenter = memberdis.getConfigServer();
         if (refreshMode == 1) {
-          refreshConfig(configCenter, wait);
+          //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);
         }
@@ -302,6 +305,7 @@ public class ConfigCenterClient {
                 LOGGER.info("watching config recieved {}", action);
                 Map<String, Object> mAction = action.toJsonObject().getMap();
                 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);
@@ -314,7 +318,8 @@ public class ConfigCenterClient {
               waiter.countDown();
             },
             e -> {
-              LOGGER.error("watcher connect to config center {} refresh port {} failed. Error message is [{}]",
+              LOGGER.error(
+                  "watcher connect to config center {} refresh port {} failed. Error message is [{}]",
                   configCenter,
                   refreshPort,
                   e.getMessage());
@@ -352,12 +357,14 @@ public class ConfigCenterClient {
       CountDownLatch latch = new CountDownLatch(1);
       String encodeServiceName = "";
       try {
-        encodeServiceName = URLEncoder.encode(StringUtils.deleteWhitespace(serviceName), StandardCharsets.UTF_8.name());
+        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);
       }
-      String path = uriConst.ITEMS + "?dimensionsInfo=" + encodeServiceName;
+      String path = uriConst.ITEMS + "?dimensionsInfo=" + encodeServiceName + "&revision="
+          + ParseConfigUtils.CURRENT_VERSION_INFO;
       clientMgr.findThreadBindClientPool().runOnContext(client -> {
         IpPort ipPort = NetUtils.parseIpPortFromURI(configcenter);
         HttpClientRequest request = client.get(ipPort.getPort(), ipPort.getHostOrIp(), path, rsp -> {
@@ -370,11 +377,17 @@ public class ConfigCenterClient {
                         }));
                 EventManager.post(new ConnSuccEvent());
               } catch (IOException e) {
-                EventManager.post(new ConnFailEvent("config refresh result parse fail " + e.getMessage()));
-                LOGGER.error("Config refresh from {} failed. Error message is [{}].", configcenter, e.getMessage());
+                EventManager.post(new ConnFailEvent(
+                    "config refresh result parse fail " + e.getMessage()));
+                LOGGER.error("Config refresh from {} failed. Error message is [{}].",
+                    configcenter,
+                    e.getMessage());
               }
               latch.countDown();
             });
+          } else if (rsp.statusCode() == HttpResponseStatus.NOT_MODIFIED.code()) {
+            //nothing changed
+            latch.countDown();
           } else {
             rsp.bodyHandler(buf -> {
               LOGGER.error("Server error message is [{}].", buf);
@@ -383,7 +396,7 @@ public class ConfigCenterClient {
             EventManager.post(new ConnFailEvent("fetch config fail"));
             LOGGER.error("Config refresh 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) {
@@ -398,7 +411,9 @@ public class ConfigCenterClient {
                 null))));
         request.exceptionHandler(e -> {
           EventManager.post(new ConnFailEvent("fetch config fail"));
-          LOGGER.error("Config refresh from {} failed. Error message is [{}].", configcenter, e.getMessage());
+          LOGGER.error("Config refresh from {} failed. Error message is [{}].",
+              configcenter,
+              e.getMessage());
           latch.countDown();
         });
         request.end();
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
index a891088..0ced4fd 100644
--- 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
@@ -40,6 +40,8 @@ public class ParseConfigUtils {
 
   public static final Map<String, Object> flatItems = new HashMap<>();
 
+  public static String CURRENT_VERSION_INFO = "default";
+
   private UpdateHandler updateHandler;
 
   public ParseConfigUtils(UpdateHandler updateHandler) {
@@ -47,6 +49,11 @@ public class ParseConfigUtils {
   }
 
   public void refreshConfigItems(Map<String, Map<String, Object>> remoteItems) {
+    CURRENT_VERSION_INFO =
+        remoteItems.getOrDefault("revision", new HashMap<>()).getOrDefault("version", "default").toString();
+    //make sure the CURRENT_VERSION_INFO != ""
+    CURRENT_VERSION_INFO = CURRENT_VERSION_INFO.equals("") ? "default" : CURRENT_VERSION_INFO;
+    remoteItems.remove("revision");//the key revision is not the config setting
     multiDimensionItems.clear();
     multiDimensionItems.putAll(remoteItems);
     doRefreshItems();
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
index 83398f1..58d76af 100644
--- 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
@@ -115,7 +115,77 @@ public class TestConfigCenterClient {
 
   @SuppressWarnings("unchecked")
   @Test
-  public void testConfigRefresh(@Mocked ClientPoolManager<HttpClientWithContext> clientMgr,
+  public void testConfigRefreshModeOne(@Mocked ClientPoolManager<HttpClientWithContext> clientMgr,
+      @Mocked HttpClientWithContext httpClientWithContext) {
+    String version1 = refreshAndGetCurrentRevision(clientMgr, httpClientWithContext, 200, "huawei");
+    //test the sdk get and change the latestRevision
+    Assert.assertEquals("huawei", version1);
+    String version2 = refreshAndGetCurrentRevision(clientMgr, httpClientWithContext, 304, "rkd");
+    //test that when return code is 304, the sdk do not change the latestRevision
+    Assert.assertNotEquals("rkd", version2);
+    String version3 = refreshAndGetCurrentRevision(clientMgr, httpClientWithContext, 200, "");
+    //make sure the current version is not ""
+    Assert.assertNotEquals("", version3);
+  }
+
+  @SuppressWarnings("unchecked")
+  private String refreshAndGetCurrentRevision(ClientPoolManager<HttpClientWithContext> clientMgr,
+      HttpClientWithContext httpClientWithContext, 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;
+        });
+
+    new MockUp<HttpClientWithContext>() {
+      @Mock
+      public void runOnContext(RunHandler handler) {
+        handler.run(httpClient);
+      }
+    };
+    new Expectations() {
+      {
+        clientMgr.findThreadBindClientPool();
+        result = httpClientWithContext;
+      }
+    };
+
+    ConfigCenterClient cc = new ConfigCenterClient(updateHandler);
+    Deencapsulation.setField(cc, "clientMgr", clientMgr);
+    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, "CURRENT_VERSION_INFO").toString();
+    return currentVersionInfo;
+  }
+
+  @SuppressWarnings("unchecked")
+  @Test
+  public void testConfigRefreshModeZero(@Mocked ClientPoolManager<HttpClientWithContext> clientMgr,
       @Mocked HttpClientWithContext httpClientWithContext) {
     ConfigCenterConfigurationSourceImpl impl = new ConfigCenterConfigurationSourceImpl();
     UpdateHandler updateHandler = impl.new UpdateHandler();