Hystrix的資源隔離策略有兩種,分別爲:線程池和信號量。說到資源隔離,那我們就要明白,我們爲什麼需要資源隔離。
在一個分佈式系統中,服務之間都是相互調用的,如下圖所示:
例如,我們容器(Tomcat)配置的線程個數爲1000,服務A-服務R,其中服務I的併發量非常的大,需要500個線程來執行,此時,服務I又掛了,那麼這500個線程很可能就夯死了,那麼剩下的服務,總共可用的線程爲500個,隨着併發量的增大,剩餘服務掛掉的風險就會越來越大,最後導致整個系統的所有服務都不可用,直到系統宕機。這就是服務的雪崩效應。Hystrix就是用來做資源隔離的,比如說,當客戶端向服務端發送請求時,給服務I分配了10個線程,只要超過了這個併發量就走降級服務,就算服務I掛了,最多也就導致服務I不可用,容器的10個線程不可用了,但是不會影響系統中的其他服務。下面,我們就來具體說下這兩種隔離策略:
1、線程池
線程池隔離的示意圖如下:
上圖的左邊2/3是線程池資源隔離示意圖,右邊的1/3是信號量資源隔離示意圖,我們先來看左邊的示意圖。
當用戶請求服務A和服務I的時候,tomcat的線程(圖中藍色箭頭標註)會將請求的任務交給服務A和服務I的內部線程池裏面的線程(圖中橘色箭頭標註)來執行,tomcat的線程就可以去幹別的事情去了,當服務A和服務I自己線程池裏面的線程執行完任務之後,就會將調用的結果返回給tomcat的線程,從而實現資源的隔離,當有大量併發的時候,服務內部的線程池的數量就決定了整個服務的併發度,例如服務A的線程池大小爲10個,當同時有12請求時,只會允許10個任務在執行,其他的任務被放在線程池隊列中,或者是直接走降級服務,此時,如果服務A掛了,就不會造成大量的tomcat線程被服務A拖死,服務I依然能夠提供服務。整個系統不會受太大的影響。
2、信號量
信號量的資源隔離只是起到一個開關的作用,例如,服務X的信號量大小爲10,那麼同時只允許10個tomcat的線程(此處是tomcat的線程,而不是服務X的獨立線程池裏面的線程)來訪問服務X,其他的請求就會被拒絕,從而達到限流保護的作用。
3、二者的比較
線程池隔離 | 信號量隔離 | |
---|---|---|
線程 | 與調用線程非相同線程 | 與調用線程相同(jetty線程) |
開銷 | 排隊、調度、上下文開銷等 | 無線程切換,開銷低 |
異步 | 支持 | 不支持 |
併發支持 | 支持(最大線程池大小) | 支持(最大信號量上限) |
當請求的服務網絡開銷比較大的時候,或者是請求比較耗時的時候,我們最好是使用線程隔離策略,這樣的話,可以保證大量的容器(tomcat)線程可用,不會由於服務原因,一直處於阻塞或等待狀態,快速失敗返回。而當我們請求緩存這些服務的時候,我們可以使用信號量隔離策略,因爲這類服務的返回通常會非常的快,不會佔用容器線程太長時間,而且也減少了線程切換的一些開銷,提高了緩存服務的效率。