Dubbo几种负载均衡的实现

钟明宏 2月前 ⋅ 25 阅读

Dubbo负载均衡的4种实现 TIM截图20200410204651.png

ConsistentHashLoadBalance 一致性Hash策略

LeastActiveLoadBalance 调用被调用次数最少的

RandomLoadBalance 随机调用

RoundRobinLoadBalance 轮询调用

一致性hash策略

TIM截图20200410221534.png

  • 第一步获取invokers的hash,对比缓存中的hash值,不一样说明Invoker增加了或者减少了,这个时候需要需要重新创建一个选择器 TIM截图20200410234531.png
  • 初始化选择器的时候会重新对计算Invoker的hash值 微信截图_20200424195733.png
  • 根据调用方法的参数 生成一个key 并计算其hash值

随机调用算法

微信截图_20200424195957.png

轮询

最少调用

@Override
protected <T> Invoker<T> doSelect(List<Invoker<T>> invokers, URL url, Invocation invocation) {
        // 获取invoker的数量
        int length = invokers.size();
        // 最小活跃值
        int leastActive = -1;
        // 具有相同最少活动值的调用者的数量 (leastActive)
        int leastCount = 0;
        // The index of invokers having the same least active value (leastActive)
        int[] leastIndexes = new int[length];
        // 每个invoker的权重
        int[] weights = new int[length];
        // 所有最不活跃invoker的权重
        int totalWeight = 0;
        // 第一个最不活跃的权重
        int firstWeight = 0;
        // Every least active invoker has the same weight value?
        boolean sameWeight = true;


        // Filter out all the least active invokers
        for (int i = 0; i < length; i++) {
            Invoker<T> invoker = invokers.get(i);
            // 回去当前invoker调用的次数
            int active = RpcStatus.getStatus(invoker.getUrl(), invocation.getMethodName()).getActive();
            // 获取调用权重 默认 100
            int afterWarmup = getWeight(invoker, invocation);
            // 保存invoker的权重值
            weights[i] = afterWarmup;
            // 第一次调用 或者 当前invoker 小于 最小活跃值,就把active 赋值给 leastActive
            if (leastActive == -1 || active < leastActive) {
                // 更新最小活跃值
                leastActive = active;
                // 重置最小活跃值为1
                leastCount = 1;
                // 将leastIndexes第一个对象设置为当前对象的索引
                leastIndexes[0] = i;
                // 最小活跃值的总权重
                totalWeight = afterWarmup;
                // 记录第一个invoker 的 权重
                firstWeight = afterWarmup;
                // Each invoke has the same weight (only one invoker here)
                sameWeight = true;
                // 遇到活跃值相等的 invoker
            } else if (active == leastActive) {
                // 更新最小invoker的索引位置
                leastIndexes[leastCount++] = i;
                // 增加总权重
                totalWeight += afterWarmup;
                // 用来判断invoker 的权重是否相同?
                if (sameWeight && i > 0
                        && afterWarmup != firstWeight) {
                    sameWeight = false;
                }
            }
        }
        // 从容器中选择一个最小获取的invoker
        if (leastCount == 1) {
            // If we got exactly one invoker having the least active value, return this invoker directly.
            return invokers.get(leastIndexes[0]);
        }
        //当最小活跃连接里面有不用权重值的时候
        if (!sameWeight && totalWeight > 0) {
            // If (not every invoker has the same weight & at least one invoker's weight>0), select randomly based on 
            // totalWeight.
            // 根据总权重获取这区间的一个随机权重
            int offsetWeight = ThreadLocalRandom.current().nextInt(totalWeight);
            // 遍历所有的最小活跃invoker,然后 offsetWeight 会减去invoker的权重,当 offsetWeight 小于0 的时候 返回当前invoker
            for (int i = 0; i < leastCount; i++) {
                int leastIndex = leastIndexes[i];
                offsetWeight -= weights[leastIndex];
                if (offsetWeight < 0) {
                    return invokers.get(leastIndex);
                }
            }
        }
        // 从所有最小活跃连接的随机获取一个invoker
        return invokers.get(leastIndexes[ThreadLocalRandom.current().nextInt(leastCount)]);
    }

全部评论: 0

    我有话说: