You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@servicecomb.apache.org by ni...@apache.org on 2018/01/09 08:38:57 UTC

[incubator-servicecomb-java-chassis] branch master updated: [SCB-209] pullTask, use rev to ensure data consistency and reduce service center work load (#479)

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

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


The following commit(s) were added to refs/heads/master by this push:
     new 4098a7d  [SCB-209] pullTask,use rev to ensure data consistency and reduce service center work load (#479)
4098a7d is described below

commit 4098a7d6b0cd436599b85288ab62142fad08dcd2
Author: weichao <30...@users.noreply.github.com>
AuthorDate: Tue Jan 9 16:38:55 2018 +0800

    [SCB-209] pullTask,use rev to ensure data consistency and reduce service center work load (#479)
    
    * [JAV-558] pullTask,use rev to ensure data consistency and reduce service center work load
    
    * delete the copy code, dealing with conflict
    
    * set local revision change
---
 .../servicecomb/serviceregistry/RegistryUtils.java |  6 ++
 .../serviceregistry/ServiceRegistry.java           |  4 ++
 .../client/LocalServiceRegistryClientImpl.java     | 37 +++++++++-
 .../client/ServiceRegistryClient.java              |  8 +++
 .../client/http/MicroserviceInstances.java         | 56 ++++++++++++++++
 .../client/http/ServiceRegistryClientImpl.java     | 69 ++++++++++++++++---
 .../consumer/MicroserviceVersions.java             | 20 ++++--
 .../registry/AbstractServiceRegistry.java          | 23 +++++--
 .../servicecomb/serviceregistry/TestRegistry.java  |  6 ++
 .../client/LocalServiceRegistryClientImplTest.java | 18 +++++
 .../client/http/TestClientHttp.java                |  6 ++
 .../client/http/TestMicroserviceInstances.java     | 78 ++++++++++++++++++++++
 .../client/http/TestServiceRegistryClientImpl.java |  2 +
 .../serviceregistry/consumer/TestAppManager.java   | 30 +++++++--
 .../consumer/TestMicroserviceManager.java          | 26 +++++++-
 .../consumer/TestMicroserviceVersions.java         | 44 +++++++++---
 16 files changed, 398 insertions(+), 35 deletions(-)

diff --git a/service-registry/src/main/java/io/servicecomb/serviceregistry/RegistryUtils.java b/service-registry/src/main/java/io/servicecomb/serviceregistry/RegistryUtils.java
index 598e7ef..15b7c5e 100644
--- a/service-registry/src/main/java/io/servicecomb/serviceregistry/RegistryUtils.java
+++ b/service-registry/src/main/java/io/servicecomb/serviceregistry/RegistryUtils.java
@@ -38,6 +38,7 @@ import io.servicecomb.serviceregistry.api.registry.Microservice;
 import io.servicecomb.serviceregistry.api.registry.MicroserviceInstance;
 import io.servicecomb.serviceregistry.cache.InstanceCacheManager;
 import io.servicecomb.serviceregistry.client.ServiceRegistryClient;
+import io.servicecomb.serviceregistry.client.http.MicroserviceInstances;
 import io.servicecomb.serviceregistry.config.ServiceRegistryConfig;
 import io.servicecomb.serviceregistry.definition.MicroserviceDefinition;
 import io.servicecomb.serviceregistry.registry.ServiceRegistryFactory;
@@ -215,4 +216,9 @@ public final class RegistryUtils {
   public static Microservice getMicroservice(String microserviceId) {
     return serviceRegistry.getRemoteMicroservice(microserviceId);
   }
+
+  public static MicroserviceInstances findServiceInstances(String appId, String serviceName,
+      String versionRule, String revision) {
+    return serviceRegistry.findServiceInstances(appId, serviceName, versionRule, revision);
+  }
 }
diff --git a/service-registry/src/main/java/io/servicecomb/serviceregistry/ServiceRegistry.java b/service-registry/src/main/java/io/servicecomb/serviceregistry/ServiceRegistry.java
index 0dd0224..9809c94 100644
--- a/service-registry/src/main/java/io/servicecomb/serviceregistry/ServiceRegistry.java
+++ b/service-registry/src/main/java/io/servicecomb/serviceregistry/ServiceRegistry.java
@@ -24,6 +24,7 @@ import io.servicecomb.serviceregistry.api.registry.Microservice;
 import io.servicecomb.serviceregistry.api.registry.MicroserviceInstance;
 import io.servicecomb.serviceregistry.cache.InstanceCacheManager;
 import io.servicecomb.serviceregistry.client.ServiceRegistryClient;
+import io.servicecomb.serviceregistry.client.http.MicroserviceInstances;
 import io.servicecomb.serviceregistry.consumer.AppManager;
 
 public interface ServiceRegistry {
@@ -48,6 +49,9 @@ public interface ServiceRegistry {
   List<MicroserviceInstance> findServiceInstance(String appId, String microserviceName,
       String microserviceVersionRule);
 
+  MicroserviceInstances findServiceInstances(String appId, String microserviceName,
+      String microserviceVersionRule, String revision);
+
   boolean updateMicroserviceProperties(Map<String, String> properties);
 
   boolean updateInstanceProperties(Map<String, String> instanceProperties);
diff --git a/service-registry/src/main/java/io/servicecomb/serviceregistry/client/LocalServiceRegistryClientImpl.java b/service-registry/src/main/java/io/servicecomb/serviceregistry/client/LocalServiceRegistryClientImpl.java
index 0691af1..83fcc39 100644
--- a/service-registry/src/main/java/io/servicecomb/serviceregistry/client/LocalServiceRegistryClientImpl.java
+++ b/service-registry/src/main/java/io/servicecomb/serviceregistry/client/LocalServiceRegistryClientImpl.java
@@ -29,6 +29,7 @@ import java.util.Map;
 import java.util.Map.Entry;
 import java.util.UUID;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicInteger;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -38,8 +39,10 @@ import org.yaml.snakeyaml.Yaml;
 import io.servicecomb.foundation.vertx.AsyncResultCallback;
 import io.servicecomb.serviceregistry.api.registry.Microservice;
 import io.servicecomb.serviceregistry.api.registry.MicroserviceInstance;
+import io.servicecomb.serviceregistry.api.response.FindInstancesResponse;
 import io.servicecomb.serviceregistry.api.response.HeartbeatResponse;
 import io.servicecomb.serviceregistry.api.response.MicroserviceInstanceChangedEvent;
+import io.servicecomb.serviceregistry.client.http.MicroserviceInstances;
 import io.servicecomb.serviceregistry.version.Version;
 import io.servicecomb.serviceregistry.version.VersionRule;
 import io.servicecomb.serviceregistry.version.VersionRuleUtils;
@@ -59,6 +62,8 @@ public class LocalServiceRegistryClientImpl implements ServiceRegistryClient {
   // second key is instance id
   private Map<String, Map<String, MicroserviceInstance>> microserviceInstanceMap = new ConcurrentHashMap<>();
 
+  private AtomicInteger revision = new AtomicInteger(0);
+
   public LocalServiceRegistryClientImpl() {
     if (StringUtils.isEmpty(LOCAL_REGISTRY_FILE)) {
       LOGGER.info("create empty local registry.");
@@ -123,6 +128,10 @@ public class LocalServiceRegistryClientImpl implements ServiceRegistryClient {
         microserviceInstanceMap.put(microservice.getServiceId(), instanceMap);
       }
     }
+
+    if(!data.isEmpty()) {
+      revision.incrementAndGet();
+    }
   }
 
   @Override
@@ -149,6 +158,7 @@ public class LocalServiceRegistryClientImpl implements ServiceRegistryClient {
     microserviceIdMap.put(serviceId, microservice);
 
     microserviceInstanceMap.computeIfAbsent(serviceId, k -> new ConcurrentHashMap<>());
+    revision.incrementAndGet();
     return serviceId;
   }
 
@@ -167,6 +177,7 @@ public class LocalServiceRegistryClientImpl implements ServiceRegistryClient {
     String instanceId =
         instance.getInstanceId() == null ? UUID.randomUUID().toString() : instance.getInstanceId();
     instanceMap.put(instanceId, instance);
+    revision.incrementAndGet();
     return instanceId;
   }
 
@@ -185,6 +196,7 @@ public class LocalServiceRegistryClientImpl implements ServiceRegistryClient {
     Map<String, MicroserviceInstance> instanceMap = microserviceInstanceMap.get(microserviceId);
     if (instanceMap != null) {
       instanceMap.remove(microserviceInstanceId);
+      revision.getAndIncrement();
     }
     return true;
   }
@@ -240,12 +252,31 @@ public class LocalServiceRegistryClientImpl implements ServiceRegistryClient {
   @Override
   public List<MicroserviceInstance> findServiceInstance(String selfMicroserviceId, String appId, String serviceName,
       String strVersionRule) {
+    MicroserviceInstances instances =
+        findServiceInstances(selfMicroserviceId, appId, serviceName, strVersionRule, null);
+    return instances.getInstancesResponse().getInstances();
+  }
+
+  @Override
+  public MicroserviceInstances findServiceInstances(String selfMicroserviceId, String appId, String serviceName,
+      String strVersionRule, String revision) {
+
+    int currentRevision = this.revision.get();
     List<MicroserviceInstance> allInstances = new ArrayList<>();
+    MicroserviceInstances microserviceInstances = new MicroserviceInstances();
+    FindInstancesResponse response = new FindInstancesResponse();
+    if (revision != null && currentRevision == Integer.parseInt(revision)) {
+      microserviceInstances.setNeedRefresh(false);
+      return microserviceInstances;
+    }
 
+    microserviceInstances.setRevision(String.valueOf(currentRevision));
     VersionRule versionRule = VersionRuleUtils.getOrCreate(strVersionRule);
     Microservice latestMicroservice = findLatest(appId, serviceName, versionRule);
     if (latestMicroservice == null) {
-      return allInstances;
+      response.setInstances(allInstances);
+      microserviceInstances.setInstancesResponse(response);
+      return microserviceInstances;
     }
 
     Version latestVersion = VersionUtils.getOrCreate(latestMicroservice.getVersion());
@@ -263,8 +294,10 @@ public class LocalServiceRegistryClientImpl implements ServiceRegistryClient {
       Map<String, MicroserviceInstance> instances = microserviceInstanceMap.get(entry.getValue().getServiceId());
       allInstances.addAll(instances.values());
     }
+    response.setInstances(allInstances);
+    microserviceInstances.setInstancesResponse(response);
 
-    return allInstances;
+    return microserviceInstances;
   }
 
   @Override
diff --git a/service-registry/src/main/java/io/servicecomb/serviceregistry/client/ServiceRegistryClient.java b/service-registry/src/main/java/io/servicecomb/serviceregistry/client/ServiceRegistryClient.java
index 1c9b750..03376d9 100644
--- a/service-registry/src/main/java/io/servicecomb/serviceregistry/client/ServiceRegistryClient.java
+++ b/service-registry/src/main/java/io/servicecomb/serviceregistry/client/ServiceRegistryClient.java
@@ -25,6 +25,7 @@ import io.servicecomb.serviceregistry.api.registry.Microservice;
 import io.servicecomb.serviceregistry.api.registry.MicroserviceInstance;
 import io.servicecomb.serviceregistry.api.response.HeartbeatResponse;
 import io.servicecomb.serviceregistry.api.response.MicroserviceInstanceChangedEvent;
+import io.servicecomb.serviceregistry.client.http.MicroserviceInstances;
 
 public interface ServiceRegistryClient {
   void init();
@@ -124,6 +125,13 @@ public interface ServiceRegistryClient {
    */
   List<MicroserviceInstance> findServiceInstance(String consumerId, String appId, String serviceName,
       String versionRule);
+
+  /**
+  *
+  * 按照app+interface+version+revision查询实例endpoints信息
+  */
+ MicroserviceInstances findServiceInstances(String consumerId, String appId, String serviceName,
+     String versionRule, String revision);
   
   /**
    * 通过serviceId, instanceId 获取instance对象。
diff --git a/service-registry/src/main/java/io/servicecomb/serviceregistry/client/http/MicroserviceInstances.java b/service-registry/src/main/java/io/servicecomb/serviceregistry/client/http/MicroserviceInstances.java
new file mode 100644
index 0000000..bba165d
--- /dev/null
+++ b/service-registry/src/main/java/io/servicecomb/serviceregistry/client/http/MicroserviceInstances.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 io.servicecomb.serviceregistry.client.http;
+
+import io.servicecomb.serviceregistry.api.response.FindInstancesResponse;
+
+/**
+ * Created by on 2017/12/28.
+ */
+public class MicroserviceInstances {
+  private boolean needRefresh = true;
+
+  private String revision;
+
+  private FindInstancesResponse instancesResponse;
+
+  public boolean isNeedRefresh() {
+    return needRefresh;
+  }
+
+  public void setNeedRefresh(boolean needRefresh) {
+    this.needRefresh = needRefresh;
+  }
+
+  public String getRevision() {
+    return revision;
+  }
+
+  public void setRevision(String revision) {
+    this.revision = revision;
+  }
+
+  public FindInstancesResponse getInstancesResponse() {
+    return instancesResponse;
+  }
+
+  public void setInstancesResponse(FindInstancesResponse instancesResponse) {
+    this.instancesResponse = instancesResponse;
+  }
+
+}
diff --git a/service-registry/src/main/java/io/servicecomb/serviceregistry/client/http/ServiceRegistryClientImpl.java b/service-registry/src/main/java/io/servicecomb/serviceregistry/client/http/ServiceRegistryClientImpl.java
index 3a5e84f..dbc4cbe 100644
--- a/service-registry/src/main/java/io/servicecomb/serviceregistry/client/http/ServiceRegistryClientImpl.java
+++ b/service-registry/src/main/java/io/servicecomb/serviceregistry/client/http/ServiceRegistryClientImpl.java
@@ -152,6 +152,36 @@ public final class ServiceRegistryClientImpl implements ServiceRegistryClient {
     };
   }
 
+  private <T> Handler<RestResponse> syncHandlerForInstances(CountDownLatch countDownLatch, MicroserviceInstances mInstances) {
+    return restResponse -> {
+      RequestContext requestContext = restResponse.getRequestContext();
+      HttpClientResponse response = restResponse.getResponse();
+      if (response == null) {
+        // 请求失败,触发请求SC的其他实例
+        if (!requestContext.isRetry()) {
+          retry(requestContext, syncHandlerForInstances(countDownLatch, mInstances));
+        } else {
+          countDownLatch.countDown();
+        }
+        return;
+      }
+      response.bodyHandler(
+          bodyBuffer -> {
+            try {
+              mInstances.setRevision(response.getHeader("X-Resource-Revision"));
+              if (response.statusCode() == 304) {
+                mInstances.setNeedRefresh(false);
+              } else {
+                mInstances.setInstancesResponse(JsonUtils.readValue(bodyBuffer.getBytes(), FindInstancesResponse.class));
+              }
+            } catch (Exception e) {
+              LOGGER.warn(bodyBuffer.toString(), e);
+            }
+            countDownLatch.countDown();
+          });
+    };
+  }
+
   @Override
   public List<Microservice> getAllMicroservices() {
     Holder<GetAllServicesResponse> holder = new Holder<>();
@@ -519,27 +549,46 @@ public final class ServiceRegistryClientImpl implements ServiceRegistryClient {
   @Override
   public List<MicroserviceInstance> findServiceInstance(String consumerId, String appId, String serviceName,
       String versionRule) {
-    Holder<FindInstancesResponse> holder = new Holder<>();
+    MicroserviceInstances instances = findServiceInstances(consumerId, appId, serviceName, versionRule, null);
+    if (instances == null) {
+      return null;
+    }
+    return instances.getInstancesResponse().getInstances();
+  }
+
+  @Override
+  public MicroserviceInstances findServiceInstances(String consumerId, String appId, String serviceName,
+      String versionRule, String revision) {
+    MicroserviceInstances microserviceInstances = new MicroserviceInstances();
     IpPort ipPort = ipPortManager.getAvailableAddress();
 
     CountDownLatch countDownLatch = new CountDownLatch(1);
+    
+    RequestParam requestParam = new RequestParam().addQueryParam("appId", appId)
+    .addQueryParam("serviceName", serviceName)
+    .addQueryParam("version", versionRule)
+    .addHeader("X-ConsumerId", consumerId);
+    if(revision != null) {
+      requestParam.addQueryParam("rev", revision);
+    }
+    
     RestUtils.get(ipPort,
         Const.REGISTRY_API.MICROSERVICE_INSTANCES,
-        new RequestParam().addQueryParam("appId", appId)
-            .addQueryParam("serviceName", serviceName)
-            .addQueryParam("version", versionRule)
-            .addHeader("X-ConsumerId", consumerId),
-        syncHandler(countDownLatch, FindInstancesResponse.class, holder));
+        requestParam,
+        syncHandlerForInstances(countDownLatch, microserviceInstances));
     try {
       countDownLatch.await();
-      if (holder.value == null) {
+      if (!microserviceInstances.isNeedRefresh()) {
+        return microserviceInstances;
+      }
+      if (microserviceInstances.getInstancesResponse() == null) {
         return null; // error
       }
-      List<MicroserviceInstance> list = holder.value.getInstances();
+      List<MicroserviceInstance> list = microserviceInstances.getInstancesResponse().getInstances();
       if (list == null) {
-        return new ArrayList<>();
+        microserviceInstances.getInstancesResponse().setInstances(new ArrayList<>());
       }
-      return list;
+      return microserviceInstances;
     } catch (Exception e) {
       LOGGER.error("find microservice instance {}/{}/{} failed",
           appId,
diff --git a/service-registry/src/main/java/io/servicecomb/serviceregistry/consumer/MicroserviceVersions.java b/service-registry/src/main/java/io/servicecomb/serviceregistry/consumer/MicroserviceVersions.java
index 1dadb89..796d1c5 100644
--- a/service-registry/src/main/java/io/servicecomb/serviceregistry/consumer/MicroserviceVersions.java
+++ b/service-registry/src/main/java/io/servicecomb/serviceregistry/consumer/MicroserviceVersions.java
@@ -33,6 +33,7 @@ import io.servicecomb.serviceregistry.RegistryUtils;
 import io.servicecomb.serviceregistry.api.registry.MicroserviceInstance;
 import io.servicecomb.serviceregistry.api.registry.MicroserviceInstanceStatus;
 import io.servicecomb.serviceregistry.api.response.MicroserviceInstanceChangedEvent;
+import io.servicecomb.serviceregistry.client.http.MicroserviceInstances;
 import io.servicecomb.serviceregistry.definition.DefinitionConst;
 import io.servicecomb.serviceregistry.task.event.PullMicroserviceVersionsInstancesEvent;
 
@@ -45,6 +46,8 @@ public class MicroserviceVersions {
 
   private String microserviceName;
 
+  private String revision = null;
+
   private List<MicroserviceInstance> instances;
 
   // key is service id
@@ -100,20 +103,26 @@ public class MicroserviceVersions {
       return;
     }
 
-    List<MicroserviceInstance> pulledInstances = RegistryUtils.findServiceInstance(appId,
+    MicroserviceInstances microserviceInstances = RegistryUtils.findServiceInstances(appId,
         microserviceName,
-        DefinitionConst.VERSION_RULE_ALL);
-    if (pulledInstances == null) {
+        DefinitionConst.VERSION_RULE_ALL,
+        revision);
+    if (microserviceInstances == null) {
       // exception happens and try pull again later.
       pendingPullCount.incrementAndGet();
       appManager.getEventBus().post(new PullMicroserviceVersionsInstancesEvent(this, TimeUnit.SECONDS.toMillis(1)));
       return;
     }
+    if (!microserviceInstances.isNeedRefresh()) {
+      return;
+    }
+    List<MicroserviceInstance> pulledInstances = microserviceInstances.getInstancesResponse().getInstances();
+    String rev = microserviceInstances.getRevision();
 
-    setInstances(pulledInstances);
+    setInstances(pulledInstances, rev);
   }
 
-  private void setInstances(List<MicroserviceInstance> pulledInstances) {
+  private void setInstances(List<MicroserviceInstance> pulledInstances, String rev) {
     synchronized (lock) {
       instances = pulledInstances
           .stream()
@@ -136,6 +145,7 @@ public class MicroserviceVersions {
       for (MicroserviceVersionRule microserviceVersionRule : versionRules.values()) {
         microserviceVersionRule.setInstances(instances);
       }
+      revision = rev;
     }
   }
 
diff --git a/service-registry/src/main/java/io/servicecomb/serviceregistry/registry/AbstractServiceRegistry.java b/service-registry/src/main/java/io/servicecomb/serviceregistry/registry/AbstractServiceRegistry.java
index c91a20b..db72748 100644
--- a/service-registry/src/main/java/io/servicecomb/serviceregistry/registry/AbstractServiceRegistry.java
+++ b/service-registry/src/main/java/io/servicecomb/serviceregistry/registry/AbstractServiceRegistry.java
@@ -37,6 +37,7 @@ import io.servicecomb.serviceregistry.cache.InstanceCacheManager;
 import io.servicecomb.serviceregistry.cache.InstanceCacheManagerNew;
 import io.servicecomb.serviceregistry.client.IpPortManager;
 import io.servicecomb.serviceregistry.client.ServiceRegistryClient;
+import io.servicecomb.serviceregistry.client.http.MicroserviceInstances;
 import io.servicecomb.serviceregistry.config.ServiceRegistryConfig;
 import io.servicecomb.serviceregistry.consumer.AppManager;
 import io.servicecomb.serviceregistry.consumer.MicroserviceVersionFactory;
@@ -202,15 +203,29 @@ public abstract class AbstractServiceRegistry implements ServiceRegistry {
 
   public List<MicroserviceInstance> findServiceInstance(String appId, String serviceName,
       String versionRule) {
-    List<MicroserviceInstance> instances = srClient.findServiceInstance(microservice.getServiceId(),
+    MicroserviceInstances instances = findServiceInstances(appId, serviceName, versionRule, null);
+    return instances.getInstancesResponse().getInstances();
+  }
+
+  public MicroserviceInstances findServiceInstances(String appId, String serviceName,
+      String versionRule, String revision) {
+    MicroserviceInstances microserviceInstances = srClient.findServiceInstances(microservice.getServiceId(),
         appId,
         serviceName,
-        versionRule);
-    if (instances == null) {
+        versionRule,
+        revision);
+
+    if (microserviceInstances == null) {
       LOGGER.error("Can not find any instances from service center due to previous errors. service={}/{}/{}", appId, serviceName, versionRule);
       return null;
     }
 
+    if (!microserviceInstances.isNeedRefresh()) {
+      LOGGER.info("instances revision is not changed, service={}/{}/{}", appId, serviceName, versionRule);
+      return microserviceInstances;
+    }
+
+    List<MicroserviceInstance> instances = microserviceInstances.getInstancesResponse().getInstances();
     LOGGER.info("find instances[{}] from service center success. service={}/{}/{}",
         instances.size(),
         appId,
@@ -222,7 +237,7 @@ public abstract class AbstractServiceRegistry implements ServiceRegistry {
           instance.getInstanceId(),
           instance.getEndpoints());
     }
-    return instances;
+    return microserviceInstances;
   }
 
   @Override
diff --git a/service-registry/src/test/java/io/servicecomb/serviceregistry/TestRegistry.java b/service-registry/src/test/java/io/servicecomb/serviceregistry/TestRegistry.java
index dbdc4fd..fd113e7 100644
--- a/service-registry/src/test/java/io/servicecomb/serviceregistry/TestRegistry.java
+++ b/service-registry/src/test/java/io/servicecomb/serviceregistry/TestRegistry.java
@@ -47,6 +47,7 @@ import io.servicecomb.config.ConfigUtil;
 import io.servicecomb.foundation.common.net.NetUtils;
 import io.servicecomb.serviceregistry.api.registry.Microservice;
 import io.servicecomb.serviceregistry.api.registry.MicroserviceInstance;
+import io.servicecomb.serviceregistry.client.http.MicroserviceInstances;
 import io.servicecomb.serviceregistry.registry.ServiceRegistryFactory;
 import mockit.Deencapsulation;
 import mockit.Expectations;
@@ -98,6 +99,11 @@ public class TestRegistry {
     Assert.assertEquals(1, instanceList.size());
     Assert.assertEquals(RegistryUtils.getMicroservice().getServiceId(), instanceList.get(0).getServiceId());
 
+    MicroserviceInstances microserviceInstances = RegistryUtils.findServiceInstances("default", "default", "0.0.1", "0");
+    List<MicroserviceInstance> instanceLists = microserviceInstances.getInstancesResponse().getInstances();
+    Assert.assertEquals(1, instanceLists.size());
+    Assert.assertEquals(RegistryUtils.getMicroservice().getServiceId(), instanceLists.get(0).getServiceId());
+
     Map<String, String> properties = new HashMap<>();
     properties.put("k", "v");
     RegistryUtils.updateInstanceProperties(properties);
diff --git a/service-registry/src/test/java/io/servicecomb/serviceregistry/client/LocalServiceRegistryClientImplTest.java b/service-registry/src/test/java/io/servicecomb/serviceregistry/client/LocalServiceRegistryClientImplTest.java
index cde6179..c024bf0 100644
--- a/service-registry/src/test/java/io/servicecomb/serviceregistry/client/LocalServiceRegistryClientImplTest.java
+++ b/service-registry/src/test/java/io/servicecomb/serviceregistry/client/LocalServiceRegistryClientImplTest.java
@@ -30,6 +30,7 @@ import org.junit.rules.ExpectedException;
 
 import io.servicecomb.serviceregistry.api.registry.Microservice;
 import io.servicecomb.serviceregistry.api.registry.MicroserviceInstance;
+import io.servicecomb.serviceregistry.client.http.MicroserviceInstances;
 import io.servicecomb.serviceregistry.definition.DefinitionConst;
 
 public class LocalServiceRegistryClientImplTest {
@@ -56,6 +57,11 @@ public class LocalServiceRegistryClientImplTest {
     List<MicroserviceInstance> m =
         registryClient.findServiceInstance("", "myapp", "springmvctest", DefinitionConst.VERSION_RULE_ALL);
     Assert.assertEquals(1, m.size());
+
+    MicroserviceInstances microserviceInstances =
+        registryClient.findServiceInstances("", "myapp", "springmvctest", DefinitionConst.VERSION_RULE_ALL, null);
+    List<MicroserviceInstance> mi = microserviceInstances.getInstancesResponse().getInstances();
+    Assert.assertEquals(1, mi.size());
   }
 
   private Microservice mockRegisterMicroservice(String appId, String name, String version) {
@@ -113,6 +119,12 @@ public class LocalServiceRegistryClientImplTest {
         registryClient.findServiceInstance("self", appId, microserviceName, DefinitionConst.VERSION_RULE_ALL);
 
     Assert.assertThat(result, Matchers.empty());
+
+    MicroserviceInstances microserviceInstances =
+        registryClient.findServiceInstances("self", appId, microserviceName, DefinitionConst.VERSION_RULE_ALL, null);
+    List<MicroserviceInstance> results = microserviceInstances.getInstancesResponse().getInstances();
+
+    Assert.assertThat(results, Matchers.empty());
   }
 
   @Test
@@ -128,6 +140,12 @@ public class LocalServiceRegistryClientImplTest {
         registryClient.findServiceInstance("self", appId, microserviceName, "1.0.0");
 
     Assert.assertThat(result, Matchers.contains(instance));
+
+    MicroserviceInstances microserviceInstances =
+        registryClient.findServiceInstances("self", appId, microserviceName, "1.0.0", "0");
+    List<MicroserviceInstance> results = microserviceInstances.getInstancesResponse().getInstances();
+
+    Assert.assertThat(results, Matchers.contains(instance));
   }
 
   @Test
diff --git a/service-registry/src/test/java/io/servicecomb/serviceregistry/client/http/TestClientHttp.java b/service-registry/src/test/java/io/servicecomb/serviceregistry/client/http/TestClientHttp.java
index 283b0df..34c395e 100644
--- a/service-registry/src/test/java/io/servicecomb/serviceregistry/client/http/TestClientHttp.java
+++ b/service-registry/src/test/java/io/servicecomb/serviceregistry/client/http/TestClientHttp.java
@@ -84,6 +84,12 @@ public class TestClientHttp {
             microservice.getServiceName(),
             microservice.getVersion()));
     Assert.assertEquals(null,
+        oClient.findServiceInstances(microservice.getServiceId(),
+            microservice.getAppId(),
+            microservice.getServiceName(),
+            microservice.getVersion(),
+            "0"));
+    Assert.assertEquals(null,
         oClient.getMicroserviceId(microservice.getAppId(),
             microservice.getServiceName(),
             microservice.getVersion()));
diff --git a/service-registry/src/test/java/io/servicecomb/serviceregistry/client/http/TestMicroserviceInstances.java b/service-registry/src/test/java/io/servicecomb/serviceregistry/client/http/TestMicroserviceInstances.java
new file mode 100644
index 0000000..7b8b1d0
--- /dev/null
+++ b/service-registry/src/test/java/io/servicecomb/serviceregistry/client/http/TestMicroserviceInstances.java
@@ -0,0 +1,78 @@
+/*
+ * 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 io.servicecomb.serviceregistry.client.http;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+import io.servicecomb.serviceregistry.api.registry.MicroserviceInstance;
+import io.servicecomb.serviceregistry.api.response.FindInstancesResponse;
+
+public class TestMicroserviceInstances {
+
+  MicroserviceInstances microserviceInstances = null;
+
+  FindInstancesResponse findInstancesResponse = null;
+
+  List<MicroserviceInstance> instances = null;
+
+  @Before
+  public void setUp() throws Exception {
+    microserviceInstances = new MicroserviceInstances();
+    findInstancesResponse = new FindInstancesResponse();
+    instances = new ArrayList<>();
+    instances.add(Mockito.mock(MicroserviceInstance.class));
+  }
+
+  @After
+  public void tearDown() throws Exception {
+    instances = null;
+    microserviceInstances = null;
+    findInstancesResponse = null;
+  }
+
+  @Test
+  public void testDefaultValues() {
+    Assert.assertNull(microserviceInstances.getInstancesResponse());
+    Assert.assertTrue(microserviceInstances.isNeedRefresh());
+    Assert.assertNull(microserviceInstances.getRevision());
+    Assert.assertNull(findInstancesResponse.getInstances());
+  }
+
+  @Test
+  public void testInitializedValues() {
+    initFields(); //Initialize the Object
+    Assert.assertEquals(1, microserviceInstances.getInstancesResponse().getInstances().size());
+    Assert.assertFalse(microserviceInstances.isNeedRefresh());
+    Assert.assertEquals("1", microserviceInstances.getRevision());
+  }
+
+  private void initFields() {
+    findInstancesResponse.setInstances(instances);
+    microserviceInstances.setInstancesResponse(findInstancesResponse);
+    microserviceInstances.setNeedRefresh(false);
+    microserviceInstances.setRevision("1");
+  }
+
+}
diff --git a/service-registry/src/test/java/io/servicecomb/serviceregistry/client/http/TestServiceRegistryClientImpl.java b/service-registry/src/test/java/io/servicecomb/serviceregistry/client/http/TestServiceRegistryClientImpl.java
index 364cc03..b9106ac 100644
--- a/service-registry/src/test/java/io/servicecomb/serviceregistry/client/http/TestServiceRegistryClientImpl.java
+++ b/service-registry/src/test/java/io/servicecomb/serviceregistry/client/http/TestServiceRegistryClientImpl.java
@@ -125,6 +125,8 @@ public class TestServiceRegistryClientImpl {
     Assert.assertEquals(null, oClient.heartbeat("microserviceId", "microserviceInstanceId"));
     Assert.assertEquals(null,
         oClient.findServiceInstance("selfMicroserviceId", "appId", "serviceName", "versionRule"));
+    Assert.assertEquals(null,
+        oClient.findServiceInstances("selfMicroserviceId", "appId", "serviceName", "versionRule", "0"));
 
     Assert.assertEquals("a", new ClientException("a").getMessage());
   }
diff --git a/service-registry/src/test/java/io/servicecomb/serviceregistry/consumer/TestAppManager.java b/service-registry/src/test/java/io/servicecomb/serviceregistry/consumer/TestAppManager.java
index 342f329..4123c82 100644
--- a/service-registry/src/test/java/io/servicecomb/serviceregistry/consumer/TestAppManager.java
+++ b/service-registry/src/test/java/io/servicecomb/serviceregistry/consumer/TestAppManager.java
@@ -19,12 +19,16 @@ package io.servicecomb.serviceregistry.consumer;
 
 import java.util.Collections;
 
+import org.junit.After;
 import org.junit.Assert;
+import org.junit.Before;
 import org.junit.Test;
 
 import com.google.common.eventbus.EventBus;
 
 import io.servicecomb.serviceregistry.RegistryUtils;
+import io.servicecomb.serviceregistry.api.response.FindInstancesResponse;
+import io.servicecomb.serviceregistry.client.http.MicroserviceInstances;
 import io.servicecomb.serviceregistry.definition.DefinitionConst;
 import mockit.Expectations;
 import mockit.Mocked;
@@ -40,12 +44,30 @@ public class TestAppManager {
 
   String versionRule = "0+";
 
+  MicroserviceInstances microserviceInstances = null;
+
+  FindInstancesResponse findInstancesResponse = null;
+
+  @Before
+  public void setUp() throws Exception {
+    microserviceInstances = new MicroserviceInstances();
+    findInstancesResponse = new FindInstancesResponse();
+    findInstancesResponse.setInstances(Collections.emptyList());
+    microserviceInstances.setInstancesResponse(findInstancesResponse);
+  }
+
+  @After
+  public void tearDown() throws Exception {
+    findInstancesResponse = null;
+    microserviceInstances = null;
+  }
+
   @Test
   public void getOrCreateMicroserviceVersionRule() {
     new Expectations(RegistryUtils.class) {
       {
-        RegistryUtils.findServiceInstance(appId, serviceName, DefinitionConst.VERSION_RULE_ALL);
-        result = Collections.emptyList();
+        RegistryUtils.findServiceInstances(appId, serviceName, DefinitionConst.VERSION_RULE_ALL, null);
+        result = microserviceInstances;
       }
     };
 
@@ -59,8 +81,8 @@ public class TestAppManager {
   public void getOrCreateMicroserviceVersions() {
     new Expectations(RegistryUtils.class) {
       {
-        RegistryUtils.findServiceInstance(appId, serviceName, DefinitionConst.VERSION_RULE_ALL);
-        result = Collections.emptyList();
+        RegistryUtils.findServiceInstances(appId, serviceName, DefinitionConst.VERSION_RULE_ALL, null);
+        result = microserviceInstances;
       }
     };
 
diff --git a/service-registry/src/test/java/io/servicecomb/serviceregistry/consumer/TestMicroserviceManager.java b/service-registry/src/test/java/io/servicecomb/serviceregistry/consumer/TestMicroserviceManager.java
index 2cc9062..048d7f3 100644
--- a/service-registry/src/test/java/io/servicecomb/serviceregistry/consumer/TestMicroserviceManager.java
+++ b/service-registry/src/test/java/io/servicecomb/serviceregistry/consumer/TestMicroserviceManager.java
@@ -22,12 +22,16 @@ import java.util.Map;
 
 import javax.xml.ws.Holder;
 
+import org.junit.After;
 import org.junit.Assert;
+import org.junit.Before;
 import org.junit.Test;
 
 import com.google.common.eventbus.EventBus;
 
 import io.servicecomb.serviceregistry.RegistryUtils;
+import io.servicecomb.serviceregistry.api.response.FindInstancesResponse;
+import io.servicecomb.serviceregistry.client.http.MicroserviceInstances;
 import io.servicecomb.serviceregistry.definition.DefinitionConst;
 import io.servicecomb.serviceregistry.task.event.PeriodicPullEvent;
 import io.servicecomb.serviceregistry.task.event.RecoveryEvent;
@@ -49,12 +53,30 @@ public class TestMicroserviceManager {
 
   MicroserviceManager microserviceManager = new MicroserviceManager(appManager, appId);
 
+  MicroserviceInstances microserviceInstances = null;
+
+  FindInstancesResponse findInstancesResponse = null;
+
+  @Before
+  public void setUp() throws Exception {
+    microserviceInstances = new MicroserviceInstances();
+    findInstancesResponse = new FindInstancesResponse();
+    findInstancesResponse.setInstances(Collections.emptyList());
+    microserviceInstances.setInstancesResponse(findInstancesResponse);
+  }
+
+  @After
+  public void tearDown() throws Exception {
+    findInstancesResponse = null;
+    microserviceInstances = null;
+  }
+
   @Test
   public void getOrCreateMicroserviceVersionRule() {
     new Expectations(RegistryUtils.class) {
       {
-        RegistryUtils.findServiceInstance(appId, serviceName, DefinitionConst.VERSION_RULE_ALL);
-        result = Collections.emptyList();
+        RegistryUtils.findServiceInstances(appId, serviceName, DefinitionConst.VERSION_RULE_ALL, null);
+        result = microserviceInstances;
       }
     };
 
diff --git a/service-registry/src/test/java/io/servicecomb/serviceregistry/consumer/TestMicroserviceVersions.java b/service-registry/src/test/java/io/servicecomb/serviceregistry/consumer/TestMicroserviceVersions.java
index eda0f56..2da6b58 100644
--- a/service-registry/src/test/java/io/servicecomb/serviceregistry/consumer/TestMicroserviceVersions.java
+++ b/service-registry/src/test/java/io/servicecomb/serviceregistry/consumer/TestMicroserviceVersions.java
@@ -23,7 +23,9 @@ import java.util.List;
 import java.util.Map;
 import java.util.concurrent.atomic.AtomicInteger;
 
+import org.junit.After;
 import org.junit.Assert;
+import org.junit.Before;
 import org.junit.Test;
 
 import com.google.common.eventbus.EventBus;
@@ -34,7 +36,9 @@ import io.servicecomb.serviceregistry.api.MicroserviceKey;
 import io.servicecomb.serviceregistry.api.registry.Microservice;
 import io.servicecomb.serviceregistry.api.registry.MicroserviceInstance;
 import io.servicecomb.serviceregistry.api.registry.MicroserviceInstanceStatus;
+import io.servicecomb.serviceregistry.api.response.FindInstancesResponse;
 import io.servicecomb.serviceregistry.api.response.MicroserviceInstanceChangedEvent;
+import io.servicecomb.serviceregistry.client.http.MicroserviceInstances;
 import io.servicecomb.serviceregistry.task.event.PullMicroserviceVersionsInstancesEvent;
 import io.servicecomb.serviceregistry.version.Version;
 import mockit.Deencapsulation;
@@ -60,6 +64,22 @@ public class TestMicroserviceVersions {
 
   AtomicInteger pendingPullCount;
 
+  MicroserviceInstances microserviceInstances = null;
+
+  FindInstancesResponse findInstancesResponse = null;
+
+  @Before
+  public void setUp() throws Exception {
+    microserviceInstances = new MicroserviceInstances();
+    findInstancesResponse = new FindInstancesResponse();
+  }
+
+  @After
+  public void tearDown() throws Exception {
+    findInstancesResponse = null;
+    microserviceInstances = null;
+  }
+
   public TestMicroserviceVersions() {
     microserviceVersions = new MicroserviceVersions(appManager, appId, microserviceName);
     pendingPullCount = Deencapsulation.getField(microserviceVersions, "pendingPullCount");
@@ -81,15 +101,23 @@ public class TestMicroserviceVersions {
     instances.add(instance);
   }
 
+  private void createMicroserviceInstances() {
+    findInstancesResponse.setInstances(instances);
+    microserviceInstances.setInstancesResponse(findInstancesResponse);
+    microserviceInstances.setRevision("1");
+    microserviceInstances.setNeedRefresh(true);
+  }
+
   private void setup(String microserviceId) {
     createMicroservice(microserviceId);
     createInstance(microserviceId);
+    createMicroserviceInstances();
 
     new MockUp<RegistryUtils>() {
       @Mock
-      List<MicroserviceInstance> findServiceInstance(String appId, String serviceName,
-          String versionRule) {
-        return instances;
+      MicroserviceInstances findServiceInstances(String appId, String serviceName,
+          String versionRule, String revision) {
+        return microserviceInstances;
       }
 
       @Mock
@@ -123,8 +151,8 @@ public class TestMicroserviceVersions {
   public void pullInstancesCancel() {
     new MockUp<RegistryUtils>() {
       @Mock
-      List<MicroserviceInstance> findServiceInstance(String appId, String serviceName,
-          String versionRule) {
+      MicroserviceInstances findServiceInstances(String appId, String serviceName,
+          String versionRule, String revision) {
         throw new Error("must not pull");
       }
     };
@@ -139,8 +167,8 @@ public class TestMicroserviceVersions {
   public void pullInstancesNull() {
     new MockUp<RegistryUtils>() {
       @Mock
-      List<MicroserviceInstance> findServiceInstance(String appId, String serviceName,
-          String versionRule) {
+      MicroserviceInstances findServiceInstances(String appId, String serviceName,
+          String versionRule, String revision) {
         return null;
       }
     };
@@ -169,7 +197,7 @@ public class TestMicroserviceVersions {
     setup(microserviceId);
 
     instances.get(0).setStatus(MicroserviceInstanceStatus.DOWN);
-    Deencapsulation.invoke(microserviceVersions, "setInstances", instances);
+    Deencapsulation.invoke(microserviceVersions, "setInstances", instances, "0");
 
     List<?> resultInstances = Deencapsulation.getField(microserviceVersions, "instances");
     Assert.assertTrue(resultInstances.isEmpty());

-- 
To stop receiving notification emails like this one, please contact
['"commits@servicecomb.apache.org" <co...@servicecomb.apache.org>'].