Administrator
发布于 2024-02-03 / 11 阅读 / 0 评论 / 0 点赞

Ribbon - 负载均衡策略

Ribbon - 负载均衡策略

  • 轮询算法

    【JAVA】线程不安全问题以及相关解决方案

    List<机器实例> list = new List();
    i++; //线程不安全
    int index = i % list.size(); // i 是请求次数 ;
    机器实例 = list.get(index);
    
  • 随机算法

  • 根据响应时间分配权重的策略

  • 最低并发策略

  • 可用性策略

  • 区域权重策略

  • 重试策略

1、简介

spring cloud的负载均衡由ribbon组件实现,ribbon是NetFlix发布的客户端负载均衡器。

2、ribbon负载均衡规则

ribbon负载均衡策略的结构类图

1.png

IRule接口中共有三个方法

2.png

抽象类AbstractLoadBalancerRule实现了IRule接口,定义了一个ILoadBalancer类型变量,用于ILoadBalancer接口定义了软负载均衡的操作方法。

3.png

3、负载均衡策略

3.1、轮询策略

轮询策略在RoundRobinRule类中实现,它将可用服务存储在一个List中,然后定义了一个原子操作类,每次调用就+1,下次调用就把这个值作为List的下标,以此决定要调用哪个服务。

下面是定义,在RoundRobinRule构造函数中,会初始化值为0

4-0.png

4.png

3.2、随机策略

随机策略在RandomRule实现,RandomRule定义规则,从现有服务中,随机选择一个服务,具体做法就是根据可选服务数量,选出一个随机数作为下标,获取服务

5-0.png

5.png

3.3、根据响应时间分配权重的策略

这个策略由 WeightedResponseTimeRule 实现,使用这个策略的话,相应时间越长的服务,越不容易被选中,响应时间越短的被选中的概率越大。

WeightedResponseTimeTule 定义了一个定时任务30S执行一次

6.png

每次执行会先计算所有服务的相应时间的和

7.png

然后用时间和减去每个服务的相应平均时间作为权重值再加上上一个服务的权重值,这样一来,相应时间越长的服务,分配的权重就会越低,由此就可以得到各个服务的权重

8.png

最后得到的各个服务的值就是一个依次递增的数列,数列的项与前一项差距越小说明相应所花时间越长,这么说可能太抽象,我们假设五个服务,把他们的list的值在x轴上做排列如下

9.png

第三个节点因为相应的平均时间较长,所以权重小,距离上一个节点距离就近一些,此时,我们取出最后一个节点(他的值最大),然后生成一个在0-这个节点值之间的随机数,那么,命中第二个和第三个节点之间的概率就会小一些,换而言之,命中其他响应时间较短的节点的概率自然就提高了

再来看具体选择节点的代码,代码中,他选取了服务权重列表的最后一个服务权重为基准,做了一系列判断

10.png

此处,先取出最后一个服务的权重,因为这个服务权重是所有服务权重之和,如果最大的权重都小于0.001d,说明所有服务相应时间都很短或者可用服务和权重列表数量不一致(有服务在期间挂了或其他),就默认使用轮询策略选择一个服务返回

11.png

这里就是按照之前说的,取一个在权重和的范围内的随机数,选择一个服务即可

3.4、最低并发策略

最低并发策略在BestAvailableRule中实现,这个算法就是给定一个随机的服务列表(为了避免大量服务请求时选择同一个并发数最小的服务造成服务导致崩溃,通过ServerListSubsetFilter来限制获取一个随机列表),然后选择出一个并发数最小的服务来请求。

12.png

3.5、可用性策略

可用性策略在AvailabilityFilteringRule中实现,他按照轮询规则来依次获取服务,如果当前获取到的服务符合规则,则返回服务,如果连续十次没有获取到符合条件的服务,就调用父类的轮询方法来直接获取服务。

13.png

选取规则默认使用AvailabilityPredicate,选取代码如下

14.png

代码中判断,如果断路器已经被打开,或者服务的连接数超过最大连接数限制就过滤这个服务,进行下一个服务的判断。

3.6、区域权重策略

这个策略在ZoneAvoidanceRule中实现。

15.png16.png17.png

这个策略中有两个条件,将 ZoneAvoidancePredicate 作为主要规则,AvailabilityPredicate 作为次要规则,然后用 CompositePredicate 将这两个规则封装作为复核规则,主要规则满足则直接返回服务,否则调用次要规则获取服务,然后在获取到的服务中轮询调用。

ZoneAvoidanceRule.getAvailableZones 用来获取可用服务,流程如下

18.png

这里的worstZones并不需要全部从可用服务中剔除,但是要随机剔除一个

19.png

3.7、重试策略

重试策略在RetryRule中实现,他的具体做法是在选定的负载均衡策略上,如果调用失败则不断调用指定的负载策略获取服务,直到超过最大时间限制或成功,其默认负载策略是轮询。

20.png


评论