Hystrix原理分析

一、容錯限流的需求

在復(fù)雜的分布式系統(tǒng)中通常有很多依賴,如果一個應(yīng)用不能對來自依賴故障進(jìn)行隔離,那么應(yīng)用本身就處于被拖垮的風(fēng)險中。在一個高流量的網(wǎng)站中,某一個單一后端一旦發(fā)生延遲,將會在數(shù)秒內(nèi)導(dǎo)致所有的應(yīng)用資源被耗盡,這也就是我們常說的雪崩效應(yīng)。

比如在電商系統(tǒng)的下單業(yè)務(wù)中,在訂單服務(wù)創(chuàng)建訂單后同步調(diào)用庫存服務(wù)進(jìn)行庫存的扣減,假如庫存服務(wù)出現(xiàn)了故障,那么會導(dǎo)致下單請求線程會被阻塞,當(dāng)有大量的下單請求時,則會占滿應(yīng)用連接數(shù)從而導(dǎo)致訂單服務(wù)無法對外提供服務(wù)。

二、容錯限流的原理

對于基本的容錯限流模式,主要有以下幾點需要考量:

  • 主動超時:在調(diào)用依賴時盡快的超時,可以設(shè)置比較短的超時時間,比如2s,防止長時間的等待。
  • 限流:限制最大并發(fā)數(shù)。
  • 熔斷:錯誤數(shù)達(dá)到閾值時,類似于保險絲熔斷。
  • 隔離:隔離不同的依賴調(diào)用
  • 服務(wù)降級:資源不足時進(jìn)行服務(wù)降級

1.斷路器模式

hystrix5.png

實現(xiàn)流程為:當(dāng)斷路器的開關(guān)為關(guān)閉時(對應(yīng)圖中的綠色),每次請求進(jìn)來都是成功的,當(dāng)后端服務(wù)出現(xiàn)問題,請求出現(xiàn)的錯誤數(shù)達(dá)到一定的閾值,則會觸發(fā)斷路器為打開狀態(tài)(對應(yīng)圖中的紅色),在斷路器為打開狀態(tài)時,進(jìn)來的所有請求都會被拒絕,當(dāng)然也不是一直會拒絕請求,而是彈性的,過了特定的時間后,斷路器會進(jìn)入半打開狀態(tài)(對應(yīng)圖中的黃色),這是會讓一部分請求通過進(jìn)行嘗試,如果嘗試還是有問題,則繼續(xù)進(jìn)入打開狀態(tài),如果嘗試沒有問題了,則會進(jìn)入關(guān)閉狀態(tài)。

2.艙壁隔離模式

hystrix6.png

艙壁隔離模式可以對資源進(jìn)行隔離,類似于船的船艙都是被隔離開來的,當(dāng)其中一個或者幾個船艙出現(xiàn)問題,比如漏水,是不會影響到其他的船艙的,從而實現(xiàn)一種資源隔離的效果。

3.容錯理念

  • 凡是依賴都有可能會失敗。
  • 凡是資源都有限制,比如CPU、Memory、Threads、Queue。
  • 網(wǎng)絡(luò)并不可靠,可能存在網(wǎng)絡(luò)抖動等其他問題。
  • 延遲是應(yīng)用穩(wěn)定的殺手,延遲會占據(jù)大量的資源。

三、什么是Hystrix

Hystrix是Netflix公司開源的一款容錯框架。 它可以完成以下幾件事情:

  • 資源隔離,包括線程池隔離和信號量隔離,避免某個依賴出現(xiàn)問題會影響到其他依賴。
  • 斷路器,當(dāng)請求失敗率達(dá)到一定的閾值時,會打開斷路器開關(guān),直接拒絕后續(xù)的請求,并且具有彈性機(jī)制,在后端服務(wù)恢復(fù)后,會自動關(guān)閉斷路器開關(guān)。
  • 降級回退,當(dāng)斷路器開關(guān)被打開,服務(wù)調(diào)用超時/異常,或者資源不足(線程、信號量)會進(jìn)入指定的fallback降級方法。
  • 請求結(jié)果緩存,hystrix實現(xiàn)了一個內(nèi)部緩存機(jī)制,可以將請求結(jié)果進(jìn)行緩存,那么對于相同的請求則會直接走緩存而不用請求后端服務(wù)。
  • 請求合并, 可以實現(xiàn)將一段時間內(nèi)的請求合并,然后只對后端服務(wù)發(fā)送一次請求。

四、Hystrix核心概念

1.資源隔離

資源隔離的思想?yún)⒖忌鲜龅呐摫诟綦x模式,在hystrix中提供了兩種資源隔離策略:線程池隔離、信號量隔離。

1844674407356205960318446744073511537700_wps圖片.png

線程池隔離:線程池隔離會為每一個依賴創(chuàng)建一個線程池來處理來自該依賴的請求,不同的依賴線程池相互隔離,就算依賴A出故障,導(dǎo)致線程池資源被耗盡,也不會影響其他依賴的線程池資源。

  • 優(yōu)點:支持排隊和超時,支持異步調(diào)用。
  • 缺點:線程的創(chuàng)建一個調(diào)度會造成一定的性能開銷。
  • 適用場景:適合耗時較長的接口場景,比如接口處理邏輯復(fù)雜,且與第三方中間件有交互,因為線程池模式的請求線程與實際轉(zhuǎn)發(fā)線程不是同一個,所以可以保證容器有足夠的線程來處理新的請求。

信號量隔離模式: 初始化信號量currentCount=0,每進(jìn)來一個請求需要先將currentCount自增,再判斷currentCount的值是否小于系統(tǒng)最大信號量,小于則繼續(xù)執(zhí)行,大于則直接返回,拒絕請求。

代碼如下:

public boolean tryAcquire() {
    int currentCount = this.count.incrementAndGet();
    if (currentCount > (Integer)this.numberOfPermits.get()) {
        this.count.decrementAndGet();
        return false;
    } else {
        return true;
    }
}
  • 優(yōu)點:輕量,無額外的開銷,只是一個簡單的計數(shù)器
  • 缺點:不支持任務(wù)排隊和主動超時;不支持異步調(diào)用
  • 適用場景:適合能快速響應(yīng)的接口場景,不適合一些耗時較長的接口場景,因為信號量模式下的請求線程與轉(zhuǎn)發(fā)處理線程是同一個,如果接口耗時過長有可能會占滿容器的線程數(shù)。
隔離方式 是否支持超時 是否支持熔斷 隔離原理 是否異步調(diào)用 資源消耗
線程池隔離 支持,可直接返回 支持,當(dāng)線程池到達(dá)maxSize后,再請求會觸發(fā)fallback接口進(jìn)行熔斷 每個服務(wù)單獨用線程池,請求線程與轉(zhuǎn)發(fā)處理線程不是同一個 可以是異步,也可以是同步??凑{(diào)用的方法 大,大量線程的上下文切換,容易造成機(jī)器負(fù)載高
信號量隔離 不支持,如果阻塞,只能通過調(diào)用協(xié)議(如:socket超時才能返回) 支持,當(dāng)信號量達(dá)到maxConcurrentRequests后。再請求會觸發(fā)fallback 通過信號量的計數(shù)器,請求線程與轉(zhuǎn)發(fā)處理線程是同一個 同步調(diào)用,不支持異步 小,只是個計數(shù)器

2.斷路器

斷路器工作原理如下:

hystrix90.png

Hystrix是基于滾筒式來處理,每一秒會產(chǎn)生一個buckets,每產(chǎn)生一個新的buckets就會移除一個最老的buckets,默認(rèn)是10秒一個窗口。buckets在內(nèi)存中就是一種數(shù)據(jù)結(jié)構(gòu),每個buckets會記錄Metrics的相關(guān)數(shù)據(jù),比如成功、失敗、超時、拒絕。

當(dāng)一個HystrixCommand進(jìn)來后,會先通過allowRequest()方法判斷是否允許通過該次請求,allowRequest()方法會通過isOpen判斷斷路器是否打開。斷路器關(guān)閉,則允許通過該次請求;斷路器打開,則會判斷是否過了睡眠周期。沒有過睡眠周期則返回false,拒絕通過該次請求,過了睡眠周期則會嘗試放行。

isOpen()方法會按照(failure) / (success+failure)公式計算出失敗率,如果失敗率大于閾值,則會觸發(fā)熔斷。公式中的成功、失敗的數(shù)據(jù)就來源于每10秒中一個窗口的滾筒數(shù)據(jù)。

對于一個依賴調(diào)用,要么調(diào)用成功,要么調(diào)用失?。òó惓?、超時、拒絕),這些調(diào)用結(jié)果都會記錄到buckets中。對于調(diào)用成功結(jié)果來說,還會判斷斷路器開關(guān)是否打開,如果是打開狀態(tài)的話,則會關(guān)閉斷路器并重置相關(guān)的計數(shù)器。

3.降級回退

降級,通常指事務(wù)高峰期,為了保證核心服務(wù)正常運行,需要停掉一些不太重要的業(yè)務(wù),或者某些服務(wù)不可用時,執(zhí)行備用邏輯從故障服務(wù)中快速失敗或快速返回,以保障主體業(yè)務(wù)不受影響。 Hystrix提供的降級主要是為了容錯,保證當(dāng)前服務(wù)不受依賴服務(wù)故障的影響,從而提高服務(wù)的健壯性。

1)哪些情況會進(jìn)入降級邏輯

  • 斷路器打開
  • 線程池/信號量資源不足
  • 執(zhí)行依賴調(diào)用超時
  • 執(zhí)行依賴調(diào)用異常

2)降級回退方式

(1)Fail Fast快速失敗

快速失敗是最普通的命令執(zhí)行方法,命令沒有重寫降級邏輯。 如果命令執(zhí)行發(fā)生任何類型的故障,它將直接拋出異常。

(2)Fail Fast無聲失敗

指在降級方法中通過返回null,空Map,空List或其他類似的響應(yīng)來完成。

(3)FallBack:Static

指在降級方法中返回靜態(tài)默認(rèn)值。 這不會導(dǎo)致服務(wù)以“無聲失敗”的方式被刪除,而是導(dǎo)致默認(rèn)行為發(fā)生。如:應(yīng)用根據(jù)命令執(zhí)行返回true / false執(zhí)行相應(yīng)邏輯,但命令執(zhí)行失敗,則默認(rèn)為true。

(4)FallBack:Stubbed

當(dāng)命令返回一個包含多個字段的復(fù)合對象時,適合以Stubbed 的方式回退。

(5)FallBack:Cache via Network

有時,如果調(diào)用依賴服務(wù)失敗,可以從緩存服務(wù)(如redis)中查詢舊數(shù)據(jù)版本。由于又會發(fā)起遠(yuǎn)程調(diào)用,所以建議重新封裝一個Command,使用不同的ThreadPoolKey,與主線程池進(jìn)行隔離。

(6)Primary+Secondary with FallBack

有時系統(tǒng)具有兩種行為- 主要和次要,或主要和故障轉(zhuǎn)移。主要和次要邏輯涉及到不同的網(wǎng)絡(luò)調(diào)用和業(yè)務(wù)邏輯,所以需要將主次邏輯封裝在不同的Command中,使用線程池進(jìn)行隔離。為了實現(xiàn)主從邏輯切換,可以將主次command封裝在外觀HystrixCommand的run方法中,并結(jié)合配置中心設(shè)置的開關(guān)切換主從邏輯。由于主次邏輯都是經(jīng)過線程池隔離的HystrixCommand,因此外觀HystrixCommand可以使用信號量隔離,而沒有必要使用線程池隔離引入不必要的開銷。

4.請求結(jié)果緩存

hystrix-cache.png

實際應(yīng)用場景很少,不予過多介紹。

5.請求合并

hystrix-xx.png

實際應(yīng)用場景很少,不予過多介紹。

五、Hystrix工作流程

1844674407355605524124348914_wps圖片.png

對于一次依賴調(diào)用,會被封裝在一個HystrixCommand對象中,調(diào)用的執(zhí)行有兩種方式,一種是調(diào)用execute()方法同步調(diào)用,另一種是調(diào)用queue()方法進(jìn)行異步調(diào)用。

執(zhí)行時會判斷斷路器開關(guān)是否打開,如果斷路器打開,則進(jìn)入getFallback()降級邏輯;如果斷路器關(guān)閉,則判斷線程池/信號量資源是否已滿,如果資源滿了,則進(jìn)入getFallback()降級邏輯;如果沒滿,則執(zhí)行run()方法。再判斷執(zhí)行run()方法是否超時,超時則進(jìn)入getFallback()降級邏輯,run()方法執(zhí)行失敗,則進(jìn)入getFallback()降級邏輯,執(zhí)行成功則報告Metrics。Metrics中的數(shù)據(jù)包括執(zhí)行成功、超時、失敗等情況的數(shù)據(jù),Hystrix會計算一個斷路器的健康值,也就是失敗率,當(dāng)失敗率超過閾值后則會觸發(fā)斷路器開關(guān)打開。

getFallback()邏輯為:如果沒有實現(xiàn)fallback()方法,則直接拋出異常,另外fallback降級也是需要資源的,在fallback時需要獲取一個針對fallback的信號量,只有獲取成功才能fallback,獲取信號量失敗,則拋出異常,獲取信號量成功,才會執(zhí)行fallback方法并且會響應(yīng)fallback方法中的內(nèi)容。

六、參考資料

楊波老師的《微服務(wù)架構(gòu)實戰(zhàn)160講》

https://github.com/Netflix/Hystrix/wiki

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容