您好,登錄后才能下訂單哦!
這篇文章主要講解了“Ribbon中BestAvailableRule和RetryRule的使用方法”,文中的講解內(nèi)容簡單清晰,易于學(xué)習(xí)與理解,下面請(qǐng)大家跟著小編的思路慢慢深入,一起來研究和學(xué)習(xí)“Ribbon中BestAvailableRule和RetryRule的使用方法”吧!
Ribbon的版本是2.3.0.release.
圖1
ClientConfigEnabledRoundRobinRule如下所示,定義了一個(gè)類屬性RoundRobinRule,choose方法中調(diào)用RoundRobinRule進(jìn)行選擇,所以這里面的是輪循算法。
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,內(nèi)部實(shí)現(xiàn)如下List-1.2,遍歷所有的服務(wù)提供者,選擇并發(fā)量最小的那個(gè)服務(wù)。
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方法,
獲取服務(wù)列表,遍歷服務(wù)
通過ServerStats獲取當(dāng)前服務(wù)實(shí)例的并發(fā)連接數(shù),如下List-3所示,并發(fā)連接數(shù)不是0,且當(dāng)前時(shí)間與上次有效更改時(shí)間間隔在范圍內(nèi),則返回當(dāng)前并發(fā)連接數(shù)。
遍歷所有的服務(wù)提供者后,如果得到的server是null,則調(diào)用父類的choose方法,用RoundRobin算法進(jìn)行選擇。
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的實(shí)現(xiàn)比較簡單,基于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)調(diào)用choose(ILoadBalancer lb, Object key),
當(dāng)前時(shí)間加上maxRetryMillis得到deadline,即截止時(shí)間
用subRule獲取服務(wù)server,如果服務(wù)有效則直接返回該服務(wù)
構(gòu)造InterruptTask,它里面有個(gè)Timer定時(shí)任務(wù),如List-2.2。之后循壞,只要當(dāng)前線程沒有被interrupt,則用subRule的RoundRobin算法選擇一個(gè)服務(wù)實(shí)例,如果這個(gè)服務(wù)有效或者當(dāng)前時(shí)間過了截止時(shí)間則跳出循壞
如果步驟3中得到的服務(wù)實(shí)例無效,且當(dāng)前時(shí)間在截止時(shí)間之內(nèi),則調(diào)用Thread.yield(),讓出線程資源給其它線程
通過源碼可知,RetryRule在subRule.choose獲得無效的服務(wù)實(shí)例后,僅僅是再次再次用subRule獲取服務(wù)實(shí)例,并不會(huì)一直嘗試下去,即嘗試一次。
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的使用方法”的內(nèi)容了,經(jīng)過本文的學(xué)習(xí)后,相信大家對(duì)Ribbon中BestAvailableRule和RetryRule的使用方法這一問題有了更深刻的體會(huì),具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是億速云,小編將為大家推送更多相關(guān)知識(shí)點(diǎn)的文章,歡迎關(guān)注!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。