三种负载均衡 Nginx、Dubbo、Ribbon 区别

描述

1.Dubbo负载均衡:支持4种(随机,轮循,最少活跃,hash),引入了JVM预热时间加权、权重自定义配置的规则,同时支持控制台动态配置权重值参数,所以是最灵活的。

2.Nginx负载均衡:支持4种,自带 轮询(支持权重)、IP_Hash(避免Session共享的问题)、最少连接数策略,可以扩展fair(响应时间)策略,更专注于功能。

3.Ribbon负载均衡:支持6种,不支持权重:轮询、随机、最少连接数、最短响应时间(随机+响应时间加权)、过滤异常节点+轮询,负载策略最全的

Dubbo 负载均衡(2.6.x)

​ Dubbo提供4种负载均衡算法,引入了JVM预热时间加权、权重自定义配置的规则,同时支持控制台动态配置权重值参数,所以最灵活。

  • Random LoadBalance:按照权重随机分配Provider,比如随机且权重Node1:Node2= 2:1,那么运行30次,大约有20次在Node1上,10次在Node2上。
  • RoundRobin LoadBalance:按照权重轮询分配。比如权重Node1:Node2= 20:10,那么运行30次:前20次里面轮询Node1和Node2大家各10次,第20次到30次,全部选择Node1。因为Dubbo默认是不会做公约数的处理,只有完成一个完整的20+10次运算,才能保证负载均衡的权重比例准确,如果Consumer只调用了20次,那么这里配置的权重的结果就是1:1了,该算法很不平滑。在2.6.5版本中修复了,跟Nginx的实现方法一样。
  • LeastActive LoadBalance:节点处理越快分配更多,避免慢节点堆积,每次筛选Provider的时候,都只取Active值最小的节点,如果最小Active值的节点有多个,则按照权重随机选取。Provider每获取到一个任务Active值++,每结束一个任务Active值--。
  • ConsistentHash LoadBalance:唯一忽略权重配置和JVM预热的算法。先把所有Provider都分配160个虚拟节点,通过Hash算法,全部分散到Hash圆上。每次Consumer调用时,会根据参数值做Hash换算,最后映射到Hash圆上,找到邻近的虚拟节点,最终获取到提供服务的Provider。但是Dubbo在实现的时候违背了Hash一致性的原则,每次Porvider发生改变的时候(新增或者剔除),都会重新创建一个Hash圆,而不是在之前的Hash圆上新增或者剔除不合格的Porvider。

Nginx 负载均衡算法

Nginx目前有4种负载均衡配置:

  • round_robin,加权轮询,是默认的HTTP负载均衡算法,适用于知道机器的性能,且默认所有的请求对于服务器而言,处理的时间相差不大。比如我Server1 比Server2的配置要高一倍,我设置为2:1的权重,可以实现比较科学的负载。算法实现上,简单的轮询很简单,给每个Server依次编号,然后只要记录一个调用index,既可以实现轮询。
  • ip_hash,IP哈希,可保持会话
  • least_conn; 避免了慢堆积,会取连接数最小的server提供服务,可以避免有些请求耗时长,有些耗时端的情况。根据实际的连接数选择服务器。
  • fair,需要插件扩展该功能,根据后端服务器的响应时间来分配请求,响应时间短的优先分配,避免慢堆积。
  • 权重配置:而且采用的是平滑的负载均衡算法,比如node1:node2:node3=1:2:5 --> node3,node3,node2,node3,node1,node3,node2,node3

Ribbon 负载均衡概述

  • RoundRobinRule:轮询。默认超过10次获取到的server都不可用,会返回一个空的server
  • RandomRule:随机,如果随机到的server为null或者不可用的话,会while不停的循环选
  • RetryRule:一定时限内循环重试。默认继承RoundRobinRule,也支持自定义注入,RetryRule会在每次选取之后,对选举的server进行判断,是否为null,是否alive,并且在500ms内会不停的选取判断。而RoundRobinRule失效的策略是超过10次,RandomRule是没有失效时间的概念,只要serverList没都挂。
@Bean
public IRule ribbonRule() {
     return new RetryRule(new BestAvailableRule());//这里配置策略,和配置文件对应
}
  • BestAvailableRule:最小连接数。遍历serverList,选取出可用的且连接数最小的一个server。该算法里面有一个LoadBalancerStats的成员变量,会存储所有server的运行状况和连接数。如果选取到的server为null,那么会调用RoundRobinRule重新选取。
  • WeightedResponseTimeRule:最小响应时间。这个策略整合了随机算法和响应时间加权算法。会开启定时任务,每30秒计算一次所有Provider的响应时间,以响应时间作为权重,响应时间越短的服务器被选中的概率越大。比如Node1:node2:node3的平均响应时间为100ms:200ms:300ms,那么nodes的的权重值是300:500:600,每次以600为基础*随机值,那么落在 0--300的概率为50%,300--500的概率33%,100--600的概率为17%,也就是平均响应时间越短的节点,被选中的概率越大。
double totalResponseTime = 0;
//遍历获取所有节点的总的平均响应时间
for (Server server : nlb.getAllServers()) {
    ServerStats ss = stats.getSingleServerStat(server);
    totalResponseTime += ss.getResponseTimeAvg();
}
Double weightSoFar = 0.0;
//然后从第一个节点开始设置自增的weightSoFar,每个结点的权重值weight为总响应时间-自己的相应时间,也就是说,node的响应时间越短,weight的值就越大,就越有可能被随机数命中
List<Double> finalWeights = new ArrayList<Double>();
for (Server server : nlb.getAllServers()) {
    ServerStats ss = stats.getSingleServerStat(server);
    double weight = totalResponseTime - ss.getResponseTimeAvg();
    weightSoFar += weight;
    finalWeights.add(weightSoFar);   
}
setWeights(finalWeights);
  • AvailabilityFilteringRule 过滤+轮询策略,先过滤出故障的或并发请求大于阈值一部分服务实例,然后再轮询。
private boolean shouldSkipServer(ServerStats stats) {        
   if ((CIRCUIT_BREAKER_FILTERING.get() && stats.isCircuitBreakerTripped()) || stats.getActiveRequestsCount() >= activeConnectionsLimit.get()) {
       return true;
   }
   return false;
}
  • ZoneAvoidanceRule 扩展了轮询策略,继承了2个过滤器:ZoneAvoidancePredicateAvailabilityPredicate,除了过滤超时和链接数过多的server,还会过滤掉不符合要求的zone里面的所有节点。

原文链接:https://blog.csdn.net/washingtin/article/details/98468119

原文地址:https://www.cnblogs.com/zgrey/p/15471062.html