Springcloud-Alibaba 〖十四〗Sentinel
官網地址: Sentinel
百度雲下載地址: Sentinel-DashBoard1.7.0 提取碼:gkaq
一. Sentinel是什麼?
Sentinel: 分佈式系統的流量防衛兵
Sentinel 具有以下特徵:
-
豐富的應用場景: Sentinel 承接了阿里巴巴近 10 年的雙十一大促流量的核心場景,例如秒殺(即突發流量控制在系統容量可以承受的範圍)、消息削峯填谷、集羣流量控制、實時熔斷下游不可用應用等。
-
完備的實時監控:Sentinel 同時提供實時的監控功能。您可以在控制檯中看到接入應用的單臺機器秒級數據,甚至 500 臺以下規模的集羣的彙總運行情況。
-
廣泛的開源生態:Sentinel 提供開箱即用的與其它開源框架/庫的整合模塊,例如與 Spring Cloud、Dubbo、gRPC 的整合。您只需要引入相應的依賴並進行簡單的配置即可快速地接入 Sentinel。
完善的 SPI 擴展點:Sentinel 提供簡單易用、完善的 SPI 擴展接口。您可以通過實現擴展接口來快速地定製邏輯。例如定製規則管理、適配動態數據源等。 -
豐富的應用場景:Sentinel 承接了阿里巴巴近 10 年的雙十一大促流量的核心場景,例如秒殺(即突發流量控制在系統容量可以承受的範圍)、消息削峯填谷、集羣流量控制、實時熔斷下游不可用應用等。
完備的實時監控:Sentinel 同時提供實時的監控功能。您可以在控制檯中看到接入應用的單臺機器秒級數據,甚至 500 臺以下規模的集羣的彙總運行情況。 -
廣泛的開源生態:Sentinel 提供開箱即用的與其它開源框架/庫的整合模塊,例如與 Spring Cloud、Dubbo、gRPC 的整合。您只需要引入相應的依賴並進行簡單的配置即可快速地接入 Sentinel。
完善的 SPI 擴展點:Sentinel 提供簡單易用、完善的 SPI 擴展接口。您可以通過實現擴展接口來快速地定製邏輯。例如定製規則管理、適配動態數據源等。
二. 安裝使用
運行jar包,sentinel默認端口8080,可以指定端口,我這裏指定8085端口
java -jar sentinel-dashboard-1.7.0.jar --server.port=8085
登錄控制檯
默認密碼和用戶都是sentinel
這裏就登錄上去了
三. 新建模塊 cloudalibaba-sentinel-service8401
3.1 項目結構
3.2 pom
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>cloud2020</artifactId>
<groupId>com.aiguigu.springcloud</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>cloudalibaba-sentinel-service8401</artifactId>
<!--pom.xml依賴-->
<dependencies>
<!--springcloud alibaba nacos-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!--springcloud alibaba sentinel-datasource-nacos 後續做持久化用到-->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
<!--springcloud alibaba 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.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>
<dependency>
<groupId>com.aiguigu.springcloud</groupId>
<artifactId>cloud-api-commons</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>
3.3 application.yml
#yml配置
server:
port: 8401
spring:
application:
name: cloudalibaba-sentinel-service
cloud:
nacos:
discovery:
#Nacos服務註冊中心地址
server-addr: localhost:8848
sentinel:
transport:
#配置sentinel dashboard地址
dashboard: localhost:8085
#默認8719端口,假如被佔用會自動從8719開始依次+1掃描,直至找到未被佔用的端口
port: 8719
management:
endpoints:
web:
exposure:
include: '*'
3.4 主啓動類
package com.atguigu.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient
public class MainApp8401 {
public static void main(String[] args) {
SpringApplication.run(MainApp8401.class,args);
}
}
3.5 業務類
package com.atguigu.springcloud.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class FlowLimitController {
@GetMapping("/testA")
public String testA(){
return "--------testA";
}
@GetMapping("/testB")
public String testB(){
return "--------testB";
}
}
3.6 測試
首先測試方法,可以訪問到
這時候來到Nacos界面,發現服務已經註冊進來
最後來到sentinel界面,由於sentinel是懶加載機制,這時我們多訪問幾次服務,發現有如下界面
這樣就完成了sentinel的基本使用
四. 流控規則
4.1 流控規則介紹
-
資源名:唯一名稱,默認請求路徑
-
針對來源:Sentinel可以針對調用者進行限流,填寫微服務名,默認default(不區分來源)
-
閾值類型/單機閾值:
- QPS(每秒鐘的請求數量):當調用該api的QPS達到閾值的時候,進行限流
- 線程數:當調用該api的線程數達到閾值的時候,進行限流
-
是否集羣:(不)需要集羣
-
流控模式:
- 直接:api達到限流條件時,直接限流
- 關聯:當關聯的資源達到閾值時,就限流自己
- 鏈路:只記錄指定鏈路上的流量(指定資源從入口資源進來的流量,如果達到閾值,就進行限流)
- 流控效果:
- 快速失敗:直接失敗,拋異常
- Warm Up:根據codeFactor(冷加載因子,默認3)的值,從閾值/codeFactor,經過預熱時長,才達到設置的QPS閾值。
- 排隊等待:勻速排隊,讓請求以勻速的速度通過,閾值類型必須設置爲QPS。否則無效。
4.2 直接 快速失敗
我們來新增一個規則,1s只能有1次訪問
表示1秒鐘內查詢1次就是OK,若超過次數1,就直接快速失敗,報默認錯誤
失敗結果
4.3 關聯 快速失敗
適合做應用的讓步
- 當關聯的資源達到閾值時,就限流自己
- 當與A關聯的資源B達到閥值後,就限流A自己
設置關聯資源/testB
postman測試
這裏我們起20個線程每隔0.3s訪問一次
可以看到/testB訪問滿了後,A服務直接掛了
4.4 流控效果——Warm Up
Warm Up方式,即預熱/冷啓動方式。當系統長期處於低水位的情況下,當流量突然增加時,直接把系統拉昇到高水位可能瞬間把系統壓垮。通過“冷啓動”,讓通過的流量緩慢增加,在一定時間內逐漸增加到閾值上限,給冷系統一個預熱的時間,避免冷系統被壓垮。
默認coldFactor爲3,即請求QPS從threshold / 3開始,經預熱時長逐漸升至設定的QPS閾值。
秒殺系統在開啓的瞬間,會有很多流量進來,很有可能把系統打死,預熱方式就是爲了保護系統,可慢慢的把流量放進來,慢慢的把閾值增長到設置的閾值。
4.5 流控效果——排隊等待
勻速排隊,讓請求以均勻的速度通過,閥值類型必須設成QPS,否則無效。
設置含義: /testA每秒1次請求,超過的話就排隊等待,等待的超時時間爲20000毫秒。
這種方式:主要用於處理間隔性突發的流量,例如消息隊列。想象一下這樣的場景, 在某一秒有大量的請求到來,而接下來的幾秒則處於空閒狀態,我們希望系統能夠在接下來的空閒期間逐漸處理這些請求,而不是在第一秒直接拒絕多餘的請求。
修改我們testB方法,打印當前線程日誌
sentinel規則設置
併發測試
五. 降級規則
-
Sentinel熔斷降級會在調用鏈路中某個資源出現不穩定狀態時(例如調用超時或異常比例升高),對這個資源的調用進行限制,讓請求快速失敗,避免影響到其它的資源而導致級聯錯誤。
-
當資源被降級後,在接下來的降級時間窗口之內,對該資源的調用都自動熔斷(默認行爲是拋出DegradeException)。
5.1 RT
controller層新增方法
@GetMapping("/testD")
public String testD() {
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "----- testD";
}
返回時間要是超過200毫秒,就會在1s內降級
測試
這裏每秒發10個線程過去
再次訪問我們的服務的時候,服務已經報錯了
永遠一秒鐘打進來10個線程(大於5個了)調用testD, 我們希望200毫秒處理完本次任務
如果超過200毫秒還沒處理完,在未來1秒鐘的時間窗口內,斷路器打開(保險絲跳閘)微服務不可用,保險絲跳閘斷電了後續我停止jmeter,沒有這麼大的訪問量了,斷路器關閉(保險絲恢復),微服務恢復OK
5.2 異常比例
首先資源量要>=5
後臺繼續用Jmeter發請求,結果如下
5.3 異常數
這裏設置異常數大於5時,時間窗口設置70s顯示