Spring Cloud Alibaba之服務(wù)容錯(cuò)組件 - Sentinel Dashboard控制臺(tái)(十二)

上一篇文章我們已經(jīng)對(duì) Sentinel 有個(gè)簡(jiǎn)單的了解,接下來我們將講解 Sentinel的具體使用。
Sentinel的使用分為兩部分:

  • Sentinel-Dashboard:Hystrix-Dashboard類似,但是它的功能更加強(qiáng)大。除了與 hystrix-dashboard 一樣提供實(shí)時(shí)監(jiān)控之外,還提供了流控規(guī)則、熔斷規(guī)則的在線維護(hù)等功能。
  • 客戶端整合:每個(gè)微服務(wù)客戶端都需要整合 sentinel 的客戶端封裝與配置,才能將監(jiān)控信息上報(bào)給 dashboard 展示以及實(shí)時(shí)的更改限流或熔斷規(guī)則等。

下面我們就分兩部分來看,如果使用Sentinel來實(shí)現(xiàn)接口限流。

部署Sentinel Dashboard

  • 下載地址:Sentinel/releases

    這里我采用最新版:sentinel-dashboard-1.6.2.jar

命令行啟動(dòng)

java -jar sentinel-dashboard-1.6.2.jar

sentinel-dashboard 不像Nacos的服務(wù)端那樣還提供了外置配置文件,比較容易修改參數(shù)。不過沒關(guān)系,由于 sentinel-dashboard是一個(gè)標(biāo)準(zhǔn)的SpringBoot應(yīng)用,所以如果需要自定義端口號(hào)等配置的話,可以通過在啟動(dòng)參數(shù)中增加參數(shù)來調(diào)整,比如:-Dserver.port=8888。

默認(rèn)情況下,sentinel-dashboard以8080端口啟動(dòng),所以可以通過訪問: http://localhost:8080 來驗(yàn)證是否啟動(dòng)成功,如果一切順利,可以看到如下界面:

注意: 只要 1.6.0 及以上的版本,才有這個(gè)簡(jiǎn)單的登錄頁面。默認(rèn)用戶名密碼都是: sentinel。對(duì)于用戶登錄相關(guān)的配置可在啟動(dòng)命令中添加下面參數(shù)來修改默認(rèn)配置:

  • Dsentinel.dashboard.auth.username=sentinel:用于指定控制臺(tái)的登錄用戶名為 sentinel;
  • Dsentinel.dashboard.auth.password=123456:用于指定控制臺(tái)的登錄密碼為 123456;如果省略這兩個(gè)參數(shù),默認(rèn)用戶和密碼均為 sentinel
  • Dserver.servlet.session.timeout=7200:用于指定 Spring Boot 服務(wù)端 session 的過期時(shí)間,如 7200 表示 7200 秒;60m 表示 60 分鐘,默認(rèn)為 30 分鐘;

輸入用戶名密碼登錄后,會(huì)看下如下頁面:


整合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控制臺(tái)地址
        dashboard: localhost:8080

控制臺(tái)相關(guān)配置項(xiàng):

配置項(xiàng) 默認(rèn)值 最小值 描述
sentinel.dashboard.app.hideAppNoMachineMillis 0 60000 是否隱藏?zé)o健康節(jié)點(diǎn)的應(yīng)用,距離最近一次主機(jī)心跳時(shí)間的毫秒數(shù),默認(rèn)關(guān)閉
sentinel.dashboard.removeAppNoMachineMillis 0 120000 是否自動(dòng)刪除無健康節(jié)點(diǎn)的應(yīng)用,距離最近一次其下節(jié)點(diǎn)的心跳時(shí)間毫秒數(shù),默認(rèn)關(guān)閉
sentinel.dashboard.unhealthyMachineMillis 60000 30000 主機(jī)失聯(lián)判定,不可關(guān)閉
sentinel.dashboard.autoRemoveMachineMillis 0 300000 距離最近心跳時(shí)間超過指定時(shí)間是否自動(dòng)刪除失聯(lián)節(jié)點(diǎn),默認(rèn)關(guān)閉
server.port 8080 - 指定端口
csp.sentinel.dashboard.server localhost:8080 - 指定地址
project.name - - 指定程序的名稱
sentinel.dashboard.auth.username [1.6版本支持] sentinel - Sentinel Dashboard登錄賬號(hào)
sentinel.dashboard.auth.password [1.6版本支持] sentinel - Sentinel Dashboard登錄密碼
server.servlet.session.timeout [1.6版本支持] 30分鐘 - 登錄Session過期時(shí)間。配置為7200表示7200秒;配置為60m表示60分鐘

控制臺(tái)配置項(xiàng)需在啟動(dòng)命令中指定,例如指定賬戶密碼,如下:

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";
    }
}

第四步: 啟動(dòng)應(yīng)用,然后通過 postman 訪問:http://localhost:9005/findById接口。

sentinel 是懶加載應(yīng)用的,所有這里需要通過postman先訪問,才能在控制臺(tái)看到應(yīng)用客戶端。

此時(shí),在Sentinel Dashboard界面中就可以看到我們啟動(dòng)的這個(gè)服務(wù)以及接口調(diào)用的實(shí)時(shí)監(jiān)控了。

實(shí)時(shí)監(jiān)控

控制臺(tái)配置規(guī)則

配置限流規(guī)則

在完成了上面配置以后,我們?cè)?Sentinel 控制臺(tái)的 alibaba-sentinel-rate-limiting服務(wù)下,單擊 簇點(diǎn)鏈路 菜單,可以看到如下頁面:


點(diǎn)擊流控按鈕,便可以為應(yīng)用設(shè)置流控規(guī)則
image.png

  • 資源名:唯一名稱,默認(rèn)請(qǐng)求路徑

  • 針對(duì)來源:Sentinel可以針對(duì)調(diào)用者進(jìn)行限流,填寫微服務(wù)名,默認(rèn)default(不區(qū)分來源)

  • 閾值類型/單機(jī)閾值

    • QPS(每秒鐘的請(qǐng)求數(shù)量):當(dāng)調(diào)用該api的QPS達(dá)到閾值的時(shí)候,進(jìn)行限流
    • 線程數(shù):當(dāng)調(diào)用該api的線程數(shù)達(dá)到閾值的時(shí)候,進(jìn)行限流
  • 是否集群:不需要集群,暫不研究

  • 流控模式

    • 直接:api達(dá)到限流條件時(shí),直接限流
    • 關(guān)聯(lián):當(dāng)關(guān)聯(lián)的資源達(dá)到閾值時(shí),就限流自己
    • 鏈路:只記錄指定鏈路上的流量(指定資源從入口資源進(jìn)來的流量,如果達(dá)到閾值,就進(jìn)行限流)【api級(jí)別的針對(duì)來源】

    鏈路模式稍微有些抽象,這里舉個(gè)簡(jiǎn)單的例子說明一下。下圖中有兩個(gè)調(diào)用鏈路,圖中的/test-b和/test-a實(shí)際就是兩個(gè)接口,它們都調(diào)用了同一個(gè)common資源,所以/test-b和/test-a就稱為common的入口資源:


    此時(shí)我為common添加一個(gè)限流規(guī)則如下:



    可以看到流控模式選擇鏈路后,需要填寫一個(gè)入口資源,我這里填的是/test-a,那么這意味著什么呢?意味著當(dāng)/test-a的QPS達(dá)到該規(guī)則的閾值后,就會(huì)對(duì)/test-a限流,同時(shí)/test-b不會(huì)受到任何影響。說明這種流控模式可以針對(duì)接口級(jí)別的來源進(jìn)行限流,而“針對(duì)來源”則是對(duì)微服務(wù)級(jí)別的來源進(jìn)行限流。

  • 流控效果

    • 快速失?。褐苯邮?,拋出異常,不做任何額外的處理,是最簡(jiǎn)單的效果
      相關(guān)源碼:com.alibaba.csp.sentinel.slots.block.flow.controller.DefaultController
    • Warm Up(預(yù)熱):會(huì)根據(jù)codeFactor(默認(rèn)3)的值,從閾值除以codeFactor,經(jīng)過預(yù)熱時(shí)長(zhǎng),才到達(dá)設(shè)置的QPS閾值。適用于將突然增大的流量轉(zhuǎn)換為緩步增長(zhǎng)的場(chǎng)景。
      相關(guān)的官方文檔:限流 - 冷啟動(dòng)
      相關(guān)源碼:com.alibaba.csp.sentinel.slots.block.flow.controller.WarmUpController
    • 排隊(duì)等待:勻速排隊(duì),讓請(qǐng)求以均勻的速度通過,若請(qǐng)求等待時(shí)間超過設(shè)置的超時(shí)時(shí)間則拋棄該請(qǐng)求,閾值類型必須設(shè)置成QPS,否則無效。適用于突發(fā)流量的場(chǎng)景。
      相關(guān)的官方文檔:限流 - 勻速器
      相關(guān)源碼:com.alibaba.csp.sentinel.slots.block.flow.controller.RateLimiterController

降級(jí)規(guī)則(斷路器模式)

點(diǎn)擊降級(jí)按鈕,便可以為應(yīng)用設(shè)置降級(jí)規(guī)則

降級(jí)策略:

  • RT:平均響應(yīng)時(shí)間(秒級(jí)統(tǒng)計(jì))超出閾值 且 在時(shí)間窗口內(nèi)的請(qǐng)求 >= 5時(shí),觸發(fā)降級(jí)(斷路器打開);時(shí)間窗口結(jié)束后,關(guān)閉降級(jí)【Sentinel默認(rèn)最大的RT為4900ms,可以通過-Dcsp.sentinel.statistic.max.rt=xxx修改】
  • 異常比例:QPS >= 5 且異常比例(秒級(jí)統(tǒng)計(jì))超過閾值時(shí),觸發(fā)降級(jí);時(shí)間窗口結(jié)束后,關(guān)閉降級(jí)
  • 異常數(shù):異常數(shù)(分鐘統(tǒng)計(jì))超過閾值時(shí),觸發(fā)降級(jí);時(shí)間窗口結(jié)束后,關(guān)閉降級(jí)【時(shí)間窗口 < 60秒可能會(huì)出現(xiàn)問題】
    關(guān)于異常數(shù)這種降級(jí)策略需要注意的點(diǎn):
    若將時(shí)間窗口的值設(shè)置小于60秒則可能會(huì)出問題,因?yàn)楫惓?shù)的統(tǒng)計(jì)是分鐘級(jí)別的,時(shí)間窗口小于60秒就有可能不斷進(jìn)入降級(jí)狀態(tài).
    降級(jí)規(guī)則的相關(guān)源碼com.alibaba.csp.sentinel.slots.block.degradeDegradeRule#passCheck(對(duì)降級(jí)的判斷都在這個(gè)方法里完成)

熱點(diǎn)規(guī)則(熱點(diǎn)參數(shù)限流規(guī)則)

Sentinel默認(rèn)顯示的端點(diǎn)并不支持熱點(diǎn)規(guī)則,要顯示熱點(diǎn)規(guī)則,需要自己添加代碼:

@GetMapping("test")
@SentinelResource("test")
public String testHot(@RequestParam(required = false) String a,
                      @RequestParam(required = false) String b) {
    return a + "-" + b;
}

點(diǎn)擊熱點(diǎn)按鈕,便可以為test設(shè)置熱點(diǎn)規(guī)則


在時(shí)間窗口以內(nèi),一旦該api指定索引的參數(shù)QPS達(dá)到了域名,就會(huì)觸發(fā)限流

  • 參數(shù)索引:從0開始,上面的代碼中:a的參數(shù)索引為0;b的參數(shù)索引為1【參數(shù)索引對(duì)應(yīng)的參數(shù)必須時(shí)基本類型或者String】

熱點(diǎn)規(guī)則適用的場(chǎng)景

  • 適用于存在熱點(diǎn)參數(shù)并希望提升API可用性的場(chǎng)景,即某個(gè)特定請(qǐng)求參數(shù)QPS偏高于其他請(qǐng)求參數(shù)時(shí),僅對(duì)該參數(shù)的請(qǐng)求限流,使用其他請(qǐng)求參數(shù)則可以正常響應(yīng),這樣可以提高一定的可用性

使用熱點(diǎn)規(guī)則需要注意的點(diǎn)

  • 參數(shù)必須是基本類型或者String類型,否則將不會(huì)生效

熱點(diǎn)規(guī)則相關(guān)源碼
com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowChecker#passCheck(對(duì)熱點(diǎn)參數(shù)規(guī)則的判斷邏輯都在這個(gè)方法里)

系統(tǒng)規(guī)則

閾值類型

  • LOAD(僅對(duì) Linux/Unix-like 機(jī)器生效):當(dāng)系統(tǒng) load1 超過閾值,且系統(tǒng)當(dāng)前的并發(fā)線程數(shù)超過系統(tǒng)容量時(shí)才會(huì)觸發(fā)系統(tǒng)保護(hù)。系統(tǒng)容量由系統(tǒng)的 maxQps * minRt 計(jì)算得出。設(shè)定參考值一般是 CPU cores * 2.5
  • RT:當(dāng)單臺(tái)機(jī)器上所有入口流量的平均 RT 達(dá)到閾值即觸發(fā)系統(tǒng)保護(hù),單位是毫秒
  • 線程數(shù):當(dāng)單臺(tái)機(jī)器上所有入口流量的并發(fā)線程數(shù)達(dá)到閾值即觸發(fā)系統(tǒng)保護(hù)
  • 入口 QPS:當(dāng)單臺(tái)機(jī)器上所有入口流量的 QPS 達(dá)到閾值即觸發(fā)系統(tǒng)保護(hù)
  • CPU 使用率:當(dāng)系統(tǒng) CPU 使用率超過閾值即觸發(fā)系統(tǒng)保護(hù)(取值范圍 0.0-1.0)

授權(quán)規(guī)則

點(diǎn)擊授權(quán)按鈕,便可以為應(yīng)用設(shè)置授權(quán)規(guī)則



資源名所代表的資源只允許流控應(yīng)用中添加的微服務(wù)使用(白名單)、不允許使用(黑名單)

代碼配置規(guī)則

流控規(guī)則

參數(shù)

Field 說明 默認(rèn)值
resource 資源名,資源名是限流規(guī)則的作用對(duì)象
count 限流閾值
grade 限流閾值類型,QPS 或線程數(shù)模式 QPS模式
limitApp 流控針對(duì)的調(diào)用來源 default,代表不區(qū)分調(diào)用來源
strategy default,代表不區(qū)分調(diào)用來源 根據(jù)資源本身
controlBehavior 流控效果(直接拒絕 / 排隊(duì)等待 / 慢啟動(dòng)模式) 直接拒絕

代碼

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);
}

降級(jí)規(guī)則

參數(shù)

Field 說明 默認(rèn)值
resource 資源名,即限流規(guī)則的作用對(duì)象
count 閾值
grade 降級(jí)模式,根據(jù) RT 降級(jí)還是根據(jù)異常比例降級(jí) RT
timeWindow 降級(jí)的時(shí)間,單位為 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);
}

熱點(diǎn)規(guī)則

參數(shù)

Field 說明 默認(rèn)值
resource 資源名,必填
count 限流閾值,必填
grade 限流模式 QPS 模式
durationInSec 統(tǒng)計(jì)窗口時(shí)間長(zhǎng)度(單位為秒) 1s
controlBehavior 流控效果(支持快速失敗和勻速排隊(duì)模式) 快速失敗
maxQueueingTimeMs 最大排隊(duì)等待時(shí)長(zhǎng)(僅在勻速排隊(duì)模式生效) 0ms
paramIdx 熱點(diǎn)參數(shù)的索引,必填,對(duì)應(yīng) SphU.entry(xxx, args) 中的參數(shù)索引位置
paramFlowItemList 參數(shù)例外項(xiàng),可以針對(duì)指定的參數(shù)值單獨(dú)設(shè)置限流閾值,不受前面 count 閾值的限制。僅支持基本類型
clusterMode 是否是集群參數(shù)流控規(guī)則 false
clusterConfig 集群流控相關(guān)配置

代碼

ParamFlowRule rule = new ParamFlowRule(resourceName)
    .setParamIdx(0)
    .setCount(5);
// 針對(duì) int 類型的參數(shù) PARAM_B,單獨(dú)設(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 說明 默認(rèn)值
highestSystemLoad 最大的 load1 -1(不生效)
avgRt 所有入口流量的平均響應(yīng)時(shí)間 -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 說明 默認(rèn)值
resource 資源名,即限流規(guī)則的作用對(duì)象
limitApp 對(duì)應(yīng)的黑名單/白名單,不同 origin 用 , 分隔,如 appA,appB default,代表不區(qū)分調(diào)用來源
strategy 限制模式,AUTHORITY_WHITE 為白名單模式,AUTHORITY_BLACK 為黑名單模式,默認(rèn)為白名單模式 AUTHORITY_WHITE

代碼

AuthorityRule rule = new AuthorityRule();
rule.setResource("test");
rule.setStrategy(RuleConstant.AUTHORITY_WHITE);
rule.setLimitApp("appA,appB");
AuthorityRuleManager.loadRules(Collections.singletonList(rule));

Sentinel組件與控制臺(tái)通信原理

  • 注冊(cè)/心跳發(fā)送
    源碼:com.alibaba.csp.sentinel.transport.heartbeat.SimpleHttpHeatbeatSender

  • 通信API
    源碼:com.alibaba.csp.sentinel.command.CommandHandler

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容