千家信息网

Ribbon中BestAvailableRule和RetryRule的使用方法

发表于:2025-01-31 作者:千家信息网编辑
千家信息网最后更新 2025年01月31日,这篇文章主要讲解了"Ribbon中BestAvailableRule和RetryRule的使用方法",文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习"Rib
千家信息网最后更新 2025年01月31日Ribbon中BestAvailableRule和RetryRule的使用方法

这篇文章主要讲解了"Ribbon中BestAvailableRule和RetryRule的使用方法",文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习"Ribbon中BestAvailableRule和RetryRule的使用方法"吧!

Ribbon的版本是2.3.0.release.

1.BestAvailableRule

图1

ClientConfigEnabledRoundRobinRule如下所示,定义了一个类属性RoundRobinRule,choose方法中调用RoundRobinRule进行选择,所以这里面的是轮循算法。

List-1.1

public class ClientConfigEnabledRoundRobinRule extends AbstractLoadBalancerRule {    RoundRobinRule roundRobinRule = new RoundRobinRule();    public ClientConfigEnabledRoundRobinRule() {    }    public void initWithNiwsConfig(IClientConfig clientConfig) {        this.roundRobinRule = new RoundRobinRule();    }    public void setLoadBalancer(ILoadBalancer lb) {        super.setLoadBalancer(lb);        this.roundRobinRule.setLoadBalancer(lb);    }    public Server choose(Object key) {        if (this.roundRobinRule != null) {            return this.roundRobinRule.choose(key);        } else {            throw new IllegalArgumentException("This class has not been initialized with the RoundRobinRule class");        }    }}

BestAvailableRule继承了ClientConfigEnabledRoundRobinRule,内部实现如下List-1.2,遍历所有的服务提供者,选择并发量最小的那个服务。

List-1.2

private LoadBalancerStats loadBalancerStats;public Server choose(Object key) {    if (this.loadBalancerStats == null) {        return super.choose(key);    } else {        List serverList = this.getLoadBalancer().getAllServers();        int minimalConcurrentConnections = 2147483647;        long currentTime = System.currentTimeMillis();        Server chosen = null;        Iterator var7 = serverList.iterator();        while(var7.hasNext()) {            Server server = (Server)var7.next();            ServerStats serverStats = this.loadBalancerStats.getSingleServerStat(server);            if (!serverStats.isCircuitBreakerTripped(currentTime)) {                int concurrentConnections = serverStats.getActiveRequestsCount(currentTime);                if (concurrentConnections < minimalConcurrentConnections) {                    minimalConcurrentConnections = concurrentConnections;                    chosen = server;                }            }        }        if (chosen == null) {            return super.choose(key);        } else {            return chosen;        }    }}public void setLoadBalancer(ILoadBalancer lb) {    super.setLoadBalancer(lb);    if (lb instanceof AbstractLoadBalancer) {        this.loadBalancerStats = ((AbstractLoadBalancer)lb).getLoadBalancerStats();    }}

choose方法重新了父类中的choose方法,

  1. 获取服务列表,遍历服务

  2. 通过ServerStats获取当前服务实例的并发连接数,如下List-3所示,并发连接数不是0,且当前时间与上次有效更改时间间隔在范围内,则返回当前并发连接数。

  3. 遍历所有的服务提供者后,如果得到的server是null,则调用父类的choose方法,用RoundRobin算法进行选择。

List-1.3

public int getActiveRequestsCount(long currentTime) {    int count = this.activeRequestsCount.get();    if (count == 0) {        return 0;    } else if (currentTime - this.lastActiveRequestsCountChangeTimestamp <= (long)(activeRequestsCountTimeout.get() * 1000) && count >= 0) {        return count;    } else {        this.activeRequestsCount.set(0);        return 0;    }}

2.RetryRule

图2

RetryRule的实现比较简单,基于RoundRobinRule,如下List-2.1所示

List-2.1

public class RetryRule extends AbstractLoadBalancerRule {    IRule subRule = new RoundRobinRule();    long maxRetryMillis = 500L;    ...    public Server choose(ILoadBalancer lb, Object key) {        long requestTime = System.currentTimeMillis();        long deadline = requestTime + this.maxRetryMillis;        Server answer = null;        answer = this.subRule.choose(key);        if ((answer == null || !answer.isAlive()) && System.currentTimeMillis() < deadline) {            InterruptTask task = new InterruptTask(deadline - System.currentTimeMillis());            while(!Thread.interrupted()) {                answer = this.subRule.choose(key);                if (answer != null && answer.isAlive() || System.currentTimeMillis() >= deadline) {                    break;                }                Thread.yield();            }            task.cancel();        }        return answer != null && answer.isAlive() ? answer : null;    }    ...

RetryRule中choose(Object key)调用choose(ILoadBalancer lb, Object key),

  1. 当前时间加上maxRetryMillis得到deadline,即截止时间

  2. 用subRule获取服务server,如果服务有效则直接返回该服务

  3. 构造InterruptTask,它里面有个Timer定时任务,如List-2.2。之后循坏,只要当前线程没有被interrupt,则用subRule的RoundRobin算法选择一个服务实例,如果这个服务有效或者当前时间过了截止时间则跳出循坏

  4. 如果步骤3中得到的服务实例无效,且当前时间在截止时间之内,则调用Thread.yield(),让出线程资源给其它线程

通过源码可知,RetryRule在subRule.choose获得无效的服务实例后,仅仅是再次再次用subRule获取服务实例,并不会一直尝试下去,即尝试一次。

List-2.2

public class InterruptTask extends TimerTask {    static Timer timer = new Timer("InterruptTimer", true);    protected Thread target = null;    public InterruptTask(long millis) {        this.target = Thread.currentThread();        timer.schedule(this, millis);    }    public boolean cancel() {        try {            return super.cancel();        } catch (Exception var2) {            return false;        }    }    public void run() {        if (this.target != null && this.target.isAlive()) {            this.target.interrupt();        }    }    ...

感谢各位的阅读,以上就是"Ribbon中BestAvailableRule和RetryRule的使用方法"的内容了,经过本文的学习后,相信大家对Ribbon中BestAvailableRule和RetryRule的使用方法这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是,小编将为大家推送更多相关知识点的文章,欢迎关注!

0