Netflix源码解析之Ribbon:负载均衡策略的定义和实现

Ribbon负载均衡策略定义

IRule其实就只做了一件事情Server choose(Object key),可以看到这个功能是在LB中定义(要求)的,LB把这个功能委托给IRule来实现。不同的IRule可以向LB提供不同的负载均衡算法。

publicinterfaceIRule{publicServer choose(Object key);publicvoid setLoadBalancer(ILoadBalancer lb);publicILoadBalancer getLoadBalancer();}

com.netflix.loadbalancer包下面的提供了常用的几种策略。有RoundRobinRule、RandomRule这样的不依赖于Server运行状况的策略,也有AvailabilityFilteringRule、WeightedResponseTimeRule等多种基于收集到的Server运行状况决策的策略。判断运行状况时有,判断单个server的,也有判断整个zone的,适用于各种不同场景需求。

实现上有些策略可以继承一个既存的简单策略用于某些启动时候,也可以包含一个简单策略。甚至有ZoneAvoidanceRule这样的可以包含复合谓词的条件判断。
IRule_implementation

Ribbon自带负载均衡策略比较

策略名 策略声明 策略描述 实现说明
BestAvailableRule ?public class BestAvailableRule extends ClientConfigEnabledRoundRobinRule 选择一个最小的并发请求的server 逐个考察Server,如果Server被tripped了,则忽略,在选择其中ActiveRequestsCount最小的server
AvailabilityFilteringRule ?public class AvailabilityFilteringRule extends PredicateBasedRule 过滤掉那些因为一直连接失败的被标记为circuit tripped的后端server,并过滤掉那些高并发的的后端server(active connections 超过配置的阈值) 使用一个AvailabilityPredicate来包含过滤server的逻辑,其实就就是检查status里记录的各个server的运行状态
WeightedResponseTimeRule ?public class WeightedResponseTimeRule extends RoundRobinRule 根据相应时间分配一个weight,相应时间越长,weight越小,被选中的可能性越低。 一个后台线程定期的从status里面读取评价响应时间,为每个server计算一个weight。Weight的计算也比较简单responsetime 减去每个server自己平均的responsetime是server的权重。当刚开始运行,没有形成statas时,使用roubine策略选择server。
RetryRule public class RetryRule extends AbstractLoadBalancerRule 对选定的负载均衡策略机上重试机制。 在一个配置时间段内当选择server不成功,则一直尝试使用subRule的方式选择一个可用的server
RoundRobinRule ?public class RoundRobinRule extends AbstractLoadBalancerRule roundRobin方式轮询选择server 轮询index,选择index对应位置的server
RandomRule ?public class RandomRule extends AbstractLoadBalancerRule 随机选择一个server 在index上随机,选择index对应位置的server
ZoneAvoidanceRule public class ZoneAvoidanceRule extends PredicateBasedRule 复合判断server所在区域的性能和server的可用性选择server 使用ZoneAvoidancePredicate和AvailabilityPredicate来判断是否选择某个server,前一个判断判定一个zone的运行性能是否可用,剔除不可用的zone(的所有server),AvailabilityPredicate用于过滤掉连接数过多的Server。

?Ribbon自带负载均衡策略实现解析

1. com.netflix.loadbalancer.BestAvailableRule
功能: 选择一个最小的并发请求的server
主要代码: 逐个考察Server,如果Server被tripped了,则忽略,在选择其中ActiveRequestsCount最小的server

for(Server server: serverList){ServerStats serverStats = loadBalancerStats.getSingleServerStat(server);if(!serverStats.isCircuitBreakerTripped(currentTime)){int concurrentConnections = serverStats.getActiveRequestsCount(currentTime);if(concurrentConnections < minimalConcurrentConnections){
minimalConcurrentConnections = concurrentConnections;
chosen = server;}}

2 com.netflix.loadbalancer.AvailabilityFilteringRule
功能: 过滤掉那些因为一直连接失败的被标记为circuit tripped的后端server,并过滤掉那些高并发的的后端server(active connections 超过配置的阈值)
主要代码 :使用一个AvailabilityPredicate来包含过滤server的逻辑,其实就就是检查status里记录的各个server的运行状态,过滤掉那些高并发的的后端server(active connections 超过配置的阈值)

boolean com.netflix.loadbalancer.AvailabilityPredicate.shouldSkipServer(ServerStats stats){if((CIRCUIT_BREAKER_FILTERING.get()&& stats.isCircuitBreakerTripped())|| stats.getActiveRequestsCount()>= activeConnectionsLimit.get()){returntrue;}returnfalse;}

3 com.netflix.loadbalancer.WeightedResponseTimeRule

功能: 根据相应时间分配一个weight,相应时间越长,weight越小,被选中的可能性越低。 ”
主要代码: 一个后台线程定期的从status里面读取评价响应时间,为每个server计算一个weight。Weight的计算也比较简单responsetime 减去每个server自己平均的responsetime是server的权重。当刚开始运行,没有形成statas时,使用roubine策略选择server。

classDynamicServerWeightTaskextendsTimerTask{publicvoid run(){ServerWeight serverWeight =newServerWeight();
serverWeight.maintainWeights();}}

maintainWeights(){List<Double> finalWeights =newArrayList<Double>();for(Server server : nlb.getAllServers()){ServerStats ss = stats.getSingleServerStat(server);double weight = totalResponseTime  ss.getResponseTimeAvg();
weightSoFar += weight;
finalWeights.add(weightSoFar);}
setWeights(finalWeights);}Server choose(ILoadBalancer lb,Object key){double randomWeight = random.nextDouble()* maxTotalWeight;// pick the server index based on the randomIndexint n =0;for(Double d : currentWeights){if(d >= randomWeight){
serverIndex = n;break;}else{
n++;}}

server = allList.get(serverIndex);}

4 com.netflix.loadbalancer.RetryRule

功能: 对选定的负载均衡策略机上重试机制。
主要代码: 在一个配置时间段内当选择server不成功,则一直尝试使用subRule的方式选择一个可用的server

answer = subRule.choose(key);if(((answer ==null)||(!answer.isAlive()))&&(System.currentTimeMillis()< deadline)){InterruptTask task =newInterruptTask(deadline -System.currentTimeMillis());while(!Thread.interrupted()){
answer = subRule.choose(key);if(((answer ==null)||(!answer.isAlive()))&&(System.currentTimeMillis()< deadline)){/* pause and retry hoping it’s transient */Thread.yield();}else{break;}}
task.cancel();

5 com.netflix.loadbalancer.RoundRobinRule

功能: roundRobin方式轮询选择server
主要代码: 轮询index,选择index对应位置的server

List<Server> allServers = lb.getAllServers();int upCount = reachableServers.size();int serverCount = allServers.size();int nextServerIndex = incrementAndGetModulo(serverCount);
server = allServers.get(nextServerIndex);

6 com.netflix.loadbalancer.RandomRule

功能: 随机选择一个server
主要代码: 在index上随机,选择index对应位置的server

List<Server> upList = lb.getReachableServers();List<Server> allList = lb.getAllServers();int serverCount = allList.size();int index = rand.nextInt(serverCount);
server = upList.get(index);

7 com.netflix.loadbalancer.ZoneAvoidanceRule

功能: 复合判断server所在区域的性能和server的可用性选择server
主要代码: 使用ZoneAvoidancePredicate和AvailabilityPredicate来判断是否选择某个server,前一个,以一个区域为单位考察可用性,对于不可用的区域整个丢弃,从剩下区域中选可用的server。判断出最差的区域,排除掉最差区域。在剩下的区域中,将按照服务器实例数的概率抽样法选择,从而判断判定一个zone的运行性能是否可用,剔除不可用的zone(的所有server),AvailabilityPredicate用于过滤掉连接数过多的Server。

public com.netflix.loadbalancer.PredicateBasedRule.Server choose(Object key){ILoadBalancer lb = getLoadBalancer();Optional<Server> server = getPredicate().chooseRoundRobinAfterFiltering(lb.getAllServers(), key);if(server.isPresent()){return server.get();}}

参照现有的若干中rule的实现风格,根据我们自己需要也可以开发出自定义的负载均衡策略。

完。

原创文章。为了维护文章的版本一致、最新、可追溯,转载请注明: 转载自 idouba

本文链接地址: Netflix源码解析之Ribbon:负载均衡策略的定义和实现

猜你喜欢

转载自m635674608.iteye.com/blog/2389683
今日推荐