上一篇文章我們已經(jīng)對 Sentinel 有個簡單的了解户盯,接下來我們將講解 Sentinel的具體使用喊崖。
Sentinel的使用分為兩部分:
- Sentinel-Dashboard: 與 Hystrix-Dashboard類似,但是它的功能更加強大豪直。除了與 hystrix-dashboard 一樣提供實時監(jiān)控之外劣摇,還提供了流控規(guī)則、熔斷規(guī)則的在線維護等功能弓乙。
- 客戶端整合:每個微服務(wù)客戶端都需要整合 sentinel 的客戶端封裝與配置末融,才能將監(jiān)控信息上報給 dashboard 展示以及實時的更改限流或熔斷規(guī)則等。
下面我們就分兩部分來看暇韧,如果使用Sentinel來實現(xiàn)接口限流勾习。
部署Sentinel Dashboard
- 下載地址:Sentinel/releases
這里我采用最新版:sentinel-dashboard-1.6.2.jar
命令行啟動
java -jar sentinel-dashboard-1.6.2.jar
sentinel-dashboard 不像Nacos的服務(wù)端那樣還提供了外置配置文件,比較容易修改參數(shù)懈玻。不過沒關(guān)系巧婶,由于 sentinel-dashboard是一個標準的SpringBoot應(yīng)用,所以如果需要自定義端口號等配置的話涂乌,可以通過在啟動參數(shù)中增加參數(shù)來調(diào)整艺栈,比如:-Dserver.port=8888
。
默認情況下湾盒,sentinel-dashboard以8080端口啟動湿右,所以可以通過訪問: http://localhost:8080 來驗證是否啟動成功,如果一切順利罚勾,可以看到如下界面:
注意: 只要 1.6.0 及以上的版本诅需,才有這個簡單的登錄頁面。默認用戶名密碼都是: sentinel
荧库。對于用戶登錄相關(guān)的配置可在啟動命令中添加下面參數(shù)來修改默認配置:
-
Dsentinel.dashboard.auth.username=sentinel
:用于指定控制臺的登錄用戶名為 sentinel堰塌; -
Dsentinel.dashboard.auth.password=123456
:用于指定控制臺的登錄密碼為 123456;如果省略這兩個參數(shù)分衫,默認用戶和密碼均為 sentinel -
Dserver.servlet.session.timeout=7200
:用于指定 Spring Boot 服務(wù)端 session 的過期時間场刑,如 7200 表示 7200 秒;60m 表示 60 分鐘,默認為 30 分鐘牵现;
輸入用戶名密碼登錄后铐懊,會看下如下頁面:
整合Sentinel
第一步: 創(chuàng)建 alibaba-sentinel-rate-limiting
web應(yīng)用,并在的pom.xml 中引入 Spring Cloud Alibaba的Sentinel模塊依賴:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.5.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Finchley.SR1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>0.2.2.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.2</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
第二步: 在Spring Cloud 應(yīng)用中 application.yml
配置 sentinel dashboard 的訪問地址:
spring:
cloud:
sentinel:
transport:
# 指定sentinel控制臺地址
dashboard: localhost:8080
控制臺相關(guān)配置項:
配置項 | 默認值 | 最小值 | 描述 |
---|---|---|---|
sentinel.dashboard.app.hideAppNoMachineMillis | 0 | 60000 | 是否隱藏無健康節(jié)點的應(yīng)用瞎疼,距離最近一次主機心跳時間的毫秒數(shù)科乎,默認關(guān)閉 |
sentinel.dashboard.removeAppNoMachineMillis | 0 | 120000 | 是否自動刪除無健康節(jié)點的應(yīng)用,距離最近一次其下節(jié)點的心跳時間毫秒數(shù)贼急,默認關(guān)閉 |
sentinel.dashboard.unhealthyMachineMillis | 60000 | 30000 | 主機失聯(lián)判定茅茂,不可關(guān)閉 |
sentinel.dashboard.autoRemoveMachineMillis | 0 | 300000 | 距離最近心跳時間超過指定時間是否自動刪除失聯(lián)節(jié)點,默認關(guān)閉 |
server.port | 8080 | - | 指定端口 |
csp.sentinel.dashboard.server | localhost:8080 | - | 指定地址 |
project.name | - | - | 指定程序的名稱 |
sentinel.dashboard.auth.username [1.6版本支持] | sentinel | - | Sentinel Dashboard登錄賬號 |
sentinel.dashboard.auth.password [1.6版本支持] | sentinel | - | Sentinel Dashboard登錄密碼 |
server.servlet.session.timeout [1.6版本支持] | 30分鐘 | - | 登錄Session過期時間太抓。配置為7200表示7200秒空闲;配置為60m表示60分鐘 |
控制臺配置項需在啟動命令中指定,例如指定賬戶密碼走敌,如下:
java -jar -Dsentinel.dashboard.auth.username=admin -Dsentinel.dashboard.auth.password=123456 sentinel-dashboard-1.6.3.jar
第三步: 創(chuàng)建應(yīng)用rest接口:
@Slf4j
@RestController
public class UserController {
@GetMapping("/findById")
public String getUser(@RequestParam String id) {
return "hello sentinel dashboard";
}
}
第四步: 啟動應(yīng)用碴倾,然后通過 postman 訪問:http://localhost:9005/findById接口。
sentinel 是懶加載應(yīng)用的掉丽,所有這里需要通過postman先訪問跌榔,才能在控制臺看到應(yīng)用客戶端。
此時捶障,在Sentinel Dashboard界面中就可以看到我們啟動的這個服務(wù)以及接口調(diào)用的實時監(jiān)控了僧须。
實時監(jiān)控
控制臺配置規(guī)則
配置限流規(guī)則
在完成了上面配置以后,我們在 Sentinel 控制臺的 alibaba-sentinel-rate-limiting
服務(wù)下残邀,單擊 簇點鏈路 菜單皆辽,可以看到如下頁面:
點擊流控按鈕,便可以為應(yīng)用設(shè)置流控規(guī)則
資源名:唯一名稱芥挣,默認請求路徑
針對來源:Sentinel可以針對調(diào)用者進行限流驱闷,填寫微服務(wù)名,默認default(不區(qū)分來源)
-
閾值類型/單機閾值:
- QPS(每秒鐘的請求數(shù)量):當調(diào)用該api的QPS達到閾值的時候空免,進行限流
- 線程數(shù):當調(diào)用該api的線程數(shù)達到閾值的時候空另,進行限流
是否集群:不需要集群,暫不研究
-
流控模式:
- 直接:api達到限流條件時蹋砚,直接限流
- 關(guān)聯(lián):當關(guān)聯(lián)的資源達到閾值時扼菠,就限流自己
- 鏈路:只記錄指定鏈路上的流量(指定資源從入口資源進來的流量,如果達到閾值坝咐,就進行限流)【api級別的針對來源】
鏈路模式稍微有些抽象循榆,這里舉個簡單的例子說明一下。下圖中有兩個調(diào)用鏈路墨坚,圖中的/test-b和/test-a實際就是兩個接口秧饮,它們都調(diào)用了同一個common資源,所以/test-b和/test-a就稱為common的入口資源:
此時我為common添加一個限流規(guī)則如下:
可以看到流控模式選擇鏈路后,需要填寫一個入口資源盗尸,我這里填的是/test-a柑船,那么這意味著什么呢?意味著當/test-a的QPS達到該規(guī)則的閾值后泼各,就會對/test-a限流鞍时,同時/test-b不會受到任何影響。說明這種流控模式可以針對接口級別的來源進行限流扣蜻,而“針對來源”則是對微服務(wù)級別的來源進行限流逆巍。
-
流控效果:
- 快速失敗:直接失敗弱贼,拋出異常蒸苇,不做任何額外的處理磷蛹,是最簡單的效果
相關(guān)源碼:com.alibaba.csp.sentinel.slots.block.flow.controller.DefaultController
- Warm Up(預熱):會根據(jù)codeFactor(默認3)的值吮旅,從閾值除以codeFactor,經(jīng)過預熱時長味咳,才到達設(shè)置的QPS閾值庇勃。適用于將突然增大的流量轉(zhuǎn)換為緩步增長的場景。
相關(guān)的官方文檔:限流 - 冷啟動
相關(guān)源碼:com.alibaba.csp.sentinel.slots.block.flow.controller.WarmUpController
- 排隊等待:勻速排隊槽驶,讓請求以均勻的速度通過责嚷,若請求等待時間超過設(shè)置的超時時間則拋棄該請求,閾值類型必須設(shè)置成QPS掂铐,否則無效罕拂。適用于突發(fā)流量的場景。
相關(guān)的官方文檔:限流 - 勻速器
相關(guān)源碼:com.alibaba.csp.sentinel.slots.block.flow.controller.RateLimiterController
- 快速失敗:直接失敗弱贼,拋出異常蒸苇,不做任何額外的處理磷蛹,是最簡單的效果
降級規(guī)則(斷路器模式)
點擊降級按鈕全陨,便可以為應(yīng)用設(shè)置降級規(guī)則
降級策略:
-
RT:平均響應(yīng)時間(秒級統(tǒng)計)超出閾值 且 在時間窗口內(nèi)的請求 >= 5時爆班,觸發(fā)降級(斷路器打開);時間窗口結(jié)束后辱姨,關(guān)閉降級【Sentinel默認最大的RT為4900ms柿菩,可以通過
-Dcsp.sentinel.statistic.max.rt=xxx
修改】 - 異常比例:QPS >= 5 且異常比例(秒級統(tǒng)計)超過閾值時,觸發(fā)降級雨涛;時間窗口結(jié)束后枢舶,關(guān)閉降級
-
異常數(shù):異常數(shù)(分鐘統(tǒng)計)超過閾值時,觸發(fā)降級替久;時間窗口結(jié)束后凉泄,關(guān)閉降級【時間窗口 < 60秒可能會出現(xiàn)問題】
關(guān)于異常數(shù)這種降級策略需要注意的點:
若將時間窗口的值設(shè)置小于60秒則可能會出問題,因為異常數(shù)的統(tǒng)計是分鐘級別的蚯根,時間窗口小于60秒就有可能不斷進入降級狀態(tài).
降級規(guī)則的相關(guān)源碼:com.alibaba.csp.sentinel.slots.block.degradeDegradeRule#passCheck
(對降級的判斷都在這個方法里完成)
熱點規(guī)則(熱點參數(shù)限流規(guī)則)
Sentinel默認顯示的端點并不支持熱點規(guī)則丈秩,要顯示熱點規(guī)則柴钻,需要自己添加代碼:
@GetMapping("test")
@SentinelResource("test")
public String testHot(@RequestParam(required = false) String a,
@RequestParam(required = false) String b) {
return a + "-" + b;
}
點擊熱點按鈕诚卸,便可以為test設(shè)置熱點規(guī)則
在時間窗口以內(nèi)避咆,一旦該api指定索引的參數(shù)QPS達到了域名,就會觸發(fā)限流
- 參數(shù)索引:從0開始秸苗,上面的代碼中:a的參數(shù)索引為0;b的參數(shù)索引為1【參數(shù)索引對應(yīng)的參數(shù)必須時基本類型或者String】
熱點規(guī)則適用的場景:
- 適用于存在熱點參數(shù)并希望提升API可用性的場景,即某個特定請求參數(shù)QPS偏高于其他請求參數(shù)時怖竭,僅對該參數(shù)的請求限流,使用其他請求參數(shù)則可以正常響應(yīng)陡蝇,這樣可以提高一定的可用性
使用熱點規(guī)則需要注意的點:
- 參數(shù)必須是基本類型或者String類型痊臭,否則將不會生效
熱點規(guī)則相關(guān)源碼:
com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowChecker#passCheck(對熱點參數(shù)規(guī)則的判斷邏輯都在這個方法里)
系統(tǒng)規(guī)則
閾值類型
- LOAD(
僅對 Linux/Unix-like 機器生效
):當系統(tǒng) load1 超過閾值,且系統(tǒng)當前的并發(fā)線程數(shù)超過系統(tǒng)容量時才會觸發(fā)系統(tǒng)保護登夫。系統(tǒng)容量由系統(tǒng)的 maxQps * minRt 計算得出广匙。設(shè)定參考值一般是CPU cores * 2.5
- RT:當單臺機器上所有入口流量的平均 RT 達到閾值即觸發(fā)系統(tǒng)保護,單位是毫秒
- 線程數(shù):當單臺機器上所有入口流量的并發(fā)線程數(shù)達到閾值即觸發(fā)系統(tǒng)保護
- 入口 QPS:當單臺機器上所有入口流量的 QPS 達到閾值即觸發(fā)系統(tǒng)保護
- CPU 使用率:當系統(tǒng) CPU 使用率超過閾值即觸發(fā)系統(tǒng)保護(取值范圍 0.0-1.0)
授權(quán)規(guī)則
點擊授權(quán)按鈕恼策,便可以為應(yīng)用設(shè)置授權(quán)規(guī)則
資源名所代表的資源只允許流控應(yīng)用中添加的微服務(wù)使用(白名單)鸦致、不允許使用(黑名單)
代碼配置規(guī)則
流控規(guī)則
參數(shù)
Field | 說明 | 默認值 |
---|---|---|
resource | 資源名,資源名是限流規(guī)則的作用對象 | 無 |
count | 限流閾值 | 無 |
grade | 限流閾值類型涣楷,QPS 或線程數(shù)模式 | QPS模式 |
limitApp | 流控針對的調(diào)用來源 | default分唾,代表不區(qū)分調(diào)用來源 |
strategy | default,代表不區(qū)分調(diào)用來源 | 根據(jù)資源本身 |
controlBehavior | 流控效果(直接拒絕 / 排隊等待 / 慢啟動模式) | 直接拒絕 |
代碼
private void initFlowQpsRule() {
List<FlowRule> rules = new ArrayList<>();
FlowRule rule = new FlowRule(resourceName);
// 設(shè)置QPS閾值為20
rule.setCount(20);
rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
rule.setLimitApp("default");
rules.add(rule);
FlowRuleManager.loadRules(rules);
}
降級規(guī)則
參數(shù)
Field | 說明 | 默認值 |
---|---|---|
resource | 資源名狮斗,即限流規(guī)則的作用對象 | 無 |
count | 閾值 | 無 |
grade | 降級模式绽乔,根據(jù) RT 降級還是根據(jù)異常比例降級 | RT |
timeWindow | 降級的時間,單位為 s | 無 |
代碼
private void initDegradeRule() {
List<DegradeRule> rules = new ArrayList<>();
DegradeRule rule = new DegradeRule();
rule.setResource(KEY);
// set threshold RT, 10 ms
rule.setCount(10);
rule.setGrade(RuleConstant.DEGRADE_GRADE_RT);
rule.setTimeWindow(10);
rules.add(rule);
DegradeRuleManager.loadRules(rules);
}
熱點規(guī)則
參數(shù)
Field | 說明 | 默認值 |
---|---|---|
resource | 資源名碳褒,必填 | 無 |
count | 限流閾值折砸,必填 | 無 |
grade | 限流模式 | QPS 模式 |
durationInSec | 統(tǒng)計窗口時間長度(單位為秒) | 1s |
controlBehavior | 流控效果(支持快速失敗和勻速排隊模式) | 快速失敗 |
maxQueueingTimeMs | 最大排隊等待時長(僅在勻速排隊模式生效) | 0ms |
paramIdx | 熱點參數(shù)的索引,必填沙峻,對應(yīng) SphU.entry(xxx, args) 中的參數(shù)索引位置 | 無 |
paramFlowItemList | 參數(shù)例外項睦授,可以針對指定的參數(shù)值單獨設(shè)置限流閾值,不受前面 count 閾值的限制专酗。僅支持基本類型 | 無 |
clusterMode | 是否是集群參數(shù)流控規(guī)則 | false |
clusterConfig | 集群流控相關(guān)配置 | 無 |
代碼
ParamFlowRule rule = new ParamFlowRule(resourceName)
.setParamIdx(0)
.setCount(5);
// 針對 int 類型的參數(shù) PARAM_B睹逃,單獨設(shè)置限流 QPS 閾值為 10,而不是全局的閾值 5.
ParamFlowItem item = new ParamFlowItem().setObject(String.valueOf(PARAM_B))
.setClassType(int.class.getName())
.setCount(10);
rule.setParamFlowItemList(Collections.singletonList(item));
ParamFlowRuleManager.loadRules(Collections.singletonList(rule));
系統(tǒng)規(guī)則
參數(shù)
Field | 說明 | 默認值 |
---|---|---|
highestSystemLoad | 最大的 load1 | -1(不生效) |
avgRt | 所有入口流量的平均響應(yīng)時間 | -1(不生效) |
maxThread | 入口流量的最大并發(fā)數(shù) | -1(不生效) |
qpa | 所有入口資源的 QPS | -1(不生效) |
代碼
private void initSystemRule() {
List<SystemRule> rules = new ArrayList<>();
SystemRule rule = new SystemRule();
rule.setHighestSystemLoad(10);
rules.add(rule);
SystemRuleManager.loadRules(rules);
}
授權(quán)規(guī)則
參數(shù)
Field | 說明 | 默認值 |
---|---|---|
resource | 資源名祷肯,即限流規(guī)則的作用對象 | 無 |
limitApp | 對應(yīng)的黑名單/白名單沉填,不同 origin 用 , 分隔,如 appA,appB | default佑笋,代表不區(qū)分調(diào)用來源 |
strategy | 限制模式翼闹,AUTHORITY_WHITE 為白名單模式,AUTHORITY_BLACK 為黑名單模式蒋纬,默認為白名單模式 | AUTHORITY_WHITE |
代碼
AuthorityRule rule = new AuthorityRule();
rule.setResource("test");
rule.setStrategy(RuleConstant.AUTHORITY_WHITE);
rule.setLimitApp("appA,appB");
AuthorityRuleManager.loadRules(Collections.singletonList(rule));
Sentinel組件與控制臺通信原理
注冊/心跳發(fā)送
源碼:com.alibaba.csp.sentinel.transport.heartbeat.SimpleHttpHeatbeatSender通信API
源碼:com.alibaba.csp.sentinel.command.CommandHandler