Dubbo 的负载均衡策略:随机策略

本文介绍 Dubbo 的负载均衡策略中的随机策略。

1

什么是负载均衡策略

应用服务化之后,每一个应用都是多个服务组合成的,每个服务有多个实例,比如一个登录操作,需要调用登录接口 API,登录接口 API 不止一个,这时,调用哪个登录接口 API 就需要进行选择,这个选择过程就叫做负载均衡,会使用不同的算法来实现负载均衡策略。

Dubbo 提供了如下 4 个负载均衡策略。

2

随机负载均衡策略

Dubbo 中的随机负载均衡策略的实现类是: RandomLoadBalance ,它分为 2 种情况。

  • 被调用服务的所有实例都是同等权重的,则随机生成一个从 0 到 实例数量 - 1 的数,并返回对应的实例。 比如:总共有 3 个实例 invokers,3 个实例的权重都为 100,随机生成一个从 0 到 2 的数,假设生成 2,则返回 invokers[2],也就是返回了第 3 个实例。
  • 被调用服务的所有实例的权重不一,则累计所有权重 totalWeight,随机生成一个从 0 到 totalWeight - 1 的数 offset,定位 offset 所在的位置,并返回对应位置的实例。 比如:下图有 5 个实例,每个实例的权重不一样,分别如表格所示,要选择实例的时候,随机生成一个从 0 到 649 的数,假设生成 251,则落在 250 - 349 的范围内,也就是选中 C 实例。

实例

权重

范围

A

100

0 - 99

B

150

100 - 249

C

100

250 - 349

D

100

350 - 449

E

200

450 - 649

这 2 种情况有什么不同呢?

第一种情况就是纯随机的策略;第二种情况则在随机的基础上,加上了权重因素,权重越大,被选择的可能性就越大。

3

随机策略的优缺点

  • 优点:实现简单,水平扩展方便
  • 缺点:当机器有异常的时候,不能根据机器的异常情况分配。

4

RandomLoadBalance 源码

public class RandomLoadBalance extends AbstractLoadBalance {

    public static final String NAME = "random";

    private final Random random = new Random();

    @Override
    protected <T> Invoker<T> doSelect(List<Invoker<T>> invokers, URL url, Invocation invocation) {
        // 待选择的被调用服务的实例数量
        int length = invokers.size(); // Number of invokers
        // 统计总权重
        int totalWeight = 0; // The sum of weights
        // 标识:每个被调用服务的实例的权重是否相同
        boolean sameWeight = true; // Every invoker has the same weight?
        // 遍历每个被调用服务,获取每个被调用服务的权重,统计所有权重之和,并判断每个调用服务的权重是否相同
        for (int i = 0; i < length; i++) {
            int weight = getWeight(invokers.get(i), invocation);
            totalWeight += weight; // Sum
            if (sameWeight && i > 0
                    && weight != getWeight(invokers.get(i - 1), invocation)) {
                // 有不相同的权重,则标识 sameWeight 为 false
                sameWeight = false;
            }
        }

        // 总权重大于 0 且 被调用服务权重有不相同的,则随机产生一个 0 到 totalWeight-1 的数,定位到该数是在哪个被调用方的范围内
        if (totalWeight > 0 && !sameWeight) {
            // If (not every invoker has the same weight & at least one invoker's weight>0), select randomly based on totalWeight.
            int offset = random.nextInt(totalWeight);
            // Return a invoker based on the random value.
            for (int i = 0; i < length; i++) {
                offset -= getWeight(invokers.get(i), invocation);
                if (offset < 0) {
                    return invokers.get(i);
                }
            }
        }

        // 所有的被调用服务的权重相同,则随机产生一个 0 到 length-1 的数,返回对应的被调用服务
        // If all invokers have the same weight value or totalWeight=0, return evenly.
        return invokers.get(random.nextInt(length));
    }

}

做个有梦想的程序猿

原文发布于微信公众号 - LieBrother(gh_b6002a4cbc1f)

原文发表时间:2018-08-10

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

扫码关注云+社区

领取腾讯云代金券