-
-
簡介
在大中型分布式系統中,通常系統很多依賴(HTTP,Hession,Netty,Dubbo等),在高并發通路下,這些依賴的穩定性與否對系統的影響非常大,但是依賴有很多不可控問題:
如網絡連接配接緩慢,資源繁忙,暫時不可用,服務脫機等。
在正常情況下:
當依賴服務 I 繁忙,其他依賴正常時:
當依賴 I 阻塞時,大多數伺服器的 線程 池就出現阻塞(BLOCK),影響整個線上服務的穩定性: 在複雜的分布式 架構 的應用程式有很多的依賴,都會不可避免地在某些時候失敗。高并發的依賴失敗時如果沒有隔離措施,目前應用服務就有被拖垮的風險。
Hystrix,旨在通過控制那些通路遠端系統、服務和第三方庫的節點,進而對延遲和故障提供更強大的容錯能力。
Hystrix源于Netflix API團隊在2011年啟動的彈性工程工作,而目前它在Netflix每天處理着數百億的隔離線程以及數千億的隔離信号調用。Hystrix是基于Apache License 2.0協定的開源的程式庫,目前托管在GitHub上。
-
-
Hystrix能夠做什麼
1)Hystrix使用指令模式HystrixCommand(Command)包裝依賴調用邏輯,每個指令在單獨線程中/信号 授權 下執行,每個command隻能執行一次。
2)提供熔斷器元件,可以自動運作或手動調用,停止目前依賴一段時間(10秒),熔斷器預設 錯誤 率門檻值為50%,超過将自動運作。
3)可配置依賴調用 逾時 時間,逾時時間一般設為比99.5%平均時間略高即可.當調用逾時時,直接傳回或執行fallback邏輯。
4)為每個依賴提供一個小的線程池(或信号),如果線程池已滿調用将被立即拒絕,預設不采用排隊.加速失敗判定時間。
5)依賴調用結果分:成功,失敗(抛出 異常 ),逾時,線程拒絕,短路。 請求失敗(異常,拒絕,逾時,短路)時執行fallback(降級)邏輯。
-
隔離政策
1、線程隔離把執行依賴代碼的線程與請求線程(如:jetty線程)分離,請求線程可以自由控制離開的時間(異步過程)。通過線程池大小可以控制并發量,當線程池飽和時可以提前拒絕服務,防止依賴問題擴散。
線上建議線程池不要設定過大,否則大量堵塞線程有可能會拖慢伺服器。
優點:
[1]:使用線程可以完全隔離第三方代碼,請求線程可以快速放回。
[2]:當一個失敗的依賴再次變成可用時,線程池将清理,并立即恢複可用,而不是一個長時間的恢複。
[3]:可以完全模拟異步調用,友善異步程式設計。
缺點:
[1]:線程池的主要缺點是它增加了CPU排程和上下文切換。
[2]:對使用ThreadLocal等依賴線程狀态的代碼增加複雜性,需要手動傳遞和清理線程狀态。
Note: Netflix公司内部認為線程隔離開銷足夠小,不會造成重大的成本或性能的影響。Netflix 内部API 每天100億的HystrixCommand依賴請求使用線程隔,每個應用大約40多個線程池,每個線程池大約5-20個線程。
2、信号量隔離
信号隔離也可以用于限制并發通路,防止阻塞擴散, 與線程隔離最大不同在于執行依賴代碼的線程依然是請求線程(該線程需要通過信号申請),如果用戶端是可信的且可以快速傳回,可以使用信号隔離替換線程隔離,降低開銷。
信号量的大小可以動态調整, 線程池大小不可以。
優點:
[1]:使用信号量沒有額外的CPU線程上下文切換開銷,比線程隔離開銷要小得多。
[2]:可以對請求限流。
缺點:
[1]:不能對依賴的請求調用進行熔斷。
預設并且推薦的隔離方式是線程隔離,通過單獨線程執行的指令可以提供一層網絡逾時提供不了的額外的保護。隻有當請求調用量很大導緻使用線程隔離開銷太大時才使用信号量隔離(一般是非網絡請求調用)。3、如何選擇
-
使用Fallback提供降級政策
當執行HystrixCommand的run方法時,如果發生任何錯誤抛出異常時:不提供Fallback:HystrixRuntimeException: * failed and no fallback available.。
Note:Fallback邏輯中最好不要有能導緻異常或錯誤的邏輯,盡量提供靜态傳回内容。提供Fallback :直接走Fallback邏輯。
-
熔斷器
1、熔斷請求判斷機制
使用無鎖循環隊列計數,每個熔斷器預設維護10個bucket,每1秒一個bucket,每個blucket記錄請求的成功、失敗、逾時、拒絕的狀态,預設錯誤超過50%且10秒内超過20個請求進行中斷攔截。
2、熔斷恢複
對于被熔斷的請求,每隔5s允許一個請求通過,若請求都是健康的,則對請求健康恢複。
OPEN、HALF-OPEN、CLOSED3、熔斷器的三種狀态
The precise way that the circuit opening and closing occurs is as follows:
-
Assuming the volume across a circuit meets a certain threshold (HystrixCommandProperties.circuitBreakerRequestVolumeThreshold())...
-
And assuming that the error percentage exceeds the threshold error percentage (HystrixCommandProperties.circuitBreakerErrorThresholdPercentage())...
-
Then the circuit-breaker transitions from CLOSED to OPEN.
-
While it is open, it short-circuits all requests made against that circuit-breaker.
-
After some amount of time (HystrixCommandProperties.circuitBreakerSleepWindowInMilliseconds()), the next single request is let through (this is the HALF-OPEN state). If the request fails, the circuit-breaker returns to the OPEN state for the duration of the sleep window. If the request succeeds, the circuit-breaker transitions to CLOSED and the logic in 1. takes over again.
4、熔斷器作用範圍
以commandKey來區分,需要控制粒度。
-
-
配置
1、統計滾動的時間視窗 default 10000 ten seconds
withMetricsRollingStatisticalWindowInMilliseconds(10000)
2、滾動時間視窗 bucket 數量 default
withMetricsRollingStatisticalWindowBuckets(10)
3、采樣時間間隔 default 500
withMetricsHealthSnapshotIntervalInMilliseconds(1)
4、熔斷器在整個統計時間内是否開啟的閥值,預設20。也就是10秒鐘内至少請求20次,熔斷器才發揮起作用
withCircuitBreakerRequestVolumeThreshold(20)
5、預設:50。當出錯率超過50%後熔斷器啟動.
withCircuitBreakerErrorThresholdPercentage(30)
6、熔斷器預設工作時間,預設:5秒.熔斷器中斷請求5秒後會關閉重試,如果請求仍然失敗,繼續打開熔斷器5秒,如此循環
withCircuitBreakerSleepWindowInMilliseconds(1000)
7、隔離政策
withExecutionIsolationStrategy(ExecutionIsolationStrategy.SEMAPHORE)
8、信号量隔離時最大并發請求數
withExecutionIsolationSemaphoreMaxConcurrentRequests(2)
9、指令組名,該指令屬于哪一個組,可以幫助我們更好的組織指令。
withGroupKey(HystrixCommandGroupKey.Factory.asKey("HelloGroup"))
10、指令名稱,每個CommandKey代表一個依賴抽象,相同的依賴要使用相同的CommandKey名稱。依賴隔離的根本就是對相同CommandKey的依賴做隔離。
andCommandKey(HystrixCommandKey.Factory.asKey("Hello")
11、所屬線程池的名稱,同樣配置的指令會共享同一線程池,若不配置,會預設使用GroupKey作為線程池名稱。
andThreadPoolKey(HystrixThreadPoolKey.Factory.asKey("HelloThreadPool"))
12、指令屬性,設定包括斷路器的配置,隔離政策,降級設定,以及一些監控名額等。
13、線程池屬性,配置包括線程池大小,排隊隊列的大小等。
-
其他特性
1、請求緩存。
2、批量執行請求。