1. 程式人生 > 實用技巧 >SpringCloud Alibaba (三):Sentinel 流量控制元件

SpringCloud Alibaba (三):Sentinel 流量控制元件

SpringCloud Alibaba (三):Sentinel 流量控制元件

Sentinel 是什麼

隨著微服務的流行,服務和服務之間的穩定性變得越來越重要。Sentinel 是面向分散式服務架構的流量控制元件,主要以流量為切入點,從限流、流量整形、熔斷降級、系統負載保護、熱點防護等多個維度來幫助開發者保障微服務的穩定性。

Sentinel 基本概念

資源

資源是 Sentinel 的關鍵概念。它可以是 Java 應用程式中的任何內容,例如,由應用程式提供的服務,或由應用程式呼叫的其它應用提供的服務,甚至可以是一段程式碼。

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

規則

圍繞資源的實時狀態設定的規則,可以包括流量控制規則、熔斷降級規則以及系統保護規則。所有規則可以動態實時調整。

規則的種類

Sentinel 的所有規則都可以在記憶體態中動態地查詢及修改,修改之後立即生效。同時 Sentinel 也提供相關 API,供您來定製自己的規則策略。

Sentinel 支援以下幾種規則:流量控制規則熔斷降級規則系統保護規則來源訪問控制規則熱點引數規則

流量控制規則 (FlowRule)

流量規則的定義0

重要屬性:

Field 說明 預設值
resource 資源名,資源名是限流規則的作用物件
count 限流閾值
grade 限流閾值型別,QPS 或執行緒數模式 QPS 模式
limitApp 流控針對的呼叫來源 default,代表不區分呼叫來源
strategy 呼叫關係限流策略:直接、鏈路、關聯 根據資源本身(直接)
controlBehavior 流控效果(直接拒絕 / 排隊等待 / 慢啟動模式),不支援按呼叫關係限流 直接拒絕

同一個資源可以同時有多個限流規則。

通過程式碼定義流量控制規則

理解上面規則的定義之後,我們可以通過呼叫 FlowRuleManager.loadRules() 方法來用硬編碼的方式定義流量控制規則,比如:

private static void initFlowQpsRule() {
List<FlowRule> rules = new ArrayList<>();
FlowRule rule1 = new FlowRule();
rule1.setResource(resource);
// Set max qps to 20
rule1.setCount(20);
rule1.setGrade(RuleConstant.FLOW_GRADE_QPS);
rule1.setLimitApp("default");
rules.add(rule1);
FlowRuleManager.loadRules(rules);
}

更多詳細內容可以參考 流量控制

熔斷降級規則 (DegradeRule)

熔斷降級規則包含下面幾個重要的屬性:

Field 說明 預設值
resource 資源名,即限流規則的作用物件
count 閾值
grade 熔斷策略,支援秒級 RT/秒級異常比例/分鐘級異常數 秒級平均 RT
timeWindow 降級的時間,單位為 s

同一個資源可以同時有多個降級規則。

理解上面規則的定義之後,我們可以通過呼叫 DegradeRuleManager.loadRules() 方法來用硬編碼的方式定義流量控制規則。

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

更多詳情可以參考 熔斷降級

系統保護規則 (SystemRule)

規則包含下面幾個重要的屬性:

Field 說明 預設值
highestSystemLoad load1 閾值,參考值 -1 (不生效)
avgRt 所有入口流量的平均響應時間 -1 (不生效)
maxThread 入口流量的最大併發數 -1 (不生效)
qps 所有入口資源的 QPS -1 (不生效)
highestCpuUsage 當前系統的 CPU 使用率(0.0-1.0) -1 (不生效)

理解上面規則的定義之後,我們可以通過呼叫 SystemRuleManager.loadRules() 方法來用硬編碼的方式定義流量控制規則。

private void initSystemProtectionRule() {
List<SystemRule> rules = new ArrayList<>();
SystemRule rule = new SystemRule();
rule.setHighestSystemLoad(10);
rules.add(rule);
SystemRuleManager.loadRules(rules);
}

更多詳情可以參考 系統自適應保護

訪問控制規則 (AuthorityRule)

很多時候,我們需要根據呼叫方來限制資源是否通過,這時候可以使用 Sentinel 的訪問控制(黑白名單)的功能。黑白名單根據資源的請求來源(origin)限制資源是否通過,若配置白名單則只有請求來源位於白名單內時才可通過;若配置黑名單則請求來源位於黑名單時不通過,其餘的請求通過。

授權規則,即黑白名單規則(AuthorityRule)非常簡單,主要有以下配置項:

  • resource:資源名,即限流規則的作用物件

  • limitApp:對應的黑名單/白名單,不同 origin 用 , 分隔,如 appA,appB

  • strategy:限制模式,AUTHORITY_WHITE 為白名單模式,AUTHORITY_BLACK 為黑名單模式,預設為白名單模式

更多詳情可以參考 來源訪問控制

熱點規則 (ParamFlowRule)

詳情可以參考 熱點引數限流

Sentinel控制檯

概述

Sentinel 提供一個輕量級的開源控制檯,它提供機器發現以及健康情況管理、監控(單機和叢集),規則管理和推送的功能。另外,鑑權在生產環境中也必不可少。這裡,我們將會詳細講述如何通過簡單的步驟就可以使用這些功能。

接下來,我們將會逐一介紹如何整合 Sentinel 核心庫和 Dashboard,讓它發揮最大的作用。同時我們也在阿里雲上提供企業級的控制檯:AHAS Sentinel 控制檯,您只需要幾個簡單的步驟,就能最直觀地看到控制檯如何實現這些功能。

Sentinel 控制檯包含如下功能:

  • 檢視機器列表以及健康情況:收集 Sentinel 客戶端傳送的心跳包,用於判斷機器是否線上。

  • 監控 (單機和叢集聚合):通過 Sentinel 客戶端暴露的監控 API,定期拉取並且聚合應用監控資訊,最終可以實現秒級的實時監控。

  • 規則管理和推送:統一管理推送規則。

  • 鑑權:生產環境中鑑權非常重要。這裡每個開發者需要根據自己的實際情況進行定製。

更詳細內容,訪問 https://github.com/alibaba/Sentinel/wiki

啟動Sentinel控制檯

1.在Sentinel的github上下載 sentinel-dashboard.jar

https://github.com/alibaba/Sentinel/releases

2.在sentinel-dashboard.jar所在資料夾執行cmd,在cmd裡執行以下啟動命令啟動sentinel-dashboard

java -Dserver.port=8081 -Dcsp.sentinel.dashboard.server=localhost:8081 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard-1.7.2.jar

3.訪問 localhost:8081,進入Sentinel控制檯,預設使用者和密碼都是 sentinel

SpringCloud Alibaba 整合 Sentinel

Sentinel 可以簡單的分為 Sentinel 核心庫和 Dashboard。核心庫不依賴 Dashboard,但是結合 Dashboard 可以取得最好的效果。

我們說的資源,可以是任何東西,服務,服務裡的方法,甚至是一段程式碼。使用 Sentinel 來進行資源保護,主要分為幾個步驟:

  1. 定義資源

  2. 定義規則

  3. 檢驗規則是否生效

先把可能需要保護的資源定義好,之後再配置規則。也可以理解為,只要有了資源,我們就可以在任何時候靈活地定義各種流量控制規則。在編碼的時候,只需要考慮這個程式碼是否需要保護,如果需要保護,就將之定義為一個資源。

定義資源

1. 新增依賴

注意:在整合spring-cloud-starter-alibaba-sentinelspring-cloud-starter-openfeign時,feign-core的版本要在10.1.0以上,即匯入2.1.0.RELEASE或以上版本的openfeign,否則會報feign.RequestTemplate.path()Ljava/lang/String;異常,因為低版本openfeign的RequestTemplate類裡沒有path方法

<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
<version>2.1.0.RELEASE</version>
</dependency>
2.新增配置
server:
port: 8080

spring:
application:
name: consumer-8080
cloud:
nacos:
discovery:
server-addr: 192.168.11.132:8848
sentinel:
transport:
dashboard: localhost:8081 # 將服務註冊到sentinel控制檯

feign:
sentinel:
enabled: true #開啟feign的sentinel支援

management:
endpoints:
web:
exposure:
include: "*"
3.在controller需要保護的方法新增 @SentinelResource 註解,把方法定義為資源
@RestController
public class FeignController {

@Autowired
private EchoService echoService; @SentinelResource(value = "echo", blockHandler = "echoBlockHandler", blockHandlerClass = EchoServiceBlockHandler.class)
@GetMapping("/feign/echo/{string}")
public String echo(@PathVariable("string")String string){
return echoService.echo(string);
}

}

@SentinelResource 用於定義資源,並提供可選的異常處理和 fallback 配置項。 @SentinelResource 註解包含以下屬性:

  • value:資源名稱,必需項(不能為空)

  • entryType:entry 型別,可選項(預設為 EntryType.OUT

  • blockHandler / blockHandlerClass: blockHandler 對應處理 BlockException 的函式名稱,可選項。blockHandler 函式訪問範圍需要是 public,返回型別需要與原方法相匹配,引數型別需要和原方法相匹配並且最後加一個額外的引數,型別為 BlockException。blockHandler 函式預設需要和原方法在同一個類中。若希望使用其他類的函式,則可以指定 blockHandlerClass 為對應的類的 Class 物件,注意對應的函式必需為 static 函式,否則無法解析。

  • fallback:fallback 函式名稱,可選項,用於在丟擲異常的時候提供 fallback 處理邏輯。fallback 函式可以針對所有型別的異常(除了 exceptionsToIgnore裡面排除掉的異常型別)進行處理。fallback 函式簽名和位置要求:

    • 返回值型別必須與原函式返回值型別一致;

    • 方法引數列表需要和原函式一致,或者可以額外多一個 Throwable 型別的引數用於接收對應的異常。

    • fallback 函式預設需要和原方法在同一個類中。若希望使用其他類的函式,則可以指定 fallbackClass 為對應的類的 Class 物件,注意對應的函式必需為 static 函式,否則無法解析。

  • defaultFallback(since 1.6.0):預設的 fallback 函式名稱,可選項,通常用於通用的 fallback 邏輯(即可以用於很多服務或方法)。預設 fallback 函式可以針對所以型別的異常(除了 exceptionsToIgnore 裡面排除掉的異常型別)進行處理。若同時配置了 fallback 和 defaultFallback,則只有 fallback 會生效。defaultFallback 函式簽名要求:

    • 返回值型別必須與原函式返回值型別一致。

    • 方法引數列表需要為空,或者可以額外多一個 Throwable 型別的引數用於接收對應的異常。

    • defaultFallback 函式預設需要和原方法在同一個類中。若希望使用其他類的函式,則可以指定 fallbackClass 為對應的類的 Class 物件,注意對應的函式必需為 static 函式,否則無法解析。

  • exceptionsToIgnore(since 1.6.0):用於指定哪些異常被排除掉,不會計入異常統計中,也不會進入 fallback 邏輯中,而是會原樣丟擲。

blockHandler 和 fallback區別

blockHandler 函式會在原方法被限流/降級/系統保護的時候呼叫,而 fallback 函式會針對所有型別的異常。

如果一個資源同時對 blockHandler 和 fallback 都進行了配置,除了流量控制規則觸發時丟擲的 BlockException 會進入 blockHandler 處理邏輯,其他規則觸發時都會進入fallback處理邏輯

4.建立EchoServiceBlockHandler類,建立blockHandler 處理邏輯
public class EchoServiceBlockHandler {

private final static Logger logger = LoggerFactory.getLogger(EchoServiceBlockHandler.class);

public static String echoBlockHandler(String string, BlockException e){
logger.error("error: "+e);
return "方法請求降級中";
}

}

在應用程式裡定義規則

1.在啟動類中定義規則,並加入容器中
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class Consumer8080 {
public static void main(String[] args) {
SpringApplication.run(Consumer8080.class, args);
}

@Bean
public SentinelResourceAspect sentinelResourceAspect(){
return new SentinelResourceAspect();
}

//流量控制規則
@Bean
public static void initFlowRule(){
List<FlowRule> rules = new ArrayList<FlowRule>();
FlowRule flowRule = new FlowRule();
flowRule.setResource("echo"); //設定資源名,即流量控制規則的作用物件
flowRule.setCount(2); //設定限流閾值,此為QPS,即每秒最高訪問量
flowRule.setGrade(RuleConstant.FLOW_GRADE_QPS); //限流閾值型別,QPS或執行緒數
rules.add(flowRule);
FlowRuleManager.loadRules(rules);
}

}
2.訪問測試

訪問 http://localhost:8080/feign/echo/hi ,快速重新整理,觸發流量控制規則,呼叫降級邏輯

在Sentinel控制檯定義規則

在Sentinel控制檯上我們可以簡單、靈活地管理規則以及推送規則,但是要注意的是,在Sentinel控制檯上定義的規則是不會被持久化的,僅在記憶體中生存,當你重啟應用時,在Sentinel控制檯上定義的規則將會丟失(應用程式裡定義的規則在sentinel控制檯上刪除,應用重啟後會重新生效)

我的個人部落格站

自動判斷
中文
中文(簡體)
中文(香港)
中文(繁體)
英語
日語
朝鮮語
德語
法語
俄語
泰語
南非語
阿拉伯語
亞塞拜然語
比利時語
保加利亞語
加泰隆語
捷克語
威爾士語
丹麥語
第維埃語
希臘語
世界語
西班牙語
愛沙尼亞語
巴士克語
法斯語
芬蘭語
法羅語
加里西亞語
古吉拉特語
希伯來語
印地語
克羅埃西亞語
匈牙利語
亞美尼亞語
印度尼西亞語
冰島語
義大利語
喬治亞語
哈薩克語
卡納拉語
孔卡尼語
吉爾吉斯語
立陶宛語
拉脫維亞語
毛利語
馬其頓語
蒙古語
馬拉地語
馬來語
馬耳他語
挪威語(伯克梅爾)
荷蘭語
北梭託語
旁遮普語
波蘭語
葡萄牙語
克丘亞語
羅馬尼亞語
梵文
北薩摩斯語
斯洛伐克語
斯洛維尼亞語
阿爾巴尼亞語
瑞典語
斯瓦希里語
敘利亞語
泰米爾語
泰盧固語
塔加路語
茨瓦納語
土耳其語
宗加語
韃靼語
烏克蘭語
烏都語
烏茲別克語
越南語
班圖語
祖魯語

自動選擇
中文
中文(簡體)
中文(香港)
中文(繁體)
英語
日語
朝鮮語
德語
法語
俄語
泰語
南非語
阿拉伯語
亞塞拜然語
比利時語
保加利亞語
加泰隆語
捷克語
威爾士語
丹麥語
第維埃語
希臘語
世界語
西班牙語
愛沙尼亞語
巴士克語
法斯語
芬蘭語
法羅語
加里西亞語
古吉拉特語
希伯來語
印地語
克羅埃西亞語
匈牙利語
亞美尼亞語
印度尼西亞語
冰島語
義大利語
喬治亞語
哈薩克語
卡納拉語
孔卡尼語
吉爾吉斯語
立陶宛語
拉脫維亞語
毛利語
馬其頓語
蒙古語
馬拉地語
馬來語
馬耳他語
挪威語(伯克梅爾)
荷蘭語
北梭託語
旁遮普語
波蘭語
葡萄牙語
克丘亞語
羅馬尼亞語
梵文
北薩摩斯語
斯洛伐克語
斯洛維尼亞語
阿爾巴尼亞語
瑞典語
斯瓦希里語
敘利亞語
泰米爾語
泰盧固語
塔加路語
茨瓦納語
土耳其語
宗加語
韃靼語
烏克蘭語
烏都語
烏茲別克語
越南語
班圖語
祖魯語

有道翻譯
百度翻譯
谷歌翻譯
谷歌翻譯(國內)

翻譯 朗讀 複製 正在查詢,請稍候…… 重試 朗讀 複製 複製 朗讀 複製 via 谷歌翻譯(國內)