1、Sentinel注解支持
在學習熔斷降級之前,我們先來看一下Sentinel的注解支持,我們使用spring-cloud-starter-alibaba-sentinel依賴,無需額外配置即可使用@SentinelResource注解定義資源。
@SentinelResource 用於定義資源,並提供可選的異常處理和 fallback 配置項。常用屬性如下:
value:資源名稱,必需項(不能為空);
blockHandler / blockHandlerClass: blockHandler 對應處理 BlockException 的函數名稱,可選項。blockHandler 函數訪問范圍需要是 public,返回類型需要與原方法相匹配,參數類型需要和原方法相匹配並且最后加一個額外的參數,類型為 BlockException。blockHandler 函數默認需要和原方法在同一個類中。若希望使用其他類的函數,則可以指定 blockHandlerClass 為對應的類的 Class 對象,注意對應的函數必需為 static 函數,否則無法解析。
1.1、改造之前的資源定義方式,使用注解定義。
1.2、啟動項目,快速訪問控制台打印如下,異常類型為FlowException,流控異常。
2、熔斷器
前面我們說過,如果依賴的服務不可用,導致服務自身被拖垮,並將不可用逐漸放大的過程叫做服務雪崩。為了防止雪崩效應,必須有一個強大的容錯機制。試想一下,如果家里沒有熔斷器,當電流過載時,電路不斷開,可能會引發燒斷電路、引發火災。使用熔斷器,電路一旦過載就會跳閘,從而可以保護電路的安全。當電路過載的問題解決后,只須關閉熔斷器,電路就可以恢復正常。
同樣,如果某個微服務不可用時,再去讓新的請求去訪問該服務已經沒有任何意義,只會無謂消耗資源。所以我們要在需要的地方加上熔斷器,熔斷器有三種狀態,狀態轉換如下:
a、正常情況下,熔斷器關閉,可正常請求依賴的服務。
b、當一段時間內,請求失敗率達到一定閾值(例如調用超時或異常比例升高),熔斷器就會打開。此時,不會在去請求依賴的服務。
c、熔斷器打開一段時間后,會自動進入“半打開”狀態。此時,熔斷器可允許一個請求訪問依賴的服務。如果該請求能夠成功調用,則關閉熔斷器;否則繼續保持打開狀態。、
3、Sentinel熔斷降級
Sentinel熔斷降級會在調用鏈路中某個資源出現不穩定狀態時,對這個資源的調用進行限制,讓請求快速失敗,避免影響到其它的資源而導致級聯錯誤。當資源被降級后,在接下來的降級時間窗口之內,對該資源的調用都自動熔斷(默認行為是拋出 DegradeException)。
Sentinel中有以下降級策略:
平均響應時間 (RuleConstant.DEGRADE_GRADE_RT):當1s內持續進入5個請求,對應時刻的平均響應時間(秒級)均超過閾值(count,以 ms 為單位),那么在接下的時間窗口(DegradeRule 中的 timeWindow,以 s 為單位)之內,對這個方法的調用都會自動地熔斷(拋出 DegradeException)。注意Sentinel默認統計的RT上限是4900ms,超出此閾值的都會算作4900ms,若需要變更此上限可以通過啟動配置項 -Dcsp.sentinel.statistic.max.rt=xxx 來配置。
異常比例 (RuleConstant.DEGRADE_GRADE_EXCEPTION_RATIO):當資源的每秒請求量 >= 5,並且每秒異常總數占通過量的比值超過閾值(DegradeRule 中的 count)之后,資源進入降級狀態,即在接下的時間窗口(DegradeRule 中的timeWindow,以 s 為單位)之內,對這個方法的調用都會自動地返回。異常比率的閾值范圍是 [0.0, 1.0],代表 0% - 100%。
異常數 (RuleConstant.DEGRADE_GRADE_EXCEPTION_COUNT):當資源近1分鍾的異常數目超過閾值之后會進行熔斷。注意由於統計時間窗口是分鍾級別的,若 timeWindow 小於 60s,則結束熔斷狀態后仍可能再進入熔斷狀態。
3.1、為createOrder資源添加降級規則,我們使用平均響應時間來作測試
3.2、現在如果一秒內有5個請求超時了的話,熔斷器就會打開,走blockHandler 方法,異常為DegradeException,間隔十分鍾后,在請求會通過,但如果再次出發降級規則,還是會進行同樣的處理。
項目源碼:https://github.com/caofanqi/study-security/tree/dev-sentinel2