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 2019/01/07 12:29:51 UTC

[servicecomb-java-chassis] branch master updated (f546b0f -> 8d2e6e8)

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 f546b0f  [CB-1102]fix empty swagger and information leak problem
     new d64c253  [SCB-1083]make some status can be invoked by custom filters
     new 8d2e6e8  [SCB-1083]fix implementations of AbstractDiscoveryFilter return null problem

The 2 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:
 .../demo/springmvc/client/TestBizkeeper.java       |   2 +-
 .../src/main/resources/microservice.yaml           |   1 +
 .../src/main/resources/microservice.yaml           |   2 +
 .../loadbalance/TestLoadBalanceHandler2.java       | 145 +++++++++++++++++++++
 .../serviceregistry/cache/InstanceCache.java       |   2 +-
 .../consumer/MicroserviceVersions.java             |   2 -
 .../discovery/AbstractDiscoveryFilter.java         |  14 +-
 .../discovery/InstanceStatusDiscoveryFilter.java   |  74 +++++++++++
 ...ecomb.serviceregistry.discovery.DiscoveryFilter |   2 +-
 .../consumer/TestMicroserviceVersions.java         |  16 ---
 10 files changed, 238 insertions(+), 22 deletions(-)
 create mode 100644 service-registry/src/main/java/org/apache/servicecomb/serviceregistry/discovery/InstanceStatusDiscoveryFilter.java
 copy {core => service-registry}/src/main/resources/META-INF/services/org.apache.servicecomb.serviceregistry.discovery.DiscoveryFilter (90%)


[servicecomb-java-chassis] 02/02: [SCB-1083]fix implementations of AbstractDiscoveryFilter return null problem

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 8d2e6e83b117ceb85cda354f8b4f973e6a8f1eca
Author: liubao <ba...@huawei.com>
AuthorDate: Mon Jan 7 10:48:29 2019 +0800

    [SCB-1083]fix implementations of AbstractDiscoveryFilter return null problem
---
 .../serviceregistry/discovery/AbstractDiscoveryFilter.java | 14 +++++++++++++-
 .../discovery/InstanceStatusDiscoveryFilter.java           |  4 ++--
 2 files changed, 15 insertions(+), 3 deletions(-)

diff --git a/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/discovery/AbstractDiscoveryFilter.java b/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/discovery/AbstractDiscoveryFilter.java
index f5cb202..21dcaa8 100644
--- a/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/discovery/AbstractDiscoveryFilter.java
+++ b/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/discovery/AbstractDiscoveryFilter.java
@@ -17,7 +17,14 @@
 
 package org.apache.servicecomb.serviceregistry.discovery;
 
+import java.util.HashMap;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
 public abstract class AbstractDiscoveryFilter implements DiscoveryFilter {
+  private static final Logger LOGGER = LoggerFactory.getLogger(AbstractDiscoveryFilter.class);
+
   @Override
   public DiscoveryTreeNode discovery(DiscoveryContext context, DiscoveryTreeNode parent) {
     if (!parent.childrenInited()) {
@@ -30,7 +37,12 @@ public abstract class AbstractDiscoveryFilter implements DiscoveryFilter {
     }
 
     String childName = findChildName(context, parent);
-    return parent.child(childName);
+    DiscoveryTreeNode node = parent.child(childName);
+    if (node == null) {
+      LOGGER.warn("discovery filter {} return null.", this.getClass().getName());
+      return new DiscoveryTreeNode().subName(parent, "empty").data(new HashMap<>());
+    }
+    return node;
   }
 
   protected abstract void init(DiscoveryContext context, DiscoveryTreeNode parent);
diff --git a/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/discovery/InstanceStatusDiscoveryFilter.java b/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/discovery/InstanceStatusDiscoveryFilter.java
index f619653..630a425 100644
--- a/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/discovery/InstanceStatusDiscoveryFilter.java
+++ b/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/discovery/InstanceStatusDiscoveryFilter.java
@@ -35,7 +35,7 @@ public class InstanceStatusDiscoveryFilter extends AbstractDiscoveryFilter {
   @Override
   public int getOrder() {
     // OperationInstancesDiscoveryFilter should execute first
-    return -5000;
+    return -20000;
   }
 
   @Override
@@ -66,7 +66,7 @@ public class InstanceStatusDiscoveryFilter extends AbstractDiscoveryFilter {
     }
 
     if (filteredServers.isEmpty()) {
-      LOGGER.warn("No instance found by filter. " + this.getClass().getName());
+      return;
     }
     DiscoveryTreeNode child = new DiscoveryTreeNode().subName(parent, UP_INSTANCES).data(filteredServers);
     parent.child(UP_INSTANCES, child);


[servicecomb-java-chassis] 01/02: [SCB-1083]make some status can be invoked by custom filters

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 d64c25341d163d21a81460b6f2ace50a469655bf
Author: liubao <ba...@huawei.com>
AuthorDate: Sat Jan 5 23:45:56 2019 +0800

    [SCB-1083]make some status can be invoked by custom filters
---
 .../demo/springmvc/client/TestBizkeeper.java       |   2 +-
 .../src/main/resources/microservice.yaml           |   1 +
 .../src/main/resources/microservice.yaml           |   2 +
 .../loadbalance/TestLoadBalanceHandler2.java       | 145 +++++++++++++++++++++
 .../serviceregistry/cache/InstanceCache.java       |   2 +-
 .../consumer/MicroserviceVersions.java             |   2 -
 .../discovery/InstanceStatusDiscoveryFilter.java   |  74 +++++++++++
 ...ecomb.serviceregistry.discovery.DiscoveryFilter |  18 +++
 .../consumer/TestMicroserviceVersions.java         |  16 ---
 9 files changed, 242 insertions(+), 20 deletions(-)

diff --git a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestBizkeeper.java b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestBizkeeper.java
index 325f59f..305447e 100644
--- a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestBizkeeper.java
+++ b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestBizkeeper.java
@@ -60,7 +60,7 @@ public class TestBizkeeper {
           "servicecomb.isolation.Consumer.springmvc.codeFirstBizkeeperTest.testTimeout.timeout.enabled", "true");
       ArchaiusUtils.setProperty(
           "servicecomb.isolation.Consumer.springmvc.codeFirstBizkeeperTest.testTimeout.timeoutInMilliseconds", 500);
-      restTemplate.getForObject(prefix + "/testTimeout?name={1}&delaytime={2}", String.class, "joker", 500);
+      restTemplate.getForObject(prefix + "/testTimeout?name={1}&delaytime={2}", String.class, "joker", 1000);
       TestMgr.check("expect: throw timeout exception", "real: not throw timeout exception");
     } catch (InvocationException e) {
       TestMgr.check(TimeoutException.class, e.getCause().getCause().getClass());
diff --git a/demo/demo-springmvc/springmvc-client/src/main/resources/microservice.yaml b/demo/demo-springmvc/springmvc-client/src/main/resources/microservice.yaml
index 9a4b220..cf392a8 100644
--- a/demo/demo-springmvc/springmvc-client/src/main/resources/microservice.yaml
+++ b/demo/demo-springmvc/springmvc-client/src/main/resources/microservice.yaml
@@ -61,6 +61,7 @@ servicecomb:
     retryEnabled: true
     retryOnSame: 1
     retryOnNext: 1
+    filter.status.enabled: false
   fallbackpolicy:
     Consumer:
       springmvc:
diff --git a/demo/demo-springmvc/springmvc-server/src/main/resources/microservice.yaml b/demo/demo-springmvc/springmvc-server/src/main/resources/microservice.yaml
index 393dc52..24fc685 100644
--- a/demo/demo-springmvc/springmvc-server/src/main/resources/microservice.yaml
+++ b/demo/demo-springmvc/springmvc-server/src/main/resources/microservice.yaml
@@ -26,6 +26,8 @@ service_description:
   - path: /test2/testpath
     property:
       checksession: true
+instance_description:
+  initialStatus : TESTING
 servicecomb:
   microserviceVersionFactory: org.apache.servicecomb.core.definition.PrivateMicroserviceVersionMetaFactory
   service:
diff --git a/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestLoadBalanceHandler2.java b/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestLoadBalanceHandler2.java
index d98d672..e497974 100644
--- a/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestLoadBalanceHandler2.java
+++ b/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestLoadBalanceHandler2.java
@@ -43,6 +43,7 @@ import org.apache.servicecomb.serviceregistry.RegistryUtils;
 import org.apache.servicecomb.serviceregistry.ServiceRegistry;
 import org.apache.servicecomb.serviceregistry.api.registry.DataCenterInfo;
 import org.apache.servicecomb.serviceregistry.api.registry.MicroserviceInstance;
+import org.apache.servicecomb.serviceregistry.api.registry.MicroserviceInstanceStatus;
 import org.apache.servicecomb.serviceregistry.cache.InstanceCacheManager;
 import org.apache.servicecomb.serviceregistry.discovery.DiscoveryTree;
 import org.apache.servicecomb.serviceregistry.discovery.DiscoveryTreeNode;
@@ -356,6 +357,150 @@ public class TestLoadBalanceHandler2 {
   }
 
   @Test
+  public void testStatusFilterUsingMockedInvocationWorks() throws Exception {
+    ArchaiusUtils.setProperty("servicecomb.loadbalance.filter.status.enabled", "false");
+
+    Invocation invocation = new NonSwaggerInvocation("testApp", "testMicroserviceName", "0.0.0+", (inv, aysnc) -> {
+      aysnc.success("OK");
+    });
+
+    InstanceCacheManager instanceCacheManager = Mockito.mock(InstanceCacheManager.class);
+    ServiceRegistry serviceRegistry = Mockito.mock(ServiceRegistry.class);
+    TransportManager transportManager = Mockito.mock(TransportManager.class);
+    Transport transport = Mockito.mock(Transport.class);
+    ArchaiusUtils.setProperty("servicecomb.loadbalance.filter.operation.enabled", "false");
+
+    // set up data
+    MicroserviceInstance myself = new MicroserviceInstance();
+    DataCenterInfo info = new DataCenterInfo();
+    info.setName("test");
+    info.setRegion("test-Region");
+    info.setAvailableZone("test-zone");
+    myself.setDataCenterInfo(info);
+
+    MicroserviceInstance allmatchInstance = new MicroserviceInstance();
+    info = new DataCenterInfo();
+    info.setName("test");
+    info.setRegion("test-Region");
+    info.setAvailableZone("test-zone");
+    List<String> allMatchEndpoint = new ArrayList<>();
+    allMatchEndpoint.add("rest://localhost:7090");
+    allmatchInstance.setEndpoints(allMatchEndpoint);
+    allmatchInstance.setDataCenterInfo(info);
+    allmatchInstance.setInstanceId("allmatchInstance");
+    allmatchInstance.setStatus(MicroserviceInstanceStatus.TESTING);
+
+    MicroserviceInstance regionMatchInstance = new MicroserviceInstance();
+    info = new DataCenterInfo();
+    info.setName("test");
+    info.setRegion("test-Region");
+    info.setAvailableZone("test-zone2");
+    List<String> regionMatchEndpoint = new ArrayList<>();
+    regionMatchEndpoint.add("rest://localhost:7091");
+    regionMatchInstance.setEndpoints(regionMatchEndpoint);
+    regionMatchInstance.setDataCenterInfo(info);
+    regionMatchInstance.setInstanceId("regionMatchInstance");
+
+    MicroserviceInstance noneMatchInstance = new MicroserviceInstance();
+    info = new DataCenterInfo();
+    info.setName("test");
+    info.setRegion("test-Region2");
+    info.setAvailableZone("test-zone2");
+    List<String> noMatchEndpoint = new ArrayList<>();
+    noMatchEndpoint.add("rest://localhost:7092");
+    noneMatchInstance.setEndpoints(noMatchEndpoint);
+    noneMatchInstance.setDataCenterInfo(info);
+    noneMatchInstance.setInstanceId("noneMatchInstance");
+
+    Map<String, MicroserviceInstance> data = new HashMap<>();
+    DiscoveryTreeNode parent = new DiscoveryTreeNode().name("parent").data(data);
+    CseContext.getInstance().setTransportManager(transportManager);
+
+    RegistryUtils.setServiceRegistry(serviceRegistry);
+
+    when(serviceRegistry.getMicroserviceInstance()).thenReturn(myself);
+    when(serviceRegistry.getInstanceCacheManager()).thenReturn(instanceCacheManager);
+    when(instanceCacheManager.getOrCreateVersionedCache("testApp", "testMicroserviceName", "0.0.0+"))
+        .thenReturn(parent);
+    when(transportManager.findTransport("rest")).thenReturn(transport);
+
+    LoadbalanceHandler handler = null;
+    LoadBalancer loadBalancer = null;
+    ServiceCombServer server = null;
+
+    DiscoveryTree discoveryTree = new DiscoveryTree();
+    discoveryTree.addFilter(new IsolationDiscoveryFilter());
+    discoveryTree.addFilter(new ZoneAwareDiscoveryFilter());
+    discoveryTree.addFilter(new ServerDiscoveryFilter());
+    discoveryTree.sort();
+    handler = new LoadbalanceHandler(discoveryTree);
+    loadBalancer = handler.getOrCreateLoadBalancer(invocation);
+    server = loadBalancer.chooseServer(invocation);
+    Assert.assertEquals(server, null);
+
+    data.put("noneMatchInstance", noneMatchInstance);
+    parent.cacheVersion(1);
+    handler = new LoadbalanceHandler();
+    loadBalancer = handler.getOrCreateLoadBalancer(invocation);
+    server = loadBalancer.chooseServer(invocation);
+    Assert.assertEquals(server.getEndpoint().getEndpoint(), "rest://localhost:7092");
+    handler.handle(invocation, (response) -> {
+      Assert.assertEquals(response.getResult(), "OK");
+    });
+
+    data.put("regionMatchInstance", regionMatchInstance);
+    parent.cacheVersion(parent.cacheVersion() + 1);
+    loadBalancer = handler.getOrCreateLoadBalancer(invocation);
+    server = loadBalancer.chooseServer(invocation);
+    Assert.assertEquals(server.getEndpoint().getEndpoint(), "rest://localhost:7091");
+    handler.handle(invocation, (response) -> {
+      Assert.assertEquals(response.getResult(), "OK");
+    });
+
+    data.put("allmatchInstance", allmatchInstance);
+    parent.cacheVersion(parent.cacheVersion() + 1);
+    loadBalancer = handler.getOrCreateLoadBalancer(invocation);
+    server = loadBalancer.chooseServer(invocation);
+    Assert.assertEquals(server.getEndpoint().getEndpoint(), "rest://localhost:7090");
+
+    ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server);
+    ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server);
+    ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server);
+    ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server);
+    ServiceCombLoadBalancerStats.INSTANCE.markFailure(server);
+
+    //if errorThresholdPercentage is 0,that means errorThresholdPercentage is not active.
+    ArchaiusUtils.setProperty("servicecomb.loadbalance.isolation.errorThresholdPercentage", "0");
+    loadBalancer = handler.getOrCreateLoadBalancer(invocation);
+    server = loadBalancer.chooseServer(invocation);
+    Assert.assertEquals(server.getEndpoint().getEndpoint(), "rest://localhost:7090");
+
+    //if errorThresholdPercentage greater than 0, it will activate.
+    ArchaiusUtils.setProperty("servicecomb.loadbalance.isolation.errorThresholdPercentage", "20");
+    ArchaiusUtils.setProperty("servicecomb.loadbalance.isolation.minIsolationTime", "10");
+    ServiceCombServer server2 = server;
+    loadBalancer = handler.getOrCreateLoadBalancer(invocation);
+    server = loadBalancer.chooseServer(invocation);
+    Assert.assertEquals(server.getEndpoint().getEndpoint(), "rest://localhost:7091");
+    ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server2);
+    loadBalancer = handler.getOrCreateLoadBalancer(invocation);
+    server = loadBalancer.chooseServer(invocation);
+    Assert.assertEquals(server.getEndpoint().getEndpoint(), "rest://localhost:7091");
+    TimeUnit.MILLISECONDS.sleep(20);
+    loadBalancer = handler.getOrCreateLoadBalancer(invocation);
+    server = loadBalancer.chooseServer(invocation);
+    Assert.assertEquals(server.getEndpoint().getEndpoint(), "rest://localhost:7090");
+    ServiceCombLoadBalancerStats.INSTANCE.markFailure(server2);
+    ServiceCombLoadBalancerStats.INSTANCE.markFailure(server2);
+    loadBalancer = handler.getOrCreateLoadBalancer(invocation);
+    server = loadBalancer.chooseServer(invocation);
+    Assert.assertEquals(server.getEndpoint().getEndpoint(), "rest://localhost:7091");
+    handler.handle(invocation, (response) -> {
+      Assert.assertEquals(response.getResult(), "OK");
+    });
+  }
+
+  @Test
   public void testConfigEndpoint() {
     ReferenceConfig referenceConfig = Mockito.mock(ReferenceConfig.class);
     OperationMeta operationMeta = Mockito.mock(OperationMeta.class);
diff --git a/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/cache/InstanceCache.java b/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/cache/InstanceCache.java
index 20583e8..98bd147 100644
--- a/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/cache/InstanceCache.java
+++ b/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/cache/InstanceCache.java
@@ -100,7 +100,7 @@ public class InstanceCache {
   protected Map<String, List<CacheEndpoint>> createTransportMap() {
     Map<String, List<CacheEndpoint>> transportMap = new HashMap<>();
     for (MicroserviceInstance instance : instanceMap.values()) {
-      // 过滤到不可用实例
+      // This is only used for service center, not change it now
       if (instance.getStatus() != MicroserviceInstanceStatus.UP) {
         continue;
       }
diff --git a/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/consumer/MicroserviceVersions.java b/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/consumer/MicroserviceVersions.java
index e85c513..bf7269f 100644
--- a/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/consumer/MicroserviceVersions.java
+++ b/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/consumer/MicroserviceVersions.java
@@ -28,7 +28,6 @@ import org.apache.servicecomb.foundation.common.utils.SPIServiceUtils;
 import org.apache.servicecomb.serviceregistry.RegistryUtils;
 import org.apache.servicecomb.serviceregistry.api.Const;
 import org.apache.servicecomb.serviceregistry.api.registry.MicroserviceInstance;
-import org.apache.servicecomb.serviceregistry.api.registry.MicroserviceInstanceStatus;
 import org.apache.servicecomb.serviceregistry.api.response.MicroserviceInstanceChangedEvent;
 import org.apache.servicecomb.serviceregistry.client.http.MicroserviceInstances;
 import org.apache.servicecomb.serviceregistry.config.ServiceRegistryConfig;
@@ -198,7 +197,6 @@ public class MicroserviceVersions {
       List<MicroserviceInstance> inUseInstances) {
     List<MicroserviceInstance> upInstances = pulledInstances
         .stream()
-        .filter(instance -> MicroserviceInstanceStatus.UP.equals(instance.getStatus()))
         .collect(Collectors.toList());
     if (upInstances.isEmpty() && inUseInstances != null && ServiceRegistryConfig.INSTANCE
         .isEmptyInstanceProtectionEnabled()) {
diff --git a/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/discovery/InstanceStatusDiscoveryFilter.java b/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/discovery/InstanceStatusDiscoveryFilter.java
new file mode 100644
index 0000000..f619653
--- /dev/null
+++ b/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/discovery/InstanceStatusDiscoveryFilter.java
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.servicecomb.serviceregistry.discovery;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.servicecomb.serviceregistry.api.registry.MicroserviceInstance;
+import org.apache.servicecomb.serviceregistry.api.registry.MicroserviceInstanceStatus;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.netflix.config.DynamicPropertyFactory;
+
+public class InstanceStatusDiscoveryFilter extends AbstractDiscoveryFilter {
+  private static final Logger LOGGER = LoggerFactory.getLogger(InstanceStatusDiscoveryFilter.class);
+
+  private static final String UP_INSTANCES = "upInstances";
+
+  @Override
+  public int getOrder() {
+    // OperationInstancesDiscoveryFilter should execute first
+    return -5000;
+  }
+
+  @Override
+  public boolean enabled() {
+    return DynamicPropertyFactory.getInstance()
+        .getBooleanProperty("servicecomb.loadbalance.filter.status.enabled", true).get();
+  }
+
+  @Override
+  public boolean isGroupingFilter() {
+    return true;
+  }
+
+  @Override
+  protected String findChildName(DiscoveryContext context, DiscoveryTreeNode parent) {
+    return UP_INSTANCES;
+  }
+
+  @Override
+  public void init(DiscoveryContext context, DiscoveryTreeNode parent) {
+    Map<String, MicroserviceInstance> instances = parent.data();
+    Map<String, MicroserviceInstance> filteredServers = new HashMap<>();
+    for (String key : instances.keySet()) {
+      MicroserviceInstance instance = instances.get(key);
+      if (MicroserviceInstanceStatus.UP == instance.getStatus()) {
+        filteredServers.put(key, instance);
+      }
+    }
+
+    if (filteredServers.isEmpty()) {
+      LOGGER.warn("No instance found by filter. " + this.getClass().getName());
+    }
+    DiscoveryTreeNode child = new DiscoveryTreeNode().subName(parent, UP_INSTANCES).data(filteredServers);
+    parent.child(UP_INSTANCES, child);
+  }
+}
diff --git a/service-registry/src/main/resources/META-INF/services/org.apache.servicecomb.serviceregistry.discovery.DiscoveryFilter b/service-registry/src/main/resources/META-INF/services/org.apache.servicecomb.serviceregistry.discovery.DiscoveryFilter
new file mode 100644
index 0000000..3e2418c
--- /dev/null
+++ b/service-registry/src/main/resources/META-INF/services/org.apache.servicecomb.serviceregistry.discovery.DiscoveryFilter
@@ -0,0 +1,18 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+org.apache.servicecomb.serviceregistry.discovery.InstanceStatusDiscoveryFilter
\ No newline at end of file
diff --git a/service-registry/src/test/java/org/apache/servicecomb/serviceregistry/consumer/TestMicroserviceVersions.java b/service-registry/src/test/java/org/apache/servicecomb/serviceregistry/consumer/TestMicroserviceVersions.java
index 1382bf9..c265634 100644
--- a/service-registry/src/test/java/org/apache/servicecomb/serviceregistry/consumer/TestMicroserviceVersions.java
+++ b/service-registry/src/test/java/org/apache/servicecomb/serviceregistry/consumer/TestMicroserviceVersions.java
@@ -30,7 +30,6 @@ import org.apache.servicecomb.serviceregistry.api.Const;
 import org.apache.servicecomb.serviceregistry.api.MicroserviceKey;
 import org.apache.servicecomb.serviceregistry.api.registry.Microservice;
 import org.apache.servicecomb.serviceregistry.api.registry.MicroserviceInstance;
-import org.apache.servicecomb.serviceregistry.api.registry.MicroserviceInstanceStatus;
 import org.apache.servicecomb.serviceregistry.api.response.FindInstancesResponse;
 import org.apache.servicecomb.serviceregistry.api.response.MicroserviceInstanceChangedEvent;
 import org.apache.servicecomb.serviceregistry.client.http.MicroserviceInstances;
@@ -255,21 +254,6 @@ public class TestMicroserviceVersions {
   }
 
   @Test
-  public void setInstances_selectUp() {
-    String microserviceId = "1";
-
-    createMicroservice(microserviceId);
-    createInstance(microserviceId);
-    createMicroserviceInstances();
-
-    instances.get(0).setStatus(MicroserviceInstanceStatus.DOWN);
-    Deencapsulation.invoke(microserviceVersions, "setInstances", instances, "0");
-
-    List<?> resultInstances = Deencapsulation.getField(microserviceVersions, "instances");
-    Assert.assertTrue(resultInstances.isEmpty());
-  }
-
-  @Test
   public void getOrCreateMicroserviceVersionRule() {
     MicroserviceVersionRule microserviceVersionRule = microserviceVersions.getOrCreateMicroserviceVersionRule("1.0.0");
     Assert.assertSame(microserviceVersionRule, microserviceVersions.getOrCreateMicroserviceVersionRule("1.0.0"));