剔除重复_微服务发生故障后,我是如何做到自动剔除异常的Server?
Ribbon 是 Netflix 出品的一套負載均衡組件,提供了許多 Rule 規則從負載列表中選取合適的 server 實例。當實例出現問題時候,需要將這部分異常的服務提供者從負載列表中剔除,從而避免雪崩效應。而 Riibbon 本身具有自動移除問題實例的功能,于是我們可以結合 Ribbon 對現有的負載均衡策略做一些改進,實現自動故障剔除功能。
工作流程
Ribbon 中實現自動移除問題實例的 Rule 是 AvailabilityFilteringRule,它的運行原理如上圖所示,大致可以分為以下幾步:
服務狀態 ServerStats
結合實際業務需求,在 serverStats 中,目前定義了兩類異常,連接異常 (主要指 tcp 層面的,包括 sokcetException,socketTimeoutException,ConnectException) 以及不可用異常(主要是底層通信框架 rxNetty 拋出的異常,包括 timeoutException 以及 PoolExhaustedException)。
參數定義
考慮到兩種異常的發生場景的差異,為這兩類異常分別設置了各自的連續失敗閾值 (connectionFailureThreshold,unavailableThreshold) 以及斷路超時時間(connectionFailureCircuitTimeout,unavailableCircuitTimeout)。其中不可用異常參數 (unavailableThreshold,unavailableCircuitTimeout) 會暴露給使用者,使用 springboot 的項目可以直接讀取 yml 文件或者托管到第三方配置中心。
而其中連接失敗異常相關的參數,考慮到較為底層,使用者不大關心,是默認設置好了,只通過讀取環境變量的方式來允許改動。
斷路器工作原理
從上面定義的參數就指定,目前斷路器統計失敗是靠連續失敗次數去判斷斷路邏輯的。之后可以根據不同場景做不同的適配。目前斷路器的工作算法大致如下
當有鏈接失敗情況出現斷路邏輯時,將會最多:1<<16 * 10 = 655360 s (如果超過自定義超時時間閾值,則最大為自定義超時時間),最少 1<<0*10 = 10 s 的請求熔斷時間,再此期間內,此 Server 將會被忽略。熔斷的超時時間在沒有超過自定義超時閾值的情況下,會隨著該 server 的失敗次數呈指數級動態增加。如果當自定義閾值很大,而一個服務實例連續失敗很多次,那他基本就沒什么希望被調用到了。。
框架中算法實現如下:
????private?long?getCircuitBreakerBlackoutPeriod(AtomicInteger?atomicInteger,?Integer?threshold,?Integer?circuitTimeout)?{????????final?int?failureCount?=?atomicInteger.get();
????????if?(failureCount?????????????return?0;
????????}
????????final?int?diff?=?(failureCount?-?threshold)?>?16???16?:?(failureCount?-?threshold);
????????int?blackOutSeconds?=?(1?<????????if?(blackOutSeconds?>?circuitTimeout)?{
????????????blackOutSeconds?=?circuitTimeout;
????????}
????????return?blackOutSeconds?*?1000L;
????}
記錄服務狀態
當 loadBalancerCommand 對服務請求做出處理之后,根據返回的狀態對 serverStats 做出記錄。
服務路由規則
AvailabilityFilteringRule 通過一定的規則選擇合適的 server 實例。首先它用 roundRobinRule 加權輪詢算法選取一個 sevrer 實例。接著對選出的 server 實例應用上述的斷路算法判斷是否應該斷路,如果是斷路狀態,那么將會重新通過 roundRobinRule 去選擇 server 實例,這里最多重試 10 次。如果經過了 10 次,還沒有選出合適的實例,意味著也許所有實例都被熔斷了。那么死活還是得挑一個的,這里會通過父類 Rule 去選擇實例,而父類 rule 的斷言器定義的是 always true。
public?Server?choose(Object?key)?{????????int?count?=?0;
????????Server?server?=?roundRobinRule.choose(key);
????????while?(count++?<=?10)?{
????????????if?(predicate.apply(new?PredicateKey(server)))?{
????????????????return?server;
????????????}
????????????server?=?roundRobinRule.choose(key);
????????}
????????return?super.choose(key);
????}
作者:fredalxin
來源鏈接:
https://fredal.xin/loadbalancer-with-ribbon
總結
以上是生活随笔為你收集整理的剔除重复_微服务发生故障后,我是如何做到自动剔除异常的Server?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: lora发射和接收原理_四个要点,帮你搞
- 下一篇: down 网卡端口周期性的up_Linu