Sentinel 的使用可以分為兩個部分:
- 核心庫(Java 用戶端):不依賴任何架構/庫,能夠運作于 Java 7 及以上的版本的運作時環境,同時對 Dubbo / Spring Cloud 等架構也有較好的支援(見 主流架構适配)。
- 控制台(Dashboard):控制台主要負責管理推送規則、監控、叢集限流配置設定管理、機器發現等。
1. 引入 Sentinel 依賴
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
2. 入門案例
資源 是 Sentinel 中的核心概念之一。最常用的資源是我們代碼中的 Java 方法。 當然,您也可以更靈活的定義你的資源,例如,把需要控制流量的代碼用 Sentinel API
SphU.entry("HelloWorld")
和
entry.exit()
包圍起來即可。在下面的例子中,我們将
System.out.println("hello world");
作為資源(被保護的邏輯),用 API 包裝起來。參考代碼如下:
SentinelService.java
package cn.javayuli.service;
import com.alibaba.csp.sentinel.Entry;
import com.alibaba.csp.sentinel.SphU;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.RuleConstant;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
/**
* 限流測試
* @author hanguilin
*/
@Service
public class SentinelService {
/**
* 處理請求
*/
public void handleRquest() {
// 配置規則.
initFlowRules();
// 1.5.0 版本開始可以直接利用 try-with-resources 特性,自動 exit entry
try (Entry entry = SphU.entry("HelloWorld")) {
// 被保護的邏輯
System.out.println("hello world");
} catch (BlockException ex) {
// 處理被流控的邏輯
System.out.println("blocked!");
}
}
/**
* 配置流控規則, QPS最大20
*/
private 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);
}
}
SentinelController.java
package cn.javayuli.controller;
import cn.javayuli.service.SentinelService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 限流測試
* @author hanguilin
*/
@RestController
public class SentinelController {
@Autowired
private SentinelService sentinelService;
/**
* 請求資源
*/
@GetMapping("getSource")
public void doGetSource () {
sentinelService.handleRquest();
}
}
3.檢查結果
啟動項目,并使用Jmeter進行壓測
配置1秒發送18個請求

配置通路接口
控制台正常列印
hello world
現在把18調成30,發現已經被鎖住了
Demo 運作之後,我們可以在日志
${currentUser}/logs/csp/${appName}-metrics.log.xxx
裡看到下面的輸出:
|--timestamp-|------date time----|--resource-|p |block|s |e|rt
1608555871000|2020-12-21 21:04:31|/getSource|10|0|10|0|42|0|0|1
1608555871000|2020-12-21 21:04:31|HelloWorld|10|0|10|0|0|0|0|0
1608555871000|2020-12-21 21:04:31|__total_inbound_traffic__|10|0|10|0|42|0|0|0
1608555872000|2020-12-21 21:04:32|/getSource|20|0|20|0|1|0|0|1
1608555872000|2020-12-21 21:04:32|HelloWorld|15|5|15|0|0|0|0|0
1608555872000|2020-12-21 21:04:32|__total_inbound_traffic__|20|0|20|0|1|0|0|0
其中
p
代表通過的請求,
block
代表被阻止的請求,
s
代表成功執行完成的請求個數,
e
代表使用者自定義的異常,
rt
代表平均響應時長。
4.熔斷降級
Sentinel 提供了
@SentinelResource
注解用于定義資源,并提供了 AspectJ 的擴充用于自動定義資源、處理
BlockException
等
@SentinelResource
用于定義資源,并提供可選的異常處理和 fallback 配置項。
@SentinelResource
注解包含以下屬性:
-
:資源名稱,必需項(不能為空)value
-
:entry 類型,可選項(預設為entryType
)EntryType.OUT
-
/blockHandler
:blockHandlerClass
對應處理blockHandler
的函數名稱,可選項。blockHandler 函數通路範圍需要是BlockException
,傳回類型需要與原方法相比對,參數類型需要和原方法相比對并且最後加一個額外的參數,類型為public
。blockHandler 函數預設需要和原方法在同一個類中。若希望使用其他類的函數,則可以指定BlockException
為對應的類的blockHandlerClass
對象,注意對應的函數必需為 static 函數,否則無法解析。Class
-
/fallback
:fallback 函數名稱,可選項,用于在抛出異常的時候提供 fallback 處理邏輯。fallback 函數可以針對所有類型的異常(除了fallbackClass
裡面排除掉的異常類型)進行處理。fallback 函數簽名和位置要求:exceptionsToIgnore
- 傳回值類型必須與原函數傳回值類型一緻;
- 方法參數清單需要和原函數一緻,或者可以額外多一個
類型的參數用于接收對應的異常。Throwable
- fallback 函數預設需要和原方法在同一個類中。若希望使用其他類的函數,則可以指定
為對應的類的fallbackClass
對象,注意對應的函數必需為 static 函數,否則無法解析。Class
-
(since 1.6.0):預設的 fallback 函數名稱,可選項,通常用于通用的 fallback 邏輯(即可以用于很多服務或方法)。預設 fallback 函數可以針對所有類型的異常(除了defaultFallback
裡面排除掉的異常類型)進行處理。若同時配置了 fallback 和 defaultFallback,則隻有 fallback 會生效。defaultFallback 函數簽名要求:exceptionsToIgnore
- 傳回值類型必須與原函數傳回值類型一緻;
- 方法參數清單需要為空,或者可以額外多一個
類型的參數用于接收對應的異常。Throwable
- defaultFallback 函數預設需要和原方法在同一個類中。若希望使用其他類的函數,則可以指定
為對應的類的fallbackClass
對象,注意對應的函數必需為 static 函數,否則無法解析。Class
-
(since 1.6.0):用于指定哪些異常被排除掉,不會計入異常統計中,也不會進入 fallback 邏輯中,而是會原樣抛出。exceptionsToIgnore
1.8.0 版本開始,
defaultFallback
支援在類級别進行配置。
注:1.6.0 之前的版本 fallback 函數隻針對降級異常( DegradeException
)進行處理,不能針對業務異常進行處理。
特别地,若 blockHandler 和 fallback 都進行了配置,則被限流降級而抛出
BlockException
時隻會進入
blockHandler
處理邏輯。若未配置
blockHandler
、
fallback
和
defaultFallback
,則被限流降級時會将
BlockException
直接抛出(若方法本身未定義 throws BlockException 則會被 JVM 包裝一層
UndeclaredThrowableException
)。
從 1.4.0 版本開始,注解方式定義資源支援自動統計業務異常,無需手動調用
Tracer.trace(ex)
來記錄業務異常。Sentinel 1.4.0 以前的版本需要自行調用
Tracer.trace(ex)
來記錄業務異常。
配置
Spring Cloud Alibaba
若您是通過 Spring Cloud Alibaba 接入的 Sentinel,則無需額外進行配置即可使用
@SentinelResource
注解。
Spring AOP
若您的應用使用了 Spring AOP(無論是 Spring Boot 還是傳統 Spring 應用),您需要通過配置的方式将
SentinelResourceAspect
注冊為一個 Spring Bean:
@Configuration
public class SentinelAspectConfiguration {
@Bean
public SentinelResourceAspect sentinelResourceAspect() {
return new SentinelResourceAspect();
}
}
我們提供了 Spring AOP 的示例,可以參見 sentinel-demo-annotation-spring-aop。
AspectJ
若您的應用直接使用了 AspectJ,那麼您需要在
aop.xml
檔案中引入對應的 Aspect:
<aspects>
<aspect name="com.alibaba.csp.sentinel.annotation.aspectj.SentinelResourceAspect"/>
</aspects>
DEMO
系列源代碼GitHub位址spring-cloud-demo
代碼
/**
* hello
*
* @param s
* @return
*/
@SentinelResource(value = "hello", blockHandler = "exceptionHandler", fallback = "helloFallback")
public String hello(long s) {
if (s == 0) {
throw new RuntimeException("error");
}
return String.format("Hello at %d", s);
}
/**
* Fallback 函數,函數簽名與原函數一緻或加一個 Throwable 類型的參數.
*
* @param s
* @return
*/
public String helloFallback(long s) {
return String.format("Halooooo %d", s);
}
/**
* Block 異常處理函數,參數最後多一個 BlockException,其餘與原函數一緻.
*
* @param s
* @param ex
* @return
*/
public String exceptionHandler(long s, BlockException ex) {
// Do some log here.
ex.printStackTrace();
return "Oops, error occurred at " + s;
}
接口測試
傳入參數1
測試結果為正常調用的結果
參數0,測試結果為回調結果
5.Sentinel控制台
概述
Sentinel 提供一個輕量級的開源控制台,它提供機器發現以及健康情況管理、監控(單機和叢集),規則管理和推送的功能。另外,鑒權在生産環境中也必不可少。這裡,我們将會詳細講述如何通過簡單的步驟就可以使用這些功能。
接下來,我們将會逐一介紹如何整合 Sentinel 核心庫和 Dashboard,讓它發揮最大的作用。同時我們也在阿裡雲上提供企業級的控制台:AHAS Sentinel 控制台,您隻需要幾個簡單的步驟,就能最直覺地看到控制台如何實作這些功能。
Sentinel 控制台包含如下功能:
- 檢視機器清單以及健康情況:收集 Sentinel 用戶端發送的心跳包,用于判斷機器是否線上。
- 監控 (單機和叢集聚合):通過 Sentinel 用戶端暴露的監控 API,定期拉取并且聚合應用監控資訊,最終可以實作秒級的實時監控。
- 規則管理和推送:統一管理推送規則。
- 鑒權:生産環境中鑒權非常重要。這裡每個開發者需要根據自己的實際情況進行定制。
注意:Sentinel 控制台目前僅支援單機部署。
下載下傳
- jar包可以在release頁面進行下載下傳
- 或者下載下傳源碼,運作時需要自行打包
注意:啟動 Sentinel 控制台需要 JDK 版本為 1.8 及以上版本。
鑒權
從 Sentinel 1.5.0 開始,控制台提供通用的鑒權接口 AuthService,使用者可根據需求自行實作。
從 Sentinel 1.6.0 起,Sentinel 控制台引入基本的登入功能,預設使用者名和密碼都是
sentinel
。
使用者可以通過如下參數進行配置:
-
用于指定控制台的登入使用者名為-Dsentinel.dashboard.auth.username=sentinel
;sentinel
-
用于指定控制台的登入密碼為-Dsentinel.dashboard.auth.password=123456
;如果省略這兩個參數,預設使用者和密碼均為123456
;sentinel
-
用于指定 Spring Boot 服務端 session 的過期時間,如-Dserver.servlet.session.timeout=7200
表示 7200 秒;7200
表示 60 分鐘,預設為 30 分鐘;60m
同樣也可以直接在 Spring properties 檔案中進行配置。
服務端
使用如下指令啟動控制台:
java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard.jar
如若8080端口沖突,可使用
-Dserver.port=新端口
進行設定。
浏覽器打開localhost:8080,使用者名和密碼均為sentinel
用戶端
在application.yml中加入如下配置
spring:
cloud:
sentinel:
transport:
port: 8719
dashboard: localhost:8080
如果是用nacos作為配置中心,需要在nacos中配置應用的配置檔案
使用
如果我們想使用Sentinel的限流和熔斷功能,除了在代碼中可以寫死外,也可直接通過控制台進行粗略的對接口進行限流和熔斷。
在Controller中加入測試方法,注意此Controller使用的時@RestController注解,如果是@Controller,請給方法加上@ResponseBody注解
/**
* 請求資源
*/
@GetMapping("/testReq")
@SentinelResource("testSource")
public String doTest () {
return "test";
}
先調用一次該方法,友善被簇點鍊路收集,調用後,可在控制台->簇點鍊路中看到該資源
點選
+流控
新增規則
使用Jmeter進行測試,每秒執行10個請求
http請求
發現此處通過QPS最大限定值後,其餘請求都被拒絕