0%

负载均衡 加权随机

给上一篇博文填个坑,讲解下负载均衡算法中最常见的加权随机算法

加权随机算法

负载均衡的一种算法实现,效果是按服务的权重设置,非顺序地请求资源服务。

源码分析

Dubbo的负载均衡算法实现,放在org.apache.dubbo.rpc.cluster包下,以org.apache.dubbo.rpc.cluster.LoadBalance定义,通过SPI功能动态加载,默认实现为org.apache.dubbo.rpc.cluster.loadbalance.RandomLoadBalance(加权随机)

源码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
protected <T> Invoker<T> doSelect(List<Invoker<T>> invokers, URL url, Invocation invocation) {
int length = invokers.size();
// 标记位,标识所有服务的权重是否全都相同
boolean sameWeight = true;
// 每个服务下标对应的权重,在x轴坐标上的位置
// 例:ABC三个服务的权重为10、20、30,为所有服务创建一个一维坐标,则A服务落在距离原点为10的位置,B落在距离原点30的位置,C落在距离原点60的位置
int[] weights = new int[length];
// 所有服务静态权重之和
int totalWeight = 0;
for (int i = 0; i < length; i++) {
int weight = getWeight(invokers.get(i), invocation);
totalWeight += weight;
// 服务距离坐标系原点的位置
weights[i] = totalWeight;
if (sameWeight && totalWeight != weight * (i + 1)) {
sameWeight = false;
}
}
// 当所有服务的权重不全相等时,触发加权随机
if (totalWeight > 0 && !sameWeight) {
// 以0到所有服务权重之和为区间取随机数
int offset = ThreadLocalRandom.current().nextInt(totalWeight);
// 将随机数放在上述建立的一位坐标中,取在随机数落点右边且最近的一台服务作为选举结果
for (int i = 0; i < length; i++) {
if (offset < weights[i]) {
return invokers.get(i);
}
}
}
// 当所有服务的权重全都相等时,完全随机调用
return invokers.get(ThreadLocalRandom.current().nextInt(length));
}

源码分析

首先Dubbo会轮训所调用资源服务的所有实例,计算所有服务的静态权重之和(totalWeight),使用0到totalWeight建立一个一位坐标系,将所有服务按照权重值分配到坐标系的每个节点

例:目前有A、B、C三个服务,权重配置分别为A=10、B=20、C=10

则A、B、C会分别位于距离坐标系原点10、30、40的位置,如下图

在所有服务的权重之和(totalWeight)范围内建立一个一位坐标系,以0为下限以totalWeight为上限取随机数,当随机数落点在服务各自的范围内时,则对应的服务作为选举结果

实例演示

没有,自己脑补吧