[ 
https://issues.apache.org/jira/browse/SCB-760?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16549062#comment-16549062
 ] 

ASF GitHub Bot commented on SCB-760:
------------------------------------

liubao68 closed pull request #821: [SCB-760]provide a way to invoke service 
with full path
URL: https://github.com/apache/incubator-servicecomb-java-chassis/pull/821
 
 
   

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

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

diff --git a/archetypes/README.md b/archetypes/README.md
index 687a6f4ca..84663b553 100644
--- a/archetypes/README.md
+++ b/archetypes/README.md
@@ -48,5 +48,5 @@ In console Interactive mode, input your GroupId, ArtifactId 
and Version of new p
 *Notice: We will publish these archetypes to maven center repository since 
1.0.0-m2, if you would like to use an archetype from an unreleased version, 
must use `archetypeRepository` option in the version 2.4 of archetype-plugin in 
order to set maven repository to apache snapshot groups: *
 
 ```bash
-mvn org.apache.maven.plugins:maven-archetype-plugin:2.4:generate 
-DarchetypeGroupId=org.apache.servicecomb.archetypes 
-DarchetypeArtifactId=business-service-jaxrs-archetype 
-DarchetypeVersion=1.0.0-m2-SNAPSHOT 
-DarchetypeRepository=https://repository.apache.org/content/groups/snapshots-group
+mvn org.apache.maven.plugins:maven-archetype-plugin:2.4:generate 
-DarchetypeGroupId=org.apache.servicecomb.archetypes 
-DarchetypeArtifactId=business-service-jaxrs-archetype 
-DarchetypeVersion=1.0.0-SNAPSHOT 
-DarchetypeRepository=https://repository.apache.org/content/groups/snapshots-group
 ```
\ 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 cc93248b5..beab26a74 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
@@ -30,6 +30,7 @@
 import org.apache.servicecomb.foundation.common.utils.Log4jUtils;
 import org.apache.servicecomb.provider.springmvc.reference.CseRestTemplate;
 import org.apache.servicecomb.provider.springmvc.reference.RestTemplateBuilder;
+import 
org.apache.servicecomb.provider.springmvc.reference.UrlWithProviderPrefixClientHttpRequestFactory;
 import 
org.apache.servicecomb.provider.springmvc.reference.UrlWithServiceNameClientHttpRequestFactory;
 import org.apache.servicecomb.swagger.invocation.exception.ExceptionFactory;
 import org.apache.servicecomb.swagger.invocation.exception.InvocationException;
@@ -47,6 +48,8 @@
 public class SpringmvcClient {
   private static RestTemplate templateUrlWithServiceName = new 
CseRestTemplate();
 
+  private static RestTemplate templateUrlWithProviderPrefix = new 
CseRestTemplate();
+
   private static RestTemplate restTemplate;
 
   private static Controller controller;
@@ -65,6 +68,7 @@ public static void run() {
 
     templateUrlWithServiceName.setRequestFactory(new 
UrlWithServiceNameClientHttpRequestFactory());
     restTemplate = RestTemplateBuilder.create();
+    templateUrlWithProviderPrefix.setRequestFactory(new 
UrlWithProviderPrefixClientHttpRequestFactory("/pojo/rest"));
     controller = BeanUtils.getBean("controller");
 
     String prefix = "cse://springmvc";
@@ -80,6 +84,7 @@ public static void run() {
     CodeFirstRestTemplateSpringmvc codeFirstClient =
         BeanUtils.getContext().getBean(CodeFirstRestTemplateSpringmvc.class);
     codeFirstClient.testCodeFirst(restTemplate, "springmvc", 
"/codeFirstSpringmvc/");
+    codeFirstClient.testCodeFirst(templateUrlWithProviderPrefix, "springmvc", 
"/pojo/rest/codeFirstSpringmvc/");
 
     String microserviceName = "springmvc";
     for (String transport : DemoConst.transports) {
@@ -115,11 +120,13 @@ public static void run() {
     TestMgr.check(true, metrics.size() > 0);
     TestMgr.check(true,
         metrics.get(
-            
"servicecomb.invocation(operation=springmvc.codeFirst.saySomething,role=PRODUCER,stage=total,statistic=count,status=200,transport=highway)")
 >= 0);
+            
"servicecomb.invocation(operation=springmvc.codeFirst.saySomething,role=PRODUCER,stage=total,statistic=count,status=200,transport=highway)")
+            >= 0);
 
     //prometheus integration test
     try {
-      String content = 
restTemplate.getForObject("cse://springmvc/codeFirstSpringmvc/prometheusForTest",
 String.class);
+      String content = restTemplate
+          
.getForObject("cse://springmvc/codeFirstSpringmvc/prometheusForTest", 
String.class);
 
       TestMgr.check(true, 
content.contains("servicecomb_invocation{operation=\"springmvc.codeFirst.addDate"));
       TestMgr.check(true, 
content.contains("servicecomb_invocation{operation=\"springmvc.codeFirst.sayHello"));
diff --git 
a/foundations/foundation-test-scaffolding/src/main/java/org/apache/servicecomb/foundation/test/scaffolding/config/ArchaiusUtils.java
 
b/foundations/foundation-test-scaffolding/src/main/java/org/apache/servicecomb/foundation/test/scaffolding/config/ArchaiusUtils.java
index d913dc999..ca91ef617 100644
--- 
a/foundations/foundation-test-scaffolding/src/main/java/org/apache/servicecomb/foundation/test/scaffolding/config/ArchaiusUtils.java
+++ 
b/foundations/foundation-test-scaffolding/src/main/java/org/apache/servicecomb/foundation/test/scaffolding/config/ArchaiusUtils.java
@@ -18,6 +18,8 @@
 package org.apache.servicecomb.foundation.test.scaffolding.config;
 
 import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.concurrent.ConcurrentHashMap;
 
 import org.springframework.util.ReflectionUtils;
 
@@ -40,23 +42,34 @@
   private static final Field FIELD_DYNAMIC_PROPERTY_SUPPORTIMPL =
       ReflectionUtils.findField(DynamicProperty.class, 
"dynamicPropertySupportImpl");
 
+  private static final Field FIELD_DYNAMIC_PROPERTY_ALL_PROPS = ReflectionUtils
+      .findField(DynamicProperty.class, "ALL_PROPS");
+
+  private static Method updatePropertyMethod =
+      ReflectionUtils.findMethod(DynamicProperty.class, "updateProperty", 
String.class, Object.class);
+
   static {
     FIELD_INSTANCE.setAccessible(true);
     FIELD_CUSTOM_CONFIGURATION_INSTALLED.setAccessible(true);
     FIELD_CONFIG.setAccessible(true);
     FIELD_INITIALIZED_WITH_DEFAULT_CONFIG.setAccessible(true);
     FIELD_DYNAMIC_PROPERTY_SUPPORTIMPL.setAccessible(true);
+    FIELD_DYNAMIC_PROPERTY_ALL_PROPS.setAccessible(true);
+    updatePropertyMethod.setAccessible(true);
   }
 
   private ArchaiusUtils() {
   }
 
+  @SuppressWarnings("unchecked")
   public static void resetConfig() {
     ReflectionUtils.setField(FIELD_INSTANCE, null, null);
     ReflectionUtils.setField(FIELD_CUSTOM_CONFIGURATION_INSTALLED, null, 
false);
     ReflectionUtils.setField(FIELD_CONFIG, null, null);
     ReflectionUtils.setField(FIELD_INITIALIZED_WITH_DEFAULT_CONFIG, null, 
false);
     ReflectionUtils.setField(FIELD_DYNAMIC_PROPERTY_SUPPORTIMPL, null, null);
+    ((ConcurrentHashMap<String, DynamicProperty>) 
ReflectionUtils.getField(FIELD_DYNAMIC_PROPERTY_ALL_PROPS, null))
+        .clear();
   }
 
   public static void setProperty(String key, Object value) {
@@ -67,4 +80,13 @@ public static void setProperty(String key, Object value) {
         .getBackingConfigurationSource();
     config.getConfiguration(0).addProperty(key, value);
   }
+
+  /**
+   * difference with setProperty is that, updateProperty value can be null
+   * @param key
+   * @param value
+   */
+  public static void updateProperty(String key, Object value) {
+    ReflectionUtils.invokeMethod(updatePropertyMethod, null, key, value);
+  }
 }
diff --git 
a/handlers/handler-flowcontrol-qps/src/test/java/org/apache/servicecomb/qps/QpsControllerManagerTest.java
 
b/handlers/handler-flowcontrol-qps/src/test/java/org/apache/servicecomb/qps/QpsControllerManagerTest.java
index 5f7f2821f..44b86b267 100644
--- 
a/handlers/handler-flowcontrol-qps/src/test/java/org/apache/servicecomb/qps/QpsControllerManagerTest.java
+++ 
b/handlers/handler-flowcontrol-qps/src/test/java/org/apache/servicecomb/qps/QpsControllerManagerTest.java
@@ -422,12 +422,12 @@ public static OperationMeta getMockOperationMeta(String 
microserviceName, String
   }
 
   public static void setConfig(String key, int value) {
-    Utils.updateProperty(key, value);
+    ArchaiusUtils.setProperty(key, value);
   }
 
   public static void setConfigWithDefaultPrefix(String key, int value) {
     String configKey = Config.CONSUMER_LIMIT_KEY_PREFIX + key;
-    Utils.updateProperty(configKey, value);
+    ArchaiusUtils.setProperty(configKey, value);
   }
 
   public static void clearState(QpsControllerManager qpsControllerManager) {
diff --git 
a/handlers/handler-flowcontrol-qps/src/test/java/org/apache/servicecomb/qps/TestConfig.java
 
b/handlers/handler-flowcontrol-qps/src/test/java/org/apache/servicecomb/qps/TestConfig.java
index 540d3031c..15d1e29b1 100644
--- 
a/handlers/handler-flowcontrol-qps/src/test/java/org/apache/servicecomb/qps/TestConfig.java
+++ 
b/handlers/handler-flowcontrol-qps/src/test/java/org/apache/servicecomb/qps/TestConfig.java
@@ -17,7 +17,10 @@
 
 package org.apache.servicecomb.qps;
 
+import org.apache.servicecomb.foundation.test.scaffolding.config.ArchaiusUtils;
+import org.junit.AfterClass;
 import org.junit.Assert;
+import org.junit.BeforeClass;
 import org.junit.Test;
 
 /**
@@ -25,20 +28,30 @@
  *
  */
 public class TestConfig {
+  @BeforeClass
+  public static void classSetup() {
+    ArchaiusUtils.resetConfig();
+  }
+
+  @AfterClass
+  public static void classTeardown() {
+    ArchaiusUtils.resetConfig();
+  }
+
   @Test
   public void testEnabled() {
     Assert.assertEquals(true, Config.INSTANCE.isProviderEnabled());
-    Utils.updateProperty(Config.PROVIDER_ENABLED, false);
+    ArchaiusUtils.updateProperty(Config.PROVIDER_ENABLED, false);
     Assert.assertEquals(false, Config.INSTANCE.isProviderEnabled());
 
-    Utils.updateProperty(Config.PROVIDER_ENABLED, null);
+    ArchaiusUtils.updateProperty(Config.PROVIDER_ENABLED, null);
     Assert.assertEquals(true, Config.INSTANCE.isProviderEnabled());
 
     Assert.assertEquals(true, Config.INSTANCE.isConsumerEnabled());
-    Utils.updateProperty(Config.CONSUMER_ENABLED, false);
+    ArchaiusUtils.updateProperty(Config.CONSUMER_ENABLED, false);
     Assert.assertEquals(false, Config.INSTANCE.isConsumerEnabled());
 
-    Utils.updateProperty(Config.CONSUMER_ENABLED, null);
+    ArchaiusUtils.updateProperty(Config.CONSUMER_ENABLED, null);
     Assert.assertEquals(true, Config.INSTANCE.isConsumerEnabled());
   }
 }
diff --git 
a/handlers/handler-flowcontrol-qps/src/test/java/org/apache/servicecomb/qps/TestProviderQpsFlowControlHandler.java
 
b/handlers/handler-flowcontrol-qps/src/test/java/org/apache/servicecomb/qps/TestProviderQpsFlowControlHandler.java
index d14e6a25a..f671eeab0 100644
--- 
a/handlers/handler-flowcontrol-qps/src/test/java/org/apache/servicecomb/qps/TestProviderQpsFlowControlHandler.java
+++ 
b/handlers/handler-flowcontrol-qps/src/test/java/org/apache/servicecomb/qps/TestProviderQpsFlowControlHandler.java
@@ -56,7 +56,7 @@
   public void setUP() {
     ArchaiusUtils.resetConfig();
     
QpsControllerManagerTest.clearState(ProviderQpsFlowControlHandler.qpsControllerMgr);
-    Utils.updateProperty(Config.PROVIDER_LIMIT_KEY_PREFIX + "test", 1);
+    ArchaiusUtils.setProperty(Config.PROVIDER_LIMIT_KEY_PREFIX + "test", 1);
   }
 
 
@@ -86,7 +86,7 @@ public void testGlobalQpsControl(final @Injectable Invocation 
invocation,
     ProviderQpsFlowControlHandler gHandler = new 
ProviderQpsFlowControlHandler();
     gHandler.handle(invocation, asyncResp);
 
-    Utils.updateProperty(Config.PROVIDER_LIMIT_KEY_GLOBAL, 3);
+    ArchaiusUtils.setProperty(Config.PROVIDER_LIMIT_KEY_GLOBAL, 3);
 
     expectedException.expect(RuntimeException.class);
     expectedException.expectMessage("test error");
diff --git 
a/providers/provider-springmvc/src/main/java/org/apache/servicecomb/provider/springmvc/reference/UrlWithProviderPrefixClientHttpRequestFactory.java
 
b/providers/provider-springmvc/src/main/java/org/apache/servicecomb/provider/springmvc/reference/UrlWithProviderPrefixClientHttpRequestFactory.java
new file mode 100644
index 000000000..6c7ba67d3
--- /dev/null
+++ 
b/providers/provider-springmvc/src/main/java/org/apache/servicecomb/provider/springmvc/reference/UrlWithProviderPrefixClientHttpRequestFactory.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.provider.springmvc.reference;
+
+import java.io.IOException;
+import java.net.URI;
+
+import org.springframework.http.HttpMethod;
+import org.springframework.http.client.ClientHttpRequest;
+import org.springframework.http.client.ClientHttpRequestFactory;
+
+/**
+ * When deploying in a container, like tomcat, users want to invoke service 
with full path, including container context
+ * root and servlet path.
+ */
+public class UrlWithProviderPrefixClientHttpRequestFactory implements 
ClientHttpRequestFactory {
+  static class UrlWithProviderPrefixClientHttpRequest extends 
CseClientHttpRequest {
+    private String prefix;
+
+    public UrlWithProviderPrefixClientHttpRequest(URI uri, HttpMethod 
httpMethod, String prefix) {
+      super(uri, httpMethod);
+      this.prefix = prefix;
+    }
+
+    @Override
+    protected String findUriPath(URI uri) {
+      return uri.getRawPath().substring(prefix.length());
+    }
+  }
+
+  private String prefix;
+
+  public UrlWithProviderPrefixClientHttpRequestFactory(String prefix) {
+    this.prefix = prefix;
+  }
+
+  @Override
+  public ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod) 
throws IOException {
+    return new UrlWithProviderPrefixClientHttpRequest(uri, httpMethod, prefix);
+  }
+}
diff --git 
a/providers/provider-springmvc/src/test/java/org/apache/servicecomb/provider/springmvc/reference/TestUrlWithProviderPrefixClientHttpRequestFactory.java
 
b/providers/provider-springmvc/src/test/java/org/apache/servicecomb/provider/springmvc/reference/TestUrlWithProviderPrefixClientHttpRequestFactory.java
new file mode 100644
index 000000000..c66684188
--- /dev/null
+++ 
b/providers/provider-springmvc/src/test/java/org/apache/servicecomb/provider/springmvc/reference/TestUrlWithProviderPrefixClientHttpRequestFactory.java
@@ -0,0 +1,80 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.servicecomb.provider.springmvc.reference;
+
+import java.io.IOException;
+import java.net.URI;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.servicecomb.common.rest.RestConst;
+import org.apache.servicecomb.core.Invocation;
+import org.apache.servicecomb.core.definition.OperationMeta;
+import org.apache.servicecomb.core.invocation.InvocationFactory;
+import org.apache.servicecomb.core.provider.consumer.ReferenceConfig;
+import 
org.apache.servicecomb.provider.springmvc.reference.UrlWithProviderPrefixClientHttpRequestFactory.UrlWithProviderPrefixClientHttpRequest;
+import org.apache.servicecomb.swagger.invocation.Response;
+import org.junit.Assert;
+import org.junit.Test;
+import org.springframework.http.HttpMethod;
+
+import mockit.Deencapsulation;
+import mockit.Expectations;
+import mockit.Mocked;
+
+public class TestUrlWithProviderPrefixClientHttpRequestFactory {
+  UrlWithProviderPrefixClientHttpRequestFactory factory = new 
UrlWithProviderPrefixClientHttpRequestFactory("/a/b/c");
+
+  URI uri = URI.create("cse://ms/a/b/c/v1/path");
+
+  @Test
+  public void findUriPath() throws IOException {
+    UrlWithProviderPrefixClientHttpRequest request =
+        (UrlWithProviderPrefixClientHttpRequest) factory.createRequest(uri, 
HttpMethod.GET);
+
+    Assert.assertEquals("/v1/path", request.findUriPath(uri));
+  }
+
+  @Test
+  public void invoke_checkPath(@Mocked Invocation invocation, @Mocked 
RequestMeta requestMeta) {
+    Map<String, String> handlerContext = new HashMap<>();
+    UrlWithProviderPrefixClientHttpRequest request = new 
UrlWithProviderPrefixClientHttpRequest(uri, HttpMethod.GET,
+        "/a/b/c") {
+      @Override
+      protected Response doInvoke(Invocation invocation) {
+        return Response.ok(null);
+      }
+    };
+
+    new Expectations(InvocationFactory.class) {
+      {
+        invocation.getHandlerContext();
+        result = handlerContext;
+        InvocationFactory.forConsumer((ReferenceConfig) any, (OperationMeta) 
any, (Object[]) any);
+        result = invocation;
+      }
+    };
+
+    Deencapsulation.setField(request, "requestMeta", requestMeta);
+    Deencapsulation.setField(request, "path", request.findUriPath(uri));
+
+    Deencapsulation.invoke(request, "invoke", new Object[] {new Object[] {}});
+
+    Assert.assertEquals("/v1/path?null", 
handlerContext.get(RestConst.REST_CLIENT_REQUEST_PATH));
+  }
+}
diff --git a/samples/bmi/build.gradle b/samples/bmi/build.gradle
index 3dfb8b530..3b7365892 100644
--- a/samples/bmi/build.gradle
+++ b/samples/bmi/build.gradle
@@ -19,7 +19,7 @@ allprojects  {
     apply plugin: 'maven'
 
     group = 'org.apache.servicecomb.samples'
-    version = '1.0.0-m2-SNAPSHOT'
+    version = '1.0.0-SNAPSHOT'
 }
 
 buildscript {
diff --git a/samples/bmi/calculator/build.gradle 
b/samples/bmi/calculator/build.gradle
index 16223d9a0..71c00197b 100644
--- a/samples/bmi/calculator/build.gradle
+++ b/samples/bmi/calculator/build.gradle
@@ -44,6 +44,6 @@ apply plugin: 'io.spring.dependency-management'
 
 dependencyManagement {
     imports {
-        mavenBom 
'org.apache.servicecomb:java-chassis-dependencies:1.0.0-m2-SNAPSHOT'
+        mavenBom 
'org.apache.servicecomb:java-chassis-dependencies:1.0.0-SNAPSHOT'
     }
 }
diff --git a/samples/bmi/webapp/build.gradle b/samples/bmi/webapp/build.gradle
index c8973f6b8..1624d9cf5 100644
--- a/samples/bmi/webapp/build.gradle
+++ b/samples/bmi/webapp/build.gradle
@@ -44,6 +44,6 @@ apply plugin: 'io.spring.dependency-management'
 
 dependencyManagement {
     imports {
-        mavenBom 
'org.apache.servicecomb:java-chassis-dependencies:1.0.0-m2-SNAPSHOT'
+        mavenBom 
'org.apache.servicecomb:java-chassis-dependencies:1.0.0-SNAPSHOT'
     }
 }
diff --git a/samples/codefirst-sample/build.gradle 
b/samples/codefirst-sample/build.gradle
index cfff44a76..67a7af595 100644
--- a/samples/codefirst-sample/build.gradle
+++ b/samples/codefirst-sample/build.gradle
@@ -19,7 +19,7 @@ allprojects  {
     apply plugin: 'maven'
 
     group = 'org.apache.servicecomb.samples'
-    version = '1.0.0-m2-SNAPSHOT'
+    version = '1.0.0-SNAPSHOT'
 }
 
 subprojects {
diff --git a/samples/codefirst-sample/codefirst-consumer/build.gradle 
b/samples/codefirst-sample/codefirst-consumer/build.gradle
index 060ad092e..90d4ddc0f 100644
--- a/samples/codefirst-sample/codefirst-consumer/build.gradle
+++ b/samples/codefirst-sample/codefirst-consumer/build.gradle
@@ -21,7 +21,7 @@ dependencies {
     compile group: 'org.apache.servicecomb', name: 'provider-pojo'
     compile group: 'org.apache.servicecomb', name: 'transport-highway'
     compile group: 'org.apache.servicecomb', name: 'transport-rest-vertx'
-    compile group: 'org.apache.servicecomb.samples', name: 'common-schema', 
version: '1.0.0-m2-SNAPSHOT'
+    compile group: 'org.apache.servicecomb.samples', name: 'common-schema', 
version: '1.0.0-SNAPSHOT'
     compile group: 'org.slf4j', name: 'slf4j-log4j12'
 }
 
@@ -46,6 +46,6 @@ apply plugin: 'io.spring.dependency-management'
 
 dependencyManagement {
     imports {
-        mavenBom 
'org.apache.servicecomb:java-chassis-dependencies:1.0.0-m2-SNAPSHOT'
+        mavenBom 
'org.apache.servicecomb:java-chassis-dependencies:1.0.0-SNAPSHOT'
     }
-}
\ No newline at end of file
+}
diff --git a/samples/codefirst-sample/codefirst-provider/build.gradle 
b/samples/codefirst-sample/codefirst-provider/build.gradle
index bb0b845f3..9c85d0717 100644
--- a/samples/codefirst-sample/codefirst-provider/build.gradle
+++ b/samples/codefirst-sample/codefirst-provider/build.gradle
@@ -22,7 +22,7 @@ dependencies {
     compile group: 'org.apache.servicecomb', name: 'provider-springmvc'
     compile group: 'org.apache.servicecomb', name: 'transport-highway'
     compile group: 'org.apache.servicecomb', name: 'transport-rest-vertx'
-    compile group: 'org.apache.servicecomb.samples', name: 'common-schema', 
version: '1.0.0-m2-SNAPSHOT'
+    compile group: 'org.apache.servicecomb.samples', name: 'common-schema', 
version: '1.0.0-SNAPSHOT'
     compile group: 'org.slf4j', name: 'slf4j-log4j12'
 }
 
@@ -47,6 +47,6 @@ apply plugin: 'io.spring.dependency-management'
 
 dependencyManagement {
     imports {
-        mavenBom 
'org.apache.servicecomb:java-chassis-dependencies:1.0.0-m2-SNAPSHOT'
+        mavenBom 
'org.apache.servicecomb:java-chassis-dependencies:1.0.0-SNAPSHOT'
     }
-}
\ No newline at end of file
+}
diff --git a/samples/trust-sample/customer/pom.xml 
b/samples/trust-sample/customer/pom.xml
index 8aa383915..fdabbffd0 100644
--- a/samples/trust-sample/customer/pom.xml
+++ b/samples/trust-sample/customer/pom.xml
@@ -21,7 +21,7 @@
   <parent>
     <groupId>org.apache.servicecomb.samples</groupId>
     <artifactId>trust-sample</artifactId>
-    <version>1.0.0-m2-SNAPSHOT</version>
+    <version>1.0.0-SNAPSHOT</version>
   </parent>
   <artifactId>customer</artifactId>
   <dependencies>
diff --git a/samples/trust-sample/hacker/pom.xml 
b/samples/trust-sample/hacker/pom.xml
index 91c7a3116..8d85ae7ac 100644
--- a/samples/trust-sample/hacker/pom.xml
+++ b/samples/trust-sample/hacker/pom.xml
@@ -21,7 +21,7 @@
   <parent>
     <groupId>org.apache.servicecomb.samples</groupId>
     <artifactId>trust-sample</artifactId>
-    <version>1.0.0-m2-SNAPSHOT</version>
+    <version>1.0.0-SNAPSHOT</version>
   </parent>
   <artifactId>hacker</artifactId>
   <dependencies>
diff --git a/samples/trust-sample/pom.xml b/samples/trust-sample/pom.xml
index d688a54c8..c7790312f 100644
--- a/samples/trust-sample/pom.xml
+++ b/samples/trust-sample/pom.xml
@@ -21,7 +21,7 @@
   <parent>
     <groupId>org.apache.servicecomb.samples</groupId>
     <artifactId>samples</artifactId>
-    <version>1.0.0-m2-SNAPSHOT</version>
+    <version>1.0.0-SNAPSHOT</version>
   </parent>
   <artifactId>trust-sample</artifactId>
   <packaging>pom</packaging>
diff --git a/samples/trust-sample/store/pom.xml 
b/samples/trust-sample/store/pom.xml
index 07e9893f3..24fc1ea82 100644
--- a/samples/trust-sample/store/pom.xml
+++ b/samples/trust-sample/store/pom.xml
@@ -21,7 +21,7 @@
   <parent>
     <groupId>org.apache.servicecomb.samples</groupId>
     <artifactId>trust-sample</artifactId>
-    <version>1.0.0-m2-SNAPSHOT</version>
+    <version>1.0.0-SNAPSHOT</version>
   </parent>
   <artifactId>store</artifactId>
   <dependencies>
diff --git 
a/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/client/LocalServiceRegistryClientImpl.java
 
b/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/client/LocalServiceRegistryClientImpl.java
index 877b886f8..196cd24d3 100644
--- 
a/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/client/LocalServiceRegistryClientImpl.java
+++ 
b/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/client/LocalServiceRegistryClientImpl.java
@@ -171,8 +171,11 @@ public String getMicroserviceId(String appId, String 
microserviceName, String st
 
   @Override
   public String registerMicroservice(Microservice microservice) {
-    String serviceId =
-        microservice.getServiceId() == null ? UUID.randomUUID().toString() : 
microservice.getServiceId();
+    String serviceId = microservice.getServiceId();
+    if (serviceId == null) {
+      serviceId = UUID.randomUUID().toString();
+      microservice.setServiceId(serviceId);
+    }
     microserviceIdMap.put(serviceId, microservice);
 
     microserviceInstanceMap.computeIfAbsent(serviceId, k -> new 
ConcurrentHashMap<>());
diff --git 
a/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/consumer/AppManager.java
 
b/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/consumer/AppManager.java
index 8093ceb5e..7cc45e221 100644
--- 
a/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/consumer/AppManager.java
+++ 
b/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/consumer/AppManager.java
@@ -43,6 +43,10 @@ public MicroserviceVersionFactory 
getMicroserviceVersionFactory() {
     return microserviceVersionFactory;
   }
 
+  public Map<String, MicroserviceManager> getApps() {
+    return apps;
+  }
+
   public void setMicroserviceVersionFactory(MicroserviceVersionFactory 
microserviceVersionFactory) {
     this.microserviceVersionFactory = microserviceVersionFactory;
   }
diff --git 
a/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/consumer/MicroserviceManager.java
 
b/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/consumer/MicroserviceManager.java
index a7bd4ae3d..2d16d0d95 100644
--- 
a/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/consumer/MicroserviceManager.java
+++ 
b/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/consumer/MicroserviceManager.java
@@ -45,6 +45,10 @@ public MicroserviceManager(AppManager appManager, String 
appId) {
     appManager.getEventBus().register(this);
   }
 
+  public Map<String, MicroserviceVersions> getVersionsByName() {
+    return versionsByName;
+  }
+
   public MicroserviceVersions getOrCreateMicroserviceVersions(String 
microserviceName) {
     MicroserviceVersions microserviceVersions = 
versionsByName.computeIfAbsent(microserviceName, name -> {
       MicroserviceVersions instance = new MicroserviceVersions(appManager, 
appId, microserviceName);
diff --git 
a/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/consumer/MicroserviceVersions.java
 
b/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/consumer/MicroserviceVersions.java
index 169328eca..f867f6ae7 100644
--- 
a/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/consumer/MicroserviceVersions.java
+++ 
b/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/consumer/MicroserviceVersions.java
@@ -17,6 +17,7 @@
 
 package org.apache.servicecomb.serviceregistry.consumer;
 
+import java.util.Comparator;
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.atomic.AtomicInteger;
@@ -48,8 +49,15 @@
 
   private String microserviceName;
 
+  // revision and pulledInstances directly equals to SC's response
   private String revision = null;
 
+  private List<MicroserviceInstance> pulledInstances;
+
+  // instances not always equals to pulledInstances
+  // in the future:
+  //  pulledInstances means all instance
+  //  instances means available instance
   private List<MicroserviceInstance> instances;
 
   // key is service id
@@ -101,6 +109,14 @@ public String getMicroserviceName() {
     return (T) versions.get(serviceId);
   }
 
+  public String getRevision() {
+    return revision;
+  }
+
+  public List<MicroserviceInstance> getPulledInstances() {
+    return pulledInstances;
+  }
+
   public void submitPull() {
     pendingPullCount.incrementAndGet();
 
@@ -127,7 +143,9 @@ public void pullInstances() {
     if (!microserviceInstances.isNeedRefresh()) {
       return;
     }
-    List<MicroserviceInstance> pulledInstances = 
microserviceInstances.getInstancesResponse().getInstances();
+
+    pulledInstances = 
microserviceInstances.getInstancesResponse().getInstances();
+    
pulledInstances.sort(Comparator.comparing(MicroserviceInstance::getInstanceId));
     String rev = microserviceInstances.getRevision();
 
     safeSetInstances(pulledInstances, rev);
diff --git 
a/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/diagnosis/Status.java
 
b/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/diagnosis/Status.java
new file mode 100644
index 000000000..47aedd4fd
--- /dev/null
+++ 
b/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/diagnosis/Status.java
@@ -0,0 +1,24 @@
+/*
+ * 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.serviceregistry.diagnosis;
+
+public enum Status {
+  NORMAL,
+  ABNORMAL,
+  UNKNOWN
+}
diff --git 
a/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/diagnosis/instance/InstanceCacheCheckTask.java
 
b/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/diagnosis/instance/InstanceCacheCheckTask.java
new file mode 100644
index 000000000..b6dd6155c
--- /dev/null
+++ 
b/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/diagnosis/instance/InstanceCacheCheckTask.java
@@ -0,0 +1,139 @@
+/*
+ * 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.serviceregistry.diagnosis.instance;
+
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.ScheduledThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.servicecomb.serviceregistry.consumer.AppManager;
+import org.apache.servicecomb.serviceregistry.registry.RemoteServiceRegistry;
+import 
org.apache.servicecomb.serviceregistry.registry.ServiceRegistryTaskInitializer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.eventbus.EventBus;
+import com.netflix.config.DynamicIntProperty;
+import com.netflix.config.DynamicPropertyFactory;
+import com.netflix.config.DynamicStringProperty;
+
+import io.vertx.core.json.Json;
+
+public class InstanceCacheCheckTask implements ServiceRegistryTaskInitializer {
+  private static final Logger LOGGER = 
LoggerFactory.getLogger(InstanceCacheCheckTask.class);
+
+  private static final int DEFAULT_DIAGNOSE_INSTANCE_CACHE_INTERVAL_IN_HOUR = 
24;
+
+  private static final String CONFIG_PREFIX = 
"servicecomb.service.registry.instance.diagnose.";
+
+  public static final String MANUAL = CONFIG_PREFIX + "manual";
+
+  public static final String AUTO_INTERVAL = CONFIG_PREFIX + "interval";
+
+  // auto task
+  private ScheduledFuture<?> scheduledFuture;
+
+  private AppManager appManager;
+
+  private ScheduledThreadPoolExecutor taskPool;
+
+  private EventBus eventBus;
+
+  private DynamicIntProperty autoCheckIntervalProperty;
+
+  private DynamicStringProperty manualCheckProperty;
+
+  private TimeUnit timeUnit = TimeUnit.HOURS;
+
+  // make test easier
+  public void setTimeUnit(TimeUnit timeUnit) {
+    this.timeUnit = timeUnit;
+  }
+
+  public void setAppManager(AppManager appManager) {
+    this.appManager = appManager;
+  }
+
+  public void setTaskPool(ScheduledThreadPoolExecutor taskPool) {
+    this.taskPool = taskPool;
+  }
+
+  public void setEventBus(EventBus eventBus) {
+    this.eventBus = eventBus;
+  }
+
+  public DynamicStringProperty getManualCheckProperty() {
+    return manualCheckProperty;
+  }
+
+  public DynamicIntProperty getAutoCheckIntervalProperty() {
+    return autoCheckIntervalProperty;
+  }
+
+  @Override
+  public void init(RemoteServiceRegistry remoteServiceRegistry) {
+    appManager = remoteServiceRegistry.getAppManager();
+    taskPool = remoteServiceRegistry.getTaskPool();
+    eventBus = remoteServiceRegistry.getEventBus();
+
+    init();
+  }
+
+  protected void init() {
+    startAutoTask();
+    registerManualTask();
+  }
+
+  private void registerManualTask() {
+    // if manual config item changed, then run task once
+    manualCheckProperty = 
DynamicPropertyFactory.getInstance().getStringProperty(MANUAL, null, 
this::runTask);
+  }
+
+  protected void startAutoTask() {
+    autoCheckIntervalProperty = 
DynamicPropertyFactory.getInstance().getIntProperty(AUTO_INTERVAL,
+        DEFAULT_DIAGNOSE_INSTANCE_CACHE_INTERVAL_IN_HOUR,
+        this::doStartAutoTask);
+    doStartAutoTask();
+  }
+
+  private void doStartAutoTask() {
+    if (scheduledFuture != null) {
+      scheduledFuture.cancel(false);
+      scheduledFuture = null;
+    }
+
+    int interval = autoCheckIntervalProperty.get();
+    if (interval <= 0) {
+      LOGGER.info("disable instance cache check task, interval={}.", interval);
+      return;
+    }
+
+    scheduledFuture = taskPool.scheduleAtFixedRate(this::runTask, interval, 
interval, timeUnit);
+  }
+
+  protected void runTask() {
+    try {
+      InstanceCacheChecker checker = new InstanceCacheChecker(appManager);
+      InstanceCacheSummary instanceCacheSummary = checker.check();
+      eventBus.post(instanceCacheSummary);
+
+      LOGGER.info("check instance cache, result={}.", 
Json.encode(instanceCacheSummary));
+    } catch (Throwable e) {
+      LOGGER.error("failed check instance cache..", e);
+    }
+  }
+}
diff --git 
a/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/diagnosis/instance/InstanceCacheChecker.java
 
b/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/diagnosis/instance/InstanceCacheChecker.java
new file mode 100644
index 000000000..8e0e1d7a7
--- /dev/null
+++ 
b/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/diagnosis/instance/InstanceCacheChecker.java
@@ -0,0 +1,140 @@
+/*
+ * 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.serviceregistry.diagnosis.instance;
+
+import java.util.Comparator;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Objects;
+import java.util.Set;
+
+import org.apache.servicecomb.serviceregistry.RegistryUtils;
+import 
org.apache.servicecomb.serviceregistry.api.registry.MicroserviceInstance;
+import 
org.apache.servicecomb.serviceregistry.client.http.MicroserviceInstances;
+import org.apache.servicecomb.serviceregistry.consumer.AppManager;
+import org.apache.servicecomb.serviceregistry.consumer.MicroserviceManager;
+import org.apache.servicecomb.serviceregistry.consumer.MicroserviceVersions;
+import org.apache.servicecomb.serviceregistry.definition.DefinitionConst;
+import org.apache.servicecomb.serviceregistry.diagnosis.Status;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import io.vertx.core.json.Json;
+
+public class InstanceCacheChecker {
+  private static final Logger LOGGER = 
LoggerFactory.getLogger(InstanceCacheChecker.class);
+
+  private AppManager appManager;
+
+  private Set<Status> statuses = new HashSet<>();
+
+  private InstanceCacheSummary instanceCacheSummary = new 
InstanceCacheSummary();
+
+  public InstanceCacheChecker(AppManager appManager) {
+    this.appManager = appManager;
+  }
+
+  public InstanceCacheSummary check() {
+    instanceCacheSummary.setAppId(RegistryUtils.getMicroservice().getAppId());
+    
instanceCacheSummary.setMicroserviceName(RegistryUtils.getMicroservice().getServiceName());
+    instanceCacheSummary.setTimestamp(System.currentTimeMillis());
+
+    for (MicroserviceManager microserviceManager : 
appManager.getApps().values()) {
+      for (MicroserviceVersions microserviceVersions : 
microserviceManager.getVersionsByName().values()) {
+        InstanceCacheResult instanceCacheResult = check(microserviceVersions);
+        addInstanceCacheResult(instanceCacheResult);
+      }
+    }
+
+    generateStatus();
+
+    return instanceCacheSummary;
+  }
+
+  private void addInstanceCacheResult(InstanceCacheResult instanceCacheResult) 
{
+    statuses.add(instanceCacheResult.getStatus());
+    instanceCacheSummary.getProducers().add(instanceCacheResult);
+  }
+
+  protected InstanceCacheResult check(MicroserviceVersions 
microserviceVersions) {
+    InstanceCacheResult instanceCacheResult = new InstanceCacheResult();
+    instanceCacheResult.setAppId(microserviceVersions.getAppId());
+    
instanceCacheResult.setMicroserviceName(microserviceVersions.getMicroserviceName());
+
+    MicroserviceInstances microserviceInstances = RegistryUtils
+        .findServiceInstances(microserviceVersions.getAppId(),
+            microserviceVersions.getMicroserviceName(),
+            DefinitionConst.VERSION_RULE_ALL,
+            null);
+    if (microserviceInstances == null) {
+      instanceCacheResult.setStatus(Status.UNKNOWN);
+      instanceCacheResult.setDetail("failed to find instances from service 
center");
+      return instanceCacheResult;
+    }
+    if (microserviceInstances.isMicroserviceNotExist()) {
+      // no problem, will be deleted from MicroserviceManager in next pull
+      instanceCacheResult.setStatus(Status.UNKNOWN);
+      instanceCacheResult.setDetail("microservice is not exist anymore, will 
be deleted from memory in next pull");
+      return instanceCacheResult;
+    }
+
+    if (!Objects.equals(microserviceInstances.getRevision(), 
microserviceVersions.getRevision())) {
+      // maybe not pull, wait for next pull we get the same revision
+      instanceCacheResult.setStatus(Status.UNKNOWN);
+      instanceCacheResult.setDetail(String.format(
+          "revision is different, will be synchronized in next pull. local 
revision=%s, remote revision=%s",
+          microserviceVersions.getRevision(), 
microserviceInstances.getRevision()));
+      return instanceCacheResult;
+    }
+
+    // compare all instances
+    List<MicroserviceInstance> remoteInstances = 
microserviceInstances.getInstancesResponse().getInstances();
+//    if (RandomUtils.nextInt(0, 2) == 0) {
+//      MicroserviceInstance microserviceInstance = new MicroserviceInstance();
+//      microserviceInstance.setInstanceId("abc");
+//      remoteInstances.add(microserviceInstance);
+//    }
+    
remoteInstances.sort(Comparator.comparing(MicroserviceInstance::getInstanceId));
+    String local = Json.encode(microserviceVersions.getPulledInstances());
+    String remote = Json.encode(remoteInstances);
+    if (local.equals(remote)) {
+      instanceCacheResult.setStatus(Status.NORMAL);
+      return instanceCacheResult;
+    }
+
+    LOGGER.error("instance cache not match. appId={}, microservice={}.\n"
+            + "local cache: {}\n"
+            + "remote cache: {}",
+        microserviceVersions.getAppId(),
+        microserviceVersions.getMicroserviceName(),
+        local,
+        remote);
+    instanceCacheResult.setStatus(Status.ABNORMAL);
+    instanceCacheResult.setDetail("instance cache not match");
+    return instanceCacheResult;
+  }
+
+  protected void generateStatus() {
+    if (statuses.contains(Status.ABNORMAL)) {
+      instanceCacheSummary.setStatus(Status.ABNORMAL);
+    } else if (statuses.contains(Status.UNKNOWN)) {
+      instanceCacheSummary.setStatus(Status.UNKNOWN);
+    } else {
+      instanceCacheSummary.setStatus(Status.NORMAL);
+    }
+  }
+}
diff --git 
a/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/diagnosis/instance/InstanceCacheResult.java
 
b/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/diagnosis/instance/InstanceCacheResult.java
new file mode 100644
index 000000000..a5ae3de63
--- /dev/null
+++ 
b/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/diagnosis/instance/InstanceCacheResult.java
@@ -0,0 +1,62 @@
+/*
+ * 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.serviceregistry.diagnosis.instance;
+
+import org.apache.servicecomb.serviceregistry.diagnosis.Status;
+
+public class InstanceCacheResult {
+  // producer appId and microserviceName
+  private String appId;
+
+  private String microserviceName;
+
+  private Status status;
+
+  private String detail;
+
+  public String getAppId() {
+    return appId;
+  }
+
+  public void setAppId(String appId) {
+    this.appId = appId;
+  }
+
+  public String getMicroserviceName() {
+    return microserviceName;
+  }
+
+  public void setMicroserviceName(String microserviceName) {
+    this.microserviceName = microserviceName;
+  }
+
+  public Status getStatus() {
+    return status;
+  }
+
+  public void setStatus(Status status) {
+    this.status = status;
+  }
+
+  public String getDetail() {
+    return detail;
+  }
+
+  public void setDetail(String detail) {
+    this.detail = detail;
+  }
+}
diff --git 
a/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/diagnosis/instance/InstanceCacheSummary.java
 
b/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/diagnosis/instance/InstanceCacheSummary.java
new file mode 100644
index 000000000..9a02cf8fc
--- /dev/null
+++ 
b/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/diagnosis/instance/InstanceCacheSummary.java
@@ -0,0 +1,79 @@
+/*
+ * 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.serviceregistry.diagnosis.instance;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.servicecomb.serviceregistry.diagnosis.Status;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+
+public class InstanceCacheSummary {
+  // consumer appId and microserviceName
+  @JsonIgnore
+  private String appId;
+
+  @JsonIgnore
+  private String microserviceName;
+
+  private Status status;
+
+  private List<InstanceCacheResult> producers = new ArrayList<>();
+
+  private long timestamp;
+
+  public String getAppId() {
+    return appId;
+  }
+
+  public void setAppId(String appId) {
+    this.appId = appId;
+  }
+
+  public String getMicroserviceName() {
+    return microserviceName;
+  }
+
+  public void setMicroserviceName(String microserviceName) {
+    this.microserviceName = microserviceName;
+  }
+
+  public Status getStatus() {
+    return status;
+  }
+
+  public void setStatus(Status status) {
+    this.status = status;
+  }
+
+  public long getTimestamp() {
+    return timestamp;
+  }
+
+  public void setTimestamp(long timestamp) {
+    this.timestamp = timestamp;
+  }
+
+  public List<InstanceCacheResult> getProducers() {
+    return producers;
+  }
+
+  public void setProducers(List<InstanceCacheResult> producers) {
+    this.producers = producers;
+  }
+}
diff --git 
a/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/registry/RemoteServiceRegistry.java
 
b/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/registry/RemoteServiceRegistry.java
index e6efa79a6..8eb4fb261 100644
--- 
a/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/registry/RemoteServiceRegistry.java
+++ 
b/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/registry/RemoteServiceRegistry.java
@@ -16,9 +16,11 @@
  */
 package org.apache.servicecomb.serviceregistry.registry;
 
+import java.util.List;
 import java.util.concurrent.ScheduledThreadPoolExecutor;
 import java.util.concurrent.TimeUnit;
 
+import org.apache.servicecomb.foundation.common.utils.SPIServiceUtils;
 import org.apache.servicecomb.serviceregistry.client.ServiceRegistryClient;
 import 
org.apache.servicecomb.serviceregistry.client.http.ServiceRegistryClientImpl;
 import org.apache.servicecomb.serviceregistry.config.ServiceRegistryConfig;
@@ -38,6 +40,9 @@
 
   private ScheduledThreadPoolExecutor taskPool;
 
+  private List<ServiceRegistryTaskInitializer> taskInitializers = 
SPIServiceUtils
+      .getOrLoadSortedService(ServiceRegistryTaskInitializer.class);
+
   public RemoteServiceRegistry(EventBus eventBus, ServiceRegistryConfig 
serviceRegistryConfig,
       MicroserviceDefinition microserviceDefinition) {
     super(eventBus, serviceRegistryConfig, microserviceDefinition);
@@ -77,6 +82,10 @@ public void run() {
         serviceRegistryConfig.getInstancePullInterval(),
         serviceRegistryConfig.getInstancePullInterval(),
         TimeUnit.SECONDS);
+
+    for (ServiceRegistryTaskInitializer initializer : taskInitializers) {
+      initializer.init(this);
+    }
   }
 
   @Subscribe
@@ -91,8 +100,7 @@ public void 
onMicroserviceRegistryTask(MicroserviceRegisterTask event) {
     }
   }
 
-  // for testing
-  ScheduledThreadPoolExecutor getTaskPool() {
+  public ScheduledThreadPoolExecutor getTaskPool() {
     return this.taskPool;
   }
 }
diff --git 
a/handlers/handler-flowcontrol-qps/src/test/java/org/apache/servicecomb/qps/Utils.java
 
b/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/registry/ServiceRegistryTaskInitializer.java
similarity index 60%
rename from 
handlers/handler-flowcontrol-qps/src/test/java/org/apache/servicecomb/qps/Utils.java
rename to 
service-registry/src/main/java/org/apache/servicecomb/serviceregistry/registry/ServiceRegistryTaskInitializer.java
index e4ceb5308..21cd84258 100644
--- 
a/handlers/handler-flowcontrol-qps/src/test/java/org/apache/servicecomb/qps/Utils.java
+++ 
b/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/registry/ServiceRegistryTaskInitializer.java
@@ -15,23 +15,12 @@
  * limitations under the License.
  */
 
-package org.apache.servicecomb.qps;
+package org.apache.servicecomb.serviceregistry.registry;
 
-import java.lang.reflect.Method;
-
-import org.springframework.util.ReflectionUtils;
-
-import com.netflix.config.DynamicProperty;
-
-public class Utils {
-  private static Method updatePropertyMethod =
-      ReflectionUtils.findMethod(DynamicProperty.class, "updateProperty", 
String.class, Object.class);
-
-  static {
-    updatePropertyMethod.setAccessible(true);
+public interface ServiceRegistryTaskInitializer {
+  default int getOrder() {
+    return 0;
   }
 
-  public static void updateProperty(String key, Object value) {
-    ReflectionUtils.invokeMethod(updatePropertyMethod, null, key, value);
-  }
+  void init(RemoteServiceRegistry remoteServiceRegistry);
 }
diff --git 
a/service-registry/src/main/resources/META-INF/services/org.apache.servicecomb.serviceregistry.registry.ServiceRegistryTaskInitializer
 
b/service-registry/src/main/resources/META-INF/services/org.apache.servicecomb.serviceregistry.registry.ServiceRegistryTaskInitializer
new file mode 100644
index 000000000..761ee02f5
--- /dev/null
+++ 
b/service-registry/src/main/resources/META-INF/services/org.apache.servicecomb.serviceregistry.registry.ServiceRegistryTaskInitializer
@@ -0,0 +1,18 @@
+#
+# 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.
+#
+
+org.apache.servicecomb.serviceregistry.diagnosis.instance.InstanceCacheCheckTask
diff --git 
a/service-registry/src/test/java/org/apache/servicecomb/serviceregistry/consumer/TestMicroserviceVersions.java
 
b/service-registry/src/test/java/org/apache/servicecomb/serviceregistry/consumer/TestMicroserviceVersions.java
index 8bd0a2d23..9614048ca 100644
--- 
a/service-registry/src/test/java/org/apache/servicecomb/serviceregistry/consumer/TestMicroserviceVersions.java
+++ 
b/service-registry/src/test/java/org/apache/servicecomb/serviceregistry/consumer/TestMicroserviceVersions.java
@@ -73,6 +73,7 @@
 
   @Before
   public void setUp() throws Exception {
+    ArchaiusUtils.resetConfig();
     microserviceInstances = new MicroserviceInstances();
     findInstancesResponse = new FindInstancesResponse();
   }
diff --git 
a/service-registry/src/test/java/org/apache/servicecomb/serviceregistry/diagnosis/instance/TestInstanceCacheCheckTask.java
 
b/service-registry/src/test/java/org/apache/servicecomb/serviceregistry/diagnosis/instance/TestInstanceCacheCheckTask.java
new file mode 100644
index 000000000..862cf6fad
--- /dev/null
+++ 
b/service-registry/src/test/java/org/apache/servicecomb/serviceregistry/diagnosis/instance/TestInstanceCacheCheckTask.java
@@ -0,0 +1,151 @@
+/*
+ * 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.serviceregistry.diagnosis.instance;
+
+import java.util.UUID;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.ScheduledThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+
+import javax.xml.ws.Holder;
+
+import org.apache.servicecomb.foundation.test.scaffolding.config.ArchaiusUtils;
+import org.apache.servicecomb.serviceregistry.consumer.AppManager;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.google.common.eventbus.EventBus;
+import com.google.common.eventbus.Subscribe;
+
+import io.vertx.core.json.Json;
+import mockit.Deencapsulation;
+import mockit.Mock;
+import mockit.MockUp;
+import mockit.Mocked;
+
+public class TestInstanceCacheCheckTask {
+  @Mocked
+  AppManager appManager;
+
+  ScheduledThreadPoolExecutor taskPool = new ScheduledThreadPoolExecutor(2,
+      task -> new Thread(task, "Service Center Task test thread"),
+      (task, executor) -> System.out.println("Too many pending tasks, reject " 
+ task.getClass().getName()));
+
+  EventBus eventBus = new EventBus();
+
+  InstanceCacheCheckTask task = new InstanceCacheCheckTask();
+
+  InstanceCacheSummary result;
+
+  @Before
+  public void setUp() {
+    task.setAppManager(appManager);
+    task.setTaskPool(taskPool);
+    task.setEventBus(eventBus);
+    task.setTimeUnit(TimeUnit.MILLISECONDS);
+
+    new MockUp<InstanceCacheChecker>() {
+      @Mock
+      InstanceCacheSummary check() {
+        return new InstanceCacheSummary();
+      }
+    };
+  }
+
+  @After
+  public void tearDown() throws Exception {
+    ArchaiusUtils.resetConfig();
+    taskPool.shutdownNow();
+  }
+
+  @Test
+  public void manualTask() throws InterruptedException {
+
+    ArchaiusUtils.setProperty(InstanceCacheCheckTask.AUTO_INTERVAL, 0);
+    CountDownLatch latch = new CountDownLatch(1);
+    eventBus.register(new Object() {
+      @Subscribe
+      public void onChecked(InstanceCacheSummary instanceCacheSummary) {
+        result = instanceCacheSummary;
+        latch.countDown();
+      }
+    });
+    task.init();
+
+    ArchaiusUtils.setProperty(InstanceCacheCheckTask.MANUAL, 
UUID.randomUUID().toString());
+    latch.await();
+
+    Assert.assertEquals("{\"status\":null,\"producers\":[],\"timestamp\":0}", 
Json.encode(result));
+  }
+
+  @Test
+  public void autoTask_normal() throws InterruptedException {
+    ArchaiusUtils.setProperty(InstanceCacheCheckTask.AUTO_INTERVAL, 1);
+    CountDownLatch latch = new CountDownLatch(1);
+    eventBus.register(new Object() {
+      @Subscribe
+      public void onChecked(InstanceCacheSummary instanceCacheSummary) {
+        result = instanceCacheSummary;
+        ((ScheduledFuture<?>) Deencapsulation.getField(task, 
"scheduledFuture")).cancel(false);
+        latch.countDown();
+      }
+    });
+    task.init();
+
+    latch.await();
+    Assert.assertNotNull(Deencapsulation.getField(task, "scheduledFuture"));
+    Assert.assertEquals("{\"status\":null,\"producers\":[],\"timestamp\":0}", 
Json.encode(result));
+  }
+
+  @Test
+  public void autoTask_clearOldTask() {
+    Holder<Boolean> cancelResult = new Holder<>();
+    ScheduledFuture<?> scheduledFuture = new MockUp<ScheduledFuture>() {
+      @Mock
+      boolean cancel(boolean mayInterruptIfRunning) {
+        cancelResult.value = true;
+        return true;
+      }
+    }.getMockInstance();
+
+    ArchaiusUtils.setProperty(InstanceCacheCheckTask.AUTO_INTERVAL, 0);
+    Deencapsulation.setField(task, "scheduledFuture", scheduledFuture);
+    task.init();
+
+    Assert.assertNull(Deencapsulation.getField(task, "scheduledFuture"));
+    Assert.assertTrue(cancelResult.value);
+  }
+
+  @Test
+  public void autoTask_invalidIntervalZero() {
+    ArchaiusUtils.setProperty(InstanceCacheCheckTask.AUTO_INTERVAL, 0);
+    task.init();
+
+    Assert.assertNull(Deencapsulation.getField(task, "scheduledFuture"));
+  }
+
+  @Test
+  public void autoTask_invalidIntervalLessThanZero() {
+    ArchaiusUtils.setProperty(InstanceCacheCheckTask.AUTO_INTERVAL, -1);
+    task.init();
+
+    Assert.assertNull(Deencapsulation.getField(task, "scheduledFuture"));
+  }
+}
diff --git 
a/service-registry/src/test/java/org/apache/servicecomb/serviceregistry/diagnosis/instance/TestInstanceCacheChecker.java
 
b/service-registry/src/test/java/org/apache/servicecomb/serviceregistry/diagnosis/instance/TestInstanceCacheChecker.java
new file mode 100644
index 000000000..7ffd600fe
--- /dev/null
+++ 
b/service-registry/src/test/java/org/apache/servicecomb/serviceregistry/diagnosis/instance/TestInstanceCacheChecker.java
@@ -0,0 +1,244 @@
+/*
+ * 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.serviceregistry.diagnosis.instance;
+
+import java.util.ArrayList;
+
+import javax.xml.ws.Holder;
+
+import org.apache.servicecomb.serviceregistry.RegistryUtils;
+import org.apache.servicecomb.serviceregistry.ServiceRegistry;
+import org.apache.servicecomb.serviceregistry.api.registry.Microservice;
+import 
org.apache.servicecomb.serviceregistry.api.registry.MicroserviceInstance;
+import 
org.apache.servicecomb.serviceregistry.api.response.FindInstancesResponse;
+import 
org.apache.servicecomb.serviceregistry.client.http.MicroserviceInstances;
+import org.apache.servicecomb.serviceregistry.definition.DefinitionConst;
+import org.apache.servicecomb.serviceregistry.diagnosis.Status;
+import org.apache.servicecomb.serviceregistry.registry.ServiceRegistryFactory;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import io.vertx.core.json.Json;
+import mockit.Mock;
+import mockit.MockUp;
+
+public class TestInstanceCacheChecker {
+  ServiceRegistry serviceRegistry = ServiceRegistryFactory.createLocal();
+
+  InstanceCacheChecker checker;
+
+  InstanceCacheSummary expectedSummary = new InstanceCacheSummary();
+
+  String appId = "appId";
+
+  String microserviceName = "msName";
+
+  @Before
+  public void setUp() throws Exception {
+    serviceRegistry.init();
+    RegistryUtils.setServiceRegistry(serviceRegistry);
+
+    checker = new InstanceCacheChecker(serviceRegistry.getAppManager());
+    expectedSummary.setStatus(Status.NORMAL);
+    expectedSummary.setTimestamp(1);
+
+    new MockUp<System>() {
+      @Mock
+      long currentTimeMillis() {
+        return 1L;
+      }
+    };
+  }
+
+  @After
+  public void tearDown() throws Exception {
+    RegistryUtils.setServiceRegistry(null);
+  }
+
+  @Test
+  public void check_appManager_empty() {
+    InstanceCacheSummary instanceCacheSummary = checker.check();
+
+    Assert.assertEquals(Json.encode(expectedSummary), 
Json.encode(instanceCacheSummary));
+  }
+
+  @Test
+  public void check_microserviceManager_empty() {
+    appId = "notExist";
+    serviceRegistry.getAppManager().getOrCreateMicroserviceVersions(appId, 
microserviceName);
+    InstanceCacheSummary instanceCacheSummary = checker.check();
+
+    InstanceCacheResult instanceCacheResult = new InstanceCacheResult();
+    instanceCacheResult.setAppId(appId);
+    instanceCacheResult.setMicroserviceName(microserviceName);
+    instanceCacheResult.setStatus(Status.NORMAL);
+
+    Assert.assertEquals(Json.encode(expectedSummary), 
Json.encode(instanceCacheSummary));
+  }
+
+  protected Holder<MicroserviceInstances> createFindServiceInstancesResult() {
+    MicroserviceInstances microserviceInstances = new MicroserviceInstances();
+    microserviceInstances.setNeedRefresh(true);
+    microserviceInstances.setRevision("first");
+    FindInstancesResponse findInstancesResponse = new FindInstancesResponse();
+    findInstancesResponse.setInstances(new ArrayList<>());
+    microserviceInstances.setInstancesResponse(findInstancesResponse);
+
+    Holder<MicroserviceInstances> findHolder = new Holder<>();
+    findHolder.value = microserviceInstances;
+    return findHolder;
+  }
+
+  protected void registerMicroservice(String appId, String microserviceName) {
+    Microservice microservice = new Microservice();
+    microservice.setAppId(appId);
+    microservice.setServiceName(microserviceName);
+    microservice.setVersion("1.0.0");
+
+    
serviceRegistry.getServiceRegistryClient().registerMicroservice(microservice);
+  }
+
+  @Test
+  public void check_findInstances_failed() {
+    Holder<MicroserviceInstances> findHolder = 
createFindServiceInstancesResult();
+
+    new MockUp<RegistryUtils>() {
+      @Mock
+      MicroserviceInstances findServiceInstances(String appId, String 
serviceName,
+          String versionRule, String revision) {
+        return findHolder.value;
+      }
+    };
+
+    registerMicroservice(appId, microserviceName);
+
+    serviceRegistry.getAppManager()
+        .getOrCreateMicroserviceVersionRule(appId, microserviceName, 
DefinitionConst.VERSION_RULE_ALL);
+
+    findHolder.value = null;
+    InstanceCacheSummary instanceCacheSummary = checker.check();
+
+    InstanceCacheResult instanceCacheResult = new InstanceCacheResult();
+    instanceCacheResult.setAppId(appId);
+    instanceCacheResult.setMicroserviceName(microserviceName);
+    instanceCacheResult.setStatus(Status.UNKNOWN);
+    instanceCacheResult.setDetail("failed to find instances from service 
center");
+    expectedSummary.getProducers().add(instanceCacheResult);
+    expectedSummary.setStatus(Status.UNKNOWN);
+
+    Assert.assertEquals(Json.encode(expectedSummary), 
Json.encode(instanceCacheSummary));
+  }
+
+  @Test
+  public void check_findInstances_serviceNotExist() {
+    Holder<MicroserviceInstances> findHolder = 
createFindServiceInstancesResult();
+
+    new MockUp<RegistryUtils>() {
+      @Mock
+      MicroserviceInstances findServiceInstances(String appId, String 
serviceName,
+          String versionRule, String revision) {
+        return findHolder.value;
+      }
+    };
+
+    registerMicroservice(appId, microserviceName);
+
+    serviceRegistry.getAppManager()
+        .getOrCreateMicroserviceVersionRule(appId, microserviceName, 
DefinitionConst.VERSION_RULE_ALL);
+
+    findHolder.value.setMicroserviceNotExist(true);
+    InstanceCacheSummary instanceCacheSummary = checker.check();
+
+    InstanceCacheResult instanceCacheResult = new InstanceCacheResult();
+    instanceCacheResult.setAppId(appId);
+    instanceCacheResult.setMicroserviceName(microserviceName);
+    instanceCacheResult.setStatus(Status.UNKNOWN);
+    instanceCacheResult.setDetail("microservice is not exist anymore, will be 
deleted from memory in next pull");
+    expectedSummary.getProducers().add(instanceCacheResult);
+    expectedSummary.setStatus(Status.UNKNOWN);
+
+    Assert.assertEquals(Json.encode(expectedSummary), 
Json.encode(instanceCacheSummary));
+  }
+
+  @Test
+  public void check_findInstances_revisionNotMatch() {
+    Holder<MicroserviceInstances> findHolder = 
createFindServiceInstancesResult();
+
+    new MockUp<RegistryUtils>() {
+      @Mock
+      MicroserviceInstances findServiceInstances(String appId, String 
serviceName,
+          String versionRule, String revision) {
+        return findHolder.value;
+      }
+    };
+
+    registerMicroservice(appId, microserviceName);
+
+    serviceRegistry.getAppManager()
+        .getOrCreateMicroserviceVersionRule(appId, microserviceName, 
DefinitionConst.VERSION_RULE_ALL);
+
+    findHolder.value.setRevision("second");
+    InstanceCacheSummary instanceCacheSummary = checker.check();
+
+    InstanceCacheResult instanceCacheResult = new InstanceCacheResult();
+    instanceCacheResult.setAppId(appId);
+    instanceCacheResult.setMicroserviceName(microserviceName);
+    instanceCacheResult.setStatus(Status.UNKNOWN);
+    instanceCacheResult.setDetail(
+        "revision is different, will be synchronized in next pull. local 
revision=first, remote revision=second");
+    expectedSummary.getProducers().add(instanceCacheResult);
+    expectedSummary.setStatus(Status.UNKNOWN);
+
+    Assert.assertEquals(Json.encode(expectedSummary), 
Json.encode(instanceCacheSummary));
+  }
+
+  @Test
+  public void check_findInstances_cacheNotMatch() {
+    Holder<MicroserviceInstances> findHolder = 
createFindServiceInstancesResult();
+
+    new MockUp<RegistryUtils>() {
+      @Mock
+      MicroserviceInstances findServiceInstances(String appId, String 
serviceName,
+          String versionRule, String revision) {
+        return findHolder.value;
+      }
+    };
+
+    registerMicroservice(appId, microserviceName);
+
+    serviceRegistry.getAppManager()
+        .getOrCreateMicroserviceVersionRule(appId, microserviceName, 
DefinitionConst.VERSION_RULE_ALL);
+
+    Holder<MicroserviceInstances> newFindHolder = 
createFindServiceInstancesResult();
+    newFindHolder.value.getInstancesResponse().getInstances().add(new 
MicroserviceInstance());
+    findHolder.value = newFindHolder.value;
+    InstanceCacheSummary instanceCacheSummary = checker.check();
+
+    InstanceCacheResult instanceCacheResult = new InstanceCacheResult();
+    instanceCacheResult.setAppId(appId);
+    instanceCacheResult.setMicroserviceName(microserviceName);
+    instanceCacheResult.setStatus(Status.ABNORMAL);
+    instanceCacheResult.setDetail(
+        "instance cache not match");
+    expectedSummary.getProducers().add(instanceCacheResult);
+    expectedSummary.setStatus(Status.ABNORMAL);
+
+    Assert.assertEquals(Json.encode(expectedSummary), 
Json.encode(instanceCacheSummary));
+  }
+}
diff --git 
a/service-registry/src/test/java/org/apache/servicecomb/serviceregistry/registry/TestLocalServiceRegistry.java
 
b/service-registry/src/test/java/org/apache/servicecomb/serviceregistry/registry/TestLocalServiceRegistry.java
index d4d2b5d15..3b01fe885 100644
--- 
a/service-registry/src/test/java/org/apache/servicecomb/serviceregistry/registry/TestLocalServiceRegistry.java
+++ 
b/service-registry/src/test/java/org/apache/servicecomb/serviceregistry/registry/TestLocalServiceRegistry.java
@@ -100,4 +100,20 @@ public void testSchema() {
     String content = 
serviceRegistry.getServiceRegistryClient().getSchema(microservice.getServiceId(),
 "s1");
     Assert.assertEquals("s1-content", content);
   }
+
+  @Test
+  public void registerMicroservice() {
+    ServiceRegistry serviceRegistry = ServiceRegistryFactory.createLocal();
+    serviceRegistry.init();
+    serviceRegistry.run();
+    
+    Microservice microservice = new Microservice();
+    microservice.setAppId("appId");
+    microservice.setServiceName("msName");
+
+    String serviceId = 
serviceRegistry.getServiceRegistryClient().registerMicroservice(microservice);
+    Microservice remoteMicroservice = 
serviceRegistry.getRemoteMicroservice(serviceId);
+
+    Assert.assertEquals(serviceId, remoteMicroservice.getServiceId());
+  }
 }
diff --git 
a/service-registry/src/test/java/org/apache/servicecomb/serviceregistry/registry/TestRemoteServiceRegistry.java
 
b/service-registry/src/test/java/org/apache/servicecomb/serviceregistry/registry/TestRemoteServiceRegistry.java
index d46ef932f..73483fac1 100644
--- 
a/service-registry/src/test/java/org/apache/servicecomb/serviceregistry/registry/TestRemoteServiceRegistry.java
+++ 
b/service-registry/src/test/java/org/apache/servicecomb/serviceregistry/registry/TestRemoteServiceRegistry.java
@@ -17,12 +17,15 @@
 package org.apache.servicecomb.serviceregistry.registry;
 
 import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.ScheduledFuture;
 import java.util.concurrent.ScheduledThreadPoolExecutor;
 import java.util.concurrent.TimeUnit;
 
 import org.apache.servicecomb.config.ConfigUtil;
 import org.apache.servicecomb.foundation.common.net.IpPort;
+import org.apache.servicecomb.foundation.common.utils.SPIServiceUtils;
 import org.apache.servicecomb.serviceregistry.RegistryUtils;
 import org.apache.servicecomb.serviceregistry.ServiceRegistry;
 import 
org.apache.servicecomb.serviceregistry.client.LocalServiceRegistryClientImpl;
@@ -65,12 +68,20 @@ protected ServiceRegistryClient 
createServiceRegistryClient() {
 
   @Test
   public void testLifeCycle(@Injectable ServiceRegistryConfig config, 
@Injectable MicroserviceDefinition definition,
-      @Injectable ServiceRegistry registry) {
+      @Injectable ServiceRegistry registry) throws InterruptedException {
     ArrayList<IpPort> ipPortList = new ArrayList<>();
     ipPortList.add(new IpPort("127.0.0.1", 9980));
     ipPortList.add(new IpPort("127.0.0.1", 9981));
 
-    new Expectations() {
+    CountDownLatch latch = new CountDownLatch(1);
+    ServiceRegistryTaskInitializer initializer = new 
MockUp<ServiceRegistryTaskInitializer>() {
+      @Mock
+      void init(RemoteServiceRegistry remoteServiceRegistry) {
+        latch.countDown();
+      }
+    }.getMockInstance();
+
+    new Expectations(SPIServiceUtils.class) {
       {
         definition.getConfiguration();
         result = ConfigUtil.createLocalConfig();
@@ -86,6 +97,8 @@ public void testLifeCycle(@Injectable ServiceRegistryConfig 
config, @Injectable
         result = 30;
         config.isWatch();
         result = false;
+        
SPIServiceUtils.getOrLoadSortedService(ServiceRegistryTaskInitializer.class);
+        result = Arrays.asList(initializer);
       }
     };
 
@@ -95,6 +108,10 @@ public void testLifeCycle(@Injectable ServiceRegistryConfig 
config, @Injectable
     RemoteServiceRegistry remote = new TestingRemoteServiceRegistry(bus, 
config, definition);
     remote.init();
     remote.run();
+
+    // should not block
+    latch.await();
+
     Assert.assertTrue(2 <= remote.getTaskPool().getTaskCount()); // includes 
complete tasks
 
     bus.post(new ShutdownEvent());
@@ -102,7 +119,6 @@ public void testLifeCycle(@Injectable ServiceRegistryConfig 
config, @Injectable
     remote.getTaskPool().schedule(new Runnable() {
       @Override
       public void run() {
-        // TODO Auto-generated method stub
 
       }
     }, 0, TimeUnit.SECONDS);


 

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


> provide a way to invoke service with full path
> ----------------------------------------------
>
>                 Key: SCB-760
>                 URL: https://issues.apache.org/jira/browse/SCB-760
>             Project: Apache ServiceComb
>          Issue Type: New Feature
>            Reporter: liubao
>            Assignee: liubao
>            Priority: Major
>
>  When deploying in a container, like tomcat, users want to invoke service 
> with full path, including container context
> root and servlet path.



--
This message was sent by Atlassian JIRA
(v7.6.3#76005)

Reply via email to