ribbon的常用负载均衡算法分析( 二 )


  1. WeightedResponseTimeRule实现类中默认情况下每隔30秒会统计一次每个服务的权重 , 在此30秒内 , 用的是轮询策略
  2. 30秒之后 , 会根据统计的结果来分配每个实例的权重 , 然后根据权重来分配调用次数
extends RoundRobinRulepublic Server choose(ILoadBalancer lb, Object key) {if (lb == null) {return null;} else {Server server = null;while(server == null) {List<Double> currentWeights = this.accumulatedWeights;if (Thread.interrupted()) {return null;}List<Server> allList = lb.getAllServers();int serverCount = allList.size();if (serverCount == 0) {return null;}int serverIndex = 0;double maxTotalWeight = currentWeights.size() == 0 ? 0.0D : (Double)currentWeights.get(currentWeights.size() - 1);//在30秒之内 , maxTotalWeight变量会一直是0.0if (maxTotalWeight >= 0.001D && serverCount == currentWeights.size()) {double randomWeight = this.random.nextDouble() * maxTotalWeight;int n = 0;for(Iterator var13 = currentWeights.iterator(); var13.hasNext(); ++n) {Double d = (Double)var13.next();if (d >= randomWeight) {serverIndex = n;break;}}server = (Server)allList.get(serverIndex);} else {server = super.choose(this.getLoadBalancer(), key);if (server == null) {return server;}}if (server == null) {Thread.yield();} else {if (server.isAlive()) {return server;}server = null;}}return server;}}debug的图例:
ribbon的常用负载均衡算法分析

文章插图
 
3.4. RetryRule 重试策略重试策略是指通过轮询策略选出一个实例 , 然后去访问 , 如果此实例为null或者已经失效 , 那么会重试其他的实例 , answer = this.subRule.choose(key); 会根据轮询策略选择一个实例 , 然后if ((answer == null || !answer.isAlive()) && System.currentTimeMillis() < deadline)判断如果实例为null或者失效 , 那么会重新选择
public Server choose(ILoadBalancer lb, Object key) {long requestTime = System.currentTimeMillis();long deadline = requestTime + this.maxRetryMillis;Server answer = null;answer = this.subRule.choose(key);if ((answer == null || !answer.isAlive()) && System.currentTimeMillis() < deadline) {InterruptTask task = new InterruptTask(deadline - System.currentTimeMillis());while(!Thread.interrupted()) {answer = this.subRule.choose(key);if (answer != null && answer.isAlive() || System.currentTimeMillis() >= deadline) {break;}Thread.yield();}task.cancel();}return answer != null && answer.isAlive() ? answer : null;}
ribbon的常用负载均衡算法分析

文章插图
 
3.5. BestAvailableRule 最低并发策略
会根据每个服务实例的并发数量来决定 , 访问并发数最少的那个服务 , int concurrentConnections = serverStats.getActiveRequestsCount(currentTime); 会获得当前遍历的实例的并发数 , 然后和其他的实例的并发数进行判断 , 最终访问并发量最少的那个实例
public Server choose(Object key) {if (this.loadBalancerStats == null) {return super.choose(key);} else {List<Server> serverList = this.getLoadBalancer().getAllServers();int minimalConcurrentConnections = 2147483647;long currentTime = System.currentTimeMillis();Server chosen = null;Iterator var7 = serverList.iterator();while(var7.hasNext()) { //遍历所有的实例Server server = (Server)var7.next();ServerStats serverStats = this.loadBalancerStats.getSingleServerStat(server);if (!serverStats.isCircuitBreakerTripped(currentTime)) {int concurrentConnections = serverStats.getActiveRequestsCount(currentTime); //判断并发数 , 并和已经判断出的最少的并发数比较if (concurrentConnections < minimalConcurrentConnections) {minimalConcurrentConnections = concurrentConnections;chosen = server;}}}if (chosen == null) {return super.choose(key);} else {return chosen;}}}3.6. AvailabilityFilteringRule 可用过滤策略此策略会聪明的过滤掉一直失败并被标记为circuit tripped的user服务 , 而且会过滤掉那些高并发的user服务
public Server choose(Object key) {int count = 0;for(Server server = this.roundRobinRule.choose(key); count++ <= 10; server = this.roundRobinRule.choose(key)) {//通过predicate来过滤if (this.predicate.Apply(new PredicateKey(server))) {return server;}}//过滤掉一些服务之后 , 会采用轮询的方式调用剩下的服务return super.choose(key);}3.7. ClientConfigEnabledRoundRobinRule 自定义策略此策略本身并没有实现什么特殊的处理逻辑 , 但是可以通过重置LoadBalancer来达到自定义一些高级策略的目的 , 可以重写initWithNiwsConfig和setLoadBalancer
public void initWithNiwsConfig(IClientConfig clientConfig) {this.roundRobinRule = new RoundRobinRule();}public void setLoadBalancer(ILoadBalancer lb) {super.setLoadBalancer(lb);this.roundRobinRule.setLoadBalancer(lb);}public Server choose(Object key) {if (this.roundRobinRule != null) {return this.roundRobinRule.choose(key);} else {throw new IllegalArgumentException("This class has not been initialized with the RoundRobinRule class");}}


推荐阅读