前言
之前老顧介紹了sentinel的fallback、blockhandler;不知道小夥伴們有沒有注意到一個問題?老顧帶着大家來看看。
問題一
sentinel的默認流控返回的是:
1. `BlockedbySentinel(flow limiting)`
當然我們可以通過@SentinelResource設置定製的fallback、blockhandler方法。
但是我們也不可能每個限制的方法上面,都要去設置@SentinelResource;這樣代碼太冗餘了。
解決方案
自定義限流頁面
默認情況下,當請求被限流時會返回默認的提示頁面。可通過二種方式設置自定義的跳轉 URL。
方式一:
1. `WebServletConfig.setBlockPage(blockPage)方法`
方式二:
1. `JVM -Dcsp.sentinel.web.servlet.block.page=xxx`
在啓動應用的時候,加入啓動參數:
1. `//設置全局生效,被流控的所有頁面都會跳轉到這裏。`
2. `-Dcsp.sentinel.web.servlet.block.page=https://www.x.com`
上面的兩種方式,都能夠做到一旦出現流控異常,就會跳轉到指定頁面。
更靈活的處理方式
上面的解決方案,只是跳轉到另一個頁面,但如果我們只要得到json返回值呢;那就需要此方式了,定義UrlBlockHandler接口限流處理邏輯,並將其註冊至 WebCallbackManager。
首先自定義一個UrlBlockHandler實現類
在一個初始化方法裏面註冊此UrlBlockHandler
來看看效果
注意此解決方案:需要引入一個jar包,這個是基於servlet
1. `<dependency>`
2. `<groupId>com.alibaba.csp</groupId>`
3. `<artifactId>sentinel-web-servlet</artifactId>`
4. `</dependency>`
問題二
在spring cloud中我們會經常使用到feign,在@FeignClient中我們可以指定fallback,我們來看看案例:
以上就是常規的在使用@FeignClient註解時,加上fallbackFactory;但每次都要爲其設置fallbackFactory參數。導致項目中會多出很多冗餘代碼。那我們能不能有一個自己定製化的默認Fallback去處理這些相同的事情呢?
解決方案
在使用sentinel時,需要引入一個jar包:
1. `<dependency>`
2. `<groupId>com.alibaba.cloud</groupId>`
3. `<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>`
4. `</dependency>`
在這個jar包中,有一段源碼:
從源碼我們可以看出,在沒有配置fallback時,並沒有向SentinelInvocationHandler構造方法中傳入FallbackFactory。這樣的話我們就有了思路:
-
編寫公共FallbackFactory
-
改寫SentinelFeign使得fallbackFactory爲void.class時,我們傳入自己的公共FallbackFactory實例
讓我們一起上代碼吧!
先定義全局的fallback處理器
再定義一個全局的FallbackFactory
再後面我們需要重新實現spring-cloud-starter-alibaba-sentinel下的SentinelFeign
上面的代碼其實是仿照SentinelFeign源碼的,唯一的區別就是畫上紅色的框的。
注意:其中有個方法setAccessible,這個是因爲SentinelInvocationHandler的構造方法是私有方法。
其實還有一種方案,就是把重寫 的SentinelFeign類,放到com.alibaba.cloud.sentinel.feign包下,也就是在自己的項目中,新建com.alibaba.cloud.sentinel.feign包
最後注入我們的SentinelFeign Bean
注意:一定要在配置文件中配置feign.sentinel.enabled=true
到這裏就可以了,以後只要定義基本屬性@FeignClient,不需要再配置fallBackFactory了哦。
當然你還有特殊的需求,再自定義的可以了。
總結
通過此文章,小夥伴就可以更好的使用Sentinel了,更方便的編寫統一的兜底方法了。如果有人使用dubbo時,sentinel也有對應的適配器;有空老顧再寫一篇文章。謝謝!!!