分布式限流框架 - Sentinel

Sentinel是面向分布式服務(wù)架構(gòu)的輕量級流量控制組件,主要以流量為切入點(diǎn),從限流、流量整形、服務(wù)降級、系統(tǒng)負(fù)載保護(hù)等多個維度來幫助我們保障微服務(wù)的穩(wěn)定性。

穩(wěn)定是系統(tǒng)的基礎(chǔ)能力,穩(wěn)定性差的系統(tǒng)會出現(xiàn)服務(wù)超時或服務(wù)不可用,給用戶帶來不好的體驗,也會對業(yè)務(wù)造成不良影響。

Sentinel的特性

Sentinel有如下特性:

  • 應(yīng)用場景豐富:幾乎涵蓋所有的應(yīng)用場景,例如秒殺、消息削峰填谷、集群流量控制等。
  • 實時監(jiān)控:Sentinel提供了實時監(jiān)控功能,開發(fā)者可以在控制臺中看到接入應(yīng)用的單臺機(jī)器秒級數(shù)據(jù),甚至500臺以下規(guī)模的集群匯總運(yùn)行情況。
  • 支持開源生態(tài):Sentinel提供開箱即用的與其它開源框架的整合,例如Spring Cloud、Dubbo、gRPC的整合。開發(fā)者只需要引入相應(yīng)的依賴并進(jìn)行簡單的配置即可快速接入Sentinel。
  • 支持SPI擴(kuò)展點(diǎn):Sentinel提供SPI擴(kuò)展點(diǎn)支持,開發(fā)者可以通過擴(kuò)展點(diǎn)來定制化限流規(guī)則,動態(tài)數(shù)據(jù)源適配等需求。

Sentinel分為兩個部分:

  • 核心庫(Java客戶端):不依賴任何框架,能夠運(yùn)行于所有Java運(yùn)行時環(huán)境,同時對Dubbo、Spring Cloud等框架也有較好的支持。
  • 控制臺(Dashboard):基于Spring Boot開發(fā),打包后可以直接運(yùn)行,不需要額外的Tomcat等應(yīng)用容器。

Sentinel的部署

Sentinel提供一個輕量級的開源控制臺,它支持機(jī)器發(fā)現(xiàn)以及健康情況管理、監(jiān)控、規(guī)則管理和推送等功能。

Sentinel Dashboard的安裝步驟如下:

  • 在GitHub中Sentinel的源碼倉庫中下載源碼或者下載已經(jīng)構(gòu)建好的jar
  • 通過以下命令啟動控制臺
java -Dserver.port=7777 -Dcsp.sentinel.dashboard.server=localhost:7777 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard.jar

默認(rèn)登陸的用戶名和密碼都是sentinel


在這里插入圖片描述

Sentinel的基本應(yīng)用

Sentinel實現(xiàn)限流

使用Sentinel的核心庫實現(xiàn)限流,主要分以下幾個步驟:

  • 定義資源
  • 定義限流規(guī)則
  • 檢驗規(guī)則是否生效

資源就是通過限流保護(hù)的基本元素,比如一個方法。

首先需要引入Sentinel的核心庫:

<dependency>
     <groupId>com.alibaba.csp</groupId>
     <artifactId>sentinel-core</artifactId>
     <version>1.7.1</version>
 </dependency>

然后定義一個普通的業(yè)務(wù)方法:

 private static void testSentinel() {
    try (Entry entry = SphU.entry("testSentinel")) {
        System.out.println("Test Sentinel " + System.currentTimeMillis());
    } catch (BlockException e) {
        //
    }
}

在testSentinel方法中,通過使用Sentinel中的SphU.entry("testSentinel")定義一個資源來實現(xiàn)流控的邏輯,它表示當(dāng)請求進(jìn)入testSentinel方法時,需要進(jìn)行限流判斷,如果拋出BlockException異常, 則表示觸發(fā)了限流。

接著我們要針對這個需要保護(hù)的資源定義限流規(guī)則:

private static void intiFlowRules() {
    List<FlowRule> rules = new ArrayList<>();
    FlowRule rule = new FlowRule();
    rule.setResource("testSentinel");
    rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
    rule.setCount(20);
    rules.add(rule);
    FlowRuleManager.loadRules(rules);
}

對于資源testSentinel,通過initFlowRules方法設(shè)置限流規(guī)則,其中的參數(shù)含義如下:

  • Grade: 限流閾值類型,QPS模式或者并發(fā)線程數(shù)模式
  • count: 限流閾值
  • resource: 設(shè)置需要保護(hù)的資源,這個資源的名稱必須與SphU.entry中使用的名稱保持一致

所以,上面代碼的意思是對于testSentinel這個方法,每秒鐘最多允許通過20個請求。

最后,通過main方法進(jìn)行測試:

public static void main(String[] args) {
    intiFlowRules();
    while (true) {
        testSentinel();
    }
}

運(yùn)行main方法之后,可以在{USER_HOME}/logs/csp/{包名-類名}-metrics.log.date文件中看到如下日志:

1588859287000|2020-05-07 21:48:07|testSentinel|20|95214|20|0|0|0|0|0
1588859288000|2020-05-07 21:48:08|testSentinel|20|523818|20|0|0|0|0|0
1588859289000|2020-05-07 21:48:09|testSentinel|20|659792|20|0|0|0|0|0

上述日志對應(yīng)字段的含義如下:

timestamp|yyyy-MM-dd HH:mm:ss|resource|passQps|blockQps|successQps|exceptionQps|rt|occupiedPassQps|concurrency|classification

passQps:              代表通過的請求
blockQps:             代表被阻止的請求
successQps:           代表成功執(zhí)行完成的請求個數(shù)
exceptionQps:         代表用戶自定義的異常
rt:                   代表平均響應(yīng)時長
occupiedPassQps:      代表優(yōu)先通過的請求
concurrency:          代表并發(fā)量
classification:       代表資源類型

從日志中可以看出,這個程序每秒穩(wěn)定輸出20次,和規(guī)則中預(yù)先設(shè)定的閾值是一樣的,而每秒被拒絕的請求高達(dá)60多萬次。

資源的定義方式

在上面的例子中,我們通過拋出異常的方式來定義一個資源,也就是當(dāng)資源被限流后,會拋出一個BlockException異常,這時我們需要捕獲該異常進(jìn)行限流后的處理:

private static void testSentinel() {
    try (Entry entry = SphU.entry("resourceName")) {
        // ......
    } catch (BlockException e) {
        // 被限流
    }
}

其中,resourceName可以定義方法名稱、接口名稱或者其它的唯一標(biāo)識。

除此之外,還可以通過返回布爾值的方式來定義資源:

if (SphO.entry("resourceName")) {
    try {
        // 被保護(hù)的業(yè)務(wù)邏輯
    } finally {
        SphO.exit();
    }
} else {
    // 資源訪問被限制
}

在這種方式中,需要注意資源使用完成之后需要調(diào)用SphO.exit(),否則會導(dǎo)致調(diào)用鏈記錄異常,拋出ErrorEntryFreeException異常。

Sentinel還可以使用@SentinelResource支持注解的方式來定義資源:

@SentinelResource(value = "findUserName", blockHandler = "blockHandlerForUserName")
public String findUserName(String id) {
    return "";
}

public String blockHandlerForUserName(String id, BlockException e) {
    // 被限流后的處理方法
    return "";
}

需要注意的是,blockHandler所配置的值blockHandlerForUserName會在觸發(fā)限流之后調(diào)用,這個方法的定義必須和原始方法findUserName的返回值、參數(shù)保持一直,而且要增加BlockException參數(shù)。

Sentinel實現(xiàn)服務(wù)熔斷

Sentinel實現(xiàn)服務(wù)熔斷操作的配置和限流類似,不同之處在于限流采用的是FlowRule,而熔斷中采用的是DegradeRule:

private static void initDegradeRule() {
   List<DegradeRule> rules = new ArrayList<>();
   DegradeRule degradeRule = new DegradeRule();
   degradeRule.setResource("KEY");
   degradeRule.setCount(10);
   degradeRule.setGrade(RuleConstant.DEGRADE_GRADE_RT);
   degradeRule.setTimeWindow(10);
   degradeRule.setMinRequestAmount(5);
   degradeRule.setRtSlowRequestAmount(5);
   rules.add(degradeRule);
}

其中幾個屬性的說明如下:

  • grade: 熔斷策略,支持秒級RT、秒級異常比例、分鐘級異常數(shù)。默認(rèn)是秒級RT
  • timeWindow: 熔斷降級的時間窗口,單位為s,也就是觸發(fā)熔斷降級之后多長時間內(nèi)自動熔斷。
  • rtSlowRequestAmount: 在RT模式下,1s內(nèi)持續(xù)多少個請求的平均RT超出閾值后觸發(fā)熔斷,默認(rèn)值是5.
  • minRequestAmount: 觸發(fā)的異常熔斷最小請求數(shù),請求數(shù)小于該值時即使異常比例超出閾值也不會觸發(fā)熔斷,默認(rèn)值是5。

Sentinel提供三種熔斷策略,對于不同策略,參數(shù)的含義也不相同。

  • 平均響應(yīng)時間(RuleConstant.DEGRADE_GRADE_RT): 如果1s內(nèi)持續(xù)進(jìn)入5個請求,對應(yīng)的平均響應(yīng)時間都超過了閾值(count,單位為ms),那么在接下來的時間窗口(timeWindow,單位為s)內(nèi),對這個方法的調(diào)用都會自動熔斷,拋出DegradeException。
  • 異常比例(RuleConstant.DEGRADE_GRADE_EXCEPTION_RATIO):如果每秒資源數(shù)大于等于minRequestAmount(默認(rèn)值為5),并且每秒的異??倲?shù)占總通過量的比例超過閾值count(count的取值范圍是[0.0,1.0],代表0% ~ 100%),則資源將進(jìn)入降級狀態(tài)。同樣,在接下來的timeWindow之內(nèi),對于這個方法的調(diào)用都會自動觸發(fā)熔斷。
  • 異常數(shù)(RuleConstant.DEGRADE_GRADE_EXCEPTION_COUNT):當(dāng)資源最近一分鐘的異常數(shù)目超過閾值之后,會觸發(fā)熔斷。需要注意的是,如果timeWindow小于60s,則結(jié)束熔斷狀態(tài)后仍然可能再進(jìn)入熔斷狀態(tài)。

到此,我們對Sentinel已經(jīng)有了基本的了解。

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

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