Hystrix是什麼?
Hystrix 能使你的系統在出現依賴服務失效的時候,通過隔離系統所依賴的服務,防止服務級聯失敗,同時提供失敗回退機制,更優雅地應對失效,并使你的系統能更快地從異常中恢複。
Hystrix能做什麼?
- 在通過第三方用戶端通路(通常是通過網絡)依賴服務出現高延遲或者失敗時,為系統提供保護和控制
- 在分布式系統中防止級聯失敗
- 快速失敗(Fail fast)同時能快速恢複
- 提供失敗回退(Fallback)和優雅的服務降級機制
- 提供近實時的監控、報警和運維控制手段
Hystrix設計原則?
- 防止單個依賴耗盡容器(例如 Tomcat)内所有使用者線程
- 降低系統負載,對無法及時處理的請求快速失敗(fail fast)而不是排隊
- 提供失敗回退,以在必要時讓失效對使用者透明化
- 使用隔離機制(例如『艙壁』/『泳道』模式,熔斷器模式等)降低依賴服務對整個系統的影響
- 針對系統服務的度量、監控和報警,提供優化以滿足近實時性的要求
- 在 Hystrix 絕大部分需要動态調整配置并快速部署到所有應用方面,提供優化以滿足快速恢複的要求
- 能保護應用不受依賴服務的整個執行過程中失敗的影響,而不僅僅是網絡請求
Hystrix實作原理-指令模式
- 将所有請求外部系統(或者叫依賴服務)的邏輯封裝到 HystrixCommand或者HystrixObservableCommand(依賴RxJava)對象中
- Run()方法為要實作的業務邏輯,這些邏輯将會在獨立的線程中被執行當請求依賴服務時出現拒絕服務、逾時或者短路(多個依賴服務順序請求,前面的依賴服務請求失敗,則後面的請求不會發出)時,執行該依賴服務的失敗回退邏輯(Fallback)
Hystrix實作原理-艙壁模式
- 貨船為了進行防止漏水和火災的擴散,會将貨倉分隔為多個,當發生災害時,将所在貨倉進行隔離就可以降低整艘船的風險。
Hystrix實作原理-隔離政策
- 應用在複雜的分布式結構中,可能會依賴許多其他的服務,并且這些服務都不可避免地有失效的可能。如果一個應用沒有與依賴服務的失效隔離開來,那麼它将有可能因為依賴服務的失效而失效。
- Hystrix将貨倉模式運用到了服務調用者上。為每一個依賴服務維護一個線程池(或者信号量),當線程池占滿,該依賴服務将會立即拒絕服務而不是排隊等待。
- 每個依賴服務都被隔離開來,Hystrix 會嚴格控制其對資源的占用,并在任何失效發生時,執行失敗回退邏輯。
Hystrix實作原理-觀察者模式
- Hystrix通過觀察者模式對服務進行狀态監聽。
- 每個任務都包含有一個對應的Metrics,所有Metrics都由一個ConcurrentHashMap來進行維護,Key是CommandKey.name()
- 在任務的不同階段會往Metrics中寫入不同的資訊,Metrics會對統計到的曆史資訊進行統計彙總,供熔斷器以及Dashboard監控時使用。
Metrics
- Metrics内部又包含了許多内部用來管理各種狀态的類,所有的狀态都是由這些類管理的
- 各種狀态的内部也是用ConcurrentHashMap來進行維護的 如:HealthCountsStream是用來統計任務失敗率的一個類
而每個狀态管理類内部又包含了各自的真實轉态資訊
如HealthCountsStream儲存的資訊的一部分如下:
Metrics如何統計
Metrics在統計各種狀态時,時運用滑動視窗思想進行統計的,在一個滑動視窗時間中又劃分了若幹個Bucket(滑動視窗時間與Bucket成整數倍關系),滑動視窗的移動是以Bucket為機關進行滑動的。
如:HealthCounts 記錄的是一個Buckets的監控狀态,Buckets為一個滑動視窗的一小部分,如果一個滑動視窗時間為 t ,Bucket數量為 n,那麼每t/n秒将建立一個HealthCounts對象。
Hystrix實作原理-熔斷機制
- 熔斷是參考電路而産生的一種保護性機制,即系統中如果存在某個服務失敗率過高時,将開啟熔斷器,對于後續的調用,不在繼續請求服務,而是進行Fallback操作。
-
熔斷所依靠的資料即是Metrics中的HealthCount所統計的錯誤率。
一個指令的調用過程如圖所示:
熔斷器的判斷流程:
1.一個指令執行前會先運作allowRequest()函數。
allowRequest()函數内部為:
- 先檢視熔斷器是否強制開啟(ForceOpen()),如果開啟則拒絕
- 再檢視熔斷器是否強制關閉(ForceClosed()),如果強制關閉則允許Request,否則進一步判斷
- 先做isOpen(),判斷熔斷器是否開啟,如果開啟則拒絕通路,如果開啟則進一步判斷
- 再做allowSingleTest(),熔斷器休眠期過後,允許且隻允許一個請求,如果這個請求正确執行,則熔斷器關閉,如果執行失敗,則熔斷器再次開啟,進入新的熔斷周期。
如何判斷逾時
在運作對應的command時,Hystrix會注冊一個Timer到一個定時線程池中,當逾時後會啟用一個HystrixTimer線程來終止的執行。
線程池的管理是用ThreadPoolExecutor來實作的,當線程池和阻塞隊列都滿後會抛出RejectedExecutionException,捕獲該異常并進行相應狀态的處理。
Note:除此之外由程式錯誤導緻的異常,斷路器打開都可以導緻任務失敗進入Fallback
失敗降級
Hystrix提供了失敗降級政策,當指令執行失敗時,Hystrix 将會執行失敗回退邏輯。失敗回退邏輯包含了通用的回應資訊,這些回應從記憶體緩存中或者其他固定邏輯中得到,而不應有任何的網絡依賴。
如果一定要在失敗回退邏輯中包含網絡請求,必須将這些網絡請求包裝在另一個 HystrixCommand 或 HystrixObservableCommand 中。
失敗降級也有頻率限時,如果同一fallback短時間請求過大,則會抛出拒絕異常。
緩存機制
除了第一次請求需要真正通路依賴服務以外,後續請求全部從緩存中擷取,可以保證在同一個使用者請求内,不會出現依賴服務傳回不同的回應的情況,且避免了不必要的線程執行。
緩存在指令内部,且有一個ConcurrentHashMap進行管理
使用緩存需要重寫父類的getCacheKey方法
配置
Command
設定隔離政策
execution.isolation.strategy = THREAD
設定逾時時間
execution.isolation.thread.timeoutInMilliseconds = 1000
信号量隔離政策設定最大并發請求數(僅在信号量隔離政策下生效)
execution.isolation.semaphore.maxConcurrentRequests = 10
設定最大Fallback數量
fallback.isolation.semaphore.maxConcurrentRequests = 10
設定熔斷器滑動視窗最小任務
circuitBreaker.requestVolumeThreshold = 20
設定熔斷器持續時間
circuitBreaker.sleepWindowInMilliseconds = 5000
設定觸發熔斷器的失敗任務門檻值(百分比)
circuitBreaker.errorThresholdPercentage = 50
設定Metrics螢幕的範圍時間(過去多少ms内)
metrics.rollingStats.timeInMilliseconds = 10000
設定螢幕内桶的數量(将螢幕範圍劃分為若幹塊)
metrics.rollingStats.numBuckets= 10
ThreadPool
設定線程池容量
coreSize = 10
設定阻塞隊列長度(優先級高于queueSizeRejectionThreshold,且一旦初始化就不能更改 )
maxQueueSize = -1
動态設定阻塞隊列長度
queueSizeRejectionThreshold = 5
空閑線程存活時間
keepAliveTimeMinutes= 1
線程池監控視窗時間範圍(10s内)
metrics.rollingStats.timeInMilliseconds = 10000
設定線程池監控滑動視窗的桶數量
metrics.rollingStats.numBuckets = 500
Note:視窗時間必須為桶數量的整數倍,否則會抛出異常
Dashboard
1.Hystrix 自帶了一個dashboard,用來監控熔斷資訊.
2.Dashboard可以監測哪些資料?
3.使用turbine可以監控叢集.
使用Turbine聚合的伺服器叢集
遇到問題
壓測過不了,提高阻塞隊列和線程池無效,增加fallback容量解決。
fallback.isolation.semaphore.maxConcurrentRequests = 100