SpringCloud Alibaba Sentinel實作熔斷與限流

官網:
https://github.com/alibaba/sentinel中文網:
https://github.com/alibaba/Sentinel/wiki/%E4%BB%8B%E7%BB%8DSentinel 是什麼?
随着微服務的流行,服務和服務之間的穩定性變得越來越重要。Sentinel 以流量為切入點,從流量控制、熔斷降級、系統負載保護等多個次元保護服務的穩定性。
Sentinel 具有以下特征:
- 豐富的應用場景:Sentinel 承接了阿裡巴巴近 10 年的雙十一大促流量的核心場景,例如秒殺(即突發流量控制在系統容量可以承受的範圍)、消息削峰填谷、叢集流量控制、實時熔斷下遊不可用應用等。
- 完備的實時監控:Sentinel 同時提供實時的監控功能。您可以在控制台中看到接入應用的單台機器秒級資料,甚至 500 台以下規模的叢集的彙總運作情況。
- 廣泛的開源生态:Sentinel 提供開箱即用的與其它開源架構/庫的整合子產品,例如與 Spring Cloud、Dubbo、gRPC 的整合。您隻需要引入相應的依賴并進行簡單的配置即可快速地接入 Sentinel。
-
完善的 SPI 擴充點:Sentinel 提供簡單易用、完善的 SPI 擴充接口。您可以通過實作擴充接口來快速地定制邏輯。例如定制規則管理、适配動态資料源等。
Sentinel 的主要特性:
Sentinel 分為兩個部分:
- 核心庫(Java 用戶端)不依賴任何架構/庫,能夠運作于所有 Java 運作時環境,同時對 Dubbo / Spring Cloud 等架構也有較好的支援。
- 控制台(Dashboard)基于 Spring Boot 開發,打包後可以直接運作,不需要額外的 Tomcat 等應用容器。
Docker 安裝 Sentinel
#拉取sentinel鏡像
docker pull bladex/sentinel-dashboard
#運作sentinel(docker裡的sentinel是8858端口)
docker run --name sentinel -d -p 8858:8858 bladex/sentinel-dashboard
#把nacos和mysql也啟動起來
通路:
http://120.92.164.250:8858/#/login賬号和密碼都是sentinel
示範
- 建立子產品 cloudalibaba-sentinel-service8401
- pom
<dependencies>
<!-- SpringCloud ailibaba nacos-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- SpringCloud ailibaba sentinel-datasource-nacos 持久化需要用到-->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
<!-- SpringCloud ailibaba sentinel-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--監控-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!--熱部署-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
- yml
server:
port: 8401
spring:
application:
name: cloudalibaba-sentinal-service
cloud:
nacos:
discovery:
#Nacos服務注冊中心位址(改成自己的伺服器ip位址,本地用localhost)
server-addr: 120.92.164.250:8848
sentinel:
transport:
#配置Sentin dashboard位址(改成自己的伺服器ip位址,本地用localhost)
dashboard: 120.92.164.250:8858
# 預設8719端口,假如被占用了會自動從8719端口+1進行掃描,直到找到未被占用的 端口
port: 8719
management:
endpoints:
web:
exposure:
include: '*'
- 啟動類
@EnableDiscoveryClient
@SpringBootApplication
public class MainApp8401 {
public static void main(String[] args) {
SpringApplication.run(MainApp8401.class, args);
}
}
-
測試,啟動8401,然後重新整理sentinel背景頁面(因為sentinel采用懶加載政策,是以需要調用服務後才在背景顯示)
在浏覽器分别輸入,然後重新整理sentinel背景頁面:
http://localhost:8401/testA http://localhost:8401/testB
規則的種類
Sentinel 的所有規則都可以在記憶體态中動态地查詢及修改,修改之後立即生效。同時 Sentinel 也提供相關 API,供您來定制自己的規則政策。
Sentinel 支援以下幾種規則:流量控制規則、熔斷降級規則、系統保護規則、來源通路控制規則 和 熱點參數規則。
流量控制規則 (FlowRule)
同一個資源可以同時有多個限流規則,檢查規則時會依次檢查。
每秒請求數超過1個就會限流。
閥值類型
QPS與線程數的差別
: QPS(每秒請求的數量):當調用該api的QPS達到閥值的時候,進行限流
: 線程數:當調用該API的線程數達到閥值的時候,進行限流
QPS是直接擋在外面,而線程數是有多少個線程在處理,放進來後,有線程是空閑狀态就對請求進行處理,都沒空閑,就限流
QPS流量控制
直接 : 快速失敗
關聯:當關聯的資源達到閥值時,就限流自己,當與A關聯的資源B達到閥值後,就限流A自己
鍊路:Sentinel 允許隻根據某個入口的統計資訊對資源限流。
- 當 QPS 超過某個門檻值的時候,則采取措施進行流量控制。流量控制的效果包括以下幾種:直接拒絕、Warm Up、勻速排隊。對應 FlowRule 中的 controlBehavior 字段。
- 注意:若使用除了直接拒絕之外的流量控制效果,則調用關系限流政策(strategy)會被忽略。
直接拒絕
- 直接拒絕(RuleConstant.CONTROL_BEHAVIOR_DEFAULT)方式是預設的流量控制方式,當QPS超過任意規則的門檻值後,新的請求就會被立即拒絕,拒絕方式為抛出FlowException。這種方式适用于對系統處理能力确切已知的情況下,比如通過壓測确定了系統的準确水位時。
Warm Up
- Warm Up(RuleConstant.CONTROL_BEHAVIOR_WARM_UP)方式,即預熱/冷啟動方式。當系統長期處于低水位的情況下,當流量突然增加時,直接把系統拉升到高水位可能瞬間把系統壓垮。通過"冷啟動",讓通過的流量緩慢增加,在一定時間内逐漸增加到門檻值上限,給冷系統一個預熱的時間,避免冷系統被壓垮。
勻速排隊
- 勻速排隊(RuleConstant.CONTROL_BEHAVIOR_RATE_LIMITER)方式會嚴格控制請求通過的間隔時間,也即是讓請求以均勻的速度通過,對應的是漏桶算法
降級規則
- RT : (平均響應時間,秒級) 平均響應時間 超出閥值 且 在時間視窗内通過的請求 >=5 ,兩哥條件同時滿足後觸發降級視窗期後關閉斷路器
- 異常比例 : (秒級) QPS >=5 且異常比例(秒級統計)超過閥值時,觸發降級;時間視窗結束後,關閉降級
- 異常數 :(分鐘統計) 超過閥值時,觸發降級;時間視窗結束後,關閉降級
系統規則
系統保護規則是從應用級别的入口流量進行控制,從單台機器的load 、cpu使用率、平均RT、入口QPS和并發線程數幾個緯度監控應用名額,讓系統盡可能的跑在最大吞吐量的同時保證系統整體的穩定性
系統保護規則則是應用整體緯度的,而不是資源緯度的,并且僅對入口流量生效。入口流量指的是進入應用的流量,比如Web 服務或Dubbo 服務端接收的請求,都屬于入口流量。
系統則支援以下的模式
- Load 自适應 : 系統的load1作為啟發名額,精細自适應系統保護。當系統load1超過啟發值,且系統目前的并發數超過估算的系統容量時才會觸發系統保護
- CPU usage :當系統CPU使用率超過閥值即觸發系統保護
- 平均RT:當單台機器上所有入口流量的平均RT達到閥值時觸發,機關是毫秒
- 并發線程數 : 當單台機器上所有入口流量的并發線程數達到閥值時觸發系統保護
- 入口 QPS : 當單台機器上所有入口流量的QPS 達到閥值即觸發系統保護
針對系統:
熱點key限流
何為熱點:熱點即經常通路的資料。很多時候我們希望統計某個熱點資料中通路頻率最高的Top Key 資料,并且對其通路進行限制:
比如:
- 商品ID作為參數,針對一段時間内最常購買的商品ID進行限制
- 商品ID作為參數,針對一段時間内頻繁通路的使用者ID進行限制
方法:
@GetMapping("/testB")
@SentinelResource(value = "testHotKey",blockHandler = "deal_testHotKey")
public String testB() {
return "----testB";
}
//兜底方法
public String deal_testHotKey(String p1, String p2, BlockException exception) {
// sentinel的預設提示都是: Blocked by Sentinel (flow limiting)
return "----deal_testHotKey, o(╥﹏╥)o";
}
設定限流 1秒
服務熔斷降級
- 除了流量控制以外,對調用鍊路中不穩定的資源進行熔斷降級也是保障高可用的重要措施之一。一個服務常常會調用别的子產品,可能是另外的一個遠端服務、資料庫,或者第三方 API 等。例如,支付的時候,可能需要遠端調用銀聯提供的 API;查詢某個商品的價格,可能需要進行資料庫查詢。然而,這個被依賴服務的穩定性是不能保證的。如果依賴的服務出現了不穩定的情況,請求的響應時間變長,那麼調用服務的方法的響應時間也會變長,線程會産生堆積,最終可能耗盡業務自身的線程池,服務本身也變得不可用。
@SentineResource
- 按資源名稱限流
@RestController
public class RateLimitController {
@GetMapping("/byResource")
@SentinelResource(value = "byResource",blockHandler = "handleException")
public CommonResult byResource() {
return new CommonResult(200,"按照資源名稱限流測試",new Payment(2020L,"serial001"));
}
//兜底方法
public CommonResult handleException(BlockException exception) {
return new CommonResult(444,exception.getClass().getCanonicalName() + "\t 服務不可用");
}
}
- 按URL位址限流
@GetMapping("/rateLimit/byUrl")
@SentinelResource(value = "byUrl",blockHandler = "handleException")
public CommonResult byUrl() {
return new CommonResult(200,"按照byUrl限流測試",new Payment(2020L,"serial002"));
}
- 自定義限流
添加自定義類
public class CustomerBlockHandler {
public static CommonResult handlerException(BlockException exception) {
return new CommonResult(444,"按照客戶自定義限流測試,Glogal handlerException ---- 1");
}
public static CommonResult handlerException2(BlockException exception) {
return new CommonResult(444,"按照客戶自定義限流測試,Glogal handlerException ---- 2");
}
}
新增接口
//CustomerBlockHandler
@GetMapping("/rateLimit/customerBlockHandler")
@SentinelResource(value = "customerBlockHandler",
blockHandlerClass = CustomerBlockHandler.class, blockHandler = "handlerException2")
public CommonResult customerBlockHandler() {
return new CommonResult(200,"按照客戶自定義限流測試",new Payment(2020L,"serial003"));
}
- 更多注解的方式
SpringCloud Alibaba Sentinel實作熔斷與限流
規則持久化
yml 添加對 datasource
datasource:
ds1:
nacos:
server-addr: 10.211.55.26:8848 #nacos
dataId: ${spring.application.name}
groupId: DEFAULT_GROUP
data-type: json
rule-type: flow
feign:
sentinel:
enabled: true #激活Sentinel 對Feign的支援
實作sentinel配置的持久化。
- 個人部落格: http://blog.yanxiaolong.cn/