1. 程式人生 > >Spring Cloud Alibaba系列(五)sentinel實現服務限流降級

Spring Cloud Alibaba系列(五)sentinel實現服務限流降級

## 一、sentinel是什麼 sentinel的官方名稱叫分散式系統的流量防衛兵。Sentinel 以流量為切入點,從流量控制、熔斷降級、系統負載保護等多個維度保護服務的穩定性。在Spring Cloud專案中最開始我們使用的是Hystrix,目前已停止更新了。現在Spring Cloud官方推薦的是rensilience4j。當然還有我們今天學習的sentinel。 Sentinel 具有以下特徵: - **豐富的應用場景**:Sentinel 承接了阿里巴巴近 10 年的雙十一大促流量的核心場景,例如秒殺(即突發流量控制在系統容量可以承受的範圍)、訊息削峰填谷、叢集流量控制、實時熔斷下游不可用應用等。 - **完備的實時監控**:Sentinel 同時提供實時的監控功能。您可以在控制檯中看到接入應用的單臺機器秒級資料,甚至 500 臺以下規模的叢集的彙總運 行情況。 - **廣泛的開源生態**:Sentinel 提供開箱即用的與其它開源框架/庫的整合模組,例如與 Spring Cloud、Dubbo、gRPC 的整合。您只需要引入相應的依賴並進行簡單的配置即可快速地接入 Sentinel。 - **完善的 SPI 擴充套件點**:Sentinel 提供簡單易用、完善的 SPI 擴充套件介面。您可以通過實現擴充套件介面來快速地定製邏輯。例如定製規則管理、適配動態資料來源等。 ## 二、sentinel實現限流 ### 2.1 安裝sentinel控制檯 - 下載地址:https://github.com/alibaba/Sentinel/releases 這裡我們直接下載jar包即可,下載後通過命令列啟動: ```java java -jar sentinel-dashboard-1.7.2.jar ``` - 預設埠:8080 - 預設使用者名稱:sentinel - 預設密碼:sentinel 啟動成功後,我們瀏覽器訪問http://localhost:8080,出現如下介面。 ![](https://i.loli.net/2020/05/08/JgpXTlHfacS7y2Q.png) ### 2.2 微服務繼承sentinel - 引入sentinel依賴 ```java ``` - 新增sentinel的相關配置 ```java server: port: 7003 spring: application: name: sentinel-provider cloud: nacos: discovery: server-addr: 127.0.0.1:8848 sentinel: transport: dashboard: 127.0.0.1:8080 ``` - 提供個介面用來測試限流 ```java @SpringBootApplication public class SentinelApplication { public static void main(String[] args) { SpringApplication.run(SentinelApplication.class, args); } } @RestController class TestController{ @GetMapping("/test") public String test(){ return "hello! sentinel!"; } } ``` 我們請求幾次這個介面後,開啟sentinel控制檯,就可以實時監控到這個sentinel-provider服務介面呼叫情況了。 ![](https://i.loli.net/2020/05/08/Mq3yC6lPOboNShx.png) ### 2.3 配置限流規則 ![](https://i.loli.net/2020/05/08/2tjGkQCJoiRA1ZD.png) 我們這裡做一個簡單的規則配置: - 閥值型別:QPS - 單機閥值:2 意思就是:該介面每秒最多允許進入兩個請求。 點選新增後,在流控規則裡發現了一條規則: ![](https://i.loli.net/2020/05/08/UvY6dJAqFntMV1i.png) 現在,我們繼續請求3次這個介面。第三次響應的內容如下: ```java Blocked by Sentinel (flow limiting) ``` 我們開啟控制檯發現拒絕了一條請求。 ![](https://i.loli.net/2020/05/08/f8YOUyJ7oTQsp6W.png) ## 三、Sentinel規則介紹 不管是限流還是降級,它都是按照某種規則進行的,下面具體介紹一下sentinel支援的幾種規則。 ### 3.1 流控規則 流量控制,其原理是監控應用流量的QPS(每秒查詢率) 或併發執行緒數等指標,當達到指定的閾值時 對流量進行控制,以避免被瞬時的流量高峰沖垮,從而保障應用的高可用性。 ![](https://i.loli.net/2020/05/11/xBKjycEeW8tiVgI.png) **資源名**:唯一名稱,預設是請求路徑,可自定義 **針對來源**:指定對哪個微服務進行限流,預設指default,意思是不區分來源,全部限制 **閾值型別**/**單機閾值**: - QPS(每秒請求數量): 當呼叫該介面的QPS達到閾值的時候,進行限流 - 執行緒數:當呼叫該介面的執行緒數達到閾值的時候,進行限流 ### 3.2 降級規則 降級規則就是當滿足什麼條件時,對服務降級——即將請求轉發到另外介面上,這個介面與業務無關,只是為了保證系統的完整性。 ![](https://i.loli.net/2020/05/11/dDjghsaJNv1qE6R.png) - RT(平均響應時間) :當資源的平均響應時間超過閾值(以 ms 為單位)之後,資源進入準降級狀態。如果接下來 1s 內持續進入 5 個請求,它們的 RT都持續超過這個閾值,那麼在接下的時間視窗(以 s 為單位)之內,就會對這個方法進行服務降級。 > 注意 Sentinel 預設統計的 RT 上限是 4900 ms,超出此閾值的都會算作 4900 ms,若需要變更此上限可以通過啟動配置項 -Dcsp.sentinel.statistic.max.rt=xxx 來配置。 - 異常比例:當資源的每秒異常總數佔通過量的比值超過閾值之後,資源進入降級狀態,即在接下的時間視窗(以 s 為單位)之內,對這個方法的呼叫都會自動地返回。異常比率的閾值範圍是 [0.0,1.0]。 - 異常數 :當資源近 1 分鐘的異常數目超過閾值之後會進行服務降級。注意由於統計時間視窗是分鐘級別的,若時間視窗小於 60s,則結束熔斷狀態後仍可能再進入熔斷狀態。 ### 3.3 熱點規則 熱點規則允許將規則具體到引數上。 我們用個例子來看看效果。 - 編寫介面 ```java @GetMapping("/myTest") @SentinelResource("test3") public String test123(String name,String age){ return name + "----"+ age; } ``` - 新增規則 ![](https://i.loli.net/2020/05/11/vX6Zre4uqy7fGCM.png) - 執行效果 ![](https://i.loli.net/2020/05/11/1hk4uxbSBcmeXi7.png) ![](https://i.loli.net/2020/05/11/r9hZ31nqWU4OYfM.png) 結果顯示,第一個引數被限流了,而第二個引數正常。 ### 3.4 系統規則 系統保護規則是從應用級別的入口流量進行控制,從單臺機器的總體 Load、RT、入口 QPS 、CPU使用率和執行緒數五個維度監控應用資料,讓系統儘可能跑在最大吞吐量的同時保證系統整體的穩定性。 系統保護規則是應用整體維度的,而不是資源維度的,並且僅對入口流量 (進入應用的流量) 生效。 - Load(僅對 Linux/Unix-like 機器生效):當系統 load1 超過閾值,且系統當前的併發執行緒數超過系統容量時才會觸發系統保護。系統容量由系統的 maxQps * minRt 計算得出。設定參考值一般是 CPU cores * 2.5。 - RT:當單臺機器上所有入口流量的平均 RT 達到閾值即觸發系統保護,單位是毫秒。 - 執行緒數:當單臺機器上所有入口流量的併發執行緒數達到閾值即觸發系統保護。 - 入口 QPS:當單臺機器上所有入口流量的 QPS 達到閾值即觸發系統保護。 - CPU使用率:當單臺機器上所有入口流量的 CPU使用率達到閾值即觸發系統保護。 ### 3.5 授權規則 很多時候,我們需要根據呼叫來源來判斷該次請求是否允許放行,這時候可以使用 Sentinel 的來源問控制的功能。來源訪問控制根據資源的請求來源(origin)限制資源是否通過: - 若配置白名單,則只有請求來源位於白名單內時才可通過; - 若配置黑名單,則請求來源位於黑名單時不通過,其餘的請求通過。 ![](https://i.loli.net/2020/05/12/t2wZLjg3aYS5Wxi.png) 流控應用:sentinel提供了RequestOriginParser來處理介面來源。 我們執行abc來源的請求訪問/test介面。 ```java @Component class requestOrigin implements RequestOriginParser{ @Override public String parseOrigin(HttpServletRequest httpServletRequest) { String server = httpServletRequest.getParameter("server"); return server; } } ``` 我們請求http://localhost:7003/test?server=abc 和 http://localhost:7003/test?server=ab來分別看看效果。 ## @SentinelResource的使用 @SentinelResource 用於定義資源,並提供可選的異常處理和 fallback 配置項。 主要引數有以下幾個 | 屬性 | 作用 | | ------------------ | ------------------------------------------------------------ | | value | 資源名稱 | | entryType | entry型別,標記流量的方向,取值IN/OUT,預設是OUT | | blockHandler | 處理BlockException的函式名稱,函式要求:1. 必須是 public;2.返回型別 引數與原方法一致;3. 預設需和原方法在同一個類中。若希望使用其他類的函式,可配置blockHandlerClass ,並指定blockHandlerClass裡面的方法。 | | blockHandlerClass | 存放blockHandler的類,對應的處理函式必須static修飾。 | | fallback | 1. 返回型別與原方法一致;2. 引數型別需要和原方法相匹配;3. 預設需和原方法在同一個類中。若希望使用其他類的函式,可配置fallbackClass | | fallbackClass | 存放fallback的類。對應的處理函式必須static修飾。 | | defaultFallback | 若同時配置了 fallback 和 defaultFallback,以fallback為準。 | | exceptionsToIgnore | 指定排除掉哪些異常。排除的異常不會計入異常統計,也不會進入fallback邏輯,而是原樣丟擲。 | | exceptionsToTrace | 需要trace的異常 | @sentinelResource可結合blockHandler用於限流處理,結合fallback用於降級處理。具體規則可通過sentinel控制檯配置,具體我就不演示了,在下一章內容中,我會分別演示限流和降級的應用。 ```java public class MySentinelResource { @SentinelResource(value="message",blockHandler="blockHandler",fallback="fallback") public String message(String str){ if(StringUtils.isBlank(str)){ throw new RuntimeException(); } return str; } /** * 限流處理 * @param str * @param ex * @return */ public String blockHandler(String str, BlockedException ex){ return str + "--"+ ex; } /** * 降級處理 * @param str * @return */ public String fallback(String str){ return null; } } ``` ## 程式碼示例 **gitee**:https://gitee.com/zhixie/spring-cloud-alibaba-learning/tree/master/sentinel-server **github**:https://github.com/binzh303/spring-cloud-alibaba-learning/tree/master/sentine