容錯機制
如果服務提供者相應非常緩慢,那么消費者對提供者的請求就會被強制等待,知道提供者相應超時。在高負載場景下,如果不作任何處理,此類問題可能會導致服務消費者的資源耗盡甚至整個系統崩潰。
雪崩效應
微服務架構的應用系統通常包含多個服務層,微服務之間通過網絡進行通信,從而支撐起整個應用系統,因此,微服務之間難免存在依賴關系。我們常把“基礎服務故障”導致“級聯故障”的現象成為雪崩效應。雪崩效應描述的是提供者不可用導致消費者不可用,並將不可用逐步擴大的過程。
如何容錯
為了防止雪崩效應,必須有一個強大的容錯機制。該容錯機制需實現以下兩點:
1.為網絡請求設置超時
必須為網絡請求設置超時。正常情況下,一個遠程調用一般在及時毫秒內就能得到響應了。如果依賴的服務不可用或者網絡有問題,那么響應時間就會變得特別長。
通常情況下,一次遠程調用對應着一個線程/進程。如果響應太慢,這個線程/進程就得不到釋放。而線程/進程又對應着系統資源,如果得不到釋放的線程/進程約積越多,資源就會逐漸被耗盡,最終導致服務的不可用。
2.使用斷路器模式
如果對某個微服務的請求有大量超時(常常說明該微服務不可用),再去讓新的請求訪問該服務已經沒有任何意義,只會無所謂消耗資源。例如,設置了超時時間為1秒,如果短時間內有大量的請求無法在1秒內得到響應,就沒有必要再去請求依賴的服務了。
短路器可理解為對容易導致錯誤的操作的代理。這種代理能夠統計一段時間內調用失敗的次數,並決定是正常請求依賴的服務還是直接返回。
斷路器可以實現快速失敗,如果它在一段時間內檢測到許多類似的錯誤(例如超時),就會在之后的一段時間內,強迫對該服務的調用快速失敗,即不再請求所依賴的服務。這樣,應用程序就無需再浪費cpu時間去等待長時間的超時。
短路器也可自動診斷是否已經恢復正常。如果發現依賴的服務已經恢復正常,那么就會恢復請求該服務。使用這種方式,就可以實現微服務的“自我修復”——當依賴的服務不正常打開斷路器時快速失敗,從而防止雪崩效應;當發現依賴的服務恢復正常時,又會恢復請求。
斷路器狀態轉換邏輯:
- 正常情況下,斷路器關閉,可正常請求依賴的服務
- 當一段時間內,請求失敗率達到一定閥值(例如錯誤率達到50%,或100次/分鍾等),斷路器就會打開。此時,不會再去請求依賴的服務。
- 斷路器打開一段時間后,會自動進入“半開”狀態。此時,斷路器可允許一個請求訪問依賴的服務。如果該請求能夠調用成功,則關閉斷路器;否則繼續保持打開狀態。
使用Hystrix實現容錯
Hystrix簡介
Hystrix是一個實現了超時機制和斷路器模式的工具類庫。是由Netfix開源的一個延遲和容錯庫,用於隔離訪問遠程系統、服務或者第三方庫,防止級聯失敗,從而提升系統可用性與容錯性。Hystrix主要通過以下幾點實現延遲和容錯。
- 包裹請求:使用HystrixCommand(或者HystrixObservableCommand)包裹對依賴的調用邏輯,每個命令在獨立線程中執行。這使用了設計模式中的“命令模式”。
- 跳閘機制:當某服務的錯誤率超過一定閥值時,Hystrix可以自動或者手動跳閘,停止請求該服務一段時間。
- 資源隔離:Hystrix為每個依賴都維護了一個小型的線程池(或者信號量)。如果該線程池已滿,發往該依賴的請求就被立即拒絕,而不是排隊等候,從而加速失敗判斷
- 監控:Hystrix可以近乎實時地監控運行指標和配置的變化,例如成功、失敗、超時、以及被拒絕的請求等。
- 回退機制:當請求失敗、超時、被拒絕,或當斷路器打開時,執行回退邏輯。回退邏輯可由開發人員自行提供,例如返回一個缺省值。
- 自我修復:斷路器打開一段時間后,會自動進入“半開”狀態。
項目整合Hystrix
1.pom.xml添加依賴
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-hystrix</artifactId> </dependency>
2.在啟動類上加注解@EnableCircuitBreaker或@EnableHystrix,從而為項目啟用短路器支持。
3.修改controller,讓其中的findById方法具備容錯能力。
為findById方法編寫了一個回退方法findByIdFallback,該方法與findById方法具有相同的參數和返回值,返回一個默認的user;在findById方法上,使用注解@HystrixCommand的findbackMethod屬性,指定回退方法。
Htstrix線程隔離策略與傳播上下文
Hystrix的隔離策略有兩種:分別是線程隔離和信號量隔離。
- THREAD(線程隔離):使用該方式,HystrixCommand將會在單獨的線程上執行,並發請求受線程池中的線程數量的限制。
- SEMAPHONRE(信號量隔離):使用該方式,HystrixCommand將會在調用線程上執行,開銷相對較小,並發請求受到信號量個數的限制。
Hystrix中默認並且推薦使用線程隔離(THREAD),因為這種方式有一個除網絡超時以外的額外保護層。
一般來說,只有當調用負載非常高時(例如每個實例每秒調用數百次)才需要使用信號量隔離,因為這種場景下使用THREAD開銷會比較高。信號量隔離一般僅適用於非網絡調用的隔離。