liubao68 closed pull request #883: [SBC-870]refactor to using custom RuleExt, 
not using Robin IRule.
URL: https://github.com/apache/incubator-servicecomb-java-chassis/pull/883
 
 
   

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

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

diff --git 
a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/RestObjectMapper.java
 
b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/RestObjectMapper.java
index f94ec2c15..327175b22 100644
--- 
a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/RestObjectMapper.java
+++ 
b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/RestObjectMapper.java
@@ -65,6 +65,8 @@ public StringBuffer format(Date date, StringBuffer 
toAppendTo, FieldPosition fie
     disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
     enable(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS);
     enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY);
+    // If required=true, need to fail, while required=false, default values is 
given.
+    enable(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES);
 
     SimpleModule module = new SimpleModule();
     // custom types
diff --git 
a/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/CustomLoadbalanceExtensionsFactory.java
 
b/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/CustomLoadbalanceExtensionsFactory.java
index cb0eef6e1..c015165be 100644
--- 
a/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/CustomLoadbalanceExtensionsFactory.java
+++ 
b/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/CustomLoadbalanceExtensionsFactory.java
@@ -18,6 +18,8 @@
 
 import org.apache.servicecomb.loadbalance.Configuration;
 import org.apache.servicecomb.loadbalance.ExtensionsFactory;
+import org.apache.servicecomb.loadbalance.RoundRobinRuleExt;
+import org.apache.servicecomb.loadbalance.RuleExt;
 import org.springframework.stereotype.Component;
 
 import com.netflix.client.DefaultLoadBalancerRetryHandler;
@@ -29,7 +31,7 @@
 @Component
 public class CustomLoadbalanceExtensionsFactory implements ExtensionsFactory {
 
-  class MyCustomRule extends RoundRobinRule {
+  class MyCustomRule extends RoundRobinRuleExt {
 
   }
 
@@ -56,7 +58,7 @@ public boolean isSupport(String key, String value) {
   }
 
   @Override
-  public IRule createLoadBalancerRule(String ruleName) {
+  public RuleExt createLoadBalancerRule(String ruleName) {
     return new MyCustomRule();
   }
 
diff --git 
a/demo/demo-pojo/pojo-client/src/main/java/org/apache/servicecomb/demo/pojo/client/PojoClient.java
 
b/demo/demo-pojo/pojo-client/src/main/java/org/apache/servicecomb/demo/pojo/client/PojoClient.java
index 3b55ebb17..ccb01ca79 100644
--- 
a/demo/demo-pojo/pojo-client/src/main/java/org/apache/servicecomb/demo/pojo/client/PojoClient.java
+++ 
b/demo/demo-pojo/pojo-client/src/main/java/org/apache/servicecomb/demo/pojo/client/PojoClient.java
@@ -111,24 +111,11 @@ public static void run() throws Exception {
       testNull(testFromXml);
       testNull(test);
       testEmpty(test);
+
       // This test case shows destroy of WeightedResponseTimeRule timer task. 
after test finished will not print:
       // "Weight adjusting job started" and thread 
"NFLoadBalancer-serverWeightTimer-unknown" destroyed.
       ArchaiusUtils.setProperty("servicecomb.loadbalance.strategy.name", 
"WeightedResponse");
       testStringArray(test);
-      boolean checkerStated = false;
-      // Timer may not start thread very fast so check for 3 times.
-      for (int i = 0; i < 3; i++) {
-        Set<Thread> allThreads = Thread.getAllStackTraces().keySet();
-        for (Thread t : allThreads) {
-          if (t.getName().equals("NFLoadBalancer-serverWeightTimer-unknown")) {
-            checkerStated = true;
-            break;
-          }
-        }
-        Thread.sleep(1000);
-      }
-      TestMgr.check(checkerStated, true);
-
       ArchaiusUtils.setProperty("servicecomb.loadbalance.strategy.name", 
"RoundRobin");
       testStringArray(test);
 
diff --git 
a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/SpringmvcClient.java
 
b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/SpringmvcClient.java
index 3e5aa1c15..2a41e0afe 100644
--- 
a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/SpringmvcClient.java
+++ 
b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/SpringmvcClient.java
@@ -167,6 +167,18 @@ public static void run() {
   private static void testController(RestTemplate template, String 
microserviceName) {
     String prefix = "cse://" + microserviceName;
 
+    TestMgr.check(7,
+        template.getForObject(prefix + "/controller/add?a=3&b=4",
+            Integer.class));
+
+    try {
+      template.getForObject(prefix + "/controller/add",
+          Integer.class);
+      TestMgr.check("failed", "success");
+    } catch (InvocationException e) {
+      TestMgr.check(e.getStatusCode(), 400);
+    }
+
     TestMgr.check("hi world [world]",
         template.getForObject(prefix + "/controller/sayhi?name=world",
             String.class));
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 2290b6ffe..03b137c79 100644
--- a/demo/demo-springmvc/springmvc-client/src/main/resources/microservice.yaml
+++ b/demo/demo-springmvc/springmvc-client/src/main/resources/microservice.yaml
@@ -56,7 +56,8 @@ servicecomb:
     enabled: true
     samplingRate: 0.5
   loadbalance:
-    NFLoadBalancerRuleClassName: 
com.netflix.loadbalancer.WeightedResponseTimeRule
+    strategy:
+      name: WeightedResponse
     retryEnabled: true
     retryOnSame: 1
     retryOnNext: 1
diff --git 
a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/Configuration.java
 
b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/Configuration.java
index f2f8f624d..2ce09e3a1 100644
--- 
a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/Configuration.java
+++ 
b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/Configuration.java
@@ -35,8 +35,6 @@
 
   public static final String RPOP_TIMER_INTERVAL_IN_MINIS = 
"servicecomb.loadbalance.stats.timerIntervalInMilis";
 
-  public static final String PROP_POLICY = "NFLoadBalancerRuleClassName";
-
   public static final String PROP_RULE_STRATEGY_NAME = "strategy.name";
 
   // 2.0 configuration items
@@ -56,17 +54,6 @@
 
   public static final String SUCCESSIVE_FAILED_TIMES = 
"SessionStickinessRule.successiveFailedTimes";
 
-  // Begin: ServerListFilters configurations
-  //Enabled filter lists, e.g servicecomb.loadbalance.serverListFilters=a,b,c
-  public static final String SERVER_LIST_FILTERS = 
"servicecomb.loadbalance.serverListFilters";
-
-  //Class name of each filter: e.g 
servicecomb.loadbalance.serverListFilter.a.className=org.apache.servicecomb.MyServerListFilterExt
-  public static final String SERVER_LIST_FILTER_CLASS_HOLDER = 
"servicecomb.loadbalance.serverListFilter.%s.className";
-
-  //Property of the class: e.g 
servicecomb.loadbalance.serverListFilter.a.myproperty=sample
-  public static final String SERVER_LIST_FILTER_PROPERTY_HOLDER = 
"servicecomb.loadbalance.serverListFilter.%s.%s";
-  //End: ServerListFilters configurations
-
   private static final double PERCENT = 100;
 
   public static final String FILTER_ISOLATION = "isolation.";
@@ -84,21 +71,11 @@
   public static final String TRANSACTIONCONTROL_OPTIONS_PREFIX_PATTERN =
       "servicecomb.loadbalance.%s.transactionControl.options";
 
-  public static final String TRANSACTIONCONTROL_POLICY_KEY_PATTERN = 
"servicecomb.loadbalance.%s.transactionControl.policy";
-
   public static final Configuration INSTANCE = new Configuration();
 
   private Configuration() {
   }
 
-  public String getPolicy(String microservice) {
-    return getStringProperty(null,
-        PROP_ROOT + microservice + "." + PROP_POLICY,
-        PROP_ROOT_20 + microservice + "." + PROP_POLICY,
-        PROP_ROOT + PROP_POLICY,
-        PROP_ROOT_20 + PROP_POLICY);
-  }
-
   public String getRuleStrategyName(String microservice) {
     return getStringProperty(null,
         PROP_ROOT + microservice + "." + PROP_RULE_STRATEGY_NAME,
@@ -234,10 +211,6 @@ public int getSingleTestTime(String microservice) {
     }
   }
 
-  public String getFlowsplitFilterPolicy(String microservice) {
-    return getStringProperty("", 
String.format(TRANSACTIONCONTROL_POLICY_KEY_PATTERN, microservice));
-  }
-
   public Map<String, String> getFlowsplitFilterOptions(String microservice) {
     String keyPrefix = 
String.format(TRANSACTIONCONTROL_OPTIONS_PREFIX_PATTERN, microservice);
     return ConfigurePropertyUtils.getPropertiesWithPrefix(keyPrefix);
diff --git 
a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/ExtensionsFactory.java
 
b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/ExtensionsFactory.java
index fa9737274..9077575ee 100644
--- 
a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/ExtensionsFactory.java
+++ 
b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/ExtensionsFactory.java
@@ -25,7 +25,7 @@
 public interface ExtensionsFactory {
   boolean isSupport(String key, String value);
 
-  default IRule createLoadBalancerRule(String ruleName) {
+  default RuleExt createLoadBalancerRule(String ruleName) {
     return null;
   }
 
diff --git 
a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/ExtensionsManager.java
 
b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/ExtensionsManager.java
index 15edefe3d..2df039560 100644
--- 
a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/ExtensionsManager.java
+++ 
b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/ExtensionsManager.java
@@ -23,8 +23,6 @@
 import org.slf4j.LoggerFactory;
 
 import com.netflix.client.RetryHandler;
-import com.netflix.loadbalancer.IRule;
-import com.netflix.loadbalancer.RoundRobinRule;
 
 public class ExtensionsManager {
   private static final Logger LOGGER = 
LoggerFactory.getLogger(ExtensionsManager.class);
@@ -35,15 +33,11 @@ public static void addExtentionsFactory(ExtensionsFactory 
factory) {
     extentionFactories.add(factory);
   }
 
-  public static IRule createLoadBalancerRule(String microservice) {
-    IRule rule = null;
+  public static RuleExt createLoadBalancerRule(String microservice) {
+    RuleExt rule = null;
 
     for (ExtensionsFactory factory : extentionFactories) {
-      if (factory.isSupport(Configuration.PROP_POLICY, 
Configuration.INSTANCE.getPolicy(microservice))) {
-        rule = factory.createLoadBalancerRule(
-            Configuration.INSTANCE.getPolicy(microservice));
-        break;
-      } else if (factory.isSupport(Configuration.PROP_RULE_STRATEGY_NAME,
+      if (factory.isSupport(Configuration.PROP_RULE_STRATEGY_NAME,
           Configuration.INSTANCE.getRuleStrategyName(microservice))) {
         rule = factory.createLoadBalancerRule(
             Configuration.INSTANCE.getRuleStrategyName(microservice));
@@ -52,7 +46,7 @@ public static IRule createLoadBalancerRule(String 
microservice) {
     }
 
     if (rule == null) {
-      rule = new RoundRobinRule();
+      rule = new RoundRobinRuleExt();
     }
 
     LOGGER.info("Using load balance rule {} for microservice {}.", 
rule.getClass().getName(), microservice);
diff --git 
a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/LoadBalancer.java
 
b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/LoadBalancer.java
index 56db6ff3a..bcc9fea7b 100644
--- 
a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/LoadBalancer.java
+++ 
b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/LoadBalancer.java
@@ -17,83 +17,47 @@
 
 package org.apache.servicecomb.loadbalance;
 
-import java.util.Collections;
 import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
 
-import com.netflix.loadbalancer.AbstractLoadBalancer;
-import com.netflix.loadbalancer.IRule;
+import org.apache.servicecomb.core.Invocation;
+import org.apache.servicecomb.foundation.common.utils.SPIServiceUtils;
+
+import com.google.common.annotations.VisibleForTesting;
 import com.netflix.loadbalancer.LoadBalancerStats;
-import com.netflix.loadbalancer.Server;
 
 /**
- *  Robbin LoadBalancer implementation. Only support IRule and basic 
operations.
+ *  A load balancer with RuleExt and ServerListFilterExt
  */
-public class LoadBalancer extends AbstractLoadBalancer {
-  private List<Server> serverList = Collections.emptyList();
+public class LoadBalancer {
+  private static AtomicInteger id = new AtomicInteger(0);
 
-  private IRule rule;
+  private RuleExt rule;
 
   private LoadBalancerStats lbStats;
 
   private String microServiceName;
 
-  public LoadBalancer(IRule rule, String microServiceName,
-      LoadBalancerStats stats) {
+  private List<ServerListFilterExt> filters;
+
+  public LoadBalancer(RuleExt rule, String microServiceName) {
     this.microServiceName = microServiceName;
     this.rule = rule;
-    this.lbStats = stats;
-  }
-
-  public void setServerList(List<Server> serverList) {
-    this.serverList = Collections.unmodifiableList(serverList);
-  }
-
-  @Override
-  public void addServers(List<Server> newServers) {
-    throw new UnsupportedOperationException("Not implemented.");
-  }
-
-  @Override
-  public Server chooseServer(Object key) {
-    // rule is shared across loadbalancers, so it will get concurrent access 
problems that it's owned loadbalancer is
-    // not 'this', but this is fine to use other loadbalancer instances only 
when serverList is correctly set
+    this.lbStats = new LoadBalancerStats(microServiceName + 
id.getAndDecrement());
+    // load new instances, because filters work on service information
+    this.filters = 
SPIServiceUtils.loadSortedService(ServerListFilterExt.class);
     this.rule.setLoadBalancer(this);
-    return rule.choose(key);
-  }
-
-  @Override
-  public void markServerDown(Server server) {
-    throw new UnsupportedOperationException("Not implemented.");
-  }
-
-  @Override
-  @Deprecated
-  public List<Server> getServerList(boolean availableOnly) {
-    return getAllServers();
-  }
-
-  @Override
-  public List<Server> getReachableServers() {
-    return getAllServers();
+    this.filters.forEach((item) -> item.setLoadBalancer(this));
   }
 
-  @Override
-  // Different types of Robin Component Rule have different usages for server 
status and list.
-  // e.g. RoundRobinRule using getAllServers & alive & readyToServe
-  // RandomRule using getReachableServers & alive
-  // WeightedResponseTimeRule using getAllServers & alive
-  // To make all rules work only on "how to choose a server from alive 
servers", we do not rely on Robbin getReachableServers.
-  // We ensure getReachableServers & getAllServers work in the same way.
-  public List<Server> getAllServers() {
-    return serverList;
+  public ServiceCombServer chooseServer(Invocation invocation) {
+    List<ServiceCombServer> servers = 
invocation.getLocalContext(LoadbalanceHandler.CONTEXT_KEY_SERVER_LIST);
+    for (ServerListFilterExt filterExt : filters) {
+      servers = filterExt.getFilteredListOfServers(servers, invocation);
+    }
+    return rule.choose(servers, invocation);
   }
 
-  @Override
-  public List<Server> getServerList(ServerGroup serverGroup) {
-    throw new UnsupportedOperationException("Not implemented.");
-  }
-
-  @Override
   public LoadBalancerStats getLoadBalancerStats() {
     return lbStats;
   }
@@ -101,4 +65,9 @@ public LoadBalancerStats getLoadBalancerStats() {
   public String getMicroServiceName() {
     return microServiceName;
   }
+
+  @VisibleForTesting
+  void setFilters(List<ServerListFilterExt> filters) {
+    this.filters = filters;
+  }
 }
diff --git 
a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/LoadBalancerCreator.java
 
b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/LoadBalancerCreator.java
deleted file mode 100644
index eedbb9ce3..000000000
--- 
a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/LoadBalancerCreator.java
+++ /dev/null
@@ -1,103 +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.loadbalance;
-
-import java.util.Collections;
-import java.util.List;
-
-import org.apache.servicecomb.core.Invocation;
-import org.apache.servicecomb.foundation.common.utils.SPIServiceUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.annotations.VisibleForTesting;
-import com.netflix.loadbalancer.IRule;
-import com.netflix.loadbalancer.LoadBalancerStats;
-import com.netflix.loadbalancer.Server;
-import com.netflix.loadbalancer.WeightedResponseTimeRule;
-
-/**
- *  Create a suitable load balancer for each invocation.
- *
- *  Robin components work good in service level state, and we want to reuse 
its IRule components and other
- *  facilities, but they are not good for operation
- *  level filters, so write a custom load balance process.
- *
- *  Load balance instance is created for each microservice(plus version rule), 
thus it is service level,
- *  it only can contains stateful information with service. e.g. 
LoadBalancerStats.
- *
- *  ServerListFilter may choose available servers according to invocation 
information, IRule will work
- *  on the result of ServerListFilter, they should not contain operation level 
state information in instance fields.
- */
-public class LoadBalancerCreator {
-  private static final Logger LOGGER = 
LoggerFactory.getLogger(LoadBalancerCreator.class);
-
-  private List<Server> serverList = Collections.emptyList();
-
-  private IRule rule;
-
-  private LoadBalancerStats lbStats;
-
-  private List<ServerListFilterExt> filters;
-
-  private String microServiceName;
-
-  public LoadBalancerCreator(IRule rule, String microServiceName) {
-    this.rule = rule;
-    this.microServiceName = microServiceName;
-    this.lbStats = new LoadBalancerStats(null);
-    // load new instances, because filters work on service information
-    this.filters = 
SPIServiceUtils.loadSortedService(ServerListFilterExt.class);
-  }
-
-  public void shutdown() {
-    // netflix components does not have a proper way to shutdown laodbalancers 
so we do it in a not quite elegant way.
-    if (this.rule instanceof WeightedResponseTimeRule) {
-      ((WeightedResponseTimeRule) this.rule).shutdown();
-    }
-  }
-
-  // every filter group has a loadBalancer instance
-  // serverList almost not changed for different invocation
-  // so every invocation will call setServerList, this is no problem
-  public void setServerList(List<Server> serverList) {
-    if (serverList.isEmpty()) {
-      LOGGER.warn("Set empty server list.");
-    }
-    this.serverList = Collections.unmodifiableList(serverList);
-  }
-
-  @VisibleForTesting
-  void setFilters(List<ServerListFilterExt> filters) {
-    this.filters = filters;
-  }
-
-  public LoadBalancer createLoadBalancer(Invocation invocation) {
-    LoadBalancer loadBalancer = new LoadBalancer(rule, microServiceName, 
lbStats);
-    List<Server> servers = this.serverList;
-    for (ServerListFilterExt filter : this.filters) {
-      filter.setLoadBalancer(loadBalancer);
-      servers = filter.getFilteredListOfServers(servers, invocation);
-      if (servers.isEmpty()) {
-        LOGGER.warn("Filter {} get empty list.", filter.getClass().getName());
-      }
-    }
-    loadBalancer.setServerList(servers);
-    return loadBalancer;
-  }
-}
diff --git 
a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/LoadbalanceHandler.java
 
b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/LoadbalanceHandler.java
index 7d6394a46..95db713fd 100644
--- 
a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/LoadbalanceHandler.java
+++ 
b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/LoadbalanceHandler.java
@@ -44,8 +44,8 @@
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.netflix.config.DynamicPropertyFactory;
 import com.netflix.loadbalancer.ILoadBalancer;
-import com.netflix.loadbalancer.IRule;
 import com.netflix.loadbalancer.Server;
 import com.netflix.loadbalancer.reactive.ExecutionContext;
 import com.netflix.loadbalancer.reactive.ExecutionInfo;
@@ -56,10 +56,11 @@
 import rx.Observable;
 
 /**
- * 负载均衡处理链
- *
+ *  Load balance handler.
  */
 public class LoadbalanceHandler implements Handler {
+  public static final String CONTEXT_KEY_SERVER_LIST = "x-context-server-list";
+
   // just a wrapper to make sure in retry mode to choose a different server.
   class RetryLoadBalancer implements ILoadBalancer {
     // Enough times to make sure to choose a different server in high volume.
@@ -67,21 +68,21 @@
 
     Server lastServer = null;
 
-    ILoadBalancer delegate;
+    LoadBalancer delegate;
 
-    RetryLoadBalancer(ILoadBalancer delegate) {
+    RetryLoadBalancer(LoadBalancer delegate) {
       this.delegate = delegate;
     }
 
     @Override
     public void addServers(List<Server> newServers) {
-      delegate.addServers(newServers);
+      throw new UnsupportedOperationException("Not implemented.");
     }
 
     @Override
     public Server chooseServer(Object key) {
       for (int i = 0; i < COUNT; i++) {
-        Server s = delegate.chooseServer(key);
+        Server s = delegate.chooseServer((Invocation) key);
         if (s != null && !s.equals(lastServer)) {
           lastServer = s;
           break;
@@ -94,23 +95,23 @@ public Server chooseServer(Object key) {
 
     @Override
     public void markServerDown(Server server) {
-      delegate.markServerDown(server);
+      throw new UnsupportedOperationException("Not implemented.");
     }
 
     @Override
     @Deprecated
     public List<Server> getServerList(boolean availableOnly) {
-      return delegate.getServerList(availableOnly);
+      throw new UnsupportedOperationException("Not implemented.");
     }
 
     @Override
     public List<Server> getReachableServers() {
-      return delegate.getReachableServers();
+      throw new UnsupportedOperationException("Not implemented.");
     }
 
     @Override
     public List<Server> getAllServers() {
-      return delegate.getAllServers();
+      throw new UnsupportedOperationException("Not implemented.");
     }
   }
 
@@ -131,34 +132,50 @@ public Thread newThread(Runnable r) {
   private DiscoveryTree discoveryTree = new DiscoveryTree();
 
   // key为grouping filter qualified name
-  private volatile Map<String, LoadBalancerCreator> loadBalancerMap = new 
ConcurrentHashMapEx<>();
+  private volatile Map<String, LoadBalancer> loadBalancerMap = new 
ConcurrentHashMapEx<>();
 
   private final Object lock = new Object();
 
-  private String policy = null;
-
   private String strategy = null;
 
 
   public LoadbalanceHandler() {
+    preCheck();
     discoveryTree.loadFromSPI(DiscoveryFilter.class);
     discoveryTree.addFilter(new ServerDiscoveryFilter());
     discoveryTree.sort();
   }
 
+  private void preCheck() {
+    // Old configurations check.Just print an error, because configurations 
may given in dynamic and fail on runtime.
+
+    String policyName = DynamicPropertyFactory.getInstance()
+        
.getStringProperty("servicecomb.loadbalance.NFLoadBalancerRuleClassName", 
null).get();
+    if (!StringUtils.isEmpty(policyName)) {
+      LOGGER.error("[servicecomb.loadbalance.NFLoadBalancerRuleClassName] is 
not supported anymore." +
+          "use [servicecomb.loadbalance.strategy.name] instead.");
+    }
+
+    String filterNames = Configuration.getStringProperty(null, 
"servicecomb.loadbalance.serverListFilters");
+    if (!StringUtils.isEmpty(filterNames)) {
+      LOGGER.error(
+          "Server list implementation changed to SPI. Configuration 
[servicecomb.loadbalance.serverListFilters]" +
+              " is not used any more. For ServiceComb defined filters, you do 
not need config and can "
+              + "remove this configuration safely. If you define your own 
filter, need to change it to SPI to make it work.");
+    }
+  }
+
   @Override
   public void handle(Invocation invocation, AsyncResponse asyncResp) throws 
Exception {
-    String policy = 
Configuration.INSTANCE.getPolicy(invocation.getMicroserviceName());
     String strategy = 
Configuration.INSTANCE.getRuleStrategyName(invocation.getMicroserviceName());
-    boolean isRuleNotChanged = isEqual(policy, this.policy) && 
isEqual(strategy, this.strategy);
-    if (!isRuleNotChanged) {
+    if (!isEqual(strategy, this.strategy)) {
       //配置变化,需要重新生成所有的lb实例
       synchronized (lock) {
         clearLoadBalancer();
       }
     }
-    this.policy = policy;
     this.strategy = strategy;
+
     LoadBalancer loadBalancer = getOrCreateLoadBalancer(invocation);
 
     if 
(!Configuration.INSTANCE.isRetryEnabled(invocation.getMicroserviceName())) {
@@ -169,20 +186,9 @@ public void handle(Invocation invocation, AsyncResponse 
asyncResp) throws Except
   }
 
   private void clearLoadBalancer() {
-    for (LoadBalancerCreator creator : loadBalancerMap.values()) {
-      creator.shutdown();
-    }
     loadBalancerMap.clear();
   }
 
-  protected void setTransactionControlFilter(String microserviceName) {
-    String policyClsName = 
Configuration.INSTANCE.getFlowsplitFilterPolicy(microserviceName);
-    if (!policyClsName.isEmpty()) {
-      LOGGER.error(Configuration.TRANSACTIONCONTROL_POLICY_KEY_PATTERN + " is 
not supported anymore." +
-          "You can change this class to SPI, and filters will be loaded by 
SPI.");
-    }
-  }
-
   private void send(Invocation invocation, AsyncResponse asyncResp, final 
LoadBalancer chosenLB) throws Exception {
     long time = System.currentTimeMillis();
     ServiceCombServer server = (ServiceCombServer) 
chosenLB.chooseServer(invocation);
@@ -355,30 +361,17 @@ protected LoadBalancer getOrCreateLoadBalancer(Invocation 
invocation) {
         invocation.getAppId(),
         invocation.getMicroserviceName(),
         invocation.getMicroserviceVersionRule());
+    invocation.addLocalContext(CONTEXT_KEY_SERVER_LIST, 
serversVersionedCache.data());
 
-    LoadBalancerCreator loadBalancerCreator = 
loadBalancerMap.computeIfAbsent(serversVersionedCache.name(), name -> {
-      return createLoadBalancerCreator(invocation.getMicroserviceName());
-    });
-    loadBalancerCreator.setServerList(serversVersionedCache.data());
-    // help users to deal with incompatible changes.
-    setTransactionControlFilter(invocation.getMicroserviceName());
-    loadServerListFilters();
-    return loadBalancerCreator.createLoadBalancer(invocation);
-  }
-
-  private LoadBalancerCreator createLoadBalancerCreator(String 
microserviceName) {
-    IRule rule = ExtensionsManager.createLoadBalancerRule(microserviceName);
-    LoadBalancerCreator creator = new LoadBalancerCreator(rule, 
microserviceName);
-    return creator;
+    return loadBalancerMap
+        .computeIfAbsent(serversVersionedCache.name(), name -> {
+          return createLoadBalancer(invocation.getMicroserviceName());
+        });
   }
 
-  private void loadServerListFilters() {
-    String filterNames = Configuration.getStringProperty(null, 
Configuration.SERVER_LIST_FILTERS);
-    if (!StringUtils.isEmpty(filterNames)) {
-      LOGGER.error("Server list implementation changed to SPI. Configuration " 
+ Configuration.SERVER_LIST_FILTERS +
-          " is not used any more. For ServiceComb defined filters, you do not 
need config and can "
-          + "remove this configuration safely. If you define your own filter, 
need to change it to SPI to make it work.");
-    }
+  private LoadBalancer createLoadBalancer(String microserviceName) {
+    RuleExt rule = ExtensionsManager.createLoadBalancerRule(microserviceName);
+    return new LoadBalancer(rule, microserviceName);
   }
 
   public boolean isEqual(String str1, String str2) {
diff --git 
a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/RandomRuleExt.java
 
b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/RandomRuleExt.java
new file mode 100644
index 000000000..60eedac52
--- /dev/null
+++ 
b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/RandomRuleExt.java
@@ -0,0 +1,39 @@
+/*
+ * 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.loadbalance;
+
+import java.util.List;
+import java.util.Random;
+
+import org.apache.servicecomb.core.Invocation;
+
+/**
+ * A random rule.
+ */
+public class RandomRuleExt implements RuleExt {
+  private Random random = new Random();
+
+  @Override
+  public ServiceCombServer choose(List<ServiceCombServer> servers, Invocation 
invocation) {
+    if (servers.size() == 0) {
+      return null;
+    }
+    int index = Math.abs(random.nextInt()) % servers.size();
+    return servers.get(index);
+  }
+}
diff --git 
a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/RoundRobinRuleExt.java
 
b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/RoundRobinRuleExt.java
new file mode 100644
index 000000000..c3a887d20
--- /dev/null
+++ 
b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/RoundRobinRuleExt.java
@@ -0,0 +1,39 @@
+/*
+ * 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.loadbalance;
+
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.apache.servicecomb.core.Invocation;
+
+/**
+ * A round robin rule
+ */
+public class RoundRobinRuleExt implements RuleExt {
+  private AtomicInteger counter = new AtomicInteger(0);
+
+  @Override
+  public ServiceCombServer choose(List<ServiceCombServer> servers, Invocation 
invocation) {
+    if (servers.size() == 0) {
+      return null;
+    }
+    int index = Math.abs(counter.getAndIncrement()) % servers.size();
+    return servers.get(index);
+  }
+}
diff --git 
a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/RuleClassNameExtentionsFactory.java
 
b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/RuleClassNameExtentionsFactory.java
deleted file mode 100644
index b6df5ef21..000000000
--- 
a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/RuleClassNameExtentionsFactory.java
+++ /dev/null
@@ -1,62 +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.loadbalance;
-
-import java.util.Collection;
-
-import org.apache.commons.lang.StringUtils;
-import org.apache.servicecomb.foundation.common.utils.JvmUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.stereotype.Component;
-
-import com.google.common.collect.Lists;
-import com.netflix.loadbalancer.IRule;
-import com.netflix.loadbalancer.RoundRobinRule;
-
-/**
- * 兼容老版本的Rule相关的配置项
- */
-@Component
-public class RuleClassNameExtentionsFactory implements ExtensionsFactory {
-  private static final Logger LOGGER = 
LoggerFactory.getLogger(RuleClassNameExtentionsFactory.class);
-
-  private static final Collection<String> ACCEPT_KEYS = Lists.newArrayList(
-      Configuration.PROP_POLICY);
-
-  // possible values
-  //      "com.netflix.loadbalancer.RoundRobinRule"
-  //      "com.netflix.loadbalancer.WeightedResponseTimeRule"
-  //      "com.netflix.loadbalancer.RandomRule"
-  //      "org.apache.servicecomb.loadbalance.SessionStickinessRule"
-  @Override
-  public boolean isSupport(String key, String value) {
-    return ACCEPT_KEYS.contains(key) && StringUtils.isNotEmpty(value);
-  }
-
-  @Override
-  public IRule createLoadBalancerRule(String ruleName) {
-    IRule rule;
-    try {
-      rule = (IRule) Class.forName(ruleName, true, 
JvmUtils.findClassLoader()).newInstance();
-    } catch (InstantiationException | IllegalAccessException | 
ClassNotFoundException e) {
-      LOGGER.warn("Loadbalance rule [{}] is incorrect, using default 
RoundRobinRule.", ruleName);
-      rule = new RoundRobinRule();
-    }
-    return rule;
-  }
-}
diff --git 
a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/RuleExt.java
 
b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/RuleExt.java
new file mode 100644
index 000000000..a95ccbcd2
--- /dev/null
+++ 
b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/RuleExt.java
@@ -0,0 +1,32 @@
+/*
+ * 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.loadbalance;
+
+import java.util.List;
+
+import org.apache.servicecomb.core.Invocation;
+
+/**
+ * Load balance rule to support invocation based filters.
+ */
+public interface RuleExt {
+  default void setLoadBalancer(LoadBalancer loadBalancer) {
+  }
+
+  ServiceCombServer choose(List<ServiceCombServer> servers, Invocation 
invocation);
+}
diff --git 
a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/RuleNameExtentionsFactory.java
 
b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/RuleNameExtentionsFactory.java
index 92d5be235..5ab7cfb95 100644
--- 
a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/RuleNameExtentionsFactory.java
+++ 
b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/RuleNameExtentionsFactory.java
@@ -21,10 +21,6 @@
 import org.springframework.stereotype.Component;
 
 import com.google.common.collect.Lists;
-import com.netflix.loadbalancer.IRule;
-import com.netflix.loadbalancer.RandomRule;
-import com.netflix.loadbalancer.RoundRobinRule;
-import com.netflix.loadbalancer.WeightedResponseTimeRule;
 
 @Component
 public class RuleNameExtentionsFactory implements ExtensionsFactory {
@@ -51,13 +47,13 @@ public boolean isSupport(String key, String value) {
   }
 
   @Override
-  public IRule createLoadBalancerRule(String ruleName) {
+  public RuleExt createLoadBalancerRule(String ruleName) {
     if (RULE_RoundRobin.equals(ruleName)) {
-      return new RoundRobinRule();
+      return new RoundRobinRuleExt();
     } else if (RULE_Random.equals(ruleName)) {
-      return new RandomRule();
+      return new RandomRuleExt();
     } else if (RULE_WeightedResponse.equals(ruleName)) {
-      return new WeightedResponseTimeRule();
+      return new WeightedResponseTimeRuleExt();
     } else if (RULE_SessionStickiness.equals(ruleName)) {
       return new SessionStickinessRule();
     } else {
diff --git 
a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/ServerListFilterExt.java
 
b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/ServerListFilterExt.java
index 7695a6827..9dba0046d 100644
--- 
a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/ServerListFilterExt.java
+++ 
b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/ServerListFilterExt.java
@@ -21,27 +21,23 @@
 
 import org.apache.servicecomb.core.Invocation;
 
-import com.netflix.loadbalancer.Server;
-
 /**
  *  Base interface for server list filters.
  *
- *  LoadBalancer.getAllServers ServerListFilterExt.getFilteredListOfServers 
IRule.choose
- *
  *  Robin ServerListFilter can not support invocation based filter strategies, 
so we create a new one to
  *  support this.
  */
 public interface ServerListFilterExt {
-  public default int getOrder() {
+  default int getOrder() {
     return 0;
   }
 
-  public default boolean enabled() {
+  default boolean enabled() {
     return true;
   }
 
-  public default void setLoadBalancer(LoadBalancer loadBalancer) {
+  default void setLoadBalancer(LoadBalancer loadBalancer) {
   }
 
-  public List<Server> getFilteredListOfServers(List<Server> servers, 
Invocation invocation);
+  List<ServiceCombServer> getFilteredListOfServers(List<ServiceCombServer> 
servers, Invocation invocation);
 }
diff --git 
a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/ServiceCombLoadBalancerStats.java
 
b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/ServiceCombLoadBalancerStats.java
index 1b7be1d77..ffde2d7ee 100644
--- 
a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/ServiceCombLoadBalancerStats.java
+++ 
b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/ServiceCombLoadBalancerStats.java
@@ -57,6 +57,8 @@
 
   public static final ServiceCombLoadBalancerStats INSTANCE;
 
+  private Timer timer;
+
   static {
     INSTANCE = new ServiceCombLoadBalancerStats();
     INSTANCE.init();
@@ -126,6 +128,14 @@ void setTimerIntervalInMilis(int milis) {
   }
 
   void init() {
+    // for testing
+    if (timer != null) {
+      timer.cancel();
+    }
+    if (serverStatsCache != null) {
+      serverStatsCache.cleanUp();
+    }
+
     serverStatsCache =
         CacheBuilder.newBuilder()
             .expireAfterAccess(serverExpireInSeconds, TimeUnit.SECONDS)
@@ -145,7 +155,7 @@ public ServiceCombServerStats load(ServiceCombServer 
server) {
                   }
                 });
 
-    Timer timer = new Timer("LoadBalancerStatsTimer", true);
+    timer = new Timer("LoadBalancerStatsTimer", true);
     timer.schedule(new TimerTask() {
       private MicroserviceInstancePing ping = 
SPIServiceUtils.getPriorityHighestService(MicroserviceInstancePing.class);
 
diff --git 
a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/ServiceCombServer.java
 
b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/ServiceCombServer.java
index 1d4edf331..800e2aebe 100644
--- 
a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/ServiceCombServer.java
+++ 
b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/ServiceCombServer.java
@@ -22,6 +22,7 @@
 import 
org.apache.servicecomb.serviceregistry.api.registry.MicroserviceInstance;
 import org.apache.servicecomb.serviceregistry.cache.CacheEndpoint;
 
+import com.google.common.annotations.VisibleForTesting;
 import com.netflix.loadbalancer.Server;
 
 /**
@@ -35,6 +36,21 @@
   // 所属服务实例
   private final MicroserviceInstance instance;
 
+  @VisibleForTesting
+  ServiceCombServer(Endpoint endpoint, MicroserviceInstance instance) {
+    super(null);
+    this.endpoint = endpoint;
+    this.instance = instance;
+
+    // Different types of Robin Component Rule have different usages for 
server status and list.
+    // e.g. RoundRobinRule using getAllServers & alive & readyToServe
+    // RandomRule using getReachableServers & alive
+    // WeightedResponseTimeRule using getAllServers & alive
+    // To make all rules work only on "how to choose a server from alive 
servers", we do not rely on Robbin defined status
+    this.setAlive(true);
+    this.setReadyToServe(true);
+  }
+
   public ServiceCombServer(Transport transport, CacheEndpoint cacheEndpoint) {
     super(null);
 
diff --git 
a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/SessionStickinessRule.java
 
b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/SessionStickinessRule.java
index d589b4d42..a489860ed 100644
--- 
a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/SessionStickinessRule.java
+++ 
b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/SessionStickinessRule.java
@@ -17,15 +17,13 @@
 
 package org.apache.servicecomb.loadbalance;
 
+import java.util.List;
+
+import org.apache.servicecomb.core.Invocation;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.netflix.loadbalancer.AbstractLoadBalancer;
-import com.netflix.loadbalancer.ILoadBalancer;
-import com.netflix.loadbalancer.IRule;
 import com.netflix.loadbalancer.LoadBalancerStats;
-import com.netflix.loadbalancer.RoundRobinRule;
-import com.netflix.loadbalancer.Server;
 import com.netflix.loadbalancer.ServerStats;
 
 /**
@@ -33,17 +31,17 @@
  * 提供当会话过期或者失败次数超过限制后,轮询选择其他服务器的能力。
  *
  */
-public class SessionStickinessRule implements IRule {
+public class SessionStickinessRule implements RuleExt {
   private static final Logger LOG = 
LoggerFactory.getLogger(SessionStickinessRule.class);
 
   private final Object lock = new Object();
 
-  private ILoadBalancer lb;
+  private LoadBalancer loadBalancer;
 
   // use random rule as the trigger rule, to prevent consumer instance select 
the same producer instance.
-  private IRule triggerRule;
+  private RuleExt triggerRule;
 
-  private volatile Server lastServer = null;
+  private volatile ServiceCombServer lastServer = null;
 
   private long lastAccessedTime = 0;
 
@@ -54,39 +52,41 @@
   private String microserviceName;
 
   public SessionStickinessRule() {
-    triggerRule = new RoundRobinRule();
+    triggerRule = new RoundRobinRuleExt();
+  }
+
+  public void setLoadBalancer(LoadBalancer loadBalancer) {
+    this.loadBalancer = loadBalancer;
   }
 
-  private Server chooseNextServer(Object key) {
-    AbstractLoadBalancer lb = (AbstractLoadBalancer) getLoadBalancer();
-    triggerRule.setLoadBalancer(lb);
-    lastServer = triggerRule.choose(key);
+  private ServiceCombServer chooseNextServer(List<ServiceCombServer> servers, 
Invocation invocation) {
+    lastServer = triggerRule.choose(servers, invocation);
     lastAccessedTime = System.currentTimeMillis();
     return lastServer;
   }
 
-  private Server chooseInitialServer(Object key) {
+  private ServiceCombServer chooseInitialServer(List<ServiceCombServer> 
servers, Invocation invocation) {
     synchronized (lock) {
       if (lastServer == null) {
-        chooseNextServer(key);
+        chooseNextServer(servers, invocation);
       }
     }
     return lastServer;
   }
 
-  private Server chooseServerWhenTimeout(Object key) {
+  private ServiceCombServer chooseServerWhenTimeout(List<ServiceCombServer> 
servers, Invocation invocation) {
     synchronized (lock) {
       if (isTimeOut()) {
-        chooseNextServer(key);
+        chooseNextServer(servers, invocation);
       }
     }
     return lastServer;
   }
 
-  private Server chooseServerErrorThresholdMet(Object key) {
+  private ServiceCombServer 
chooseServerErrorThresholdMet(List<ServiceCombServer> servers, Invocation 
invocation) {
     synchronized (lock) {
       if (errorThresholdMet) {
-        chooseNextServer(key);
+        chooseNextServer(servers, invocation);
         errorThresholdMet = false;
       }
     }
@@ -101,8 +101,7 @@ private boolean isTimeOut() {
   }
 
   private boolean isErrorThresholdMet() {
-    AbstractLoadBalancer lb = (AbstractLoadBalancer) getLoadBalancer();
-    LoadBalancerStats stats = lb.getLoadBalancerStats();
+    LoadBalancerStats stats = loadBalancer.getLoadBalancerStats();
 
     if (stats != null && stats.getServerStats() != null && 
stats.getServerStats().size() > 0) {
       ServerStats serverStats = stats.getSingleServerStat(lastServer);
@@ -117,14 +116,14 @@ private boolean isErrorThresholdMet() {
   }
 
   @Override
-  public Server choose(Object key) {
+  public ServiceCombServer choose(List<ServiceCombServer> servers, Invocation 
invocation) {
     if (lastServer == null) {
-      return chooseInitialServer(key);
+      return chooseInitialServer(servers, invocation);
     }
 
     if (isTimeOut()) {
       LOG.warn("session timeout. choose another server.");
-      return chooseServerWhenTimeout(key);
+      return chooseServerWhenTimeout(servers, invocation);
     } else {
       this.lastAccessedTime = System.currentTimeMillis();
     }
@@ -132,28 +131,13 @@ public Server choose(Object key) {
     if (isErrorThresholdMet()) {
       LOG.warn("reached max error. choose another server.");
       errorThresholdMet = true;
-      return chooseServerErrorThresholdMet(key);
+      return chooseServerErrorThresholdMet(servers, invocation);
     }
 
-    if (!isLastServerExists(lastServer)) {
-      return chooseNextServer(key);
+    if (!servers.contains(lastServer)) {
+      return chooseNextServer(servers, invocation);
     }
 
     return lastServer;
   }
-
-  private boolean isLastServerExists(Server lastServer2) {
-    return this.lb.getReachableServers().contains(lastServer2);
-  }
-
-  @Override
-  public void setLoadBalancer(ILoadBalancer lb) {
-    this.lb = lb;
-    this.microserviceName = ((LoadBalancer) lb).getMicroServiceName();
-  }
-
-  @Override
-  public ILoadBalancer getLoadBalancer() {
-    return this.lb;
-  }
 }
diff --git 
a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/WeightedResponseTimeRuleExt.java
 
b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/WeightedResponseTimeRuleExt.java
new file mode 100644
index 000000000..529c0a35d
--- /dev/null
+++ 
b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/WeightedResponseTimeRuleExt.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.loadbalance;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+
+import org.apache.servicecomb.core.Invocation;
+
+import com.netflix.loadbalancer.ServerStats;
+
+/**
+ * Rule based on response time.
+ */
+public class WeightedResponseTimeRuleExt extends RoundRobinRuleExt {
+  // 10ms
+  private static final double MIN_GAP = 10d;
+
+  private static final int RANDOM_PERCENT = 10;
+
+  private Random random = new Random();
+
+  private LoadBalancer loadBalancer;
+
+  private double totalWeightsCache = 0d;
+
+  @Override
+  public void setLoadBalancer(LoadBalancer loadBalancer) {
+    this.loadBalancer = loadBalancer;
+  }
+
+  @Override
+  public ServiceCombServer choose(List<ServiceCombServer> servers, Invocation 
invocation) {
+    List<Double> stats = calculateTotalWeights(servers);
+
+    if (stats.size() > 0) {
+      double finalTotal = stats.get(stats.size() - 1);
+      List<Double> weights = new ArrayList<>(servers.size());
+      for (int i = 0; i < stats.size() - 1; i++) {
+        weights.add(finalTotal - stats.get(i));
+      }
+      double ran = random.nextDouble() * finalTotal * (servers.size() - 1);
+      for (int i = 0; i < weights.size(); i++) {
+        ran -= weights.get(i);
+        if (ran < 0) {
+          return servers.get(i);
+        }
+      }
+      return servers.get(servers.size() - 1);
+    }
+    return super.choose(servers, invocation);
+  }
+
+  private List<Double> calculateTotalWeights(List<ServiceCombServer> servers) {
+    if (totalWeightsCache > MIN_GAP * servers.size()) {
+      return doCalculateTotalWeights(servers);
+    }
+    // 10% possibilities to use weighed response rule when the normal access 
is very fast.
+    if (random.nextInt(RANDOM_PERCENT) == 0) {
+      return doCalculateTotalWeights(servers);
+    } else {
+      return new ArrayList<>();
+    }
+  }
+
+  private List<Double> doCalculateTotalWeights(List<ServiceCombServer> 
servers) {
+    List<Double> stats = new ArrayList<>(servers.size() + 1);
+    double totalWeights = 0;
+    boolean needRandom = false;
+    for (ServiceCombServer server : servers) {
+      ServerStats serverStats = 
loadBalancer.getLoadBalancerStats().getSingleServerStat(server);
+      double avgTime = serverStats.getResponseTimeAvg();
+      if (!needRandom && avgTime > MIN_GAP) {
+        needRandom = true;
+      }
+      totalWeights += avgTime;
+      stats.add(avgTime);
+    }
+    stats.add(totalWeights);
+    totalWeightsCache = totalWeights;
+    if (needRandom) {
+      return stats;
+    } else {
+      return new ArrayList<>();
+    }
+  }
+}
diff --git 
a/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/MyServerListFilterExt.java
 
b/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/MyServerListFilterExt.java
index ed0878988..6f93b44c7 100644
--- 
a/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/MyServerListFilterExt.java
+++ 
b/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/MyServerListFilterExt.java
@@ -30,7 +30,7 @@
  */
 public class MyServerListFilterExt implements ServerListFilterExt {
   @Override
-  public List<Server> getFilteredListOfServers(List<Server> serverList, 
Invocation invocation) {
+  public List<ServiceCombServer> 
getFilteredListOfServers(List<ServiceCombServer> serverList, Invocation 
invocation) {
     if (invocation.getAppId().equals("test")) {
       return new ArrayList<>();
     }
diff --git 
a/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestConfiguration.java
 
b/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestConfiguration.java
index 08d498dd7..6ef2160a8 100644
--- 
a/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestConfiguration.java
+++ 
b/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestConfiguration.java
@@ -35,7 +35,6 @@
   public void testConstants() {
 
     assertEquals("servicecomb.loadbalance.", Configuration.PROP_ROOT);
-    assertEquals("NFLoadBalancerRuleClassName", Configuration.PROP_POLICY);
     assertEquals("ribbon.", Configuration.PROP_ROOT_20);
     assertEquals("retryEnabled", Configuration.PROP_RETRY_ENABLED);
     assertEquals("retryOnNext", Configuration.PROP_RETRY_ONNEXT);
@@ -47,7 +46,6 @@ public void testConstants() {
 
   @Test
   public void testFullConfigurationWithArgsString() {
-    assertNull(Configuration.INSTANCE.getPolicy("test"));
     assertNotNull(Configuration.INSTANCE.getRetryOnNext("test"));
     assertNotNull(Configuration.INSTANCE.getRetryOnSame("test"));
     assertNotNull(Configuration.INSTANCE.isRetryEnabled("test"));
diff --git 
a/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestExtensionsManager.java
 
b/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestExtensionsManager.java
index 69c4a1eca..169e91a79 100644
--- 
a/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestExtensionsManager.java
+++ 
b/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestExtensionsManager.java
@@ -60,17 +60,16 @@ public void testRuleName() {
 
     BeansHolder holder = new BeansHolder();
     List<ExtensionsFactory> extensionsFactories = new ArrayList<>();
-    extensionsFactories.add(new RuleClassNameExtentionsFactory());
     extensionsFactories.add(new RuleNameExtentionsFactory());
     extensionsFactories.add(new DefaultRetryExtensionsFactory());
     Deencapsulation.setField(holder, "extentionsFactories", 
extensionsFactories);
     holder.init();
 
-    Assert.assertEquals(RoundRobinRule.class.getName(),
+    Assert.assertEquals(RoundRobinRuleExt.class.getName(),
         
ExtensionsManager.createLoadBalancerRule("mytest1").getClass().getName());
-    Assert.assertEquals(RandomRule.class.getName(),
+    Assert.assertEquals(RandomRuleExt.class.getName(),
         
ExtensionsManager.createLoadBalancerRule("mytest2").getClass().getName());
-    Assert.assertEquals(WeightedResponseTimeRule.class.getName(),
+    Assert.assertEquals(WeightedResponseTimeRuleExt.class.getName(),
         
ExtensionsManager.createLoadBalancerRule("mytest3").getClass().getName());
     Assert.assertEquals(SessionStickinessRule.class.getName(),
         
ExtensionsManager.createLoadBalancerRule("mytest4").getClass().getName());
@@ -84,36 +83,12 @@ public void testRuleName() {
 
   @Test
   public void testRuleClassName() {
-    
System.setProperty("servicecomb.loadbalance.mytest1.NFLoadBalancerRuleClassName",
-        "com.netflix.loadbalancer.RoundRobinRule");
-    
System.setProperty("servicecomb.loadbalance.mytest2.NFLoadBalancerRuleClassName",
-        "com.netflix.loadbalancer.WeightedResponseTimeRule");
-    
System.setProperty("servicecomb.loadbalance.mytest3.NFLoadBalancerRuleClassName",
 "com.netflix.loadbalancer.RandomRule");
-    
System.setProperty("servicecomb.loadbalance.mytest4.NFLoadBalancerRuleClassName",
-        "org.apache.servicecomb.loadbalance.SessionStickinessRule");
-
     BeansHolder holder = new BeansHolder();
     List<ExtensionsFactory> extensionsFactories = new ArrayList<>();
-    extensionsFactories.add(new RuleClassNameExtentionsFactory());
     extensionsFactories.add(new RuleNameExtentionsFactory());
     extensionsFactories.add(new DefaultRetryExtensionsFactory());
     Deencapsulation.setField(holder, "extentionsFactories", 
extensionsFactories);
     holder.init();
-
-    Assert.assertEquals(RoundRobinRule.class.getName(),
-        
ExtensionsManager.createLoadBalancerRule("mytest1").getClass().getName());
-    Assert.assertEquals(WeightedResponseTimeRule.class.getName(),
-        
ExtensionsManager.createLoadBalancerRule("mytest2").getClass().getName());
-    Assert.assertEquals(RandomRule.class.getName(),
-        
ExtensionsManager.createLoadBalancerRule("mytest3").getClass().getName());
-    Assert.assertEquals(SessionStickinessRule.class.getName(),
-        
ExtensionsManager.createLoadBalancerRule("mytest4").getClass().getName());
-
-    
System.getProperties().remove("servicecomb.loadbalance.mytest1.NFLoadBalancerRuleClassName");
-    
System.getProperties().remove("servicecomb.loadbalance.mytest2.NFLoadBalancerRuleClassName");
-    
System.getProperties().remove("servicecomb.loadbalance.mytest3.NFLoadBalancerRuleClassName");
-    
System.getProperties().remove("servicecomb.loadbalance.mytest4.NFLoadBalancerRuleClassName");
-
     RetryHandler retryHandler = 
ExtensionsManager.createRetryHandler("mytest1");
     
Assert.assertTrue(DefaultLoadBalancerRetryHandler.class.isInstance(retryHandler));
     Assert.assertFalse(retryHandler.isRetriableException(new 
InvocationException(400, "", ""), false));
diff --git 
a/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestLoadBalanceCreator.java
 
b/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestLoadBalanceCreator.java
index f088e718b..e0019b7a1 100644
--- 
a/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestLoadBalanceCreator.java
+++ 
b/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestLoadBalanceCreator.java
@@ -20,42 +20,49 @@
 import java.util.ArrayList;
 import java.util.List;
 
+import org.apache.servicecomb.core.Endpoint;
 import org.apache.servicecomb.core.Invocation;
+import org.apache.servicecomb.core.Transport;
 import org.apache.servicecomb.foundation.test.scaffolding.config.ArchaiusUtils;
+import 
org.apache.servicecomb.serviceregistry.api.registry.MicroserviceInstance;
 import org.junit.Assert;
 import org.junit.Test;
 
-import com.netflix.loadbalancer.RandomRule;
-import com.netflix.loadbalancer.RoundRobinRule;
 import com.netflix.loadbalancer.Server;
-import com.netflix.loadbalancer.WeightedResponseTimeRule;
 
 import mockit.Deencapsulation;
 import mockit.Expectations;
 import mockit.Injectable;
-import mockit.Mocked;
 
 public class TestLoadBalanceCreator {
   @Test
-  public void testLoadBalanceWithRoundRobinRuleAndFilter(@Injectable 
Invocation invocation) {
+  public void testLoadBalanceWithRoundRobinRuleAndFilter(@Injectable 
Invocation invocation,
+      @Injectable Transport transport) {
     // Robin components implementations require getReachableServers & 
getServerList have the same size, we add a test case for this.
-    RoundRobinRule rule = new RoundRobinRule();
-    List<Server> servers = new ArrayList<>();
-    Server server = new Server("host1", 80);
-    server.setAlive(true);
-    Server server2 = new Server("host2", 80);
-    server2.setAlive(true);
+    RoundRobinRuleExt rule = new RoundRobinRuleExt();
+    List<ServiceCombServer> servers = new ArrayList<>();
+    Endpoint host1 = new Endpoint(transport, "host1");
+    MicroserviceInstance instance1 = new MicroserviceInstance();
+    instance1.setInstanceId("instance1");
+    ServiceCombServer server = new ServiceCombServer(host1, instance1);
+
+    Endpoint host2 = new Endpoint(transport, "host2");
+    MicroserviceInstance instance2 = new MicroserviceInstance();
+    instance2.setInstanceId("instance2");
+    ServiceCombServer server2 = new ServiceCombServer(host2, instance2);
+
     servers.add(server);
     servers.add(server2);
-    LoadBalancerCreator lbCreator = new LoadBalancerCreator(rule, "test");
+    LoadBalancer lb = new LoadBalancer(rule, "test");
 
     List<ServerListFilterExt> filters = new ArrayList<>();
 
     filters.add(new ServerListFilterExt() {
       @Override
-      public List<Server> getFilteredListOfServers(List<Server> serverList, 
Invocation invocation) {
-        List<Server> filteredServers = new ArrayList<>();
-        for (Server server : servers) {
+      public List<ServiceCombServer> 
getFilteredListOfServers(List<ServiceCombServer> serverList,
+          Invocation invocation) {
+        List<ServiceCombServer> filteredServers = new ArrayList<>();
+        for (ServiceCombServer server : servers) {
           if (server.getHost().equals("host1")) {
             continue;
           }
@@ -64,37 +71,50 @@ public void 
testLoadBalanceWithRoundRobinRuleAndFilter(@Injectable Invocation in
         return filteredServers;
       }
     });
-    lbCreator.setFilters(filters);
+    lb.setFilters(filters);
 
-    LoadBalancer lb = lbCreator.createLoadBalancer(invocation);
-    Server s = lb.chooseServer("test");
+    new Expectations() {
+      {
+        invocation.getLocalContext(LoadbalanceHandler.CONTEXT_KEY_SERVER_LIST);
+        result = servers;
+      }
+    };
+    Server s = lb.chooseServer(invocation);
     Assert.assertEquals(server2, s);
-    s = lb.chooseServer("test");
+    s = lb.chooseServer(invocation);
     Assert.assertEquals(server2, s);
-    s = lb.chooseServer("test");
+    s = lb.chooseServer(invocation);
     Assert.assertEquals(server2, s);
   }
 
   @Test
-  public void testLoadBalanceWithRandomRuleAndFilter(@Injectable Invocation 
invocation) {
+  public void testLoadBalanceWithRandomRuleAndFilter(@Injectable Invocation 
invocation,
+      @Injectable Transport transport) {
     // Robin components implementations require getReachableServers & 
getServerList have the same size, we add a test case for this.
-    RandomRule rule = new RandomRule();
-    LoadBalancerCreator lbCreator = new LoadBalancerCreator(rule, "service");
-
-    List<Server> servers = new ArrayList<>();
-    Server server = new Server("host1", 80);
-    server.setAlive(true);
-    Server server2 = new Server("host2", 80);
-    server2.setAlive(true);
+    RandomRuleExt rule = new RandomRuleExt();
+    LoadBalancer lb = new LoadBalancer(rule, "service");
+
+    List<ServiceCombServer> servers = new ArrayList<>();
+    Endpoint host1 = new Endpoint(transport, "host1");
+    MicroserviceInstance instance1 = new MicroserviceInstance();
+    instance1.setInstanceId("instance1");
+    ServiceCombServer server = new ServiceCombServer(host1, instance1);
+
+    Endpoint host2 = new Endpoint(transport, "host2");
+    MicroserviceInstance instance2 = new MicroserviceInstance();
+    instance2.setInstanceId("instance2");
+    ServiceCombServer server2 = new ServiceCombServer(host2, instance2);
+
     servers.add(server);
     servers.add(server2);
-    lbCreator.setServerList(servers);
+
     List<ServerListFilterExt> filters = new ArrayList<>();
     filters.add(new ServerListFilterExt() {
       @Override
-      public List<Server> getFilteredListOfServers(List<Server> serverList, 
Invocation invocation) {
-        List<Server> filteredServers = new ArrayList<>();
-        for (Server server : servers) {
+      public List<ServiceCombServer> 
getFilteredListOfServers(List<ServiceCombServer> serverList,
+          Invocation invocation) {
+        List<ServiceCombServer> filteredServers = new ArrayList<>();
+        for (ServiceCombServer server : servers) {
           if (server.getHost().equals("host1")) {
             continue;
           }
@@ -103,47 +123,54 @@ public void 
testLoadBalanceWithRandomRuleAndFilter(@Injectable Invocation invoca
         return filteredServers;
       }
     });
-    lbCreator.setFilters(filters);
-    LoadBalancer lb = lbCreator.createLoadBalancer(invocation);
-    Server s = lb.chooseServer("test");
+    lb.setFilters(filters);
+    new Expectations() {
+      {
+        invocation.getLocalContext(LoadbalanceHandler.CONTEXT_KEY_SERVER_LIST);
+        result = servers;
+      }
+    };
+    Server s = lb.chooseServer(invocation);
     Assert.assertEquals(server2, s);
-    s = lb.chooseServer("test");
+    s = lb.chooseServer(invocation);
     Assert.assertEquals(server2, s);
-    s = lb.chooseServer("test");
+    s = lb.chooseServer(invocation);
     Assert.assertEquals(server2, s);
   }
 
   @Test
-  public void testLoadBalanceWithWeightedResponseTimeRuleAndFilter(@Mocked 
ServiceCombServer server,
-      @Mocked ServiceCombServer server2, @Injectable Invocation invocation) {
+  public void testLoadBalanceWithWeightedResponseTimeRuleAndFilter(@Injectable 
Endpoint endpoint1,
+      @Injectable Endpoint endpoint2, @Injectable Invocation invocation) {
     // Robin components implementations require getReachableServers & 
getServerList have the same size, we add a test case for this.
-    WeightedResponseTimeRule rule = new WeightedResponseTimeRule();
-    LoadBalancerCreator lbCreator = new LoadBalancerCreator(rule, "service");
-    List<Server> servers = new ArrayList<>();
+    WeightedResponseTimeRuleExt rule = new WeightedResponseTimeRuleExt();
+    LoadBalancer lb = new LoadBalancer(rule, "service");
+
+    List<ServiceCombServer> servers = new ArrayList<>();
+    MicroserviceInstance instance1 = new MicroserviceInstance();
+    instance1.setInstanceId("ii01");
+    MicroserviceInstance instance2 = new MicroserviceInstance();
+    instance2.setInstanceId("ii02");
+    ServiceCombServer server = new ServiceCombServer(endpoint1, instance1);
+    ServiceCombServer server2 = new ServiceCombServer(endpoint2, instance2);
 
     new Expectations() {
       {
-        server.getHost();
+        endpoint1.getEndpoint();
         result = "host1";
-
-        server2.isReadyToServe();
-        result = true;
-        server2.isAlive();
-        result = true;
-        server2.getHost();
+        endpoint2.getEndpoint();
         result = "host2";
       }
     };
 
     servers.add(server);
     servers.add(server2);
-    lbCreator.setServerList(servers);
     List<ServerListFilterExt> filters = new ArrayList<>();
     filters.add(new ServerListFilterExt() {
       @Override
-      public List<Server> getFilteredListOfServers(List<Server> serverList, 
Invocation invocation) {
-        List<Server> filteredServers = new ArrayList<>();
-        for (Server server : servers) {
+      public List<ServiceCombServer> 
getFilteredListOfServers(List<ServiceCombServer> serverList,
+          Invocation invocation) {
+        List<ServiceCombServer> filteredServers = new ArrayList<>();
+        for (ServiceCombServer server : servers) {
           if (server.getHost().equals("host1")) {
             continue;
           }
@@ -152,41 +179,59 @@ public void 
testLoadBalanceWithWeightedResponseTimeRuleAndFilter(@Mocked Service
         return filteredServers;
       }
     });
-    lbCreator.setFilters(filters);
-    LoadBalancer lb = lbCreator.createLoadBalancer(invocation);
-    Server s = lb.chooseServer("test");
+    lb.setFilters(filters);
+    new Expectations() {
+      {
+        invocation.getLocalContext(LoadbalanceHandler.CONTEXT_KEY_SERVER_LIST);
+        result = servers;
+      }
+    };
+    Server s = lb.chooseServer(invocation);
     Assert.assertEquals(server2, s);
-    s = lb.chooseServer("test");
+    s = lb.chooseServer(invocation);
     Assert.assertEquals(server2, s);
-    s = lb.chooseServer("test");
+    s = lb.chooseServer(invocation);
     Assert.assertEquals(server2, s);
   }
 
   @Test
-  public void testLoadBalanceWithSessionSticknessRule(@Injectable Invocation 
invocation) {
+  public void testLoadBalanceWithSessionSticknessRule(@Injectable Invocation 
invocation,
+      @Injectable Transport transport) {
     SessionStickinessRule rule = new SessionStickinessRule();
-    LoadBalancerCreator lbCreator = new LoadBalancerCreator(rule, "service");
+    LoadBalancer lb = new LoadBalancer(rule, "service");
+
+    List<ServiceCombServer> servers = new ArrayList<>();
+    Endpoint host1 = new Endpoint(transport, "host1");
+    MicroserviceInstance instance1 = new MicroserviceInstance();
+    ServiceCombServer server = new ServiceCombServer(host1, instance1);
+    instance1.setInstanceId("instance1");
+
+    Endpoint host2 = new Endpoint(transport, "host2");
+    MicroserviceInstance instance2 = new MicroserviceInstance();
+    ServiceCombServer server2 = new ServiceCombServer(host2, instance2);
+    instance2.setInstanceId("instance2");
 
-    List<Server> servers = new ArrayList<>();
-    Server server = new Server("host1", 80);
-    server.setAlive(true);
-    Server server2 = new Server("host2", 80);
-    server2.setAlive(true);
     servers.add(server);
     servers.add(server2);
-    lbCreator.setServerList(servers);
-    lbCreator.setFilters(new ArrayList<>());
-    LoadBalancer lb = lbCreator.createLoadBalancer(invocation);
-    Server s = lb.chooseServer("test");
-    Assert.assertEquals(server2, s);
-    s = lb.chooseServer("test");
-    Assert.assertEquals(server2, s);
+
+    lb.setFilters(new ArrayList<>());
+    new Expectations() {
+      {
+        invocation.getLocalContext(LoadbalanceHandler.CONTEXT_KEY_SERVER_LIST);
+        result = servers;
+      }
+    };
+
+    Server s = lb.chooseServer(invocation);
+    Assert.assertEquals(server, s);
+    s = lb.chooseServer(invocation);
+    Assert.assertEquals(server, s);
 
     long time = Deencapsulation.getField(rule, "lastAccessedTime");
     Deencapsulation.setField(rule, "lastAccessedTime", time - 1000 * 300);
     
ArchaiusUtils.setProperty("cse.loadbalance.service.SessionStickinessRule.sessionTimeoutInSeconds",
 9);
-    s = lb.chooseServer("test");
-    Assert.assertEquals(server, s);
+    s = lb.chooseServer(invocation);
+    Assert.assertEquals(server2, s);
 
     
ArchaiusUtils.setProperty("cse.loadbalance.service.SessionStickinessRule.successiveFailedTimes",
 5);
     lb.getLoadBalancerStats().incrementSuccessiveConnectionFailureCount(s);
@@ -194,7 +239,7 @@ public void 
testLoadBalanceWithSessionSticknessRule(@Injectable Invocation invoc
     lb.getLoadBalancerStats().incrementSuccessiveConnectionFailureCount(s);
     lb.getLoadBalancerStats().incrementSuccessiveConnectionFailureCount(s);
     lb.getLoadBalancerStats().incrementSuccessiveConnectionFailureCount(s);
-    s = lb.chooseServer("test");
-    Assert.assertEquals(server2, s);
+    s = lb.chooseServer(invocation);
+    Assert.assertEquals(server, s);
   }
 }
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 b5262b54c..276e45412 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
@@ -17,6 +17,8 @@
 
 package org.apache.servicecomb.loadbalance;
 
+import static org.mockito.Mockito.when;
+
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
@@ -25,6 +27,10 @@
 import org.apache.servicecomb.core.CseContext;
 import org.apache.servicecomb.core.Invocation;
 import org.apache.servicecomb.core.Transport;
+import org.apache.servicecomb.core.definition.MicroserviceMeta;
+import org.apache.servicecomb.core.definition.OperationMeta;
+import org.apache.servicecomb.core.definition.SchemaMeta;
+import org.apache.servicecomb.core.provider.consumer.ReferenceConfig;
 import org.apache.servicecomb.core.transport.TransportManager;
 import org.apache.servicecomb.foundation.test.scaffolding.config.ArchaiusUtils;
 import org.apache.servicecomb.serviceregistry.RegistryUtils;
@@ -35,6 +41,7 @@
 import org.apache.servicecomb.serviceregistry.discovery.DiscoveryTreeNode;
 import org.junit.After;
 import org.junit.Assert;
+import org.junit.BeforeClass;
 import org.junit.Test;
 import org.mockito.Mockito;
 
@@ -43,6 +50,11 @@
  *
  */
 public class TestLoadBalanceHandler2 {
+  @BeforeClass
+  public static void beforeClass() {
+    // avoid mock
+    ServiceCombLoadBalancerStats.INSTANCE.init();
+  }
 
   @After
   public void teardown() {
@@ -52,7 +64,18 @@ public void teardown() {
 
   @Test
   public void testZoneAwareAndIsolationFilterWorks() {
-    Invocation invocation = Mockito.mock(Invocation.class);
+    ReferenceConfig referenceConfig = Mockito.mock(ReferenceConfig.class);
+    OperationMeta operationMeta = Mockito.mock(OperationMeta.class);
+    SchemaMeta schemaMeta = Mockito.mock(SchemaMeta.class);
+    when(operationMeta.getSchemaMeta()).thenReturn(schemaMeta);
+    MicroserviceMeta microserviceMeta = Mockito.mock(MicroserviceMeta.class);
+    when(schemaMeta.getMicroserviceMeta()).thenReturn(microserviceMeta);
+    when(schemaMeta.getMicroserviceName()).thenReturn("testMicroserviceName");
+    when(microserviceMeta.getAppId()).thenReturn("testApp");
+    when(referenceConfig.getVersionRule()).thenReturn("0.0.0+");
+    when(referenceConfig.getTransport()).thenReturn("rest");
+    Invocation invocation = new Invocation(referenceConfig, operationMeta, new 
Object[0]);
+
     InstanceCacheManager instanceCacheManager = 
Mockito.mock(InstanceCacheManager.class);
     ServiceRegistry serviceRegistry = Mockito.mock(ServiceRegistry.class);
     TransportManager transportManager = Mockito.mock(TransportManager.class);
@@ -106,15 +129,11 @@ public void testZoneAwareAndIsolationFilterWorks() {
 
     RegistryUtils.setServiceRegistry(serviceRegistry);
 
-    Mockito.when(invocation.getAppId()).thenReturn("testApp");
-    
Mockito.when(invocation.getMicroserviceName()).thenReturn("testMicroserviceName");
-    Mockito.when(invocation.getMicroserviceVersionRule()).thenReturn("0.0.0+");
-    Mockito.when(invocation.getConfigTransportName()).thenReturn("rest");
-    Mockito.when(serviceRegistry.getMicroserviceInstance()).thenReturn(myself);
-    
Mockito.when(serviceRegistry.getInstanceCacheManager()).thenReturn(instanceCacheManager);
-    Mockito.when(instanceCacheManager.getOrCreateVersionedCache("testApp", 
"testMicroserviceName", "0.0.0+"))
+    when(serviceRegistry.getMicroserviceInstance()).thenReturn(myself);
+    
when(serviceRegistry.getInstanceCacheManager()).thenReturn(instanceCacheManager);
+    when(instanceCacheManager.getOrCreateVersionedCache("testApp", 
"testMicroserviceName", "0.0.0+"))
         .thenReturn(parent);
-    Mockito.when(transportManager.findTransport("rest")).thenReturn(transport);
+    when(transportManager.findTransport("rest")).thenReturn(transport);
 
     LoadbalanceHandler handler = null;
     LoadBalancer loadBalancer = null;
@@ -122,26 +141,26 @@ public void testZoneAwareAndIsolationFilterWorks() {
 
     handler = new LoadbalanceHandler();
     loadBalancer = handler.getOrCreateLoadBalancer(invocation);
-    server = (ServiceCombServer) loadBalancer.chooseServer();
+    server = (ServiceCombServer) loadBalancer.chooseServer(invocation);
     Assert.assertEquals(server, null);
 
     data.put("noneMatchInstance", noneMatchInstance);
     parent.cacheVersion(1);
     handler = new LoadbalanceHandler();
     loadBalancer = handler.getOrCreateLoadBalancer(invocation);
-    server = (ServiceCombServer) loadBalancer.chooseServer();
+    server = (ServiceCombServer) loadBalancer.chooseServer(invocation);
     Assert.assertEquals(server.getEndpoint().getEndpoint(), 
"rest://localhost:9092");
 
     data.put("regionMatchInstance", regionMatchInstance);
     parent.cacheVersion(parent.cacheVersion() + 1);
     loadBalancer = handler.getOrCreateLoadBalancer(invocation);
-    server = (ServiceCombServer) loadBalancer.chooseServer();
+    server = (ServiceCombServer) loadBalancer.chooseServer(invocation);
     Assert.assertEquals(server.getEndpoint().getEndpoint(), 
"rest://localhost:9091");
 
     data.put("allmatchInstance", allmatchInstance);
     parent.cacheVersion(parent.cacheVersion() + 1);
     loadBalancer = handler.getOrCreateLoadBalancer(invocation);
-    server = (ServiceCombServer) loadBalancer.chooseServer();
+    server = (ServiceCombServer) loadBalancer.chooseServer(invocation);
     Assert.assertEquals(server.getEndpoint().getEndpoint(), 
"rest://localhost:9090");
 
     ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server);
@@ -153,23 +172,23 @@ public void testZoneAwareAndIsolationFilterWorks() {
     //if errorThresholdPercentage is 0,that means errorThresholdPercentage is 
not active.
     
ArchaiusUtils.setProperty("servicecomb.loadbalance.isolation.errorThresholdPercentage",
 "0");
     loadBalancer = handler.getOrCreateLoadBalancer(invocation);
-    server = (ServiceCombServer) loadBalancer.chooseServer();
+    server = (ServiceCombServer) loadBalancer.chooseServer(invocation);
     Assert.assertEquals(server.getEndpoint().getEndpoint(), 
"rest://localhost:9090");
 
     //if errorThresholdPercentage greater than 0, it will activate.
     
ArchaiusUtils.setProperty("servicecomb.loadbalance.isolation.errorThresholdPercentage",
 "20");
     ServiceCombServer server2 = server;
     loadBalancer = handler.getOrCreateLoadBalancer(invocation);
-    server = (ServiceCombServer) loadBalancer.chooseServer();
+    server = (ServiceCombServer) loadBalancer.chooseServer(invocation);
     Assert.assertEquals(server.getEndpoint().getEndpoint(), 
"rest://localhost:9091");
     ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server2);
     loadBalancer = handler.getOrCreateLoadBalancer(invocation);
-    server = (ServiceCombServer) loadBalancer.chooseServer();
+    server = (ServiceCombServer) loadBalancer.chooseServer(invocation);
     Assert.assertEquals(server.getEndpoint().getEndpoint(), 
"rest://localhost:9090");
     ServiceCombLoadBalancerStats.INSTANCE.markFailure(server2);
     ServiceCombLoadBalancerStats.INSTANCE.markFailure(server2);
     loadBalancer = handler.getOrCreateLoadBalancer(invocation);
-    server = (ServiceCombServer) loadBalancer.chooseServer();
+    server = (ServiceCombServer) loadBalancer.chooseServer(invocation);
     Assert.assertEquals(server.getEndpoint().getEndpoint(), 
"rest://localhost:9091");
   }
 }
diff --git 
a/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestLoadBalancer.java
 
b/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestLoadBalancer.java
index a61fa4fa2..761c23cbe 100644
--- 
a/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestLoadBalancer.java
+++ 
b/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestLoadBalancer.java
@@ -17,117 +17,33 @@
 
 package org.apache.servicecomb.loadbalance;
 
-import static org.junit.Assert.assertNotNull;
+import static org.mockito.Mockito.when;
 
 import java.util.ArrayList;
 import java.util.List;
 
+import org.apache.servicecomb.core.Invocation;
 import org.junit.Assert;
 import org.junit.Test;
 import org.mockito.Mockito;
 
-import com.netflix.loadbalancer.AbstractLoadBalancer.ServerGroup;
-import com.netflix.loadbalancer.IRule;
-import com.netflix.loadbalancer.Server;
-
 public class TestLoadBalancer {
-  private IRule rule = Mockito.mock(IRule.class);
+  private RuleExt rule = Mockito.mock(RuleExt.class);
 
-  @SuppressWarnings("deprecation")
   @Test
   public void testLoadBalancerFullOperationWithoutException() {
-    List<Server> newServers = new ArrayList<>();
-    Server server = Mockito.mock(Server.class);
-    newServers.add(server);
-    LoadBalancer loadBalancer = new LoadBalancer(rule, "test", null);
-    loadBalancer.setServerList(newServers);
-    loadBalancer.chooseServer();
-
-    Object key = Mockito.mock(Object.class);
-
-    loadBalancer.chooseServer(key);
-    loadBalancer.getAllServers();
-    loadBalancer.getServerList(true);
-    loadBalancer.getServerList(false);
-    loadBalancer.getLoadBalancerStats();
-    loadBalancer.getReachableServers();
-
-    assertNotNull(loadBalancer.getAllServers());
-  }
-
-  @Test
-  public void testAddServerException() {
-    boolean status = true;
-    List<Server> newServers = new ArrayList<>();
-    Server server = Mockito.mock(Server.class);
-
-    newServers.add(server);
-    LoadBalancer loadBalancer = new LoadBalancer(rule, "test", null);
-    loadBalancer.setServerList(newServers);
-    try {
-
-      loadBalancer.addServers(newServers);
-    } catch (Exception e) {
-
-      status = false;
-
-      Assert.assertEquals("Not implemented.", e.getMessage());
-    }
-
-    Assert.assertFalse(status);
-  }
-
-  @Test
-  public void testServerListException() {
-    boolean status = true;
-    List<Server> newServers = new ArrayList<>();
-    Server server = Mockito.mock(Server.class);
-
-    newServers.add(server);
-    LoadBalancer loadBalancer = new LoadBalancer(rule, "test", null);
-    loadBalancer.setServerList(newServers);
-    try {
-
-      loadBalancer.getServerList(ServerGroup.ALL);
-    } catch (Exception e) {
-
-      status = false;
-
-      Assert.assertEquals("Not implemented.", e.getMessage());
-    }
-
-    Assert.assertFalse(status);
-  }
-
-  @Test
-  public void testMarkServerDownException() {
-    boolean status = true;
-    List<Server> newServers = new ArrayList<>();
-    Server server = Mockito.mock(Server.class);
-
+    List<ServiceCombServer> newServers = new ArrayList<>();
+    ServiceCombServer server = Mockito.mock(ServiceCombServer.class);
+    Invocation invocation = Mockito.mock(Invocation.class);
     newServers.add(server);
-    LoadBalancer loadBalancer = new LoadBalancer(rule, "test", null);
-    loadBalancer.setServerList(newServers);
-    try {
-
-      loadBalancer.markServerDown(server);
-    } catch (Exception e) {
+    
when(invocation.getLocalContext(LoadbalanceHandler.CONTEXT_KEY_SERVER_LIST)).thenReturn(newServers);
+    LoadBalancer loadBalancer = new LoadBalancer(rule, "test");
+    loadBalancer.chooseServer(invocation);
 
-      status = false;
+    when(rule.choose(newServers, invocation)).thenReturn(server);
 
-      Assert.assertEquals("Not implemented.", e.getMessage());
-    }
-
-    Assert.assertFalse(status);
-  }
-
-  @Test
-  public void testGetAllServers() {
-    List<Server> servers = new ArrayList<>();
-    Server server = Mockito.mock(Server.class);
-    servers.add(server);
-    LoadBalancer loadBalancer = new LoadBalancer(rule, "test", null);
-    loadBalancer.setServerList(servers);
-    Assert.assertEquals(servers, loadBalancer.getAllServers());
+    Assert.assertEquals(server, loadBalancer.chooseServer(invocation));
+    Assert.assertNotNull(loadBalancer.getLoadBalancerStats());
+    Assert.assertEquals("test", loadBalancer.getMicroServiceName());
   }
 }
diff --git 
a/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestLoadbalanceHandler.java
 
b/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestLoadbalanceHandler.java
index faa86f961..eedf60c6f 100644
--- 
a/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestLoadbalanceHandler.java
+++ 
b/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestLoadbalanceHandler.java
@@ -74,7 +74,7 @@
 
   LoadbalanceHandler handler;
 
-  Map<String, LoadBalancerCreator> loadBalancerMap;
+  Map<String, LoadBalancer> loadBalancerMap;
 
   @Injectable
   Invocation invocation;
@@ -137,7 +137,6 @@ InstanceCacheManager getInstanceCacheManager() {
 
     BeansHolder holder = new BeansHolder();
     List<ExtensionsFactory> extensionsFactories = new ArrayList<>();
-    extensionsFactories.add(new RuleClassNameExtentionsFactory());
     extensionsFactories.add(new RuleNameExtentionsFactory());
     extensionsFactories.add(new DefaultRetryExtensionsFactory());
     Deencapsulation.setField(holder, "extentionsFactories", 
extensionsFactories);
@@ -154,34 +153,6 @@ public void teardown() {
     ArchaiusUtils.resetConfig();
   }
 
-  @Test
-  public void getOrCreateLoadBalancer() throws Exception {
-    LoadbalanceHandler handler = new LoadbalanceHandler();
-
-    MicroserviceInstance instance = new MicroserviceInstance();
-    instance.setInstanceId("id");
-    instance.getEndpoints().add("rest://localhost:8080");
-
-    Map<String, MicroserviceInstance> instanceMap = new HashMap<>();
-    instanceMap.put(instance.getInstanceId(), instance);
-
-    VersionedCache instanceVersionedCache =
-        new 
VersionedCache().autoCacheVersion().name("instanceCache").data(instanceMap);
-
-    new Expectations() {
-      {
-        invocation.getConfigTransportName();
-        result = "rest";
-        instanceCacheManager.getOrCreateVersionedCache(anyString, anyString, 
anyString);
-        result = instanceVersionedCache;
-      }
-    };
-
-    LoadBalancer lb = handler.getOrCreateLoadBalancer(invocation);
-
-    Assert.assertEquals("[rest://localhost:8080]", 
Deencapsulation.getField(lb, "serverList").toString());
-  }
-
   @Test
   public void send_noEndPoint(@Injectable LoadBalancer loadBalancer) {
     new Expectations(loadBalancer) {
diff --git 
a/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestRoundRobinRuleExt.java
 
b/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestRoundRobinRuleExt.java
new file mode 100644
index 000000000..ce78b503e
--- /dev/null
+++ 
b/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestRoundRobinRuleExt.java
@@ -0,0 +1,76 @@
+/*
+ * 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.loadbalance;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.apache.servicecomb.core.Invocation;
+import org.junit.Assert;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+public class TestRoundRobinRuleExt {
+  @Test
+  public void testRoundRobin() {
+    RoundRobinRuleExt rule = new RoundRobinRuleExt();
+    LoadBalancer loadBalancer = new LoadBalancer(rule, "testService");
+    List<ServiceCombServer> servers = new ArrayList<>();
+    Invocation invocation = Mockito.mock(Invocation.class);
+    for (int i = 0; i < 2; i++) {
+      ServiceCombServer server = Mockito.mock(ServiceCombServer.class);
+      Mockito.when(server.toString()).thenReturn("server " + i);
+      servers.add(server);
+      loadBalancer.getLoadBalancerStats().noteResponseTime(server, 1);
+    }
+
+    AtomicInteger server1 = new AtomicInteger(0);
+    AtomicInteger server2 = new AtomicInteger(0);
+    for (int i = 0; i < 2000; i++) {
+      if (rule.choose(servers, invocation).toString().equals("server 0")) {
+        server1.incrementAndGet();
+      } else {
+        server2.incrementAndGet();
+      }
+    }
+    Assert.assertEquals(server1.get(), server2.get());
+  }
+
+  @Test
+  public void testBenchmarkRobin() {
+    // less than 0.001ms
+    RoundRobinRuleExt rule = new RoundRobinRuleExt();
+    LoadBalancer loadBalancer = new LoadBalancer(rule, "testService");
+    List<ServiceCombServer> servers = new ArrayList<>();
+    Invocation invocation = Mockito.mock(Invocation.class);
+    for (int i = 0; i < 100; i++) {
+      ServiceCombServer server = Mockito.mock(ServiceCombServer.class);
+      Mockito.when(server.toString()).thenReturn("server " + i);
+      servers.add(server);
+      loadBalancer.getLoadBalancerStats().noteResponseTime(server, 2);
+    }
+    long begin = System.currentTimeMillis();
+    for (int i = 0; i < 10000; i++) {
+      rule.choose(servers, invocation);
+    }
+    long taken = System.currentTimeMillis() - begin;
+    System.out.println("taken " + taken);
+    Assert.assertEquals("actual token " + taken, taken < 10 * 5, true);  // 5 
* times make slow machine happy
+  }
+}
diff --git 
a/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestServiceCombLoadBalancerStats.java
 
b/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestServiceCombLoadBalancerStats.java
index 11dfe77bb..fb884529c 100644
--- 
a/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestServiceCombLoadBalancerStats.java
+++ 
b/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestServiceCombLoadBalancerStats.java
@@ -39,7 +39,7 @@
   @BeforeClass
   public static void beforeClass() {
     // avoid mock
-    ServiceCombLoadBalancerStats.INSTANCE.getClass();
+    ServiceCombLoadBalancerStats.INSTANCE.init();
   }
 
   @Test
diff --git 
a/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestSessionSticknessRule.java
 
b/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestSessionSticknessRule.java
index 6ebead209..303735c96 100644
--- 
a/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestSessionSticknessRule.java
+++ 
b/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestSessionSticknessRule.java
@@ -20,9 +20,11 @@
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 
+import org.apache.servicecomb.core.Invocation;
 import org.apache.servicecomb.core.Transport;
 import 
org.apache.servicecomb.serviceregistry.api.registry.MicroserviceInstance;
 import org.apache.servicecomb.serviceregistry.cache.CacheEndpoint;
@@ -49,22 +51,20 @@ public void testRuleFullOperation() {
     instance1.setInstanceId("1234");
     ServiceCombServer mockedServer =
         new ServiceCombServer(transport, new 
CacheEndpoint("rest:127.0.0.1:8889", instance1));
-    Object key = Mockito.mock(Object.class);
+    Invocation invocation = mock(Invocation.class);
     LoadBalancerStats stats = mock(LoadBalancerStats.class);
     Mockito.when(mockedLb.getLoadBalancerStats()).thenReturn(stats);
-    Deencapsulation.invoke(rule, "chooseServerWhenTimeout", key);
+    Deencapsulation.invoke(rule, "chooseServerWhenTimeout", 
Arrays.asList(mockedServer), invocation);
     mockedServer.setAlive(true);
     mockedServer.setReadyToServe(true);
-    List<Server> allServers = Arrays.asList(mockedServer);
-    when(mockedLb.getReachableServers()).thenReturn(allServers);
-    when(mockedLb.getAllServers()).thenReturn(allServers);
-
+    List<ServiceCombServer> allServers = Arrays.asList(mockedServer);
     rule.setLoadBalancer(mockedLb);
-    Assert.assertEquals(rule.getLoadBalancer(), mockedLb);
-    Server s = rule.choose("default");
+
+
+    Server s = rule.choose(allServers, invocation);
     Assert.assertEquals(s, mockedServer);
 
-    s = rule.choose("default");
+    s = rule.choose(allServers, invocation);
     Assert.assertEquals(s, mockedServer);
   }
 
@@ -77,9 +77,12 @@ public void testServerWithoutTimeoutAndWithThreshold() {
 
     Object key = new Object();
 
-    Server s = new Server("test");
+    Invocation invocation = mock(Invocation.class);
+    ServiceCombServer server = mock(ServiceCombServer.class);
+    List<ServiceCombServer> servers = new ArrayList<>();
+    servers.add(server);
 
-    Deencapsulation.setField(ss, "lastServer", s);
+    Deencapsulation.setField(ss, "lastServer", server);
 
     new MockUp<SessionStickinessRule>() {
 
@@ -98,7 +101,7 @@ private boolean isErrorThresholdMet() {
     };
 
     try {
-      ss.choose(key);
+      ss.choose(servers, invocation);
     } catch (Exception e) {
       status = false;
     }
@@ -112,11 +115,12 @@ public void testServerWithTimeout() {
 
     SessionStickinessRule ss = new SessionStickinessRule();
 
-    Object key = new Object();
-
-    Server s = new Server("test");
+    Invocation invocation = mock(Invocation.class);
+    ServiceCombServer server = mock(ServiceCombServer.class);
+    List<ServiceCombServer> servers = new ArrayList<>();
+    servers.add(server);
 
-    Deencapsulation.setField(ss, "lastServer", s);
+    Deencapsulation.setField(ss, "lastServer", server);
 
     new MockUp<SessionStickinessRule>() {
 
@@ -127,7 +131,7 @@ private boolean isTimeOut() {
     };
 
     try {
-      ss.choose(key);
+      ss.choose(servers, invocation);
     } catch (Exception e) {
       status = false;
     }
@@ -144,9 +148,12 @@ public void testServerWithoutTimeoutException() {
 
     Object key = new Object();
 
-    Server s = new Server("test");
+    Invocation invocation = mock(Invocation.class);
+    ServiceCombServer server = mock(ServiceCombServer.class);
+    List<ServiceCombServer> servers = new ArrayList<>();
+    servers.add(server);
 
-    Deencapsulation.setField(ss, "lastServer", s);
+    Deencapsulation.setField(ss, "lastServer", server);
 
     new MockUp<SessionStickinessRule>() {
 
@@ -157,7 +164,7 @@ private boolean isTimeOut() {
     };
 
     try {
-      ss.choose(key);
+      ss.choose(servers, invocation);
     } catch (Exception e) {
       status = false;
     }
@@ -173,9 +180,12 @@ public void testServerWithoutTimeoutAndThreshold() {
 
     Object key = new Object();
 
-    Server s = new Server("test");
+    Invocation invocation = mock(Invocation.class);
+    ServiceCombServer server = mock(ServiceCombServer.class);
+    List<ServiceCombServer> servers = new ArrayList<>();
+    servers.add(server);
 
-    Deencapsulation.setField(ss, "lastServer", s);
+    Deencapsulation.setField(ss, "lastServer", server);
 
     new MockUp<SessionStickinessRule>() {
 
@@ -202,7 +212,7 @@ private boolean isLastServerExists(Server server) {
     };
 
     try {
-      ss.choose(key);
+      ss.choose(servers, invocation);
     } catch (Exception e) {
       status = false;
     }
@@ -217,26 +227,14 @@ public void testServerWithActualServerObj() {
 
     Object key = new Object();
 
-    Server s = new Server("test");
-
-    Deencapsulation.setField(ss, "lastServer", s);
-    try {
-      ss.choose(key);
-    } catch (Exception e) {
-      status = false;
-    }
-    Assert.assertTrue(status);
-  }
-
-  @Test
-  public void testServerWithKey() {
-
-    boolean status = true;
-    SessionStickinessRule ss = new SessionStickinessRule();
+    Invocation invocation = mock(Invocation.class);
+    ServiceCombServer server = mock(ServiceCombServer.class);
+    List<ServiceCombServer> servers = new ArrayList<>();
+    servers.add(server);
 
-    Object key = new Object();
+    Deencapsulation.setField(ss, "lastServer", server);
     try {
-      ss.choose(key);
+      ss.choose(servers, invocation);
     } catch (Exception e) {
       status = false;
     }
@@ -248,6 +246,7 @@ public void testLastServerNotExist() {
     SessionStickinessRule rule = new SessionStickinessRule();
 
     Transport transport = mock(Transport.class);
+    Invocation invocation = mock(Invocation.class);
     MicroserviceInstance instance1 = new MicroserviceInstance();
     instance1.setInstanceId("1234");
     ServiceCombServer mockedServer =
@@ -255,13 +254,11 @@ public void testLastServerNotExist() {
     mockedServer.setAlive(true);
     mockedServer.setReadyToServe(true);
     mockedServer.setId("mockedServer");
-    List<Server> allServers = Arrays.asList(mockedServer);
-    LoadBalancer lb = new LoadBalancer(rule, "mockedServer", null);
-    lb.setServerList(allServers);
-
+    List<ServiceCombServer> allServers = Arrays.asList(mockedServer);
+    LoadBalancer lb = new LoadBalancer(rule, "mockedServer");
+    
when(invocation.getLocalContext(LoadbalanceHandler.CONTEXT_KEY_SERVER_LIST)).thenReturn(allServers);
     rule.setLoadBalancer(lb);
-    Assert.assertEquals(lb, rule.getLoadBalancer());
-    Server server = new Server("test");
+    ServiceCombServer server = new ServiceCombServer(transport, new 
CacheEndpoint("rest:127.0.0.1:8890", instance1));
     Deencapsulation.setField(rule, "lastServer", server);
 
     new MockUp<SessionStickinessRule>(rule) {
@@ -276,7 +273,7 @@ private boolean isErrorThresholdMet() {
       }
     };
     Object key = Mockito.mock(Object.class);
-    Server s = rule.choose(key);
+    Server s = rule.choose(allServers, invocation);
     Assert.assertEquals(mockedServer, s);
   }
 }
diff --git 
a/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestWeightedResponseTimeRuleExt.java
 
b/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestWeightedResponseTimeRuleExt.java
new file mode 100644
index 000000000..0d4e0031f
--- /dev/null
+++ 
b/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestWeightedResponseTimeRuleExt.java
@@ -0,0 +1,126 @@
+/*
+ * 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.loadbalance;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.apache.servicecomb.core.Invocation;
+import org.junit.Assert;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+public class TestWeightedResponseTimeRuleExt {
+  @Test
+  public void testRoundRobin() {
+    WeightedResponseTimeRuleExt rule = new WeightedResponseTimeRuleExt();
+    LoadBalancer loadBalancer = new LoadBalancer(rule, "testService");
+    List<ServiceCombServer> servers = new ArrayList<>();
+    Invocation invocation = Mockito.mock(Invocation.class);
+    for (int i = 0; i < 2; i++) {
+      ServiceCombServer server = Mockito.mock(ServiceCombServer.class);
+      Mockito.when(server.toString()).thenReturn("server " + i);
+      servers.add(server);
+      loadBalancer.getLoadBalancerStats().noteResponseTime(server, 1);
+    }
+
+    AtomicInteger server1 = new AtomicInteger(0);
+    AtomicInteger server2 = new AtomicInteger(0);
+    for (int i = 0; i < 2000; i++) {
+      if (rule.choose(servers, invocation).toString().equals("server 0")) {
+        server1.incrementAndGet();
+      } else {
+        server2.incrementAndGet();
+      }
+    }
+    Assert.assertEquals(server1.get(), server2.get());
+  }
+
+  @Test
+  public void testWeighed() {
+    WeightedResponseTimeRuleExt rule = new WeightedResponseTimeRuleExt();
+    LoadBalancer loadBalancer = new LoadBalancer(rule, "testService");
+    List<ServiceCombServer> servers = new ArrayList<>();
+    Invocation invocation = Mockito.mock(Invocation.class);
+    for (int i = 0; i < 2; i++) {
+      ServiceCombServer server = Mockito.mock(ServiceCombServer.class);
+      Mockito.when(server.toString()).thenReturn("server " + i);
+      servers.add(server);
+      loadBalancer.getLoadBalancerStats().noteResponseTime(server, 20 * 
Math.pow(4, i + 1));
+    }
+
+    AtomicInteger server1 = new AtomicInteger(0);
+    AtomicInteger server2 = new AtomicInteger(0);
+    for (int i = 0; i < 2000; i++) {
+      if (rule.choose(servers, invocation).toString().equals("server 0")) {
+        server1.incrementAndGet();
+      } else {
+        server2.incrementAndGet();
+      }
+    }
+    double percent = (double) server1.get() / (server2.get() + server1.get());
+    System.out.println("percent" + percent);
+    Assert.assertEquals("actually percent: " + percent, 0.70d < percent, 
percent < 0.90d);
+  }
+
+  @Test
+  public void testBenchmark() {
+    // 100 instances will taken less than 0.1ms. Because we use weighed rule 
when response time more than 10ms,
+    // This only taken 1/1000 time.
+    WeightedResponseTimeRuleExt rule = new WeightedResponseTimeRuleExt();
+    LoadBalancer loadBalancer = new LoadBalancer(rule, "testService");
+    List<ServiceCombServer> servers = new ArrayList<>();
+    Invocation invocation = Mockito.mock(Invocation.class);
+    for (int i = 0; i < 100; i++) {
+      ServiceCombServer server = Mockito.mock(ServiceCombServer.class);
+      Mockito.when(server.toString()).thenReturn("server " + i);
+      servers.add(server);
+      loadBalancer.getLoadBalancerStats().noteResponseTime(server, i);
+    }
+    long begin = System.currentTimeMillis();
+    for (int i = 0; i < 10000; i++) {
+      rule.choose(servers, invocation);
+    }
+    long taken = System.currentTimeMillis() - begin;
+    System.out.println("taken " + taken);
+    Assert.assertEquals("actually taken: " + taken, taken < 1000 * 5, true); 
// 5 * times make slow machine happy
+  }
+
+  @Test
+  public void testBenchmarkRobin() {
+    // 100 instances will taken less than 0.02ms. Not as good as 
RoundRobinRule, which taken less than 0.001ms
+    WeightedResponseTimeRuleExt rule = new WeightedResponseTimeRuleExt();
+    LoadBalancer loadBalancer = new LoadBalancer(rule, "testService");
+    List<ServiceCombServer> servers = new ArrayList<>();
+    Invocation invocation = Mockito.mock(Invocation.class);
+    for (int i = 0; i < 100; i++) {
+      ServiceCombServer server = Mockito.mock(ServiceCombServer.class);
+      Mockito.when(server.toString()).thenReturn("server " + i);
+      servers.add(server);
+      loadBalancer.getLoadBalancerStats().noteResponseTime(server, 2);
+    }
+    long begin = System.currentTimeMillis();
+    for (int i = 0; i < 10000; i++) {
+      rule.choose(servers, invocation);
+    }
+    long taken = System.currentTimeMillis() - begin;
+    System.out.println("taken " + taken);
+    Assert.assertEquals("actually taken: " + taken, taken < 200 * 2, true); // 
5 * times make slow machine happy
+  }
+}
diff --git 
a/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/filter/TestServerDiscoveryFilter.java
 
b/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/filter/TestServerDiscoveryFilter.java
index 3a5e8b959..5dbd6a45c 100644
--- 
a/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/filter/TestServerDiscoveryFilter.java
+++ 
b/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/filter/TestServerDiscoveryFilter.java
@@ -72,6 +72,7 @@ public void createEndpointNormal() {
       }
     };
     MicroserviceInstance instance = new MicroserviceInstance();
+    instance.setInstanceId("0000001");
 
     ServiceCombServer server = (ServiceCombServer) 
filter.createEndpoint(Const.RESTFUL, "rest://localhost:8080", instance);
     Assert.assertSame(instance, server.getInstance());
diff --git 
a/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/engine/SwaggerProducerOperation.java
 
b/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/engine/SwaggerProducerOperation.java
index 5c3caf091..30e812fca 100644
--- 
a/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/engine/SwaggerProducerOperation.java
+++ 
b/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/engine/SwaggerProducerOperation.java
@@ -21,13 +21,17 @@
 import java.util.List;
 import java.util.concurrent.CompletableFuture;
 
+import javax.ws.rs.core.Response.Status;
+
 import org.apache.servicecomb.foundation.common.utils.SPIServiceUtils;
 import org.apache.servicecomb.swagger.invocation.AsyncResponse;
 import org.apache.servicecomb.swagger.invocation.Response;
 import org.apache.servicecomb.swagger.invocation.SwaggerInvocation;
 import 
org.apache.servicecomb.swagger.invocation.arguments.producer.ProducerArgumentsMapper;
 import org.apache.servicecomb.swagger.invocation.context.ContextUtils;
+import org.apache.servicecomb.swagger.invocation.exception.CommonExceptionData;
 import org.apache.servicecomb.swagger.invocation.exception.ExceptionFactory;
+import org.apache.servicecomb.swagger.invocation.exception.InvocationException;
 import 
org.apache.servicecomb.swagger.invocation.extension.ProducerInvokeExtension;
 import 
org.apache.servicecomb.swagger.invocation.response.producer.ProducerResponseMapper;
 
@@ -159,6 +163,10 @@ public Response doInvoke(SwaggerInvocation invocation) {
       }
       Object result = producerMethod.invoke(producerInstance, args);
       response = responseMapper.mapResponse(invocation.getStatus(), result);
+    } catch (IllegalArgumentException ae) {
+      response = processException(invocation,
+          new InvocationException(Status.BAD_REQUEST.getStatusCode(), "",
+              new CommonExceptionData(ae.getMessage()), ae));
     } catch (Throwable e) {
       response = processException(invocation, e);
     }


 

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


With regards,
Apache Git Services

Reply via email to