Dubbo源码学习--RoundRobinLoadBalance负载均衡(四)

RoundRobin LoadBalance

  • 轮循,按公约后的权重设置轮循比率。

  • 存在慢的提供者累积请求的问题,比如:第二台机器很慢,但没挂,当请求调到第二台时就卡在那,久而久之,所有请求都卡在调到第二台上。

1)获取轮询key  服务名+方法名

获取可供调用的invokers个数length

设置最大权重的默认值maxWeight=0

设置最小权重的默认值minWeight=Integer.MAX_VALUE

2)遍历所有Inokers,比较出得出maxWeight和minWeight

3)如果权重是不一样的

根据key获取自增序列

自增序列加一与最大权重取模默认得到currentWeigth

遍历所有invokers筛选出大于currentWeight的invokers

设置可供调用的invokers的个数length

4)自增序列加一并与length取模,从invokers获取invoker

public class RoundRobinLoadBalance extends AbstractLoadBalance {

    public static final String NAME = "roundrobin";

    private final ConcurrentMap sequences = new ConcurrentHashMap();

    protected  Invoker doSelect(List> invokers, URL url, Invocation invocation) {
        String key = invokers.get(0).getUrl().getServiceKey() + "." + invocation.getMethodName();
        int length = invokers.size(); // Number of invokers
        int maxWeight = 0; // The maximum weight 最大权重值
        int minWeight = Integer.MAX_VALUE; // The minimum weight 最小权重支持,默认最大
        final LinkedHashMap, IntegerWrapper> invokerToWeightMap = new LinkedHashMap, IntegerWrapper>();
		//权重值总数
        int weightSum = 0;
        for (int i = 0; i < length; i++) {
			//获取权重值
            int weight = getWeight(invokers.get(i), invocation);
			//获取最大和最小权重值
            maxWeight = Math.max(maxWeight, weight); // Choose the maximum weight
            minWeight = Math.min(minWeight, weight); // Choose the minimum weight
            if (weight > 0) {
                invokerToWeightMap.put(invokers.get(i), new IntegerWrapper(weight));
                weightSum += weight;
            }
        }
        AtomicPositiveInteger sequence = sequences.get(key);
        if (sequence == null) {
            sequences.putIfAbsent(key, new AtomicPositiveInteger());
            sequence = sequences.get(key);
        }
        int currentSequence = sequence.getAndIncrement();
        if (maxWeight > 0 && minWeight < maxWeight) {
			//轮询当前值
            int mod = currentSequence % weightSum;
            for (int i = 0; i < maxWeight; i++) {
				//轮询当前值的余数轮询从服务中获取
                for (Map.Entry, IntegerWrapper> each : invokerToWeightMap.entrySet()) {
                    final Invoker k = each.getKey();
                    final IntegerWrapper v = each.getValue();
                    if (mod == 0 && v.getValue() > 0) {
                        return k;
                    }
                    if (v.getValue() > 0) {
                        v.decrement();
                        mod--;
                    }
                }
            }
        }
        // Round robin
		//直接轮询找服务
        return invokers.get(currentSequence % length);
    }

    private static final class IntegerWrapper {
        private int value;

        public IntegerWrapper(int value) {
            this.value = value;
        }

        public int getValue() {
            return value;
        }

        public void setValue(int value) {
            this.value = value;
        }

        public void decrement() {
            this.value--;
        }
    }

}

你可能感兴趣的:(RPC及Dubbo入门源码学习,RPC及Dubbo原理学习)