springcloud ribbon 源碼分析(10)——對ribbon自己原生的另外幾種負載均衡算法的IRule源碼初探一下

簡單看看其他的一些ribbon支持的負載均衡算法的IRule的源碼

(1)RoundRobinRule:系統內置的默認負載均衡規範,直接round robin輪詢,從一堆server list中,不斷的輪詢選擇出來一個server,每個server平攤到的這個請求,基本上是平均的

這個算法,說白了是輪詢,就是一臺接着一臺去請求,是按照順序來的

但是我debug源碼時,發現ribbon在做輪詢負載均衡時使用的不是RoundRobinRule裏邊的輪詢算法,而是通過 nextIndex.getAndIncrement() % eligible.size() 來取模實現輪詢負載。不知道是不是和我的ribbon源碼版本有關係,我的版本爲ribbon-2.2.2,如果有人知道,還請留言告知!感謝!

public class RoundRobinRule extends AbstractLoadBalancerRule {
   
    //輪詢算法
    private int incrementAndGetModulo(int modulo) {
        for (;;) {
            //下一個服務器循環計數器nextServerCyclicCounter默認爲0
            int current = nextServerCyclicCounter.get();
            //modulo爲serverCount,即服務列表size,服務總數量
            int next = (current + 1) % modulo;
            if (nextServerCyclicCounter.compareAndSet(current, next))
                return next;
        }
    }
}

 

(2)AvailabilityFilteringRule:這個rule就是會考察服務器的可用性

如果3次連接失敗,就會等待30秒後再次訪問;如果不斷失敗,那麼等待時間會不斷邊長

如果某個服務器的併發請求太高了,那麼會繞過去,不再訪問

先用round robin算法,輪詢依次選擇一臺server,如果判斷這個server是存活的可用的,如果這臺server是不可以訪問的,那麼就用round robin算法再次選擇下一臺server,依次循環往復,10次。

public class AvailabilityFilteringRule extends PredicateBasedRule { 

    @Override
    public Server choose(Object key) {
        int count = 0;
        Server server = roundRobinRule.choose(key);
        while (count++ <= 10) {
            if (predicate.apply(new PredicateKey(server))) {
                return server;
            }
            server = roundRobinRule.choose(key);
        }
        return super.choose(key);
    }
}

 

(3)WeightedResponseTimeRule:帶着權重的,每個服務器可以有權重,權重越高優先訪問,如果某個服務器響應時間比較長,那麼權重就會降低,減少訪問

public class WeightedResponseTimeRule extends RoundRobinRule {

    @Override
    public Server choose(ILoadBalancer lb, Object key) {
        if (lb == null) {
            return null;
        }
        Server server = null;

        while (server == null) {
            // get hold of the current reference in case it is changed from the other thread
            List<Double> currentWeights = accumulatedWeights;
            if (Thread.interrupted()) {
                return null;
            }
            List<Server> allList = lb.getAllServers();

            int serverCount = allList.size();

            if (serverCount == 0) {
                return null;
            }

            int serverIndex = 0;

            // last one in the list is the sum of all weights
            double maxTotalWeight = currentWeights.size() == 0 ? 0 : currentWeights.get(currentWeights.size() - 1); 
            // No server has been hit yet and total weight is not initialized
            // fallback to use round robin
            if (maxTotalWeight < 0.001d) {
                server =  super.choose(getLoadBalancer(), key);
                if(server == null) {
                    return server;
                }
            } else {
                // generate a random weight between 0 (inclusive) to maxTotalWeight (exclusive)
                double randomWeight = random.nextDouble() * maxTotalWeight;
                // pick the server index based on the randomIndex
                int n = 0;
                for (Double d : currentWeights) {
                    if (d >= randomWeight) {
                        serverIndex = n;
                        break;
                    } else {
                        n++;
                    }
                }

                server = allList.get(serverIndex);
            }

            if (server == null) {
                /* Transient. */
                Thread.yield();
                continue;
            }

            if (server.isAlive()) {
                return (server);
            }

            // Next.
            server = null;
        }
        return server;
    }
}

 

(4)ZoneAvoidanceRule:根據機房和服務器來進行負載均衡,說白了,就是機房的意思,看了源碼就是知道了,這個就是所謂的spring cloud ribbon環境中的默認的Rule

public class ZoneAvoidanceRule extends PredicateBasedRule {

    static String randomChooseZone(Map<String, ZoneSnapshot> snapshot,
            Set<String> chooseFrom) {
        if (chooseFrom == null || chooseFrom.size() == 0) {
            return null;
        }
        String selectedZone = chooseFrom.iterator().next();
        if (chooseFrom.size() == 1) {
            return selectedZone;
        }
        int totalServerCount = 0;
        for (String zone : chooseFrom) {
            totalServerCount += snapshot.get(zone).getInstanceCount();
        }
        int index = random.nextInt(totalServerCount) + 1;
        int sum = 0;
        for (String zone : chooseFrom) {
            sum += snapshot.get(zone).getInstanceCount();
            if (index <= sum) {
                selectedZone = zone;
                break;
            }
        }
        return selectedZone;
    }
}

 

 下邊幾種不常用的IRule就不貼源碼了。。。

(5)BestAvailableRule:忽略那些請求失敗的服務器,然後儘量找併發比較低的服務器來請求

(6)RandomRule:隨機找一個服務器,儘量將流量分散在各個服務器上

(7)RetryRule:可以重試,就是通過round robin找到的服務器請求失敗,可以重新找一個服務器

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章