Ribbon负载均衡算法详解
本篇教程之前一篇博客的基础之上,工程代码在前一篇博客的代码基础上添加功能.
请参考:
https://mp.csdn.net/postedit/95932412
一. 负载均衡实现

1. 自定义负载均衡策略
package com.syc.cloud.config;
import com.netflix.loadbalancer.*;
import org.springframework.cloud.netflix.ribbon.RibbonClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* 自定义负载均衡策略
*/
@Configuration
@RibbonClient(name = "eureka-provider")
public class RibbonClientConfig {
@Bean
public IRule ribbonRule() {
System.out.println("<<<<<<<<<<<<<<<<<ribbon rule called!>>>>>>>>>>>>");
//默认轮询策略(RoundRobinRule) 随机轮询(RandomRule) 权重(WeightedResponseTimeRule) 最小的并发策略(BestAvailableRule)
// return new RoundRobinRule();
//return new RandomRule();
//return new BestAvailableRule();
//return new ZoneAvoidanceRule();
//return new RetryRule();
return new WeightedResponseTimeRule();
//return new ClientConfigEnabledRoundRobinRule();
}
}
2. 接口测试
多次访问该接口,不同的负载均衡策略输出结果不同.

2.1 轮询负载均衡策略

2.2 随机负载均衡策略

二. 负载均衡策略
1. Ribbon的七种负载均衡策略

2. Ribbon源码分析过程
本文基于ribbon 2.2.5 版本.

根据代码中的接口实现和继承,整理出如下图关系.

可以看出负载均衡接口为com.netflix.loadbalancer.IRule,然后由抽象类AbstractLoadBalancerRule实现IRule接口,各个负载均衡策略都是AbstractLoadBalancerRule的具体实现.

3. 接下来分不同策略分别来看.
1️⃣. RandomRule 随机负载均衡
逻辑比较简单,核心是拿到服务的数量,然后随机选择一个状态为UP的Server.

2️⃣. RoundRobinRule 简单轮询负载均衡
以轮询的方式依次将请求调度不同的服务器,即每次调度执行i = (i + 1) mod n,并选出第i台服务器.
通常是初始化一个计数器,通过这个计算器得到这次轮到的服务,如果10次都没找到,就没有服务.


3️⃣. RetryRule
在一段时间内,一直轮询,直到找到可用服务。在初始化时,设置了默认的时间为500毫秒,也可以自己修改。

4️⃣. WeightedResponseTimeRule 加权响应时间负载均衡
一个后台线程定期的从status里面读取评价响应时间,为每个server计算一个weight.Weight的计算也比较简单responsetime 减去每个server自己平均的responsetime是server的权重.当刚开始运行,没有形成status时,使用roubine策略选择 server.
初始化时,启动一个定时器,每隔30秒去统计每个服务的权重.得到权重之后,通过随机数的方式,决定哪个服务被选中.
比如:
3个服务,平均响应时间为: A:100,B:200,C:300毫秒
-
则A的权重: 600-100 = 500;
-
B的权重: 500+600-200 = 900;
-
C的权重: 900+600-300 = 1200.
取最后一条数据取到1200,则随机1200
-
如果随机数在0-500,则选A;
-
如果随机数在500-900,则选B;
-
如果随机数在900-1200,则选C.
如果没有服务命中或者权重没有初始化,则取轮询的结果.

5️⃣. BestAvailableRule
该类继承自ClientConfigEnabledRoundRobinRule.
先根据负载均衡统计结果,过滤掉故障服务,然后选出并发请求最小的服务.
-
如果无结果,就轮询一个;
-
依赖负载均衡统计类,如果统计类为空,则轮询一个.

6️⃣. AvailabilityFilteringRule
继承PredicateBasedRule.
先轮询出一个服务,如果不匹配过滤条件,则继续轮询10次,如果10次之后还未找到,就轮询一个.

条件:
排除故障 或者 超过设置的并发阈值的(阈值默认2的31次方减1,可以自定义).
7️⃣. ZoneAvoidanceRule 区域感知轮询负载均衡
继承PredicateBasedRule.
区域感知负载均衡内置电路跳闸逻辑,可被配置基于区域同源关系(Zone Affinity,也就是更倾向于选择发出调用的服务所在的托管区域内,这样可以降低延迟,节省成本)选择目标服务实例.它监控每个区域中运行实例的行为,而且能够实时的快速丢弃一整个区域.这样在面对整个区域故障时,帮我们提升了弹性.
该策略先过滤掉整个不可用zone(区域)的服务,再过滤故障或者超阈值的服务,然后轮询一个.

以上是从Spring cloud Ribbon源码出发,分析了ribbon的七种负载均衡策略.
三. Ribbon自带负载均衡策略比较