你若要喜愛你自己的價值,你就得給世界創造價值。
Sentinel的組成部分
Sentinel 主要由以下兩個部分組成。
-
Sentinel核心庫(Java客戶端) :Sentinel的核心庫不依賴任何框架或庫,能夠執行於Java 8及以上的版本的執行時環境中,同時對 Spring Cloud、Dubbo 等微服務框架提供了很好的支援。
-
Sentinel控制檯(Dashboard) :Sentinel提供的一個輕量級的開源控制檯,它為使用者提供了機器自發現、簇點鏈路自發現、監控、規則配置等功能。
Sentinel 核心庫不依賴 Sentinel Dashboard,但兩者結合使用可以有效的提高效率,讓 Sentinel 發揮它最大的作用。
Sentinel的工作機制
- 對主流框架提供適配或者顯示的 API,來定義需要保護的資源,並提供設施對資源進行實時統計和呼叫鏈路分析。
- 根據預設的規則,結合對資源的實時統計資訊,對流量進行控制。同時,Sentinel 提供開放的介面,方便您定義及改變規則。
- Sentinel 提供實時的監控系統,方便您快速瞭解目前系統的狀態
Sentinel 的開發流程
Sentinel 的開發流程如下:
-
引入Sentinel依賴:在專案中引入 Sentinel 的依賴,將 Sentinel 整合到專案中;
-
定義資源:透過對主流框架提供適配或 Sentinel 提供的顯式 API 和註解,可以定義需要保護的資源,此外 Sentinel 還提供了資源的實時統計和呼叫鏈路分析;
-
定義規則:根據實時統計資訊,對資源定義規則,例如流控規則、熔斷規則、熱點規則、系統規則以及授權規則等。
-
檢驗規則是否在生效:執行程式,檢驗規則是否生效,檢視效果。
引入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 包。
Sentinel的基本概念
Sentinel的基本概念有兩個部分,它們分別是:資源和規則。
資源
「資源」 是Sentinel的關鍵概念。它可以是Java應用程式中的任何內容,例如由應用程式提供的服務或者是服務裡的方法,甚至可以是一段程式碼。
資源的定義
透過Sentinel提供的API來定義一個資源,使其能夠被Sentinel保護起來,通常情況下,我們可以使用方法名、URL 甚至是服務名來作為資源名來描述某個資源。
只要透過 Sentinel API 定義的程式碼,就是資源,能夠被Sentinel保護起來。大部分情況下,可以使用方法簽名,URL,甚至服務名稱作為資源名來標示資源。
採用原生API的模式
最常用的資源是我們程式碼中的Java方法,也可以更靈活的定義你的資源。例如,把需要控制流量的程式碼用Sentinel API的SphU.entry("resourceName")
和entry.exit()
包圍起來即可。參考程式碼如下:
public static void main(String[] args) {
// 配置規則.
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 則是用來指定一個函式來處理 BlockException 異常的。簡單點說,該屬性用於指定服務限流後的後續處理邏輯。 | 可選項 | blockHandler 函式訪問範圍需要是 public;返回型別需要與原方法相匹配;引數型別需要和原方法相匹配並且最後加一個額外的引數,型別為 BlockException;blockHandler 函式預設需要和原方法在同一個類中,若希望使用其他類的函式,則可以指定 blockHandler 為對應的類的 Class 物件,注意對應的函式必需為 static 函式,否則無法解析。 |
blockHandlerClass | 若 blockHandler 函式與原方法不在同一個類中,則需要使用該屬性指定 blockHandler 函式所在的類。 | 可選項 | 不能單獨使用,必須與 blockHandler 屬性配合使用;該屬性指定的類中的 blockHandler 函式必須為 static 函式,否則無法解析。 |
fallback | 用於在丟擲異常(包括 BlockException)時,提供 fallback 處理邏輯。fallback 函式可以針對所有型別的異常(除了 exceptionsToIgnore 裡面排除掉的異常型別)進行處理。 | 可選項 | 返回值型別必須與原函式返回值型別一致;方法引數列表需要和原函式一致,或者可以額外多一個 Throwable 型別的引數用於接收對應的異常;fallback 函式預設需要和原方法在同一個類中,若希望使用其他類的函式,則可以指定 fallbackClass 為對應的類的 Class 物件,注意對應的函式必需為 static 函式,否則無法解析。 |
fallbackClass | 若fallback函式與原方法不在同一個類中,則需要使用該屬性指定 fallback 函式所在的類。 | 可選項 | 不能單獨使用,必須與 fallback 或 defaultFallback 屬性配合使用;該屬性指定的類中的 fallback 函式必須為 static 函式,否則無法解析。 |
defaultFallback | 預設的 fallback 函式名稱,通常用於通用的 fallback 邏輯(即可以用於很多服務或方法)。預設 fallback 函式可以針對所以型別的異常(除了 exceptionsToIgnore 裡面排除掉的異常型別)進行處理。 | 可選項 | 返回值型別必須與原函式返回值型別一致;方法引數列表需要為空,或者可以額外多一個 Throwable 型別的引數用於接收對應的異常;defaultFallback 函式預設需要和原方法在同一個類中。若希望使用其他類的函式,則可以指定 fallbackClass 為對應的類的 Class 物件,注意對應的函式必需為 static 函式,否則無法解析。 |
exceptionsToIgnore | 用於指定哪些異常被排除掉,不會計入異常統計中,也不會進入 fallback 邏輯中,而是會原樣丟擲。 | 可選項 | —— |
注意:在 Sentinel 1.6.0 之前,fallback 函式只針對降級異常(DegradeException)進行處理,不能處理業務異常。
使用註解模式的定義資源的程式碼:
@SentinelResource("resourceName")
public void helloWorld() {
// 資源中的邏輯
System.out.println("resource");
}
注意:註解支援模組需要配合 Spring AOP 或者 AspectJ 一起使用。
規則
「規則」 是圍繞資源而設定的,Sentinel支援 流量控制、熔斷降級、系統保護、來源訪問控制和熱點引數 等多種規則,所有這些規則都可以動態實時調整。
規則定義
透過流控規則來指定允許該資源透過的請求次數,例如下面的程式碼定義了資源,每秒最多隻能透過 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 代表成功執行完成的請求個數
- e 代表使用者自定義的異常
- rt 代表平均響應時長。
可以看到,這個程式每秒穩定輸出 "resource" 20 次,和規則中預先設定的閾值是一樣的。