You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@servicecomb.apache.org by li...@apache.org on 2020/06/02 03:39:42 UTC

[servicecomb-java-chassis] branch master updated (9a0c45f -> e0d13ea)

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

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


    from 9a0c45f  [SCB-1967] add simple load balance
     new e10beac  [SCB-1971] Introduce SPI mechanism to enable/disable zero-config and changes to adapt to new interfaces
     new 8343d11  [SCB-1971] Address PR comments
     new 2c97d08  [SCB-1971] fix an issue
     new ffeb8b3  [SCB-1971] Address comments
     new e0d13ea  [SCB-1971] Clean up

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


Summary of changes:
 .../zeroconfig/ZeroConfigDiscovery.java}           |  47 ++--
 .../zeroconfig/ZeroConfigRegistration.java         | 177 +++++++++++++
 .../ZeroConfigRegistryApplicationListener.java     |  91 -------
 .../zeroconfig/ZeroConfigRegistryConstants.java    |   3 +
 .../zeroconfig/client/ZeroConfigClient.java        | 287 +++++++++++++++++++++
 .../servicecomb/zeroconfig/server/ServerUtil.java  |   2 +-
 .../org.apache.servicecomb.registry.api.Discovery  |   2 +-
 ...rg.apache.servicecomb.registry.api.Registration |   2 +-
 .../zeroconfig/client/TestZeroConfigClient.java    | 269 +++++++++++++++++++
 9 files changed, 763 insertions(+), 117 deletions(-)
 copy service-registry/{registry-local/src/main/java/org/apache/servicecomb/localregistry/LocalDiscovery.java => registry-zero-config/src/main/java/org/apache/servicecomb/zeroconfig/ZeroConfigDiscovery.java} (68%)
 create mode 100644 service-registry/registry-zero-config/src/main/java/org/apache/servicecomb/zeroconfig/ZeroConfigRegistration.java
 delete mode 100644 service-registry/registry-zero-config/src/main/java/org/apache/servicecomb/zeroconfig/ZeroConfigRegistryApplicationListener.java
 create mode 100644 service-registry/registry-zero-config/src/main/java/org/apache/servicecomb/zeroconfig/client/ZeroConfigClient.java
 copy service-registry/{registry-local => registry-zero-config}/src/main/resources/META-INF/services/org.apache.servicecomb.registry.api.Discovery (93%)
 copy service-registry/{registry-local => registry-zero-config}/src/main/resources/META-INF/services/org.apache.servicecomb.registry.api.Registration (93%)
 create mode 100644 service-registry/registry-zero-config/src/test/java/org/apache/servicecomb/zeroconfig/client/TestZeroConfigClient.java


[servicecomb-java-chassis] 04/05: [SCB-1971] Address comments

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

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

commit ffeb8b3d86fb85ea842c49e5f301e9c43d4a1e4c
Author: Jun Gan <ju...@gmail.com>
AuthorDate: Mon Jun 1 10:14:21 2020 -0400

    [SCB-1971] Address comments
---
 .../zeroconfig/ZeroConfigRegistryConstants.java        |  1 +
 .../zeroconfig/client/ZeroConfigClient.java            | 18 +++++-------------
 .../servicecomb/zeroconfig/server/ServerUtil.java      |  2 +-
 .../zeroconfig/client/TestZeroConfigClient.java        | 18 +++---------------
 4 files changed, 10 insertions(+), 29 deletions(-)

diff --git a/service-registry/registry-zero-config/src/main/java/org/apache/servicecomb/zeroconfig/ZeroConfigRegistryConstants.java b/service-registry/registry-zero-config/src/main/java/org/apache/servicecomb/zeroconfig/ZeroConfigRegistryConstants.java
index 412912f..483f702 100644
--- a/service-registry/registry-zero-config/src/main/java/org/apache/servicecomb/zeroconfig/ZeroConfigRegistryConstants.java
+++ b/service-registry/registry-zero-config/src/main/java/org/apache/servicecomb/zeroconfig/ZeroConfigRegistryConstants.java
@@ -23,6 +23,7 @@ public interface ZeroConfigRegistryConstants {
   // MulticastSocket related
   String GROUP = "225.0.0.0";
   Integer PORT = 6666;
+  String ENCODE = "UTF-8";
   /**
    * ttl=1,local network, ttl=32,local network station, ttl=64,local area;ttl=128,local continent
    * ttl=255,all places. Default value is 1;
diff --git a/service-registry/registry-zero-config/src/main/java/org/apache/servicecomb/zeroconfig/client/ZeroConfigClient.java b/service-registry/registry-zero-config/src/main/java/org/apache/servicecomb/zeroconfig/client/ZeroConfigClient.java
index 83c5550..7bd8c46 100644
--- a/service-registry/registry-zero-config/src/main/java/org/apache/servicecomb/zeroconfig/client/ZeroConfigClient.java
+++ b/service-registry/registry-zero-config/src/main/java/org/apache/servicecomb/zeroconfig/client/ZeroConfigClient.java
@@ -101,7 +101,7 @@ public class ZeroConfigClient {
 
   private String doRegister(Map<String, String> serviceInstanceDataMap) {
     try {
-      byte[] instanceData = serviceInstanceDataMap.toString().getBytes();
+      byte[] instanceData = serviceInstanceDataMap.toString().getBytes(ENCODE);
       DatagramPacket instanceDataPacket = new DatagramPacket(instanceData, instanceData.length,
           InetAddress.getByName(GROUP), PORT);
       this.multicastSocket.send(instanceDataPacket);
@@ -134,7 +134,7 @@ public class ZeroConfigClient {
       unregisterEventMap.put(EVENT, UNREGISTER_EVENT);
       unregisterEventMap.put(SERVICE_ID, foundInstance.getServiceId());
       unregisterEventMap.put(INSTANCE_ID, foundInstance.getInstanceId());
-      byte[] unregisterEventBytes = unregisterEventMap.toString().getBytes();
+      byte[] unregisterEventBytes = unregisterEventMap.toString().getBytes(ENCODE);
       DatagramPacket unregisterEventDataPacket = new DatagramPacket(unregisterEventBytes,
           unregisterEventBytes.length, InetAddress.getByName(GROUP), PORT);
       this.multicastSocket.send(unregisterEventDataPacket);
@@ -171,6 +171,7 @@ public class ZeroConfigClient {
     }
   }
 
+
   public String getSchema(String microserviceId, String schemaId) {
     Microservice selfMicroservice = ZeroConfigRegistration.INSTANCE.getSelfMicroservice();
     LOGGER.info("Retrieve schema content for Microservice ID: {}, Schema ID: {}",
@@ -179,17 +180,8 @@ public class ZeroConfigClient {
     if (selfMicroservice.getServiceId().equals(microserviceId)) {
       return selfMicroservice.getSchemaMap().computeIfPresent(schemaId, (k, v) -> v);
     } else {
-      // called by consumer to load provider's schema content for the very first time
-      String providerEndpoint = this.getEndpointForMicroservice(microserviceId);
-      if (providerEndpoint == null) {
-        throw new IllegalArgumentException("Provider's endpoint can NOT be Null");
-      }
-      String providerSchemaContentEndpoint =
-          providerEndpoint + "/schemaEndpoint/schemas?schemaId=" + schemaId;
-
-      LOGGER.info("Retrieve schema content from endpoint:{}", providerSchemaContentEndpoint);
-      // Make a rest call to provider's endpoint directly to retrieve the schema content
-      return restTemplate.getForObject(providerSchemaContentEndpoint, String.class);
+      // TODO will need to rely on the registry-schema-discovery module to getSchema
+      return null;
     }
   }
 
diff --git a/service-registry/registry-zero-config/src/main/java/org/apache/servicecomb/zeroconfig/server/ServerUtil.java b/service-registry/registry-zero-config/src/main/java/org/apache/servicecomb/zeroconfig/server/ServerUtil.java
index 6126205..824bffa 100644
--- a/service-registry/registry-zero-config/src/main/java/org/apache/servicecomb/zeroconfig/server/ServerUtil.java
+++ b/service-registry/registry-zero-config/src/main/java/org/apache/servicecomb/zeroconfig/server/ServerUtil.java
@@ -188,7 +188,7 @@ public class ServerUtil {
       while (true) {
         DatagramPacket receivePacketBuffer = new DatagramPacket(buffer, buffer.length);
         multicastSocket.receive(receivePacketBuffer);
-        String receivedPacketString = new String(receivePacketBuffer.getData());
+        String receivedPacketString = new String(receivePacketBuffer.getData(), ENCODE);
 
         Map<String, String> receivedStringMap = getMapFromString(receivedPacketString);
 
diff --git a/service-registry/registry-zero-config/src/test/java/org/apache/servicecomb/zeroconfig/client/TestZeroConfigClient.java b/service-registry/registry-zero-config/src/test/java/org/apache/servicecomb/zeroconfig/client/TestZeroConfigClient.java
index 025fcef..0ca085d 100644
--- a/service-registry/registry-zero-config/src/test/java/org/apache/servicecomb/zeroconfig/client/TestZeroConfigClient.java
+++ b/service-registry/registry-zero-config/src/test/java/org/apache/servicecomb/zeroconfig/client/TestZeroConfigClient.java
@@ -207,27 +207,15 @@ public class TestZeroConfigClient {
     verifyZeroInteractions(zeroConfigRegistryService);
   }
 
+  // TODO
   @Test
-  public void test_getSchema_forOtherMicroservice_shouldCallZeroConfigRegistryService_And_Succeed() {
-    when(zeroConfigRegistryService.getMicroservice(otherServiceId))
-        .thenReturn(prepareServerServiceInstance(true));
-    String schemaContentEndpoint = endpoint1 + "/schemaEndpoint/schemas?schemaId=" + schemaId1;
-    when(restTemplate.getForObject(schemaContentEndpoint, String.class)).thenReturn(schemaContent1);
-
+  public void test_getSchema_forOtherMicroservice_shouldReturnNull() {
     String returnedResult = target.getSchema(otherServiceId, schemaId1);
 
-    Assert.assertEquals(schemaContent1, returnedResult);
+    Assert.assertNull(returnedResult);
   }
 
-  @Test(expected = IllegalArgumentException.class)
-  public void test_getSchema_whenProviderEndpointIsNull_shouldThrowIllegalArgumentException() {
-    when(zeroConfigRegistryService.getMicroservice(otherServiceId))
-        .thenReturn(prepareServerServiceInstance(false));
-
-    target.getSchema(otherServiceId, schemaId1);
 
-    verifyZeroInteractions(restTemplate);
-  }
 
   // test findMicroserviceInstance method
   @Test


[servicecomb-java-chassis] 05/05: [SCB-1971] Clean up

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

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

commit e0d13ea6ce27f2fc9ee1031bf69ce7774953973a
Author: Jun Gan <ju...@gmail.com>
AuthorDate: Mon Jun 1 16:24:39 2020 -0400

    [SCB-1971] Clean up
---
 .../servicecomb/zeroconfig/client/ZeroConfigClient.java      | 12 +++---------
 .../servicecomb/zeroconfig/client/TestZeroConfigClient.java  |  6 +-----
 2 files changed, 4 insertions(+), 14 deletions(-)

diff --git a/service-registry/registry-zero-config/src/main/java/org/apache/servicecomb/zeroconfig/client/ZeroConfigClient.java b/service-registry/registry-zero-config/src/main/java/org/apache/servicecomb/zeroconfig/client/ZeroConfigClient.java
index 7bd8c46..e52172d 100644
--- a/service-registry/registry-zero-config/src/main/java/org/apache/servicecomb/zeroconfig/client/ZeroConfigClient.java
+++ b/service-registry/registry-zero-config/src/main/java/org/apache/servicecomb/zeroconfig/client/ZeroConfigClient.java
@@ -41,7 +41,6 @@ import org.apache.servicecomb.zeroconfig.server.ServerUtil;
 import org.apache.servicecomb.zeroconfig.server.ZeroConfigRegistryService;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import org.springframework.web.client.RestTemplate;
 
 import static org.apache.servicecomb.zeroconfig.ZeroConfigRegistryConstants.*;
 
@@ -53,25 +52,21 @@ public class ZeroConfigClient {
 
   // Constructor Parameters
   private ZeroConfigRegistryService zeroConfigRegistryService;
-  private RestTemplate restTemplate;
   private MulticastSocket multicastSocket;
 
   // Constructor
-
   private ZeroConfigClient(ZeroConfigRegistryService zeroConfigRegistryService,
-      MulticastSocket multicastSocket, RestTemplate restTemplate) {
+      MulticastSocket multicastSocket) {
     this.zeroConfigRegistryService = zeroConfigRegistryService;
-    this.restTemplate = restTemplate;
     this.multicastSocket = multicastSocket;
   }
 
   @VisibleForTesting
   public ZeroConfigClient initZeroConfigClientWithMocked(
       ZeroConfigRegistryService zeroConfigRegistryService,
-      MulticastSocket multicastSocket, RestTemplate restTemplate) {
+      MulticastSocket multicastSocket) {
     this.zeroConfigRegistryService = zeroConfigRegistryService;
     this.multicastSocket = multicastSocket;
-    this.restTemplate = restTemplate;
     return this;
   }
 
@@ -86,8 +81,7 @@ public class ZeroConfigClient {
       LOGGER.error("Failed to create MulticastSocket object in Zero-Config mode", e);
       //throw new ServiceCombException("Failed to create MulticastSocket object", e);
     }
-    return new ZeroConfigClient(new ZeroConfigRegistryService(), multicastSocket,
-        new RestTemplate());
+    return new ZeroConfigClient(new ZeroConfigRegistryService(), multicastSocket);
   }
 
   public boolean register() {
diff --git a/service-registry/registry-zero-config/src/test/java/org/apache/servicecomb/zeroconfig/client/TestZeroConfigClient.java b/service-registry/registry-zero-config/src/test/java/org/apache/servicecomb/zeroconfig/client/TestZeroConfigClient.java
index 0ca085d..7054f0f 100644
--- a/service-registry/registry-zero-config/src/test/java/org/apache/servicecomb/zeroconfig/client/TestZeroConfigClient.java
+++ b/service-registry/registry-zero-config/src/test/java/org/apache/servicecomb/zeroconfig/client/TestZeroConfigClient.java
@@ -40,7 +40,6 @@ import org.junit.Before;
 import org.junit.Test;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
-import org.springframework.web.client.RestTemplate;
 
 public class TestZeroConfigClient {
 
@@ -52,9 +51,6 @@ public class TestZeroConfigClient {
   @Mock
   MulticastSocket multicastSocket;
 
-  @Mock
-  RestTemplate restTemplate;
-
   // testing data
   String selfServiceId = "123";
   String selfInstanceId = "instanceId";
@@ -72,7 +68,7 @@ public class TestZeroConfigClient {
   @Before
   public void setUp() {
     MockitoAnnotations.initMocks(this);
-    target = ZeroConfigClient.INSTANCE.initZeroConfigClientWithMocked(zeroConfigRegistryService, multicastSocket, restTemplate);
+    target = ZeroConfigClient.INSTANCE.initZeroConfigClientWithMocked(zeroConfigRegistryService, multicastSocket);
 
     prepareSelfMicroserviceAndInstance();
   }


[servicecomb-java-chassis] 02/05: [SCB-1971] Address PR comments

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

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

commit 8343d11e1e11a7422051b2e968227341743acd16
Author: Jun Gan <ju...@gmail.com>
AuthorDate: Sun May 31 23:12:32 2020 -0400

    [SCB-1971] Address PR comments
---
 .../zeroconfig/ZeroConfigDiscovery.java            |  5 ++-
 .../zeroconfig/ZeroConfigRegistration.java         | 39 ++++++++++++++-----
 .../zeroconfig/ZeroConfigRegistryConstants.java    |  2 +
 .../zeroconfig/client/ZeroConfigClient.java        | 44 +++++++++-------------
 .../zeroconfig/client/TestZeroConfigClient.java    | 11 +-----
 5 files changed, 55 insertions(+), 46 deletions(-)

diff --git a/service-registry/registry-zero-config/src/main/java/org/apache/servicecomb/zeroconfig/ZeroConfigDiscovery.java b/service-registry/registry-zero-config/src/main/java/org/apache/servicecomb/zeroconfig/ZeroConfigDiscovery.java
index 3ce2871..ae7edff 100644
--- a/service-registry/registry-zero-config/src/main/java/org/apache/servicecomb/zeroconfig/ZeroConfigDiscovery.java
+++ b/service-registry/registry-zero-config/src/main/java/org/apache/servicecomb/zeroconfig/ZeroConfigDiscovery.java
@@ -17,6 +17,7 @@
 package org.apache.servicecomb.zeroconfig;
 
 import com.netflix.config.DynamicPropertyFactory;
+import com.sun.xml.internal.bind.v2.TODO;
 import java.util.Collection;
 import java.util.List;
 import org.apache.servicecomb.registry.api.Discovery;
@@ -25,10 +26,11 @@ import org.apache.servicecomb.registry.api.registry.MicroserviceInstance;
 import org.apache.servicecomb.registry.api.registry.MicroserviceInstances;
 import org.apache.servicecomb.zeroconfig.client.ZeroConfigClient;
 
+import static org.apache.servicecomb.zeroconfig.ZeroConfigRegistryConstants.ENABLED;
+
 public class ZeroConfigDiscovery implements Discovery {
 
   private static final String NAME = "zero-config discovery";
-  private static final String ENABLED = "servicecomb.zeroconfig.registry.discovery.enabled";
 
   private ZeroConfigClient zeroConfigClient = ZeroConfigClient.INSTANCE;
   private String revision;
@@ -68,6 +70,7 @@ public class ZeroConfigDiscovery implements Discovery {
     return zeroConfigClient.getAllMicroservices();
   }
 
+  //TODO
   @Override
   public String getSchema(String microserviceId, Collection<MicroserviceInstance> instances,
       String schemaId) {
diff --git a/service-registry/registry-zero-config/src/main/java/org/apache/servicecomb/zeroconfig/ZeroConfigRegistration.java b/service-registry/registry-zero-config/src/main/java/org/apache/servicecomb/zeroconfig/ZeroConfigRegistration.java
index 06c0849..745f43f 100644
--- a/service-registry/registry-zero-config/src/main/java/org/apache/servicecomb/zeroconfig/ZeroConfigRegistration.java
+++ b/service-registry/registry-zero-config/src/main/java/org/apache/servicecomb/zeroconfig/ZeroConfigRegistration.java
@@ -16,8 +16,10 @@
  */
 package org.apache.servicecomb.zeroconfig;
 
+import com.google.common.annotations.VisibleForTesting;
 import com.netflix.config.DynamicPropertyFactory;
 import java.util.Collection;
+import org.apache.commons.lang.StringUtils;
 import org.apache.servicecomb.config.ConfigUtil;
 import org.apache.servicecomb.config.archaius.sources.MicroserviceConfigLoader;
 import org.apache.servicecomb.registry.api.Registration;
@@ -33,6 +35,8 @@ import org.apache.servicecomb.zeroconfig.server.ServerUtil;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import static org.apache.servicecomb.zeroconfig.ZeroConfigRegistryConstants.ENABLED;
+
 public class ZeroConfigRegistration implements Registration {
 
   private static final Logger LOGGER = LoggerFactory.getLogger(ZeroConfigRegistration.class);
@@ -40,7 +44,6 @@ public class ZeroConfigRegistration implements Registration {
   public static ZeroConfigRegistration INSTANCE = new ZeroConfigRegistration();
 
   private static final String NAME = "zero-config registration";
-  private static final String ENABLED = "servicecomb.zeroconfig.registry.registration.enabled";
 
   private ZeroConfigClient zeroConfigClient = ZeroConfigClient.INSTANCE;
 
@@ -63,10 +66,27 @@ public class ZeroConfigRegistration implements Registration {
     this.selfMicroservice = microserviceFactory.create(microserviceDefinition);
     this.selfMicroserviceInstance = selfMicroservice.getInstance();
 
+    setServiceIdAndInstanceId();
+
     ServerUtil.init();
     ClientUtil.init();
   }
 
+  private void  setServiceIdAndInstanceId(){
+    // set serviceId
+    if (StringUtils.isEmpty(selfMicroservice.getServiceId())) {
+      String serviceId = ClientUtil.generateServiceId(selfMicroservice);
+      selfMicroservice.setServiceId(serviceId);
+      selfMicroserviceInstance.setServiceId(serviceId);
+    }
+
+    // set instanceId
+    if (StringUtils.isEmpty(selfMicroserviceInstance.getInstanceId())) {
+      String instanceId = ClientUtil.generateServiceInstanceId();
+      selfMicroserviceInstance.setInstanceId(instanceId);
+    }
+  }
+
   @Override
   public void run() {
     // register service instance
@@ -134,23 +154,24 @@ public class ZeroConfigRegistration implements Registration {
   }
 
   // setter/getter
-
-  public void setSelfMicroservice(
-      Microservice selfMicroservice) {
-    this.selfMicroservice = selfMicroservice;
-  }
-
   public Microservice getSelfMicroservice() {
     return this.selfMicroservice;
   }
 
+  public MicroserviceInstance getSelfMicroserviceInstance() {
+    return this.selfMicroserviceInstance;
+  }
+
+  @VisibleForTesting
   public void setSelfMicroserviceInstance(
       MicroserviceInstance selfMicroserviceInstance) {
     this.selfMicroserviceInstance = selfMicroserviceInstance;
   }
 
-  public MicroserviceInstance getSelfMicroserviceInstance() {
-    return this.selfMicroserviceInstance;
+  @VisibleForTesting
+  public void setSelfMicroservice(
+      Microservice selfMicroservice) {
+    this.selfMicroservice = selfMicroservice;
   }
 
 }
diff --git a/service-registry/registry-zero-config/src/main/java/org/apache/servicecomb/zeroconfig/ZeroConfigRegistryConstants.java b/service-registry/registry-zero-config/src/main/java/org/apache/servicecomb/zeroconfig/ZeroConfigRegistryConstants.java
index 417b958..412912f 100644
--- a/service-registry/registry-zero-config/src/main/java/org/apache/servicecomb/zeroconfig/ZeroConfigRegistryConstants.java
+++ b/service-registry/registry-zero-config/src/main/java/org/apache/servicecomb/zeroconfig/ZeroConfigRegistryConstants.java
@@ -18,6 +18,8 @@ package org.apache.servicecomb.zeroconfig;
 
 public interface ZeroConfigRegistryConstants {
 
+  String ENABLED = "servicecomb.zeroconfig.registry.enabled";
+
   // MulticastSocket related
   String GROUP = "225.0.0.0";
   Integer PORT = 6666;
diff --git a/service-registry/registry-zero-config/src/main/java/org/apache/servicecomb/zeroconfig/client/ZeroConfigClient.java b/service-registry/registry-zero-config/src/main/java/org/apache/servicecomb/zeroconfig/client/ZeroConfigClient.java
index 23e290a..83c5550 100644
--- a/service-registry/registry-zero-config/src/main/java/org/apache/servicecomb/zeroconfig/client/ZeroConfigClient.java
+++ b/service-registry/registry-zero-config/src/main/java/org/apache/servicecomb/zeroconfig/client/ZeroConfigClient.java
@@ -16,6 +16,7 @@
  */
 package org.apache.servicecomb.zeroconfig.client;
 
+import com.google.common.annotations.VisibleForTesting;
 import java.io.IOException;
 import java.net.DatagramPacket;
 import java.net.InetAddress;
@@ -56,13 +57,24 @@ public class ZeroConfigClient {
   private MulticastSocket multicastSocket;
 
   // Constructor
-  public ZeroConfigClient(ZeroConfigRegistryService zeroConfigRegistryService,
+
+  private ZeroConfigClient(ZeroConfigRegistryService zeroConfigRegistryService,
       MulticastSocket multicastSocket, RestTemplate restTemplate) {
     this.zeroConfigRegistryService = zeroConfigRegistryService;
     this.restTemplate = restTemplate;
     this.multicastSocket = multicastSocket;
   }
 
+  @VisibleForTesting
+  public ZeroConfigClient initZeroConfigClientWithMocked(
+      ZeroConfigRegistryService zeroConfigRegistryService,
+      MulticastSocket multicastSocket, RestTemplate restTemplate) {
+    this.zeroConfigRegistryService = zeroConfigRegistryService;
+    this.multicastSocket = multicastSocket;
+    this.restTemplate = restTemplate;
+    return this;
+  }
+
   // builder method
   private static ZeroConfigClient buildZeroConfigClient() {
     MulticastSocket multicastSocket = null;
@@ -263,34 +275,14 @@ public class ZeroConfigClient {
   }
 
   private Map<String, String> prepareRegisterData() {
-    // set serviceId
-    Microservice selfMicroservice = ZeroConfigRegistration.INSTANCE.getSelfMicroservice();
-    MicroserviceInstance selfMicroserviceInstance = ZeroConfigRegistration.INSTANCE
+    // Convert to Multicast data format
+    Microservice selfService = ZeroConfigRegistration.INSTANCE.getSelfMicroservice();
+    MicroserviceInstance selfInstance = ZeroConfigRegistration.INSTANCE
         .getSelfMicroserviceInstance();
 
-    if (selfMicroservice == null || selfMicroserviceInstance == null) {
-      return null;
-    }
-
-    String serviceId = selfMicroservice.getServiceId();
-    if (StringUtils.isEmpty(serviceId)) {
-      serviceId = ClientUtil.generateServiceId(selfMicroservice);
-      selfMicroservice.setServiceId(serviceId);
-      selfMicroserviceInstance.setServiceId(serviceId);
-    }
-
-    // set instanceId
-    String instanceId = selfMicroserviceInstance
-        .getInstanceId(); // allow client to set the instanceId
-    if (StringUtils.isEmpty(instanceId)) {
-      instanceId = ClientUtil.generateServiceInstanceId();
-      selfMicroserviceInstance.setInstanceId(instanceId);
-    }
-
-    // Convert to Multicast data format
     Optional<Map<String, String>> optionalDataMap = ClientUtil
-        .convertToRegisterDataModel(serviceId, instanceId, selfMicroserviceInstance,
-            selfMicroservice);
+        .convertToRegisterDataModel(selfService.getServiceId(), selfInstance.getInstanceId(),
+            selfInstance, selfService);
 
     return optionalDataMap.orElse(null);
   }
diff --git a/service-registry/registry-zero-config/src/test/java/org/apache/servicecomb/zeroconfig/client/TestZeroConfigClient.java b/service-registry/registry-zero-config/src/test/java/org/apache/servicecomb/zeroconfig/client/TestZeroConfigClient.java
index e77e715..025fcef 100644
--- a/service-registry/registry-zero-config/src/test/java/org/apache/servicecomb/zeroconfig/client/TestZeroConfigClient.java
+++ b/service-registry/registry-zero-config/src/test/java/org/apache/servicecomb/zeroconfig/client/TestZeroConfigClient.java
@@ -72,7 +72,7 @@ public class TestZeroConfigClient {
   @Before
   public void setUp() {
     MockitoAnnotations.initMocks(this);
-    target = new ZeroConfigClient(zeroConfigRegistryService, multicastSocket, restTemplate);
+    target = ZeroConfigClient.INSTANCE.initZeroConfigClientWithMocked(zeroConfigRegistryService, multicastSocket, restTemplate);
 
     prepareSelfMicroserviceAndInstance();
   }
@@ -137,15 +137,6 @@ public class TestZeroConfigClient {
   }
 
   @Test
-  public void test_register_withWrongData_RegisterShouldFail() {
-    ZeroConfigRegistration.INSTANCE.setSelfMicroservice(null);
-
-    boolean returnedResult = target.register();
-
-    Assert.assertFalse(returnedResult);
-  }
-
-  @Test
   public void test_register_MulticastThrowException_RegisterShouldFail() throws IOException {
     doThrow(IOException.class).when(multicastSocket).send(anyObject());
 


[servicecomb-java-chassis] 03/05: [SCB-1971] fix an issue

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

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

commit 2c97d08b1d66e690760ee9c0dedcdc795dd78fb4
Author: Jun Gan <ju...@gmail.com>
AuthorDate: Sun May 31 23:39:11 2020 -0400

    [SCB-1971] fix an issue
---
 .../main/java/org/apache/servicecomb/zeroconfig/ZeroConfigDiscovery.java | 1 -
 1 file changed, 1 deletion(-)

diff --git a/service-registry/registry-zero-config/src/main/java/org/apache/servicecomb/zeroconfig/ZeroConfigDiscovery.java b/service-registry/registry-zero-config/src/main/java/org/apache/servicecomb/zeroconfig/ZeroConfigDiscovery.java
index ae7edff..3b3cfcf 100644
--- a/service-registry/registry-zero-config/src/main/java/org/apache/servicecomb/zeroconfig/ZeroConfigDiscovery.java
+++ b/service-registry/registry-zero-config/src/main/java/org/apache/servicecomb/zeroconfig/ZeroConfigDiscovery.java
@@ -17,7 +17,6 @@
 package org.apache.servicecomb.zeroconfig;
 
 import com.netflix.config.DynamicPropertyFactory;
-import com.sun.xml.internal.bind.v2.TODO;
 import java.util.Collection;
 import java.util.List;
 import org.apache.servicecomb.registry.api.Discovery;


[servicecomb-java-chassis] 01/05: [SCB-1971] Introduce SPI mechanism to enable/disable zero-config and changes to adapt to new interfaces

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

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

commit e10beacf3fc7ad6d46e4f9d718970319ccf97450
Author: Jun Gan <ju...@gmail.com>
AuthorDate: Sun May 31 21:26:56 2020 -0400

    [SCB-1971] Introduce SPI mechanism to enable/disable zero-config and changes to adapt to new interfaces
---
 .../zeroconfig/ZeroConfigDiscovery.java            | 103 +++++++
 .../zeroconfig/ZeroConfigRegistration.java         | 156 +++++++++++
 .../ZeroConfigRegistryApplicationListener.java     |  91 ------
 .../zeroconfig/client/ZeroConfigClient.java        | 309 +++++++++++++++++++++
 .../org.apache.servicecomb.registry.api.Discovery  |  18 ++
 ...rg.apache.servicecomb.registry.api.Registration |  18 ++
 .../zeroconfig/client/TestZeroConfigClient.java    | 294 ++++++++++++++++++++
 7 files changed, 898 insertions(+), 91 deletions(-)

diff --git a/service-registry/registry-zero-config/src/main/java/org/apache/servicecomb/zeroconfig/ZeroConfigDiscovery.java b/service-registry/registry-zero-config/src/main/java/org/apache/servicecomb/zeroconfig/ZeroConfigDiscovery.java
new file mode 100644
index 0000000..3ce2871
--- /dev/null
+++ b/service-registry/registry-zero-config/src/main/java/org/apache/servicecomb/zeroconfig/ZeroConfigDiscovery.java
@@ -0,0 +1,103 @@
+/*
+ * 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.zeroconfig;
+
+import com.netflix.config.DynamicPropertyFactory;
+import java.util.Collection;
+import java.util.List;
+import org.apache.servicecomb.registry.api.Discovery;
+import org.apache.servicecomb.registry.api.registry.Microservice;
+import org.apache.servicecomb.registry.api.registry.MicroserviceInstance;
+import org.apache.servicecomb.registry.api.registry.MicroserviceInstances;
+import org.apache.servicecomb.zeroconfig.client.ZeroConfigClient;
+
+public class ZeroConfigDiscovery implements Discovery {
+
+  private static final String NAME = "zero-config discovery";
+  private static final String ENABLED = "servicecomb.zeroconfig.registry.discovery.enabled";
+
+  private ZeroConfigClient zeroConfigClient = ZeroConfigClient.INSTANCE;
+  private String revision;
+
+  @Override
+  public boolean enabled() {
+    return DynamicPropertyFactory.getInstance().getBooleanProperty(ENABLED, true).get();
+  }
+
+  @Override
+  public void init() {
+    // done in registration
+  }
+
+  @Override
+  public void run() {
+    // done in registration
+  }
+
+  @Override
+  public void destroy() {
+    // done in registration
+  }
+
+  @Override
+  public int getOrder() {
+    return 101;
+  }
+
+  @Override
+  public Microservice getMicroservice(String microserviceId) {
+    return zeroConfigClient.getMicroservice(microserviceId);
+  }
+
+  @Override
+  public List<Microservice> getAllMicroservices() {
+    return zeroConfigClient.getAllMicroservices();
+  }
+
+  @Override
+  public String getSchema(String microserviceId, Collection<MicroserviceInstance> instances,
+      String schemaId) {
+    return zeroConfigClient.getSchema(microserviceId, schemaId);
+  }
+
+  @Override
+  public MicroserviceInstance getMicroserviceInstance(String serviceId, String instanceId) {
+    return zeroConfigClient.findMicroserviceInstance(serviceId, instanceId);
+  }
+
+  @Override
+  public MicroserviceInstances findServiceInstances(String appId, String serviceName,
+      String versionRule) {
+    return zeroConfigClient.findServiceInstances(appId, serviceName, versionRule);
+  }
+
+  @Override
+  public String getRevision() {
+    return this.revision;
+  }
+
+  @Override
+  public void setRevision(String revision) {
+    this.revision = revision;
+  }
+
+  @Override
+  public String name() {
+    return NAME;
+  }
+
+}
diff --git a/service-registry/registry-zero-config/src/main/java/org/apache/servicecomb/zeroconfig/ZeroConfigRegistration.java b/service-registry/registry-zero-config/src/main/java/org/apache/servicecomb/zeroconfig/ZeroConfigRegistration.java
new file mode 100644
index 0000000..06c0849
--- /dev/null
+++ b/service-registry/registry-zero-config/src/main/java/org/apache/servicecomb/zeroconfig/ZeroConfigRegistration.java
@@ -0,0 +1,156 @@
+/*
+ * 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.zeroconfig;
+
+import com.netflix.config.DynamicPropertyFactory;
+import java.util.Collection;
+import org.apache.servicecomb.config.ConfigUtil;
+import org.apache.servicecomb.config.archaius.sources.MicroserviceConfigLoader;
+import org.apache.servicecomb.registry.api.Registration;
+import org.apache.servicecomb.registry.api.registry.BasePath;
+import org.apache.servicecomb.registry.api.registry.Microservice;
+import org.apache.servicecomb.registry.api.registry.MicroserviceFactory;
+import org.apache.servicecomb.registry.api.registry.MicroserviceInstance;
+import org.apache.servicecomb.registry.api.registry.MicroserviceInstanceStatus;
+import org.apache.servicecomb.registry.definition.MicroserviceDefinition;
+import org.apache.servicecomb.zeroconfig.client.ClientUtil;
+import org.apache.servicecomb.zeroconfig.client.ZeroConfigClient;
+import org.apache.servicecomb.zeroconfig.server.ServerUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ZeroConfigRegistration implements Registration {
+
+  private static final Logger LOGGER = LoggerFactory.getLogger(ZeroConfigRegistration.class);
+
+  public static ZeroConfigRegistration INSTANCE = new ZeroConfigRegistration();
+
+  private static final String NAME = "zero-config registration";
+  private static final String ENABLED = "servicecomb.zeroconfig.registry.registration.enabled";
+
+  private ZeroConfigClient zeroConfigClient = ZeroConfigClient.INSTANCE;
+
+  // registration objects
+  private Microservice selfMicroservice;
+  private MicroserviceInstance selfMicroserviceInstance;
+
+  @Override
+  public boolean enabled() {
+    return DynamicPropertyFactory.getInstance().getBooleanProperty(ENABLED, true).get();
+  }
+
+  @Override
+  public void init() {
+    // init self Microservice & MicroserviceInstance objects
+    MicroserviceConfigLoader loader = ConfigUtil.getMicroserviceConfigLoader();
+    MicroserviceDefinition microserviceDefinition = new MicroserviceDefinition(
+        loader.getConfigModels());
+    MicroserviceFactory microserviceFactory = new MicroserviceFactory();
+    this.selfMicroservice = microserviceFactory.create(microserviceDefinition);
+    this.selfMicroserviceInstance = selfMicroservice.getInstance();
+
+    ServerUtil.init();
+    ClientUtil.init();
+  }
+
+  @Override
+  public void run() {
+    // register service instance
+    boolean registerResult = zeroConfigClient.register();
+
+    if (!registerResult) {
+      LOGGER.error("Failed to Register Service Instance in Zero-Config mode");
+    }
+  }
+
+  @Override
+  public void destroy() {
+    // unregister service instance
+    boolean unregisterResult = zeroConfigClient.unregister();
+
+    if (!unregisterResult) {
+      LOGGER.error("Failed to Unregister Service Instance in Zero-Config mode");
+    }
+  }
+
+  @Override
+  public int getOrder() {
+    return 101;
+  }
+
+  @Override
+  public String name() {
+    return NAME;
+  }
+
+  @Override
+  public MicroserviceInstance getMicroserviceInstance() {
+    return this.selfMicroserviceInstance;
+  }
+
+  @Override
+  public Microservice getMicroservice() {
+    return this.selfMicroservice;
+  }
+
+  @Override
+  public String getAppId() {
+    return this.selfMicroservice.getAppId();
+  }
+
+  @Override
+  public boolean updateMicroserviceInstanceStatus(MicroserviceInstanceStatus status) {
+    this.selfMicroserviceInstance.setStatus(status);
+    return true;
+  }
+
+  @Override
+  public void addSchema(String schemaId, String content) {
+    this.selfMicroservice.addSchema(schemaId, content);
+  }
+
+  @Override
+  public void addEndpoint(String endpoint) {
+    this.selfMicroserviceInstance.getEndpoints().add(endpoint);
+  }
+
+  @Override
+  public void addBasePath(Collection<BasePath> basePaths) {
+    this.selfMicroservice.getPaths().addAll(basePaths);
+  }
+
+  // setter/getter
+
+  public void setSelfMicroservice(
+      Microservice selfMicroservice) {
+    this.selfMicroservice = selfMicroservice;
+  }
+
+  public Microservice getSelfMicroservice() {
+    return this.selfMicroservice;
+  }
+
+  public void setSelfMicroserviceInstance(
+      MicroserviceInstance selfMicroserviceInstance) {
+    this.selfMicroserviceInstance = selfMicroserviceInstance;
+  }
+
+  public MicroserviceInstance getSelfMicroserviceInstance() {
+    return this.selfMicroserviceInstance;
+  }
+
+}
diff --git a/service-registry/registry-zero-config/src/main/java/org/apache/servicecomb/zeroconfig/ZeroConfigRegistryApplicationListener.java b/service-registry/registry-zero-config/src/main/java/org/apache/servicecomb/zeroconfig/ZeroConfigRegistryApplicationListener.java
deleted file mode 100644
index af4f8dd..0000000
--- a/service-registry/registry-zero-config/src/main/java/org/apache/servicecomb/zeroconfig/ZeroConfigRegistryApplicationListener.java
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.servicecomb.zeroconfig;
-
-import com.netflix.config.DynamicPropertyFactory;
-import org.apache.servicecomb.foundation.common.exceptions.ServiceCombException;
-import org.apache.servicecomb.serviceregistry.ServiceRegistry;
-import org.apache.servicecomb.serviceregistry.client.ServiceRegistryClient;
-import org.apache.servicecomb.serviceregistry.config.ServiceRegistryConfig;
-
-import org.apache.servicecomb.zeroconfig.client.ClientUtil;
-import org.apache.servicecomb.zeroconfig.client.ZeroConfigRegistryClientImpl;
-import org.apache.servicecomb.zeroconfig.server.ServerUtil;
-import org.apache.servicecomb.zeroconfig.server.ZeroConfigRegistryService;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.BeansException;
-import org.springframework.context.ApplicationContext;
-import org.springframework.context.ApplicationContextAware;
-import org.springframework.context.ApplicationEvent;
-import org.springframework.context.ApplicationListener;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.core.annotation.Order;
-import org.springframework.web.client.RestTemplate;
-
-import java.io.IOException;
-import java.net.MulticastSocket;
-import java.util.function.Function;
-
-/**
- * ZeroConfigServiceRegistryClientImpl is injected before cse application listener (order is -1000)
- */
-
-@Configuration
-@Order(-1001)
-public class ZeroConfigRegistryApplicationListener implements ApplicationListener<ApplicationEvent>,
-    ApplicationContextAware {
-
-  private static final Logger LOGGER = LoggerFactory
-      .getLogger(ZeroConfigRegistryApplicationListener.class);
-
-  private MulticastSocket multicastSocket;
-
-  @Override
-  public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
-
-    // same mechanism as Local registry to enable the Zero Config registry
-    boolean enable = DynamicPropertyFactory.getInstance()
-        .getBooleanProperty("servicecomb.zeroconfig.enabled", true).get();
-
-    if (!enable) {
-      return;
-    }
-
-    LOGGER.info("ServiceComb is running in zero-config registry mode");
-    
-    ServerUtil.init();
-    ClientUtil.init();
-
-    try {
-      this.multicastSocket = new MulticastSocket();
-    } catch (IOException e) {
-      throw new ServiceCombException("Failed to create MulticastSocket object", e);
-    }
-
-    Function<ServiceRegistry, ServiceRegistryClient> registryClientConstructor =
-        serviceRegistry -> new ZeroConfigRegistryClientImpl(new ZeroConfigRegistryService(),
-            multicastSocket, new RestTemplate());
-
-    ServiceRegistryConfig.INSTANCE.setServiceRegistryClientConstructor(registryClientConstructor);
-
-  }
-
-  @Override
-  public void onApplicationEvent(ApplicationEvent event) {
-  }
-}
diff --git a/service-registry/registry-zero-config/src/main/java/org/apache/servicecomb/zeroconfig/client/ZeroConfigClient.java b/service-registry/registry-zero-config/src/main/java/org/apache/servicecomb/zeroconfig/client/ZeroConfigClient.java
new file mode 100644
index 0000000..23e290a
--- /dev/null
+++ b/service-registry/registry-zero-config/src/main/java/org/apache/servicecomb/zeroconfig/client/ZeroConfigClient.java
@@ -0,0 +1,309 @@
+/*
+ * 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.zeroconfig.client;
+
+import java.io.IOException;
+import java.net.DatagramPacket;
+import java.net.InetAddress;
+import java.net.MulticastSocket;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import org.apache.commons.lang.StringUtils;
+import org.apache.servicecomb.registry.api.registry.FindInstancesResponse;
+import org.apache.servicecomb.registry.api.registry.Microservice;
+import org.apache.servicecomb.registry.api.registry.MicroserviceInstance;
+import org.apache.servicecomb.registry.api.registry.MicroserviceInstances;
+import org.apache.servicecomb.registry.version.Version;
+import org.apache.servicecomb.registry.version.VersionRule;
+import org.apache.servicecomb.registry.version.VersionRuleUtils;
+import org.apache.servicecomb.registry.version.VersionUtils;
+import org.apache.servicecomb.zeroconfig.ZeroConfigRegistration;
+import org.apache.servicecomb.zeroconfig.server.ServerMicroserviceInstance;
+import org.apache.servicecomb.zeroconfig.server.ServerUtil;
+import org.apache.servicecomb.zeroconfig.server.ZeroConfigRegistryService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.web.client.RestTemplate;
+
+import static org.apache.servicecomb.zeroconfig.ZeroConfigRegistryConstants.*;
+
+public class ZeroConfigClient {
+
+  private static final Logger LOGGER = LoggerFactory.getLogger(ZeroConfigClient.class);
+
+  public static ZeroConfigClient INSTANCE = buildZeroConfigClient();
+
+  // Constructor Parameters
+  private ZeroConfigRegistryService zeroConfigRegistryService;
+  private RestTemplate restTemplate;
+  private MulticastSocket multicastSocket;
+
+  // Constructor
+  public ZeroConfigClient(ZeroConfigRegistryService zeroConfigRegistryService,
+      MulticastSocket multicastSocket, RestTemplate restTemplate) {
+    this.zeroConfigRegistryService = zeroConfigRegistryService;
+    this.restTemplate = restTemplate;
+    this.multicastSocket = multicastSocket;
+  }
+
+  // builder method
+  private static ZeroConfigClient buildZeroConfigClient() {
+    MulticastSocket multicastSocket = null;
+    try {
+      multicastSocket = new MulticastSocket();
+      multicastSocket.setLoopbackMode(false);
+    } catch (IOException e) {
+      // since we support multiple registries, not blocking other type of registries
+      LOGGER.error("Failed to create MulticastSocket object in Zero-Config mode", e);
+      //throw new ServiceCombException("Failed to create MulticastSocket object", e);
+    }
+    return new ZeroConfigClient(new ZeroConfigRegistryService(), multicastSocket,
+        new RestTemplate());
+  }
+
+  public boolean register() {
+    Map<String, String> data = prepareRegisterData();
+    if (data == null || data.isEmpty()) {
+      return false;
+    }
+    String serviceInstanceId = doRegister(data);
+    return StringUtils.isNotEmpty(serviceInstanceId);
+  }
+
+  private String doRegister(Map<String, String> serviceInstanceDataMap) {
+    try {
+      byte[] instanceData = serviceInstanceDataMap.toString().getBytes();
+      DatagramPacket instanceDataPacket = new DatagramPacket(instanceData, instanceData.length,
+          InetAddress.getByName(GROUP), PORT);
+      this.multicastSocket.send(instanceDataPacket);
+
+      // set this variable for heartbeat itself status
+      serviceInstanceDataMap.put(EVENT, HEARTBEAT_EVENT);
+      ClientUtil.setServiceInstanceMapForHeartbeat(serviceInstanceDataMap);
+    } catch (IOException e) {
+      LOGGER.error(
+          "Failed to Multicast Microservice Instance Registration Event in Zero-Config mode. servcieId: {} instanceId:{}",
+          serviceInstanceDataMap.get(SERVICE_ID), serviceInstanceDataMap.get(INSTANCE_ID), e);
+      return null;
+    }
+    return serviceInstanceDataMap.get(INSTANCE_ID);
+  }
+
+  public boolean unregister() {
+    ServerMicroserviceInstance foundInstance = preUnregisterCheck();
+    if (foundInstance == null) {
+      LOGGER.warn(
+          "Failed to unregister as Microservice Instance doesn't exist in server side in Zero-Config mode");
+      return false;
+    }
+
+    try {
+      LOGGER.info(
+          "Start Multicast Microservice Instance Unregister Event in Zero-Config mode. Service ID: {}, Instance ID:{}",
+          foundInstance.getServiceId(), foundInstance.getInstanceId());
+      Map<String, String> unregisterEventMap = new HashMap<>();
+      unregisterEventMap.put(EVENT, UNREGISTER_EVENT);
+      unregisterEventMap.put(SERVICE_ID, foundInstance.getServiceId());
+      unregisterEventMap.put(INSTANCE_ID, foundInstance.getInstanceId());
+      byte[] unregisterEventBytes = unregisterEventMap.toString().getBytes();
+      DatagramPacket unregisterEventDataPacket = new DatagramPacket(unregisterEventBytes,
+          unregisterEventBytes.length, InetAddress.getByName(GROUP), PORT);
+      this.multicastSocket.send(unregisterEventDataPacket);
+      return true;
+    } catch (IOException e) {
+      LOGGER.error(
+          "Failed to Multicast Microservice Instance Unregister Event in Zero-Config mode. Service ID: {}, Instance ID:{}",
+          foundInstance.getServiceId(), foundInstance.getInstanceId(), e);
+      return false;
+    }
+
+  }
+
+  public List<Microservice> getAllMicroservices() {
+    List<Microservice> resultAllServices = new ArrayList<>();
+    Map<String, Map<String, ServerMicroserviceInstance>> allServicesMap = ServerUtil.microserviceInstanceMap;
+    allServicesMap.forEach((serviceId, instanceIdMap) -> {
+      instanceIdMap.forEach((instanceId, instance) -> {
+        resultAllServices.add(ClientUtil.convertToClientMicroservice(instance));
+      });
+    });
+    return resultAllServices;
+  }
+
+  public Microservice getMicroservice(String microserviceId) {
+    Microservice selfMicroservice = ZeroConfigRegistration.INSTANCE.getSelfMicroservice();
+    // for registration
+    if (selfMicroservice.getServiceId().equals(microserviceId)) {
+      return selfMicroservice;
+    } else {
+      // called when consumer discover provider for the very first time
+      return ClientUtil
+          .convertToClientMicroservice(zeroConfigRegistryService.getMicroservice(microserviceId));
+    }
+  }
+
+  public String getSchema(String microserviceId, String schemaId) {
+    Microservice selfMicroservice = ZeroConfigRegistration.INSTANCE.getSelfMicroservice();
+    LOGGER.info("Retrieve schema content for Microservice ID: {}, Schema ID: {}",
+        microserviceId, schemaId);
+    // called by service registration task when registering itself
+    if (selfMicroservice.getServiceId().equals(microserviceId)) {
+      return selfMicroservice.getSchemaMap().computeIfPresent(schemaId, (k, v) -> v);
+    } else {
+      // called by consumer to load provider's schema content for the very first time
+      String providerEndpoint = this.getEndpointForMicroservice(microserviceId);
+      if (providerEndpoint == null) {
+        throw new IllegalArgumentException("Provider's endpoint can NOT be Null");
+      }
+      String providerSchemaContentEndpoint =
+          providerEndpoint + "/schemaEndpoint/schemas?schemaId=" + schemaId;
+
+      LOGGER.info("Retrieve schema content from endpoint:{}", providerSchemaContentEndpoint);
+      // Make a rest call to provider's endpoint directly to retrieve the schema content
+      return restTemplate.getForObject(providerSchemaContentEndpoint, String.class);
+    }
+  }
+
+  private String getEndpointForMicroservice(String microserviceId) {
+    ServerMicroserviceInstance serverMicroserviceInstance = zeroConfigRegistryService
+        .getMicroservice(microserviceId);
+    LOGGER.info("Retrieve endpoint for serve rMicroservice Instance: {}",
+        serverMicroserviceInstance);
+    if (serverMicroserviceInstance != null && !serverMicroserviceInstance.getEndpoints()
+        .isEmpty()) {
+      return serverMicroserviceInstance.getEndpoints().get(0)
+          .replace(ENDPOINT_PREFIX_REST, ENDPOINT_PREFIX_HTTP);
+    }
+    return null;
+  }
+
+  public MicroserviceInstance findMicroserviceInstance(String serviceId, String instanceId) {
+    Optional<ServerMicroserviceInstance> optionalInstance = this.zeroConfigRegistryService.
+        findServiceInstance(serviceId, instanceId);
+
+    if (optionalInstance.isPresent()) {
+      return ClientUtil
+          .convertToClientMicroserviceInstance(optionalInstance.get());
+    } else {
+      LOGGER.error(
+          "Invalid serviceId OR instanceId! Failed to retrieve Microservice Instance for serviceId {} and instanceId {}",
+          serviceId, instanceId);
+      return null;
+    }
+  }
+
+  public MicroserviceInstances findServiceInstances(String appId, String providerServiceName,
+      String strVersionRule) {
+    LOGGER.info(
+        "Find service instance for App ID: {}, Provider ServiceName: {}, versionRule: {} in Zero-Config mode",
+        appId, providerServiceName, strVersionRule);
+
+    MicroserviceInstances resultMicroserviceInstances = new MicroserviceInstances();
+    FindInstancesResponse response = new FindInstancesResponse();
+    List<MicroserviceInstance> resultInstanceList = new ArrayList<>();
+
+    // 1.  find matched appId and serviceName from "Server"
+    List<ServerMicroserviceInstance> tempServerInstanceList = this.zeroConfigRegistryService.
+        findServiceInstances(appId, providerServiceName);
+
+    // 2.  find matched instance based on the strVersionRule
+    VersionRule versionRule = VersionRuleUtils.getOrCreate(strVersionRule);
+
+    ServerMicroserviceInstance latestVersionInstance = findLatestVersionInstance(
+        tempServerInstanceList, versionRule);
+    if (latestVersionInstance != null) {
+      Version latestVersion = VersionUtils.getOrCreate(latestVersionInstance.getVersion());
+      for (ServerMicroserviceInstance serverInstance : tempServerInstanceList) {
+        Version version = VersionUtils.getOrCreate(serverInstance.getVersion());
+        if (!versionRule.isMatch(version, latestVersion)) {
+          continue;
+        }
+        resultInstanceList.add(ClientUtil.convertToClientMicroserviceInstance(serverInstance));
+      }
+    }
+
+    response.setInstances(resultInstanceList);
+    resultMicroserviceInstances.setInstancesResponse(response);
+    return resultMicroserviceInstances;
+  }
+
+  private ServerMicroserviceInstance findLatestVersionInstance(
+      List<ServerMicroserviceInstance> instanceList, VersionRule versionRule) {
+    Version latestVersion = null;
+    ServerMicroserviceInstance latestVersionInstance = null;
+    for (ServerMicroserviceInstance serverInstance : instanceList) {
+      Version version = VersionUtils.getOrCreate(serverInstance.getVersion());
+      if (!versionRule.isAccept(version)) {
+        continue;
+      }
+
+      if (latestVersion == null || version.compareTo(latestVersion) > 0) {
+        latestVersion = version;
+        latestVersionInstance = serverInstance;
+      }
+    }
+    return latestVersionInstance;
+  }
+
+  private Map<String, String> prepareRegisterData() {
+    // set serviceId
+    Microservice selfMicroservice = ZeroConfigRegistration.INSTANCE.getSelfMicroservice();
+    MicroserviceInstance selfMicroserviceInstance = ZeroConfigRegistration.INSTANCE
+        .getSelfMicroserviceInstance();
+
+    if (selfMicroservice == null || selfMicroserviceInstance == null) {
+      return null;
+    }
+
+    String serviceId = selfMicroservice.getServiceId();
+    if (StringUtils.isEmpty(serviceId)) {
+      serviceId = ClientUtil.generateServiceId(selfMicroservice);
+      selfMicroservice.setServiceId(serviceId);
+      selfMicroserviceInstance.setServiceId(serviceId);
+    }
+
+    // set instanceId
+    String instanceId = selfMicroserviceInstance
+        .getInstanceId(); // allow client to set the instanceId
+    if (StringUtils.isEmpty(instanceId)) {
+      instanceId = ClientUtil.generateServiceInstanceId();
+      selfMicroserviceInstance.setInstanceId(instanceId);
+    }
+
+    // Convert to Multicast data format
+    Optional<Map<String, String>> optionalDataMap = ClientUtil
+        .convertToRegisterDataModel(serviceId, instanceId, selfMicroserviceInstance,
+            selfMicroservice);
+
+    return optionalDataMap.orElse(null);
+  }
+
+  private ServerMicroserviceInstance preUnregisterCheck() {
+    MicroserviceInstance instance = ZeroConfigRegistration.INSTANCE.getSelfMicroserviceInstance();
+    String serviceId = instance.getServiceId();
+    String instanceId = instance.getInstanceId();
+    Optional<ServerMicroserviceInstance> optionalInstance = zeroConfigRegistryService
+        .findServiceInstance(serviceId, instanceId);
+    if (optionalInstance.isPresent()) {
+      return optionalInstance.get();
+    }
+    return null;
+  }
+}
diff --git a/service-registry/registry-zero-config/src/main/resources/META-INF/services/org.apache.servicecomb.registry.api.Discovery b/service-registry/registry-zero-config/src/main/resources/META-INF/services/org.apache.servicecomb.registry.api.Discovery
new file mode 100644
index 0000000..b1d5d1e
--- /dev/null
+++ b/service-registry/registry-zero-config/src/main/resources/META-INF/services/org.apache.servicecomb.registry.api.Discovery
@@ -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.zeroconfig.ZeroConfigDiscovery
\ No newline at end of file
diff --git a/service-registry/registry-zero-config/src/main/resources/META-INF/services/org.apache.servicecomb.registry.api.Registration b/service-registry/registry-zero-config/src/main/resources/META-INF/services/org.apache.servicecomb.registry.api.Registration
new file mode 100644
index 0000000..6f13cf8
--- /dev/null
+++ b/service-registry/registry-zero-config/src/main/resources/META-INF/services/org.apache.servicecomb.registry.api.Registration
@@ -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.zeroconfig.ZeroConfigRegistration
\ No newline at end of file
diff --git a/service-registry/registry-zero-config/src/test/java/org/apache/servicecomb/zeroconfig/client/TestZeroConfigClient.java b/service-registry/registry-zero-config/src/test/java/org/apache/servicecomb/zeroconfig/client/TestZeroConfigClient.java
new file mode 100644
index 0000000..e77e715
--- /dev/null
+++ b/service-registry/registry-zero-config/src/test/java/org/apache/servicecomb/zeroconfig/client/TestZeroConfigClient.java
@@ -0,0 +1,294 @@
+/*
+ * 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.zeroconfig.client;
+
+import static org.mockito.Matchers.anyObject;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.mockito.Mockito.when;
+
+import java.io.IOException;
+import java.net.MulticastSocket;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+import org.apache.servicecomb.registry.api.registry.Microservice;
+import org.apache.servicecomb.registry.api.registry.MicroserviceInstance;
+import org.apache.servicecomb.registry.api.registry.MicroserviceInstanceStatus;
+import org.apache.servicecomb.registry.api.registry.MicroserviceInstances;
+import org.apache.servicecomb.zeroconfig.ZeroConfigRegistration;
+import org.apache.servicecomb.zeroconfig.server.ServerMicroserviceInstance;
+import org.apache.servicecomb.zeroconfig.server.ZeroConfigRegistryService;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.springframework.web.client.RestTemplate;
+
+public class TestZeroConfigClient {
+
+  ZeroConfigClient target;
+
+  @Mock
+  ZeroConfigRegistryService zeroConfigRegistryService;
+
+  @Mock
+  MulticastSocket multicastSocket;
+
+  @Mock
+  RestTemplate restTemplate;
+
+  // testing data
+  String selfServiceId = "123";
+  String selfInstanceId = "instanceId";
+  String otherServiceId = "456";
+  String appId = "appId";
+  String serviceName = "serviceName";
+  String version = "0.0.0.1";
+  String status = "UP";
+  String host = "host";
+  String schemaId1 = "schemaId1";
+  String schemaContent1 = "schemaContent1";
+  String endpoint1 = "endpoint1";
+  String strVersionRule = "0.0.0.0+";
+
+  @Before
+  public void setUp() {
+    MockitoAnnotations.initMocks(this);
+    target = new ZeroConfigClient(zeroConfigRegistryService, multicastSocket, restTemplate);
+
+    prepareSelfMicroserviceAndInstance();
+  }
+
+  private void prepareSelfMicroserviceAndInstance() {
+    // Microservice
+    Microservice microservice = new Microservice();
+    microservice.setServiceId(selfServiceId);
+    microservice.setServiceName(serviceName);
+    microservice.setAppId(appId);
+    microservice.setVersion(version);
+    microservice.setStatus(status);
+    List<String> schemas = new ArrayList<>();
+    schemas.add(schemaId1);
+    microservice.setSchemas(schemas);
+    microservice.addSchema(schemaId1, schemaContent1);
+
+    // MicroserviceInstance
+    MicroserviceInstance microserviceInstance = new MicroserviceInstance();
+    microserviceInstance.setServiceId(selfServiceId);
+    microserviceInstance.setInstanceId(selfInstanceId);
+    List<String> endpointList = new ArrayList<>();
+    endpointList.add(endpoint1);
+    microserviceInstance.setEndpoints(endpointList);
+    microserviceInstance.setStatus(MicroserviceInstanceStatus.UP);
+    microserviceInstance.setHostName(host);
+
+    microservice.setInstance(microserviceInstance);
+    ZeroConfigRegistration.INSTANCE.setSelfMicroservice(microservice);
+    ZeroConfigRegistration.INSTANCE.setSelfMicroserviceInstance(microserviceInstance);
+  }
+
+  private ServerMicroserviceInstance prepareServerServiceInstance(boolean withEndpoint) {
+    ServerMicroserviceInstance serverServiceInstance = new ServerMicroserviceInstance();
+    serverServiceInstance.setServiceId(otherServiceId);
+    serverServiceInstance.setInstanceId(selfInstanceId);
+    serverServiceInstance.setServiceName(serviceName);
+    serverServiceInstance.setAppId(appId);
+    serverServiceInstance.setVersion(version);
+    serverServiceInstance.setStatus(status);
+    serverServiceInstance.setHostName(host);
+
+    List<String> schemas = new ArrayList<>();
+    schemas.add(schemaId1);
+    serverServiceInstance.setSchemas(schemas);
+
+    if (withEndpoint) {
+      List<String> endpointList = new ArrayList<>();
+      endpointList.add(endpoint1);
+      serverServiceInstance.setEndpoints(endpointList);
+    }
+
+    return serverServiceInstance;
+  }
+
+  // test register method
+  @Test
+  public void test_register_withCorrectData_RegisterShouldSucceed() {
+    boolean returnedResult = target.register();
+
+    Assert.assertTrue(returnedResult);
+  }
+
+  @Test
+  public void test_register_withWrongData_RegisterShouldFail() {
+    ZeroConfigRegistration.INSTANCE.setSelfMicroservice(null);
+
+    boolean returnedResult = target.register();
+
+    Assert.assertFalse(returnedResult);
+  }
+
+  @Test
+  public void test_register_MulticastThrowException_RegisterShouldFail() throws IOException {
+    doThrow(IOException.class).when(multicastSocket).send(anyObject());
+
+    boolean returnedResult = target.register();
+
+    Assert.assertFalse(returnedResult);
+  }
+
+  // test unregister method
+  @Test
+  public void test_unregister_withCorrectData_UnregisterShouldSucceed() {
+    when(zeroConfigRegistryService.findServiceInstance(selfServiceId, selfInstanceId))
+        .thenReturn(Optional.of(prepareServerServiceInstance(true)));
+
+    boolean returnedResult = target.unregister();
+
+    Assert.assertTrue(returnedResult);
+  }
+
+  @Test
+  public void test_unregister_withWrongData_UnregisterShouldFail() {
+    when(zeroConfigRegistryService.findServiceInstance(selfServiceId, selfInstanceId))
+        .thenReturn(Optional.empty());
+
+    boolean returnedResult = target.unregister();
+
+    Assert.assertFalse(returnedResult);
+  }
+
+  @Test
+  public void test_unregister_MulticastThrowException_UnregisterShouldFail() throws IOException {
+    when(zeroConfigRegistryService.findServiceInstance(selfServiceId, selfInstanceId))
+        .thenReturn(Optional.of(prepareServerServiceInstance(true)));
+    doThrow(IOException.class).when(multicastSocket).send(anyObject());
+
+    boolean returnedResult = target.unregister();
+
+    Assert.assertFalse(returnedResult);
+  }
+
+  // test getMicroservice method
+  @Test
+  public void test_getMicroservice_forItself_shouldReturnItself_And_NotCallZeroConfigRegistryService() {
+    Microservice returnedResult = target.getMicroservice(selfServiceId);
+
+    Assert
+        .assertEquals(ZeroConfigRegistration.INSTANCE.getSelfMicroservice().getServiceId(),
+            returnedResult.getServiceId());
+    verifyZeroInteractions(zeroConfigRegistryService);
+  }
+
+  @Test
+  public void test_getMicroservice_forOtherService_shouldCallZeroConfigRegistryService() {
+    when(zeroConfigRegistryService.getMicroservice(otherServiceId))
+        .thenReturn(prepareServerServiceInstance(true));
+
+    Microservice returnedResult = target.getMicroservice(otherServiceId);
+
+    Assert.assertEquals(otherServiceId, returnedResult.getServiceId());
+    verify(zeroConfigRegistryService, times(1)).getMicroservice(otherServiceId);
+  }
+
+  // test getSchema method
+  @Test
+  public void test_getSchema_forSelfMicroservice_shouldNotCallZeroConfigRegistryService_And_Succeed() {
+    String returnedResult = target.getSchema(selfServiceId, schemaId1);
+    Assert.assertEquals(schemaContent1, returnedResult);
+    verifyZeroInteractions(zeroConfigRegistryService);
+  }
+
+  @Test
+  public void test_getSchema_forOtherMicroservice_shouldCallZeroConfigRegistryService_And_Succeed() {
+    when(zeroConfigRegistryService.getMicroservice(otherServiceId))
+        .thenReturn(prepareServerServiceInstance(true));
+    String schemaContentEndpoint = endpoint1 + "/schemaEndpoint/schemas?schemaId=" + schemaId1;
+    when(restTemplate.getForObject(schemaContentEndpoint, String.class)).thenReturn(schemaContent1);
+
+    String returnedResult = target.getSchema(otherServiceId, schemaId1);
+
+    Assert.assertEquals(schemaContent1, returnedResult);
+  }
+
+  @Test(expected = IllegalArgumentException.class)
+  public void test_getSchema_whenProviderEndpointIsNull_shouldThrowIllegalArgumentException() {
+    when(zeroConfigRegistryService.getMicroservice(otherServiceId))
+        .thenReturn(prepareServerServiceInstance(false));
+
+    target.getSchema(otherServiceId, schemaId1);
+
+    verifyZeroInteractions(restTemplate);
+  }
+
+  // test findMicroserviceInstance method
+  @Test
+  public void test_findMicroserviceInstance_forNonExistInstance_shouldReturnNull() {
+    when(zeroConfigRegistryService.findServiceInstance(selfServiceId, selfInstanceId))
+        .thenReturn(Optional.empty());
+
+    MicroserviceInstance returnedResult = target
+        .findMicroserviceInstance(selfServiceId, selfInstanceId);
+
+    Assert.assertNull(returnedResult);
+  }
+
+  @Test
+  public void test_findMicroServiceInstance_forExistInstance_shouldReturnInstance() {
+    when(zeroConfigRegistryService.findServiceInstance(otherServiceId, selfInstanceId))
+        .thenReturn(Optional.of(prepareServerServiceInstance(true)));
+
+    MicroserviceInstance returnedResult = target
+        .findMicroserviceInstance(otherServiceId, selfInstanceId);
+
+    Assert.assertNotNull(returnedResult);
+    Assert.assertEquals(otherServiceId, returnedResult.getServiceId());
+    Assert.assertEquals(selfInstanceId, returnedResult.getInstanceId());
+  }
+
+  @Test
+  public void test_findServiceInstances_forNonExistInstance_shouldReturnEmptyResult() {
+    List<ServerMicroserviceInstance> serverMicroserviceInstancesList = new ArrayList<>();
+    when(zeroConfigRegistryService.findServiceInstances(selfServiceId, selfInstanceId))
+        .thenReturn(serverMicroserviceInstancesList);
+
+    MicroserviceInstances returnedResult = target
+        .findServiceInstances(appId, serviceName, strVersionRule);
+
+    Assert.assertEquals(0, returnedResult.getInstancesResponse().getInstances().size());
+  }
+
+  @Test
+  public void test_findServiceInstances_forExistInstance_shouldReturnInstances() {
+    List<ServerMicroserviceInstance> serverMicroserviceInstancesList = new ArrayList<>();
+    serverMicroserviceInstancesList.add(prepareServerServiceInstance(true));
+    when(zeroConfigRegistryService.findServiceInstances(appId, serviceName))
+        .thenReturn(serverMicroserviceInstancesList);
+
+    MicroserviceInstances returnedResult = target
+        .findServiceInstances(appId, serviceName, strVersionRule);
+    List<MicroserviceInstance> returnedInstanceList = returnedResult.getInstancesResponse()
+        .getInstances();
+
+    Assert.assertEquals(1, returnedInstanceList.size());
+    Assert.assertEquals(selfInstanceId, returnedInstanceList.get(0).getInstanceId());
+  }
+}
+