日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Ribbon源码解析(二)

發布時間:2024/4/13 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Ribbon源码解析(二) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

目錄

ServerListFilter

AbstractServerListFilter

ZoneAffinityServerListFilter

ServerListSubsetFilter

ZonePreferenceServerListFilter

ServerListUpdater

IRule

AbstractLoadBalancerRule

RoundRobinRule?

WeightedResponseTimeRule 加權輪詢

ClientConfigEnabledRoundRobinRule

BestAvailableRule 最小并發數規則

PredicateBasedRule 基于斷言器規則

AvailabilityFilteringRule 可用性過濾規則

ZoneAvoidanceRule 可用區規則

RandomRule 隨機規則

RetryRule 重試規則

IRule所有內置規則


ServerListFilter

該接口用于過濾Server列表,返回可使用服務。

public interface ServerListFilter<T extends Server> {public List<T> getFilteredListOfServers(List<T> servers); }

AbstractServerListFilter

規定了Server來源:來自于負載均衡器LB,這種可用/不可用是通過指標收集庫/存儲庫LoadBalancerStats計算出來的。

public abstract class AbstractServerListFilter<T extends Server> implements ServerListFilter<T> {private volatile LoadBalancerStats stats; }

ZoneAffinityServerListFilter

它借助于ZoneAffinityPredicate來過濾出和zone相關的服務器。

@Overridepublic List<T> getFilteredListOfServers(List<T> servers) {if (zone != null && (zoneAffinity || zoneExclusive) && servers !=null && servers.size() > 0){List<T> filteredServers = Lists.newArrayList(Iterables.filter(servers, this.zoneAffinityPredicate.getServerOnlyPredicate()));if (shouldEnableZoneAffinity(filteredServers)) {return filteredServers;} else if (zoneAffinity) {overrideCounter.increment();}}return servers;}

過濾邏輯中,最重要的乃shouldEnableZoneAffinity()這個方法,

  • true:最終只留下本zone的Server列表
  • false,返回所有Server,相當于忽略此Filter的操作

具體參數見:

次數使用的過濾斷言器是ZoneAffinityPredicate

ServerListSubsetFilter

一種服務器列表篩選器實現。它將負載均衡器使用的Server數量限制為所有服務器的子集。由于服務器比較多的情況。

因為全部返回出去,比如上千臺,那么都需要保留其httpclient鏈接在連接池中,挺耗資源的

在server list非常多的場景下,沒有必要在連接池的保持這么多的連接,ServerListSubsetFilter可以在這種場景下對server [list進行精簡,通過剔除相對不健康(failureCount、activeRequestCount)的server來達到此目標。

ZonePreferenceServerListFilter

它是Spring Cloud默認使用的篩選器。它的特點是:能夠優先過濾出與請求調用方處于同區域的服務實例

ServerListUpdater

定時觸發相應的動作,被DynamicServerListLoadBalancer用于動態的更新服務列表。

public interface ServerListUpdater {public interface UpdateAction {void doUpdate();}// 使用給定的更新操作啟動serverList更新程序這個調用應該是冪等的void start(UpdateAction updateAction);// 停止服務器列表更新程序。這個調用應該是冪等的void stop();// 最后更新的時間Date的String表示形式String getLastUpdate();// 自上次更新以來已經過的ms數long getDurationSinceLastUpdateMs();//錯過更新周期的數量(如果有的話)int getNumberMissedCycles();// 使用的線程數int getCoreThreads(); }

IRule

為LoadBalancer定義“規則”的接口,它是負載均衡算法的實現。負載均衡策略,根據特定算法中從服務列表中選取一個要訪問的Server。

public interface IRule {// 最為重要的一個方法:從lb.allServers/lb.upServers根據key找到一臺Server// 若沒找到返回nullpublic Server choose(Object key);public void setLoadBalancer(ILoadBalancer lb);public ILoadBalancer getLoadBalancer(); }

AbstractLoadBalancerRule

該抽象類僅事把IRule和ILoadBalancer完成綁定,所以根據Rule選擇的Server列表均來自ILoadBalancer內。

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

RoundRobinRule?

線性輪詢,計數加1。輪詢所有server列表。假設所有機器性能相同。

WeightedResponseTimeRule 加權輪詢

它繼承自輪詢算法,相較于它,增加了響應時間作為權重,為每個Server動態分配權重,然后按照權重輪詢(加權循環)。
當沒有為服務器收集足夠的統計信息時,此規則將回退到RoundRobinRule。所以他是依賴于LoadBalancerStats統計數據的。

ClientConfigEnabledRoundRobinRule

它的規則是可以通過ClientConfig來配置的,并非是固定的。它選擇策略的實現很簡單,內部定義了RoundRobinRule,choose方法還是采用了RoundRobinRule的choose方法,所以它的選擇策略和RoundRobinRule的選擇策略一致。

public class ClientConfigEnabledRoundRobinRule extends AbstractLoadBalancerRule {RoundRobinRule roundRobinRule = new RoundRobinRule();@Overridepublic Server choose(Object key) {if (roundRobinRule != null) {return roundRobinRule.choose(key);} else {throw new IllegalArgumentException("This class has not been initialized with the RoundRobinRule class");}} }

BestAvailableRule 最小并發數規則

該策略的特性跳過已經被熔斷的實例,并且順表找出最空閑(也就是并發請求數最低的)的實例。統計數據來自云LoadBalancerStats / ServerStats

public class BestAvailableRule extends ClientConfigEnabledRoundRobinRule {// 也就是說:LoadBalancerStats是來自于lb的private LoadBalancerStats loadBalancerStats;@Overridepublic void setLoadBalancer(ILoadBalancer lb) {super.setLoadBalancer(lb);if (lb instanceof AbstractLoadBalancer) {loadBalancerStats = ((AbstractLoadBalancer) lb).getLoadBalancerStats(); }} }

?

@Overridepublic Server choose(Object key) {// 若沒有統計信息,就回退到輪詢策略if (loadBalancerStats == null) {return super.choose(key);}List<Server> serverList = getLoadBalancer().getAllServers();// 記錄所有Server中最小并發數int minimalConcurrentConnections = Integer.MAX_VALUE;long currentTime = System.currentTimeMillis();Server chosen = null;for (Server server: serverList) {ServerStats serverStats = loadBalancerStats.getSingleServerStat(server);// 只要該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;}}

PredicateBasedRule 基于斷言器規則

基于斷言器AbstractServerPredicate來實現Server的篩選。規則:

  • 先通過內部指定的一個AbstractServerPredicate斷言器過濾產生一個ServerList
  • 然后再采用線性輪詢的方式從中選取一個服務實例
public abstract class PredicateBasedRule extends ClientConfigEnabledRoundRobinRule {public abstract AbstractServerPredicate getPredicate();@Overridepublic Server choose(Object key) {ILoadBalancer lb = getLoadBalancer();Optional<Server> server = getPredicate().chooseRoundRobinAfterFiltering(lb.getAllServers(), key);if (server.isPresent()) {return server.get();} else {return null;} } }

AvailabilityFilteringRule 可用性過濾規則

它依賴于AvailabilityPredicate完成過濾后,在使用線性輪詢方式選擇Server。它的choose邏輯是:

  • 輪詢選一臺Server出來,交給predicate去判斷是否合格(沒有被熔斷,且活躍連接數沒超過閾值才算合格),若合格就直接返回,否則重復此動作一共重復10次

它能實現故障實例的自動T除,這個特點在大規模集群下特別實用

  • 若10次都還沒找到合格的,那就調用父類兜底getPredicate().chooseRoundRobinAfterFiltering()去輪詢一臺出來。

沒有使用父類的先過濾再輪詢,而是先輪詢再過濾。對于很多服務器的情況提高性能。

public class AvailabilityFilteringRule extends PredicateBasedRule {private AbstractServerPredicate predicate;public AvailabilityFilteringRule() {super();predicate = CompositePredicate.withPredicate(new AvailabilityPredicate(this, null)).addFallbackPredicate(AbstractServerPredicate.alwaysTrue()).build();}@Overridepublic AbstractServerPredicate getPredicate() {return predicate;}...@Overridepublic Server choose(Object key) {int count = 0;Server server = roundRobinRule.choose(key);//嘗試10次while (count++ <= 10) {if (predicate.apply(new PredicateKey(server))) {return server;}server = roundRobinRule.choose(key);}return super.choose(key);}}

ZoneAvoidanceRule 可用區規則

使用的是一個CompositePredicate的組合過濾器:

private CompositePredicate createCompositePredicate(ZoneAvoidancePredicate p1, AvailabilityPredicate p2) {return CompositePredicate.withPredicates(p1, p2).addFallbackPredicate(p2).addFallbackPredicate(AbstractServerPredicate.alwaysTrue()).build();}

RandomRule 隨機規則

隨機選擇一個server。使用ThreadLocalRandom.current().nextInt(serverCount);隨機來一個。幾乎不再使用。

public class RandomRule extends AbstractLoadBalancerRule {public Server choose(ILoadBalancer lb, Object key) {...Server server = null;while (server == null) {...List<Server> upList = lb.getReachableServers();List<Server> allList = lb.getAllServers();int serverCount = allList.size();int index = chooseRandomInt(serverCount);server = upList.get(index);...}return server;}protected int chooseRandomInt(int serverCount) {return ThreadLocalRandom.current().nextInt(serverCount);}}

隨機器選擇的是ThreadLocalRandom,用于多線程。

BUG:

隨機數是通過allList.size(),也就是all所有Server的size,但是,取值的時候卻用upList.get(index)來取值。

RetryRule 重試規則

它可以在給定的任何IRule的基礎上再包一層重試邏輯(默認給定的RoundRobinRule規則)。RetryRule中又定義了一個subRule,它默認的實現類是RoundRobinRule(你可以自己指定任何IRule實現),每次先采用subRule#choose()規則來選擇一個服務實例,如果選到的實例正常就返回不需要重試;如果選擇的服務實例為null或者已經失效,則在失效時間deadline之前不斷的進行重試(重試時獲取服務的策略還是subRule#choose()來選擇),如果超過了deadline還是沒取到則會返回一個null。

// 選擇方法public Server choose(ILoadBalancer lb, Object key) {// 計算出一個開始選擇 和 結束選擇的時間long requestTime = System.currentTimeMillis();long deadline = requestTime + maxRetryMillis;// 先通過subRule選擇出一個serverServer answer = null;answer = subRule.choose(key);// 如果選擇出的Server為null,或者不是活的// 并且還在結束時間之前,就執行重試策略if (((answer == null) || (!answer.isAlive())) && (System.currentTimeMillis() < deadline)) {InterruptTask task = new InterruptTask(deadline - System.currentTimeMillis());while (!Thread.interrupted()) {... // 持續不斷的調用subRule.choose(key),直到獲取到或者時間到了}task.cancel();}// 如果最終還是沒獲取到可用的,那就返回null。否則返回正常結果if ((answer == null) || (!answer.isAlive())) {return null;} else {return answer;}}

?

因為它屬于包裝器模式的一種實現,因此在實際生產中,推薦使用它來包裝實際的IRule,這樣會使得實例Server更加的健康,對網絡波動的容忍度更高些,RetryRule配合上RoundRobinRule的組合(也就是默認組合)效果很好:因為RoundRobinRule失效的策略是超過10次,而如果再配合上RetryRule,容錯性就會更強。

IRule所有內置規則

規則名

父類

說明

備注

RoundRobinRule

-

線性輪詢

輪詢index,選擇index對應位置的server

WeightedResponseTimeRule

RoundRobinRule

根據rt分配一個權重值,rt時間越長,weight越小,被選中的可能性就越低

使用一個后臺線程默認每30s重新計算一次權重值

BestAvailableRule

ClientConfigEnabled…

選擇一個活躍請求數最小的Server

忽略已經被熔斷的Server

PredicateBasedRule

ClientConfigEnabled…

基于斷言器實現的規則

本類為抽象類,具體過濾規則交給子類

AvailabilityFilteringRule

PredicateBasedRule

過濾掉已熔斷or活躍請求數太高的Server后,剩下的執行線性輪詢

依賴于AvailabilityPredicate這個斷言器實現過濾

ZoneAvoidanceRule

PredicateBasedRule

復合判斷。先選出可用區,然后在按上規則篩選出復合條件的Server們,執行線性輪詢

使用ZoneAvoidancePredicate和AvailabilityPredicate兩個主斷言器實現過濾

RandomRule

-

完全隨機選擇

此實現有bug,有bug,有bug

RetryRule

-

對任何IRule包一層重試機制

在一個配置時間段內當選擇server不成功,則一直嘗試使用subRule的方式選擇一個可用的server

?

總結

以上是生活随笔為你收集整理的Ribbon源码解析(二)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。