Dubbo learning (eight) load balancing

Overview

In the last section, when we selected the cluster, the final invoker and load balancing selection method were selected. Let's first look at the code designed to load balance in the previous section, the AbstractClusterInvoker class:

   private Invoker<T> doSelect(LoadBalance loadbalance, Invocation invocation,
                                List<Invoker<T>> invokers, List<Invoker<T>> selected) throws RpcException {

        if (CollectionUtils.isEmpty(invokers)) {
            return null;
        }
        if (invokers.size() == 1) {
            return invokers.get(0);
        }

        // 调用 loadbalance 的 select 方法
        Invoker<T> invoker = loadbalance.select(invokers, getUrl(), invocation);

        ...
    }     

Here are the advantages and disadvantages of several load balancing modes.

1297993-20200303161933558-267203461.png

Let's analyze several load balancing implementation processes.

AbstractLoadBalance parent class analysis

public abstract class AbstractLoadBalance implements LoadBalance {


    /**
     * Calculate the weight according to the uptime proportion of warmup time
     * the new weight will be within 1(inclusive) to weight(inclusive)
     *
     * warmup : 预热时间
     *
     * @param uptime the uptime in milliseconds
     * @param warmup the warmup time in milliseconds
     * @param weight the weight of an invoker
     * @return weight which takes warmup into account
     */
    static int calculateWarmupWeight(int uptime, int warmup, int weight) {
        int ww = (int) ( uptime / ((float) warmup / weight));
        return ww < 1 ? 1 : (Math.min(ww, weight));
    }

    @Override
    public <T> Invoker<T> select(List<Invoker<T>> invokers, URL url, Invocation invocation) {
        if (CollectionUtils.isEmpty(invokers)) {
            return null;
        }
        if (invokers.size() == 1) {
            return invokers.get(0);
        }
        return doSelect(invokers, url, invocation);
    }

    protected abstract <T> Invoker<T> doSelect(List<Invoker<T>> invokers, URL url, Invocation invocation);


    /**
     * Get the weight of the invoker's invocation which takes warmup time into account
     * if the uptime is within the warmup time, the weight will be reduce proportionally
     * 
     * 
     * When calculating the weight here, the core is the proportion of uptime / warmuptime. It can be known that when starting to start, the smaller the proportion of uptime is less than the weight is smaller 
     * When the startup is long, the proportion is larger and the weight is naturally larger. . 
     * 
     * @param invoker the invoker 
     * @param invocation the invocation of this invoker 
     * @return weight 
     * / 
    int getWeight (Invoker <?> invoker, Invocation invocation) { 
        int weight; 
        URL url = invoker.getUrl (); 
        // Multiple registry scenario, load balance among multiple registries. 
        if (REGISTRY_SERVICE_REFERENCE_PATH.equals (url.getServiceInterface ())) { 
            weight = url.getParameter (REGISTRY_KEY + "." + WEIGHT_KEY, DEFAULT_WEIGHT); 
        } else {
            weight = url.getMethodParameter(invocation.getMethodName(), WEIGHT_KEY, DEFAULT_WEIGHT);
            if (weight > 0) {
                long timestamp = invoker.getUrl().getParameter(TIMESTAMP_KEY, 0L);
                if (timestamp > 0L) {
                    long uptime = System.currentTimeMillis() - timestamp;
                    if (uptime < 0) {
                        return 1;
                    }
                    // 默认的预热时间是 10 分钟
                    int warmup = invoker.getUrl().getParameter(WARMUP_KEY, DEFAULT_WARMUP);
                    if (uptime > 0 && uptime < warmup) {
                        weight = calculateWarmupWeight((int)uptime, warmup, weight);
                    }
                }
            }
        }
        return Math.max(weight, 0);
    }
}

RandomLoadBalance

    @Override
    protected <T> Invoker<T> doSelect(List<Invoker<T>> invokers, URL url, Invocation invocation) {
        // Number of invokers
        int length = invokers.size();
        // Every invoker has the same weight?
        boolean sameWeight = true;
        // the weight of every invokers
        int[] weights = new int[length];
        // the first invoker's weight
        int firstWeight = getWeight(invokers.get(0), invocation);
        weights[0] = firstWeight;
        // The sum of weights
        int totalWeight = firstWeight;
        for (int i = 1; i < length; i++) {
            int weight = getWeight(invokers.get(i), invocation);
            // save for later use 
            weights [i] = weight; 
            // Sum 
            totalWeight + = weight; 
            if (sameWeight && weight! = firstWeight) { 
                sameWeight = false; 
            } 
        } 
        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 = ThreadLocalRandom.current (). nextInt (totalWeight); 
            // Return a invoker based on the random value. 
            / / The loop subtracts the weight of the service provider from the offset number. When the offset is less than 0, the corresponding Invoker is returned.
            // To illustrate, we have servers = [A, B, C], weights = [5, 3, 2], offset = 7. 
            // 第一次循环,offset - 5 = 2 > 0,即 offset > 5,
            // indicates that it will not fall on the interval corresponding to server A. 
            // The second cycle, offset-3 = -1 <0, that is 5 <offset <8, 
            // indicates that it will fall on the interval corresponding to server B 

            for (int i = 0; i <length; i ++) { 
                    offset- 
                = weights [i]; 
                if (offset <0) { return invokers.get (i); 
                } 
            } 
        } 
        // If all invokers have the same weight value or totalWeight = 0, return evenly. 
        return invokers.get (ThreadLocalRandom .current (). nextInt (length)); 
    }

to sum up

The other types of analysis are no longer in-depth, and they are all based on the equilibrium algorithm to obtain an invoker.

References

  • http://dubbo.apache.org/zh-cn/docs/source_code_guide/loadbalance.html

Guess you like

Origin www.cnblogs.com/Benjious/p/12720952.html