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找到的服务器请求失败,可以重新找一个服务器

 

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