javascript
【SpringCloud】Netflix源码解析之Ribbon:负载均衡策略的定义和实现
Ribbon負載均衡策略定義
IRule其實就只做了一件事情Server choose(Object key),可以看到這個功能是在LB中定義(要求)的,LB把這個功能委托給IRule來實現。不同的IRule可以向LB提供不同的負載均衡算法。
public interface IRule{ public Serverchoose(Object key); public void setLoadBalancer(ILoadBalancerlb); public ILoadBalancergetLoadBalancer(); }com.netflix.loadbalancer包下面的提供了常用的幾種策略。有RoundRobinRule、RandomRule這樣的不依賴于Server運行狀況的策略,也有AvailabilityFilteringRule、WeightedResponseTimeRule等多種基于收集到的Server運行狀況決策的策略。判斷運行狀況時有,判斷單個server的,也有判斷整個zone的,適用于各種不同場景需求。
實現上有些策略可以繼承一個既存的簡單策略用于某些啟動時候,也可以包含一個簡單策略。甚至有ZoneAvoidanceRule這樣的可以包含復合謂詞的條件判斷。TODOTODO IRue hireachy
Ribbon自帶負載均衡策略比較
| 策略名 | 策略聲明 | 策略描述 | 實現說明 |
| BestAvailableRule | public class BestAvailableRule extends ClientConfigEnabledRoundRobinRule | 選擇一個最小的并發請求的server | 逐個考察Server,如果Server被tripped了,則忽略,在選擇其中ActiveRequestsCount最小的server |
| AvailabilityFilteringRule | public class AvailabilityFilteringRule extends PredicateBasedRule | 過濾掉那些因為一直連接失敗的被標記為circuit tripped的后端server,并過濾掉那些高并發的的后端server(active connections 超過配置的閾值) | 使用一個AvailabilityPredicate來包含過濾server的邏輯,其實就就是檢查status里記錄的各個server的運行狀態 |
| WeightedResponseTimeRule | public class WeightedResponseTimeRule extends RoundRobinRule | 根據相應時間分配一個weight,相應時間越長,weight越小,被選中的可能性越低。 | 一個后臺線程定期的從status里面讀取評價響應時間,為每個server計算一個weight。Weight的計算也比較簡單responsetime 減去每個server自己平均的responsetime是server的權重。當剛開始運行,沒有形成statas時,使用roubine策略選擇server。 |
| RetryRule | public class RetryRule extends AbstractLoadBalancerRule | 對選定的負載均衡策略機上重試機制。 | 在一個配置時間段內當選擇server不成功,則一直嘗試使用subRule的方式選擇一個可用的server |
| RoundRobinRule | public class RoundRobinRule extends AbstractLoadBalancerRule | roundRobin方式輪詢選擇server | 輪詢index,選擇index對應位置的server |
| RandomRule | public class RandomRule extends AbstractLoadBalancerRule | 隨機選擇一個server | 在index上隨機,選擇index對應位置的server |
| ZoneAvoidanceRule | public class ZoneAvoidanceRule extends PredicateBasedRule | 復合判斷server所在區域的性能和server的可用性選擇server | 使用ZoneAvoidancePredicate和AvailabilityPredicate來判斷是否選擇某個server,前一個判斷判定一個zone的運行性能是否可用,剔除不可用的zone(的所有server),AvailabilityPredicate用于過濾掉連接數過多的Server。 |
Ribbon自帶負載均衡策略實現解析
1. com.netflix.loadbalancer.BestAvailableRule
功能:選擇一個最小的并發請求的server
主要代碼:逐個考察Server,如果Server被tripped了,則忽略,在選擇其中ActiveRequestsCount最小的server
for (Serverserver: serverList) { ServerStatsserverStats = loadBalancerStats.getSingleServerStat(server); if (!serverStats.isCircuitBreakerTripped(currentTime)) { int concurrentConnections = serverStats.getActiveRequestsCount(currentTime); if (concurrentConnections < minimalConcurrentConnections) { minimalConcurrentConnections = concurrentConnections; chosen = server; } }2 com.netflix.loadbalancer.AvailabilityFilteringRule
功能:過濾掉那些因為一直連接失敗的被標記為circuit tripped的后端server,并過濾掉那些高并發的的后端server(active connections 超過配置的閾值)
主要代碼:使用一個AvailabilityPredicate來包含過濾server的邏輯,其實就就是檢查status里記錄的各個server的運行狀態,過濾掉那些高并發的的后端server(active connections 超過配置的閾值)
boolean com.netflix.loadbalancer.AvailabilityPredicate.shouldSkipServer(ServerStatsstats) { if ((CIRCUIT_BREAKER_FILTERING.get() && stats.isCircuitBreakerTripped()) || stats.getActiveRequestsCount() >= activeConnectionsLimit.get()) { return true; } return false; }3 com.netflix.loadbalancer.WeightedResponseTimeRule
功能:根據相應時間分配一個weight,相應時間越長,weight越小,被選中的可能性越低。 ”
主要代碼:一個后臺線程定期的從status里面讀取評價響應時間,為每個server計算一個weight。Weight的計算也比較簡單responsetime 減去每個server自己平均的responsetime是server的權重。當剛開始運行,沒有形成statas時,使用roubine策略選擇server。
class DynamicServerWeightTask extends TimerTask { public void run() { ServerWeightserverWeight = new ServerWeight(); serverWeight.maintainWeights(); } }maintainWeights(){ List<Double> finalWeights = new ArrayList<Double>(); for (Serverserver : nlb.getAllServers()) { ServerStatsss = stats.getSingleServerStat(server); double weight = totalResponseTime – ss.getResponseTimeAvg(); weightSoFar += weight; finalWeights.add(weightSoFar); } setWeights(finalWeights);}Serverchoose(ILoadBalancerlb, Object key) { 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);}4 com.netflix.loadbalancer.RetryRule
功能:對選定的負載均衡策略機上重試機制。
主要代碼:在一個配置時間段內當選擇server不成功,則一直嘗試使用subRule的方式選擇一個可用的server
answer = subRule.choose(key); if (((answer == null) || (!answer.isAlive())) && (System.currentTimeMillis() < deadline)) { InterruptTasktask = new InterruptTask(deadline - System.currentTimeMillis()); while (!Thread.interrupted()) { answer = subRule.choose(key); if (((answer == null) || (!answer.isAlive())) && (System.currentTimeMillis() < deadline)) { /* pause and retry hoping it’s transient */ Thread.yield(); } else { break; } } task.cancel();5 com.netflix.loadbalancer.RoundRobinRule
功能:roundRobin方式輪詢選擇server
主要代碼:輪詢index,選擇index對應位置的server
List<Server> allServers = lb.getAllServers(); int upCount = reachableServers.size(); int serverCount = allServers.size(); int nextServerIndex = incrementAndGetModulo(serverCount); server = allServers.get(nextServerIndex);6 com.netflix.loadbalancer.RandomRule
功能:隨機選擇一個server
主要代碼:在index上隨機,選擇index對應位置的server
List<Server> upList = lb.getReachableServers(); List<Server> allList = lb.getAllServers(); int serverCount = allList.size(); int index = rand.nextInt(serverCount); server = upList.get(index);7 com.netflix.loadbalancer.ZoneAvoidanceRule
功能:復合判斷server所在區域的性能和server的可用性選擇server
主要代碼:使用ZoneAvoidancePredicate和AvailabilityPredicate來判斷是否選擇某個server,前一個,以一個區域為單位考察可用性,對于不可用的區域整個丟棄,從剩下區域中選可用的server。判斷出最差的區域,排除掉最差區域。在剩下的區域中,將按照服務器實例數的概率抽樣法選擇,從而判斷判定一個zone的運行性能是否可用,剔除不可用的zone(的所有server),AvailabilityPredicate用于過濾掉連接數過多的Server。
public com.netflix.loadbalancer.PredicateBasedRule.Serverchoose(Object key) { ILoadBalancerlb = getLoadBalancer(); Optional<Server> server = getPredicate().chooseRoundRobinAfterFiltering(lb.getAllServers(), key); if (server.isPresent()) { return server.get(); } }參照現有的若干中rule的實現風格,根據我們自己需要也可以開發出自定義的負載均衡策略。完。
?
?
參考資料:
http://www.tuicool.com/articles/7zIbIb3
?
轉載于:https://www.cnblogs.com/junneyang/p/6379486.html
總結
以上是生活随笔為你收集整理的【SpringCloud】Netflix源码解析之Ribbon:负载均衡策略的定义和实现的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 事件(二):事件处理程序
- 下一篇: javascript事件监听与事件委托