SpringCloud Alibaba之SentinelResource註解

前言

在前一篇文章中,我們介紹瞭如何使用Sentinel的Api進行限流降級,但我們發現實現起來比較麻煩,而且重複代碼非常多;今天老顧就介紹一下@SentinelResource註解,如何利用此註解簡化代碼。

自定義資源

用註解方式定義資源,其實非常簡單,在需要通過Sentinel來控制流量的地方使用@SentinelResource註解,比如下面以控制請求入口的某個方法爲例:圖片

到這裏一個需要被保護的方法就定義完成了,非常簡單吧;下面我們分別說說,定義了資源點之後,我們如何實現不同的保護策略,包括:限流、降級等。

在定義了資源點之後,我們就可以通過Dashboard來設置限流和降級策略來對資源點進行保護了。同時,也可以通過@SentinelResource來指定出現限流和降級時候的異常處理策略。下面,就來一起分別看看限流和降級都是如何實現的。

實現限流控制

啓動應用,啓動Sentinel-Dashboard。發一個請求到/test-sentinel-resource接口上,使得Sentinel-Dashboard上可以在簇點鏈路上看到定義的資源:圖片

對資源設置流控規則圖片

快速請求http://localhost/test-sentinel-resource?a=1,超過流控閥值,發現服務器報了流量異常

圖片
表明了流控起到了效果。

實現限流的異常處理

默認情況下,Sentinel對控制資源的限流處理是直接拋出異常,也就是上面貼出的日誌內容。在沒有合理的業務承接或者前端對接情況下可以這樣,但是正常情況爲了更好的用戶業務,都會實現一些被限流之後的特殊處理,我們不希望展示一個生硬的報錯。那麼只需要基於上面的例子做一些加工,比如:圖片

上面的代碼,主要做了兩件事:

  • 通過@SentinelResource註解的blockHandler屬性制定具體的處理函數
  • 實現處理函數,該函數的傳參必須與資源點的傳參一樣,並且最後加上BlockException異常參數;同時,返回類型也必須一樣。

完成上面的改動之後,再嘗試訪問接口(注意限流規則需要配置好),此時前端就不會返回異常信息了,後端會打印blockHandler中定義的日誌輸出。而在實際應用的時候,只要根據業務需要對限流請求做緩存或者前端提示等都可以基於此方法來實現。

圖片

實現熔斷降級

@SentinelResource註解除了可以用來做限流控制之外,還能實現與Hystrix類似的熔斷降級策略。下面就來具體看看如何使用吧。

上面的案例代碼,如果不傳參數a,就會報異常;正好可以測試降級

我們來配置一下降級策略圖片

快速刷新請求http://localhost/test-sentinel-resource,服務器報了降級異常圖片

不過我們在前端,發現返回是限流了圖片

這個代表了降級策略,也會進入定義的blockHandler方法。但如果我們要區分出降級的異常,降級的處理方式需要另外處理,可以利用fallback屬性

熔斷的降級處理

在Sentinel中定義熔斷的降級處理方法非常簡單,與Hystrix非常相似。只需要使用@SentinelResource註解的fallback屬性來指定具體的方法名即可。這裏也需要注意傳參與返回必須一致。比如:

圖片

請求接口不傳參數a,就會返回降級圖片

更多註解屬性說明

  • value資源名稱,必需項(不能爲空)
  • entryTypeentry 類型,可選項(默認爲 EntryType.OUT)
  • blockHandler / blockHandlerClass: blockHandler對應處理 BlockException 的函數名稱,可選項。blockHandler 函數訪問範圍需要是 public,返回類型需要與原方法相匹配,參數類型需要和原方法相匹配並且最後加一個額外的參數,類型爲 BlockException。blockHandler 函數默認需要和原方法在同一個類中。若希望使用其他類的函數,則可以指定blockHandlerClass 爲對應的類的 Class 對象,注意對應的函數必需爲 static 函數,否則無法解析。
  • fallbackfallback 函數名稱,可選項,用於在拋出異常的時候提供 fallback 處理邏輯。fallback 函數可以針對所有類型的異常(除了exceptionsToIgnore裏面排除掉的異常類型)進行處理。fallback 函數簽名和位置要求:
    • 返回值類型必須與原函數返回值類型一致;
    • 方法參數列表需要和原函數一致,或者可以額外多一個 Throwable 類型的參數用於接收對應的異常。
    • fallback 函數默認需要和原方法在同一個類中。若希望使用其他類的函數,則可以指定fallbackClass 爲對應的類的 Class 對象,注意對應的函數必需爲 static 函數,否則無法解析。
  • defaultFallback(since 1.6.0):默認的 fallback 函數名稱,可選項,通常用於通用的 fallback 邏輯(即可以用於很多服務或方法)。默認 fallback 函數可以針對所有類型的異常(除了exceptionsToIgnore裏面排除掉的異常類型)進行處理。若同時配置了 fallback 和 defaultFallback,則只有 fallback 會生效。defaultFallback 函數簽名要求
    • 返回值類型必須與原函數返回值類型一致;
    • 方法參數列表需要爲空,或者可以額外多一個 Throwable 類型的參數用於接收對應的異常。
    • defaultFallback 函數默認需要和原方法在同一個類中。若希望使用其他類的函數,則可以指定 fallbackClass 爲對應的類的 Class 對象,注意對應的函數必需爲 static 函數,否則無法解析。
  • exceptionsToIgnore(since 1.6.0):用於指定哪些異常被排除掉,不會計入異常統計中,也不會進入 fallback 邏輯中,而是會原樣拋出。

總結

blockHandler 和 fallback 都進行了配置,則被限流降級而拋出 BlockException 時只會進入 blockHandler 處理邏輯。若未配置 blockHandler、fallback 和 defaultFallback,則被限流降級時會將 BlockException 直接拋出。

從 1.4.0 版本開始,註解方式定義資源支持自動統計業務異常,無需手動調用 Tracer.trace(ex) 來記錄業務異常。Sentinel 1.4.0 以前的版本需要自行調用 Tracer.trace(ex) 來記錄業務異常。

老顧

如果喜歡本文,可以關注我們的官方賬號,第一時間獲取資訊。
你的關注是對我們更新最大的動力哦~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章