负载均衡策略_Spring cloud Ribbon 客户端负载均衡详解(三)负载均衡策略

通过之前的源码解读,我们已经对Ribbon实现的负载均衡器以及其中包含的服务实例过滤器、服务实例信息的存储对象、区域的信息快照等都有了深入的认识和理解,但是对于负载均衡器中的服务实例选择策略只是讲解了几个默认实现的内容,而对于IRule的其他实现还没有详细的解读,下面我们来看看在Ribbon中共提供了那些负载均衡的策略实现。

f8299d4f8c823bc2ea997bb71c61c245.png

如上图所示,我们可以看到在Ribbon中实现了非常多的选择策略,其中也包含了我们在前面内容中提到过的:RoundRobinRule和ZoneAvoidanceRule。下面我们来详细的解读一下IRule接口的各个实现。

AbstractLoadBalancerRule

负载均衡策略的抽象类,在该抽象类中定义了负载均衡器ILoadBalancer对象,该对象能够在具体实现选择服务策略时,获取到一些负载均衡器中维护的信息来作为分配依据,并以此设计一些算法来实现针对特定场景的高效策略。

public abstract class AbstractLoadBalancerRule implements IRule, IClientConfigAware {    private ILoadBalancer lb;    @Override    public void setLoadBalancer(ILoadBalancer lb){        this.lb = lb;    }    @Override    public ILoadBalancer getLoadBalancer(){        return lb;    }}

RandomRule

该策略实现了从服务实例清单中随机选择一个服务实例的功能。它的具体实现如下,可以看到IRule接口的choose(Object key)函数实现,委托给了该类中的choose(ILoadBalancer lb, Object key),该方法增加了一个负载均衡器对象的参数。从具体的实现上看,它会使用传入的负载均衡器来获得可用实例列表upList和所有实例列表allList,并通过rand.nextInt(serverCount)函数来获取一个随机数,并将该随机数作为upList的索引值来返回具体实例。同时,具体的选择逻辑在一个while (server == null)循环之内,而根据选择逻辑的实现,正常情况下每次选择都应该能够选出一个服务实例,如果出现死循环获取不到服务实例时,则很有可能存在并发的Bug。

@Overridepublic Server choose(Object key) {return choose(getLoadBalancer(), key);}public Server choose(ILoadBalancer lb, Object key) {...Server server = null;while (server == null) {        if (Thread.interrupted()) {            return null;        }        List upList = lb.getReachableServers();        List allList = lb.getAllServers();        int serverCount = allList.size();        if (serverCount == 0) {            return null;        }        int index = rand.nextInt(serverCount);        server = upList.get(index);if (server == null) {            Thread.yield();            continue;        }        if (server.isAlive()) {            return (server);        }    server = null;        Thread.yield();    }    return server;}

RoundRobinRule

该策略实现了按照线性轮询的方式依次选择每个服务实例的功能。它的具体实现如下,其详细结构与RandomRule非常类似。除了循环条件不同外,就是从可用列表中获取所谓的逻辑不同。从循环条件中,我们可以看到增加了一个count计数变量,该变量会在每次循环之后累加,也就是说如果一直选择不到server超过10次,那么就会结束尝试,并打印一个警告信息No available alive servers after 10 tries from load balancer: ...。而线性轮询的实现则是通过AtomicInteger nextServerCyclicCounter对象实现,每次进行实例选择时通过调用incrementAndGetModulo函数实现递增。

public Server choose(ILoadBalancer lb, Object key) {    ...    Server server = null;    int count = 0;    while (server == null && count++ < 10) {        List reachableServers = lb.getReachableServers();        List allServers = lb.getAllServers();        int upCount = reachableServers.size();        int serverCount = allServers.size();        if ((upCount == 0) || (serverCount == 0)) {            log.warn("No up servers available from load balancer: " + lb);            return null;        }        int nextServerIndex = incrementAndGetModulo(serverCount);        server = allServers.get(nextServerIndex);        if (server == null) {            Thread.yield();            continue;        }        if (server.isAlive() && (server.isReadyToServe())) {            return (server);        }        server = null;    }    if (count >= 10) {        log.warn("No available alive servers after 10 tries from load balancer: "                + lb);    }    return server;}

RetryRule

该策略实现了一个具备重试机制的实例选择功能。从下面的实现中我们可以看到,在其内部还定义了一个IRule对象,默认使用了RoundRobinRule实例。而在choose方法中的则实现了对内部定义的策略进行反复尝试的策略,若期间能够选择到具体的服务实例就返回,若选择不到就根据设置的尝试结束时间为阈值(maxRetryMillis参数定义的值 + choose方法开始执行的时间戳),当超过该阈值后就返回null。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值