负载均衡
集群负载均衡时,Dubbo 提供了多种均衡策略,默认是 random
随机调用。
在具体实现上,Dubbo 提供的是客户端负载均衡,即 Consumer 使用负载均衡算法决定将请求提交到哪个 Provider 实例。
您可以自行扩展负载均衡策略,参见:负载均衡扩展
负载均衡策略
目前 Dubbo 有以下内置负载均衡算法,用户可以直接配置使用
| 算法 | 特性 | 备注 | | :————————– | :——————– – | :———————————————- | | RandomLoadBalance | 加权随机 | 默认算法,默认权重相同 | | RoundRobinLoadBalance | 加权轮询 | 基于 Nginx 的平滑加权轮询算法,默认权重相同, | | LeastActiveLoadBalance | 最少活跃优先 + 加权随机 | 背后是能者多劳的思想 | | ShortestResponseLoadBalance | 最短响应优先 + 加权随机 | 更关注响应速度 | | ConsistentHashLoadBalance | 一致性哈希 | 输入参数确定,provider 确定,适合有状态请求 |
随机
- 加权随机,按权重设置随机概率。
- 一段上的碰撞概率高,但调用量越大,分布越均匀,使用概率后权重也更均匀,有利于动态调整 provider 权重。
- 缺点:存在慢 provider 累积请求的问题,例如:第二台机器很慢,但没有挂掉,当请求转到第二台机器时,就卡在那里了,时间久了,所有请求都卡在第二台机器上。上台。
轮询
- 加权轮询,约定后按权重设置轮询比例,循环调用节点
- 缺点:也存在慢 provider 累积请求的问题。
在加权轮询过程中,如果某个节点的权重过大,就会出现一段时间内调用过于集中的问题,例如 ABC 三个节点有以下权重:{A: 3, B: 2, C: 1}
那么按照最原始的轮询算法,调用过程就会变成:A A A B B C
对此,Dubbo 参考了 Nginx 的平滑加权轮询算法进行了优化,调用过程可以抽象成以下表格
| 轮询前总权重 | 本轮获胜者 | 总权重 | 轮询后权重(获胜者减去总权重) | | :—————— | :——- | :——- | :———- —————– | | 开始轮询 | \ | \ | A(0), B(0), C(0)
| | A(3), B(2), C(1)
| A | 6 | A(-3), B(2), C(1)
| | A(0), B(4), C(2)
| B | 6 | A(0), B(-2), C(2)
| | A(3), B(0), C(3)
| A | 6 | A(-3), B(0), C(3)
| | A(0), B(2), C(4)
| C | 6 | A(0), B(2), C(-2)
| | A(3), B(4), C(-1)
| B | 6 | A(3), B(-2), C(-1)
| | A(6), B(0), C(0)
| A | 6 | A(0), B(0), C(0)
|
我们发现,经过总权重(3+2+1)轮后,循环回到起点,整个过程中节点流量平滑,即使在短时间内,概率也是按照预期分布的。
如果用户有加权轮询的需求,可以放心地使用此算法。
最少活跃
- 加权最少活跃调用优先级,活跃数越低,调用优先级越高,相同活跃数则加权随机。活跃数指的是调用前后计数的差值(对于特定 provider:发送的请求数 - 返回的响应数),表示特定 provider 累积的任务量。活跃数越低,provider 的处理能力越强。
- 让慢 provider 接收更少的请求,因为 provider 越慢,调用前后计数的差值越大;相对而言,处理能力强的节点可以处理更多的请求。
###最短响应
- 加权最短响应优先级,在最新的滑动窗口内,响应时间越短,调用优先级越高。相同响应时间则加权随机。
- 让响应速度快的 provider 处理更多的请求。
- 缺点:可能会导致流量过于集中在高性能节点上。
这里的响应时间 = 窗口时间内 provider 的平均响应时间,默认窗口时间为 30s。
###一致性哈希
- 一致性哈希,相同参数的请求始终发送到同一个 provider。
- 当某个 provider 宕机时,原本发送到该 provider 的请求会根据虚拟节点分散到其他 provider,不会造成剧烈变化。
- 算法参见:Consistent Hashing | WIKIPEDIA
- 默认只对第一个参数 Hash,如果要修改,请配置
<dubbo:parameter key="hash.arguments" value="0,1" />
- 默认情况下使用 160 个虚拟节点,如果需要修改,请配置
<dubbo:parameter key="hash.nodes" value="320" />
配置
服务器服务级别
<dubbo:service interface="..." loadbalance="roundrobin" />
客户端服务级别
<dubbo:reference interface="..." loadbalance="roundrobin" />
服务器方法级别
<dubbo:service interface="...">
<dubbo:method name="..." loadbalance="roundrobin"/>
</dubbo:service>
客户端方法级别
<dubbo:reference interface="...">
<dubbo:method name="..." loadbalance="roundrobin"/>
</dubbo:reference>