【深入淺出Sentinel原理及實戰(zhàn)】「基礎實戰(zhàn)專題」零基礎實現(xiàn)服務流量控制實戰(zhàn)開發(fā)指南(2)

你若要喜愛你自己的價值,你就得給世界創(chuàng)造價值。

Sentinel的組成部分

Sentinel 主要由以下兩個部分組成。

  • Sentinel核心庫(Java客戶端) :Sentinel的核心庫不依賴任何框架或庫,能夠運行于Java 8及以上的版本的運行時環(huán)境中,同時對 Spring Cloud、Dubbo 等微服務框架提供了很好的支持。

  • Sentinel控制臺(Dashboard) :Sentinel提供的一個輕量級的開源控制臺,它為用戶提供了機器自發(fā)現(xiàn)、簇點鏈路自發(fā)現(xiàn)、監(jiān)控、規(guī)則配置等功能。

Sentinel 核心庫不依賴 Sentinel Dashboard,但兩者結合使用可以有效的提高效率,讓 Sentinel 發(fā)揮它最大的作用。

Sentinel的工作機制

  • 對主流框架提供適配或者顯示的 API,來定義需要保護的資源,并提供設施對資源進行實時統(tǒng)計和調(diào)用鏈路分析。
  • 根據(jù)預設的規(guī)則,結合對資源的實時統(tǒng)計信息,對流量進行控制。同時,Sentinel 提供開放的接口,方便您定義及改變規(guī)則。
  • Sentinel 提供實時的監(jiān)控系統(tǒng),方便您快速了解目前系統(tǒng)的狀態(tài)

Sentinel 的開發(fā)流程

Sentinel 的開發(fā)流程如下:

  • 引入Sentinel依賴:在項目中引入 Sentinel 的依賴,將 Sentinel 整合到項目中;

  • 定義資源:通過對主流框架提供適配或 Sentinel 提供的顯式 API 和注解,可以定義需要保護的資源,此外 Sentinel 還提供了資源的實時統(tǒng)計和調(diào)用鏈路分析;

  • 定義規(guī)則:根據(jù)實時統(tǒng)計信息,對資源定義規(guī)則,例如流控規(guī)則、熔斷規(guī)則、熱點規(guī)則、系統(tǒng)規(guī)則以及授權規(guī)則等。

  • 檢驗規(guī)則是否在生效:運行程序,檢驗規(guī)則是否生效,查看效果。

引入Sentinel的Maven依賴

如果您的應用使用了 Maven,則在 pom.xml 文件中加入以下代碼即可:

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

如果您未使用依賴管理工具,請到 Maven Center Repository 直接下載 JAR 包。

image

Sentinel的基本概念

Sentinel的基本概念有兩個部分,它們分別是:資源和規(guī)則。

資源

「資源」 是Sentinel的關鍵概念。它可以是Java應用程序中的任何內(nèi)容,例如由應用程序提供的服務或者是服務里的方法,甚至可以是一段代碼。

資源的定義

通過Sentinel提供的API來定義一個資源,使其能夠被Sentinel保護起來,通常情況下,我們可以使用方法名、URL 甚至是服務名來作為資源名來描述某個資源。

只要通過 Sentinel API 定義的代碼,就是資源,能夠被Sentinel保護起來。大部分情況下,可以使用方法簽名,URL,甚至服務名稱作為資源名來標示資源。

采用原生API的模式

最常用的資源是我們代碼中的Java方法,也可以更靈活的定義你的資源。例如,把需要控制流量的代碼用Sentinel API的SphU.entry("resourceName")entry.exit() 包圍起來即可。參考代碼如下:

public static void main(String[] args) {
    // 配置規(guī)則.
    initFlowRules();
    while (true) {
        // 1.5.0版本開始可以直接利用 try-with-resources 特性
        try (Entry entry = SphU.entry("resourceName")) {
            // 被保護的邏輯
            System.out.println("resource");
     } catch (BlockException ex) {
            // 處理被流控的邏輯
        System.out.println("blocked!");
     }
    }
}

在上面的例子中,將System.out.println("resource"); 作為資源(被保護的邏輯),用 API 包裝起來。完成以上兩步后,代碼端的改造就完成了。

采用AOP注解的模式

通過提供的@SentinelResource注解支持模塊,來定義我們的資源,@SentinelResource注解是Sentinel提供的最重要的注解之一,它還包含了多個屬性,如下表。

屬性 說明 必填與否 使用要求
value 用于指定資源的名稱 必填 ——
entryType entry 類型 可選項(默認為 EntryType.OUT) ——
blockHandler 服務限流后會拋出 BlockException 異常,而 blockHandler 則是用來指定一個函數(shù)來處理 BlockException 異常的。簡單點說,該屬性用于指定服務限流后的后續(xù)處理邏輯。 可選項 blockHandler 函數(shù)訪問范圍需要是 public;返回類型需要與原方法相匹配;參數(shù)類型需要和原方法相匹配并且最后加一個額外的參數(shù),類型為 BlockException;blockHandler 函數(shù)默認需要和原方法在同一個類中,若希望使用其他類的函數(shù),則可以指定 blockHandler 為對應的類的 Class 對象,注意對應的函數(shù)必需為 static 函數(shù),否則無法解析。
blockHandlerClass 若 blockHandler 函數(shù)與原方法不在同一個類中,則需要使用該屬性指定 blockHandler 函數(shù)所在的類。 可選項 不能單獨使用,必須與 blockHandler 屬性配合使用;該屬性指定的類中的 blockHandler 函數(shù)必須為 static 函數(shù),否則無法解析。
fallback 用于在拋出異常(包括 BlockException)時,提供 fallback 處理邏輯。fallback 函數(shù)可以針對所有類型的異常(除了 exceptionsToIgnore 里面排除掉的異常類型)進行處理。 可選項 返回值類型必須與原函數(shù)返回值類型一致;方法參數(shù)列表需要和原函數(shù)一致,或者可以額外多一個 Throwable 類型的參數(shù)用于接收對應的異常;fallback 函數(shù)默認需要和原方法在同一個類中,若希望使用其他類的函數(shù),則可以指定 fallbackClass 為對應的類的 Class 對象,注意對應的函數(shù)必需為 static 函數(shù),否則無法解析。
fallbackClass 若fallback函數(shù)與原方法不在同一個類中,則需要使用該屬性指定 fallback 函數(shù)所在的類。 可選項 不能單獨使用,必須與 fallback 或 defaultFallback 屬性配合使用;該屬性指定的類中的 fallback 函數(shù)必須為 static 函數(shù),否則無法解析。
defaultFallback 默認的 fallback 函數(shù)名稱,通常用于通用的 fallback 邏輯(即可以用于很多服務或方法)。默認 fallback 函數(shù)可以針對所以類型的異常(除了 exceptionsToIgnore 里面排除掉的異常類型)進行處理。 可選項 返回值類型必須與原函數(shù)返回值類型一致;方法參數(shù)列表需要為空,或者可以額外多一個 Throwable 類型的參數(shù)用于接收對應的異常;defaultFallback 函數(shù)默認需要和原方法在同一個類中。若希望使用其他類的函數(shù),則可以指定 fallbackClass 為對應的類的 Class 對象,注意對應的函數(shù)必需為 static 函數(shù),否則無法解析。
exceptionsToIgnore 用于指定哪些異常被排除掉,不會計入異常統(tǒng)計中,也不會進入 fallback 邏輯中,而是會原樣拋出。 可選項 ——

注意:在 Sentinel 1.6.0 之前,fallback 函數(shù)只針對降級異常(DegradeException)進行處理,不能處理業(yè)務異常。

使用注解模式的定義資源的代碼:

@SentinelResource("resourceName")
public void helloWorld() {
    // 資源中的邏輯
    System.out.println("resource");
}

注意:注解支持模塊需要配合 Spring AOP 或者 AspectJ 一起使用。

規(guī)則

「規(guī)則」 是圍繞資源而設定的,Sentinel支持 流量控制、熔斷降級、系統(tǒng)保護、來源訪問控制和熱點參數(shù) 等多種規(guī)則,所有這些規(guī)則都可以動態(tài)實時調(diào)整。

規(guī)則定義

通過流控規(guī)則來指定允許該資源通過的請求次數(shù),例如下面的代碼定義了資源,每秒最多只能通過 20 個請求。

private static void initFlowRules(){
    List<FlowRule> rules = new ArrayList<>();
    FlowRule rule = new FlowRule();
    rule.setResource("HelloWorld");
    rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
    // Set limit QPS to 20.
    rule.setCount(20);
    rules.add(rule);
    FlowRuleManager.loadRules(rules);
}

完成上面步驟之后,Sentinel 就能夠正常工作了。

檢查效果

當服務運行之后,我們可以在日志 ~/logs/csp/${appName}-metrics.log.xxx 里看到下面的輸出:

|--timestamp-|------date time----|--resource-|p |block|s |e|rt
1529999204000|2022-06-26 15:41:44| resource |20|0    |20|0|0
1529999205000|2022-06-26 15:41:45| resource |20|5579 |20|0|728
1529999206000|2022-06-26 15:41:46| resource |20|15698|20|0|0
1529991207000|2022-06-26 15:41:47| resource |20|19262|20|0|0
1529993308000|2022-06-26 15:41:48| resource |20|19502|20|0|0
1529991209000|2022-06-26 15:41:49| resource  |20|18386|20|0|0
  • p 代表通過的請求
  • block 代表被阻止的請求
  • s 代表成功執(zhí)行完成的請求個數(shù)
  • e 代表用戶自定義的異常
  • rt 代表平均響應時長。

可以看到,這個程序每秒穩(wěn)定輸出 "resource" 20 次,和規(guī)則中預先設定的閾值是一樣的。

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

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

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