Hystrix 資源隔離概念講解與實操
1. 前言
在本節(jié)中,我將為各位同學介紹 Hystrix 的最后一個特性,那就是服務資源隔離。雖然服務資源隔離是 Hystrix 的最后一個特性,但是其在 Hystrix 中占著舉足輕重的地位,同時,也是治理微服務項目的重要舉措,所以各位一定要學好本節(jié)內容。
本節(jié)主要內容:
-
服務資源隔離概念介紹;
-
Hystrix 實現(xiàn)服務資源隔離。
2. 什么是服務資源隔離
在我們正式介紹什么是服務資源隔離之前,我們先來了解一些前置的概念,這些概念是理解服務資源隔離的前提。
進程與線程
進程:進程(Process)是計算機中的程序關于某數(shù)據(jù)集合上的一次運行活動,是系統(tǒng)進行資源分配和調度的基本單位,是操作系統(tǒng)結構的基礎。在當代面向線程設計的計算機結構中,進程是線程的容器。
我們可以把進程理解為我們項目運行的載體,就比如我們乘坐的公交車,公交車相對于我們來說就是一個載體,來承載我們到達不同的目的地,進程就是如此,只不過在進程中被承載的是線程罷了。
線程:線程(Thread)是操作系統(tǒng)能夠進行運算調度的最小單位。我們可以把線程理解為,執(zhí)行某一具體的計算機系統(tǒng)任務的執(zhí)行者,比如在公交車中,負責開公交車的司機師傅就可以被當做一個線程。
在一個進程中,可以存在多個線程,即在一輛公交車中可以存在多名乘客,他們分別都去往不同的目的地,但是,一個線程只能屬于一個進程,不屬于不同的兩個進程,即一名乘客同一時刻只能乘坐一輛公交車,不可能在同一時刻乘坐兩輛公交車。
在理解了什么是進程與線程之后,我們來看一下在我們的 Web 項目中,進程與線程都是怎樣存在的,以及他們之間的關系是怎樣的。
Web 項目中的進程與線程
我們的每一個 Web 項目都可以被看作一個進程,且一個 Web 項目只能是一個進程。在我們的 Web 項目中,常規(guī)情況下只有兩個線程,分別是主線程和工作線程,其中,主線程負責我們的項目啟動以及一些項目初始化工作,而工作線程則主要負責項目中的請求處理與業(yè)務邏輯執(zhí)行,項目中進程與線程的關系如下圖所示:

根據(jù)上圖,我們可以這樣理解:一個 Web 項目在計算機系統(tǒng)中就是一個進程,而在這個進程中,存在一個主線程和一個工作線程,并且主線程主要負責項目啟動,而工作線程主要負責請求的處理。
在理解了這個關系之后,讓我們來看一下什么是服務資源隔離。
服務資源隔離
在介紹服務資源隔離之前,我們需要先了解什么是服務資源。
服務資源一般來講,指的是項目正常運行所需要的基礎環(huán)境、基礎設施、靜態(tài)資源文件等內容,而對于 Web 項目來說,其項目本身即是一種服務資源,服務調用者通過調用項目提供的服務來滿足他們的業(yè)務需求。
而對于服務提供者來說,這些業(yè)務需求的實現(xiàn)在項目中一般就是我們所開發(fā)的接口,所以,在項目中所實現(xiàn)的業(yè)務接口即是我們這里所說的服務資源。
那么,為什么需要把服務資源進行隔離呢?
我們知道,正常情況下,在 Web 項目中只有一個工作線程,且這個工作線程負責接口請求的處理。在正常應用場景下,服務調用者會調用我們項目所提供的接口來滿足業(yè)務需求,這里假設我們的一個 Web 項目中具有 5 個接口,服務調用者會根據(jù)業(yè)務順序來調用我們的接口,如果一切順利,則業(yè)務即可正常順利地進行下去。
但是,如果服務調用者在調用接口時,其中一個接口所需要處理的業(yè)務比較復雜,導致這個接口不能及時的結束,這就導致我們后續(xù)的接口調用只能等待,直到該接口處理完畢后才能繼續(xù)向下執(zhí)行,如果該接口一直不能處理完畢,則后續(xù)接口就會一直等待,從而影響業(yè)務的正常開展,這種現(xiàn)象就被稱為服務資源等待,如下圖所示:

我們可以把上圖中的工作線程訪問理解為服務調用者,在服務調用者調用接口 2 時,由于接口 2 遲遲不能處理,導致接口 2 出現(xiàn)服務等待,并最終影響后續(xù)的接口 3、接口 4、接口 5 的調用,從而影響了業(yè)務的順利進行。
如果通過采取某種措施,使?jié)M足同一業(yè)務需求的不同服務資源間進行隔離,來有效緩解或解決服務資源等待問題,那么業(yè)務就可以正常順利地開展下去,所以人們就提出了服務資源隔離的概念。
3. Hystrix 實現(xiàn)服務資源隔離
在 Hystrix 中,實現(xiàn)服務資源隔離有兩種方式,分別是線程池隔離和信號量隔離。
3.1 線程池隔離實現(xiàn)服務資源隔離
通過對處理項目中的工作線程的隔離,來避免工作線程處理接口時所產生的阻塞行為,從而保證工作線程可以順利地調用接口來滿足業(yè)務需要。
而隔離工作線程的方式,就是為每個接口分配一個線程池,并在線程池中維護一定數(shù)量的線程,這樣,當上述的接口 2 發(fā)生服務資源等待時,由于每個接口都分配了不同的線程池,所以不會影響到后續(xù)的 3 4 5 接口,如下圖所示:

可以看到,由于為每個服務接口均分配了不同的線程池,所以在接口 2 出現(xiàn)服務等待時,并不會影響后續(xù)接口的調用,從而保證了業(yè)務的順利進行。
我們繼續(xù)以 hello 方法為例,來看如何實現(xiàn)線程池隔離。
@RequestMapping(value = "hello", method = RequestMethod.GET)
@HystrixCommand(threadPoolKey = "HelloHystrix", threadPoolProperties = {
@HystrixProperty(name = "coresize", value = "2"),
@HystrixProperty(name = "allowMaximumSizeToDivergeFromCoreSize", value = "true"),
@HystrixProperty(name = "maximumSize", value = "2"),
@HystrixProperty(name = "maxQueueSize", value = "2")
})
@ResponseBody
public String hello() throws InterruptedException {
return "helloWorld";
}
代碼解釋:
第 2 行,我們通過配置 HystrixCommand 注解的 threadPoolKey 屬性來為本接口分配一個名稱為 HelloHystrix 的線程池。
第 3 行,我們通過配置 threadPoolProperties 中的參數(shù)屬性,來維護 HelloHystrix 線程池中的核心線程數(shù)量、最大線程數(shù)量。
通過添加上述注解并配置其中的屬性,我們就可以通過線程池隔離的方式來實現(xiàn)服務資源隔離。
Tips: 線程池中的線程數(shù)量,一定要根據(jù)該接口所實現(xiàn)的業(yè)務需求來設置,設置過多,則會浪費資源空間,設置過少,則不能支撐業(yè)務需要,所以配置線程數(shù)量一定要謹慎。
3.2 信號量隔離實現(xiàn)服務資源隔離
信號量隔離和線程池隔離的方式很相似,只不過把分配線程池的方式改為了分配信號量(至于什么是信號量,請同學們自行查閱)。
在處理請求時,Hystrix 會分配一個信號量的閥值,當服務接收到一個請求后,信號量的閥值減 1 ,當請求處理完畢后,信號量的閥值加 1,當信號量的閥值減為 0 時,則不再接收請求,即該請求會被拒絕處理。
@RequestMapping(value = "hello", method = RequestMethod.GET)
@HystrixCommand(fallbackMethod="helloFail", commandProperties = {
@HystrixProperty(name = HystrixPropertiesManager.EXECUTION_ISOLATION_STRATEGY, value = "SEMAPHORE"),
@HystrixProperty(name = HystrixPropertiesManager.EXECUTION_ISOLATION_SEMAPHORE_MAX_CONCURRENT_REQUESTS, value = "100")
})
@ResponseBody
public String hello() throws InterruptedException {
return "helloWorld";
}
public String helloFail() {
return "helloFailed";
}
代碼解釋:
第 4 行,通過指定 HystrixPropertiesManager.EXECUTION_ISOLATION_STRATEGY
參數(shù)的值為 SEMAPHORE ,來聲明該接口使用信號量隔離。
第 7 行,通過指定 HystrixPropertiesManager.EXECUTION_ISOLATION_SEMAPHORE_MAX_CONCURRENT_REQUESTS
參數(shù)的值為 100 ,可以理解為設置信號量的閥值為 100 。
通過添加上述配置參數(shù),我們就可以通過信號量隔離的方式來實現(xiàn)服務資源隔離。
Tips: 一定要合理設置信號量的閥值,不要隨意設定,如果閥值設置過大,則請求不會停止,如果閥值設置過小,則不能滿足業(yè)務需要。
4. 視頻演示
5. 小結

本小節(jié)從服務資源隔離的前提概念開始介紹,采用圖文并茂的方式,詳細介紹了進程和線程、Web 項目中的進程與線程、服務資源隔離產生的原因,以及服務資源隔離的概念;接著,我們采用代碼實現(xiàn)的方式,對 Hystrix 中的線程池隔離和信號量隔離這兩種實現(xiàn)服務資源隔離的措施進行了介紹,并對其中需要注意的地方做了補充。
服務資源隔離是微服務項目治理中的最后一關,同時也是至關重要的一關,微服務項目經(jīng)常由于服務沒有響應而導致后續(xù)服務癱瘓,所以,掌握服務資源隔離是保證微服務項目正常運行的關鍵所在。