一、什么是Sentinel?
它是分布式系統的流量防衛兵,與Hystrix的作用一樣,它能保證在某一個服務出現問題的情況下,不會導致整體服務的聯級故障,以提高分布式系統的彈性。它是hystrix的替代品。比起hystrix來說,Sentinel可以通過web界面來進行更加細粒度的配置流控、速率控制、服務熔斷、服務降級。Sentinel組件由Java客戶端和Dashboard構成。sentinel生態圈和主要功能特性如下
二、Sentinel使用
1、安裝和啟動: 去https://github.com/alibaba/Sentinel/releases下載sentinel-dashboard-1.8.2.jar包,運行前需要安裝Java8環境,切換到jar包目錄cmd執行 java -jar sentinel-dashboard-1.8.2.jar即可啟動。訪問http://localhost:8080即可顯示web控制台登錄界面(默認賬號密碼sentinel)。
2、創建服務模塊
a.引入jar包
< ! --Springcloud ailibaba sentinel --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba,sentinel</artifactId> </dependency>
b.修改yml配置文件,配置Sentinel dashboard地址
server: port: 8401 spring: application: name: cloudalibaba-sentinel-service cloud: nacos: discovery: server-addr: localhost:8848 sentinel: transport: #配置sentinel dashboard地址 dashboard: localhost:8080 #默認8719端口,假如被占角會自動從8719開始依次+1掃描,直至找到未被占用的端口 port: 8719 management: endpoints: web: exposure: include: "*"
c.編寫微服務接口Controller,到此sentinel監控搭建完,訪問sentinel控制台,即可顯示被監控的8848微服務(sentinel懶加載-需要先調用一次8848服務接口才能顯示)。界面如下
三、Sentinel流控規則
Sentinel支持流量控制,它監控應用流量的QPS或並發線程數等指標,當達到指定閾值時對流量進行控制,避免系統被瞬時的流量高峰沖垮,保障應用高可用性。
1.閾值類型:
QPS:每秒請求數,當前調用該api的QPS到達閾值的時候進行限流。
線程數:當調用該api的線程數到達閾值的時候,進行限流。
2.流控模式:
直接:當api大達到限流條件時,直接限流
關聯:當關聯的資源到達閾值,就限流自己
鏈路:只記錄指定路上的流量,指定資源從入口資源進來的流量,如果達到閾值,就進行限流,api級別的限流
3.流控效果:
快速失敗:直接返回失敗、拋異常
預熱(WarmUP):當系統長期處於低水位的情況下,當流量突然增加時,直接把系統拉升到高水位可能瞬間把系統壓垮。通過"冷啟動",讓通過的流量緩慢增加,在一定時間內逐漸增加到閾值上限,給冷系統一個預熱的時間,避免冷系統被壓垮。
排隊等待:會嚴格控制請求通過的間隔時間,也即是讓請求以均勻的速度通過,對應的是漏桶算法。
以下配置界面:
四、Sentnel熔斷降級
Sentinel熔斷降級會在調用鏈路中某個資源出現不穩定狀態時(例如調用超時或異常比例升高),對這個資源的調用進行限制,讓請求快速失敗,避免影響到其它的資源而導致級聯錯誤。當資源被降級后,在接下來的降級時間窗口之內,對該資源的調用都自動熔斷(默認行為是拋出 DegradeException)。Sentinel降級策略包含平均響應時間RT、異常比例、異常數。
平均響應時間(DEGRADE_GRADE_RT):當1s內持續進入5個請求,對應時刻的平均響應時間(秒級)均超過閾值( count,以ms為單位),那么在接下的時間窗口(以s為單位)之內,對這個方法的調用都會自動地熔斷(拋出DegradeException )。注意Sentinel默認統計的RT上限是4900 ms,超出此閾值的都會算作4900ms,若需要變更此上限可以通過啟動配置項-Dcsp.sentinel.statistic.max.rt=xx來配置。
異常比例( DEGRADE_GRADE_EXCEPTION_RATIo ):當資源的每秒請求量>=5,並且每秒異常總數占通過量的比值超過閾值( DegradeRule 中的 count)之后,資源進入降級狀態,即在接下的時間窗口( DegradeRule中的 timewindow,以s為單位)之內,對這個方法的調用都會自動地返回。異常比率的閾值范圍是[0.0,1.0],代表0% - 100%。
異常數( DEGRADE_GRADE_EXCEPTION_coUNT ):當資源近1分鍾的異常數目超過閾值之后會進行熔斷。注意由於統計時間窗口是分鍾級別的,若 timevindow小於60s,則結束熔斷狀態后仍可能再進入熔斷狀態。
以下是配置界面:
五、熱點參數限流
熱點即經常訪問的數據。很多時候我們希望統計某個熱點數據中訪問頻次最高的TopK數據,並對其訪問進行限制。比如:·用戶ID為參數,針對一段時間內頻繁訪問的用戶ID進行限制。
熱點參數限流會統計傳入參數中的熱點參數,並根據配置的限流閾值與模式,對包含熱點參數的資源調用進行限流。熱點參數限流可以看做是一種特殊的流量控制,僅對包含熱點參數的資源調用生效。
1、啟用熱點參數限流功能:
a.在服務模塊中引入如下依賴:
<dependency> <groupId>com.alibaba.csp</groupId> <artifactId>sentinel-parameter-flow-control</artifactId> </dependency>
b.為對應的資源接口配置熱點參數限流規則,在調用的時候傳入相應的參數,即可使熱點參數限流生效。舉例如下:
@GetMapping("/getHotKey") @SentinelResource(value = "testHotKey" ,blockHandler = "deal_testHotKey") //blockHandler指定兜底方法,value指定資源名 public string getHotKey(@RequestParam(value = "p1") string p1,@RequestParam(value = "p2") string p2) { return "------testHotKey" ; } public string deal_testHotKey (string p1,string p2,BlockException exception) { return "------deal_testHotKey,o(T-T)o" ; }
結合以上代碼和配置規則,表示:當請求http://localhost:8401/getHotKey?p1=xxxx&p2=xxx資源接口的時候,如果該方法第一個參數每秒的QPS超過1次,就馬上降級調用兜底方法deal_testHotKey 。(如果不配置blockHandler,會使用系統默認的兜底方法返回Blocked by Sentinel (flow limiting)或將異常顯示到前台,不推薦這樣做)
2、限流規則中參數例外項:在1中,當熱點參數是某個特殊值的時候,我們要求不降級限流怎么辦?配置規則里提供了參數例外項來解決這個問題,具體如下,通過添加規則組來對每個特殊值添加不同的閾值。
六、系統規則
系統保護規則是從應用級別的入口流量進行控制,從單台機器的load、CPU使用率、平均RT、入口QPS和並發線程數等幾個維度監控應用指標,讓系統盡可能跑在最大吞吐量的同時保證系統整體的穩定性。系統保護規則是應用整體維度的,而不是資源維度的,並且僅對入口流量生效。入口流量指的是進入應用的流量( EntryType.IN ),比如Web服務或Dubbo服務端接收的請求,都屬於入口流量。系統規則支持以下模式:
1、Load自適應(僅對 Linux/Unix-like機器生效):系統的load1作為啟發指標,進行自適應系統保護。當系統load1超過設定的啟發值,且系統當前的並發線程數超過估算的系統容量時才會觸發系統保護(BBR階段)。系統容量由系統的 maxQps * minRt估算得出。設定參考值一般是CPu cores * 2.5。
2、CPU使用率(1.5.0+版本)︰當系統CPU使用率超過閾值即觸發系統保護(取值范圍0.0-1.0) ,比較靈敏。
3、平均RT:當單台機器上所有入口流量的平均RT達到閾值即觸發系統保護,單位是毫秒。
4、並發線程數:當單台機器上所有入口流量的並發線程數達到閾值即觸發系統保護。
5、入口QPS:當單台機器上所有入口流量的QPS達到閾值即觸發系統保護。
規則配置如圖:
七、自定義限流處理邏輯
在編碼過程中,我們通常需要將業務邏輯與異常處理代碼分離,實現解耦。在上面的例子中業務邏輯代碼和兜底方法在同一個類中,顯然不合適,sentinel提供的注解@SentinelResource注解提供了一個blockHandelClass特性能夠方便我們進行代碼分離。實現過程如下:
1、創建一個專門的兜底方法類CustomerBlockHandler
public class CustomerBlockHandler
{ public static CommonResult handleException(BlockException exception)
{ return new CommonResult( code: 200,message:"自定義的限流處理信息");
} public static commonResult handleException2(BlockException exception)
{ return new CommonResult( code: 200,message:"自定義的限流處理信息2");
}
}
2、在資源接口方法上增加注解@SentinelResource(value = "customerBlockHandler",blockHandlerclass= CustomerBlockHandler.class,blockHandler = "handleException”)
@GetMapping("/rateLimit/customerBlockHandler")
@SentinelResource(value = "customerBlockHandler", blockHandlerclass = customerBlockHandler.class, //指定兜底類
blockHandler= "handlerException") //指定兜底類中的兜底方法 public commonResult customerBlockHandler()
{ return new CommonResult( code: 200,message:"按客戶自定義" , new Payment(id: 2020L,serial:."serial003"));
}
八、資源接口邏輯異常處理
前面的@SentinelResource的blockHandler指定方法只用於不滿足sentinel控制台配置規則時的兜底,本身並不處理資源接口的異常,該注解提供了另外一個特性fallback,用於指定資源接口內部異常時要執行的兜底方法。例如
@sentinelResource(value = "fallback" ,fallback = "handlerFallback") //fallback只負責業務異常 public commonResult<Payment> fallback(@Pathvariable Long id) { CommonResult<Payment> result =restTemplate.getForobject(url:SERVICE_URL + "/paymentsQL/"+id ,commonResult.class,id); if (id == 4) { throw new IllegalArgumentException ("IllegalArgumentException,非法參數異常...."); } return result; }
//業務邏輯異常時執行 public CommonResult handlerFallback(@Pathvariable Long id, Throwable e) { Payment payment = new Payment(id, serial: "nu1l"); return new CommonResult<>( code: 44, message:"兜底異常FandlerFallback,exception內容"+t .getMessage(), payment); }
異常忽略:sentinel提供了一個特性exceptionsToIgnore = {illegalArgumentException.class}用於忽略資源接口異常,表示如果觸發該類型的異常,就不再用fallback兜底,不會觸發降級,讓其自行處理后續。
九、Sentinel規則持久化
前面的規則配置在微服務重啟后會丟失,也就是說他們的配置是臨時的,我們需要對這些業務規則進行持久化。我們將限流規則持久化進nacos,只要刷新微服務,就可以看到之前配置的規則。實現方式如下:
1、在微服務中引入jar包
<! --Springcloud ailibaba sentinel-datasource-nacos做持久化用到--> <dependency> <groupid>com.alibaba.csp</ groupId> <artifactId>sentinel-datasource-nacos</artifactId> </dependency>
2、yml配置文件中增加nacos數據源配置
spring: cloud: sentinel: transport: port:8719 datasource: ds1: nacos: server-addr: localhost:8848 datald: ${spring.application.name} groupld: DEFAULT_GROUP data-type: json rule-type: flow
3、登錄nacos控制台配置流控規則:配置列表下新增配置,選json格式,填入如下json代碼
[ { "resource":"/rateLimit/byUrl", "limitApp": "default", "grade": 1, "count": 1, "clusterMode": false } ]
json中內容表示配規則,其中,resource表示資源名,limitApp表示來源應用,grade表示閾值類型-0線程數1QPS,count表示單機閾值,strategy表示流控模式-0直接1關聯2鏈路,controBehavior表示流控效果-0快速失敗1Warmup2排隊等待,clusterMode表示是否集群。