您好,登录后才能下订单哦!
这篇文章主要讲解了“Ribbon中BestAvailableRule和RetryRule的使用方法”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Ribbon中BestAvailableRule和RetryRule的使用方法”吧!
Ribbon的版本是2.3.0.release.
图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<Server> 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方法,
获取服务列表,遍历服务
通过ServerStats获取当前服务实例的并发连接数,如下List-3所示,并发连接数不是0,且当前时间与上次有效更改时间间隔在范围内,则返回当前并发连接数。
遍历所有的服务提供者后,如果得到的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的实现比较简单,基于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),
当前时间加上maxRetryMillis得到deadline,即截止时间
用subRule获取服务server,如果服务有效则直接返回该服务
构造InterruptTask,它里面有个Timer定时任务,如List-2.2。之后循坏,只要当前线程没有被interrupt,则用subRule的RoundRobin算法选择一个服务实例,如果这个服务有效或者当前时间过了截止时间则跳出循坏
如果步骤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的使用方法这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是亿速云,小编将为大家推送更多相关知识点的文章,欢迎关注!
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。