概述
继RandomLoadBalance加权随机算法之后,我们继续分析LeastActiveLoadBalance最小活跃数负载均衡
源码分析
LeastActiveLoadBalance是基于加权最小活跃数算法实现的。就是当一个服务提供者在单位时间内处理请求的效率越快,则处理的请求数越多;如果两个服务提供者单位时间内处理请求的效率一直,则通过权重来分配请求,权重越大,获得新请求的概率也越大。
1 | public class LeastActiveLoadBalance extends AbstractLoadBalance { |
- 遍历 invokers 列表,寻找活跃数最小的 Invoker
- 如果有多个 Invoker 具有相同的最小活跃数,此时记录下这些 Invoker 在 invokers 集合中的下标,并累加它们的权重,比较它们的权重值是否相等
- 如果只有一个 Invoker 具有最小的活跃数,此时直接返回该 Invoker 即可
- 如果有多个 Invoker 具有最小活跃数,且它们的权重不相等,此时处理方式和 RandomLoadBalance 一致
- 如果有多个 Invoker 具有最小活跃数,但它们的权重相等,此时随机返回一个即可
存在的问题
①处直接从url中获取来权重,而②处是经过降权的权重(有服务预热阶段),而offsetWeight是用①处的权重随机生成的,这就会导致offsetWeight减去经过降权的权重会一直大于零,导致无法选中 Invoker。所以我们需要把①处的权重也改为降级过的权重
int afterWarmup = getWeight(invoker, invocation);
。当一组 Invoker 具有相同的最小活跃数,且其中一个 Invoker 的权重值为1,此时这个 Invoker 无法被选中。缺陷代码如下:
1
2
3
4
5
6
7int offsetWeight = random.nextInt(totalWeight);
for (int i = 0; i < leastCount; i++) {
int leastIndex = leastIndexs[i];
offsetWeight -= getWeight(invokers.get(leastIndex), invocation);
if (offsetWeight <= 0) // ❌
return invokers.get(leastIndex);
}问题出在了
offsetWeight <= 0
上,举例说明,假设有一组 Invoker 的权重为 5、2、1,offsetWeight 最大值为 7。假设 offsetWeight = 7,你会发现,当 for 循环进行第二次遍历后 offsetWeight = 7 - 5 - 2 = 0,提前返回了。此时,此时权重为1的 Invoker 就没有机会被选中了。该问题修改后的代码如下:1
int offsetWeight = random.nextInt(totalWeight) + 1;
关于 LeastActiveLoadBalance 就先到这了,下一篇我们继续分析 ConsistentHashLoadBalance。