Spring Boot4使用Sentinel進(jìn)行限流的操作方法
Sentinel介紹
隨著微服務(wù)的流行,服務(wù)和服務(wù)之間的穩(wěn)定性變得越來越重要。Sentinel 是面向分布式、多語言異構(gòu)化服務(wù)架構(gòu)的流量治理組件,主要以流量為切入點(diǎn),從流量路由、流量控制、流量整形、熔斷降級、系統(tǒng)自適應(yīng)過載保護(hù)、熱點(diǎn)流量防護(hù)等多個(gè)維度來幫助開發(fā)者保障微服務(wù)的穩(wěn)定性。
Sentinel 社區(qū)正在將流量治理相關(guān)標(biāo)準(zhǔn)抽出到 OpenSergo spec 中,Sentinel 作為流量治理標(biāo)準(zhǔn)實(shí)現(xiàn)

Sentinel規(guī)則類型
針對Sentinel的規(guī)則重新學(xué)習(xí)下,詳細(xì)使用文檔參見 官方文檔
| 規(guī)則類型 | 核心作用維度 | 典型應(yīng)用場景 | 觸發(fā)后果 | 作用 |
|---|---|---|---|---|
| 流控規(guī)則 (Flow) | 限制流量 (QPS/線程數(shù)) | 秒殺限流、防止突發(fā)流量沖垮系統(tǒng) | 請求被拒絕/排隊(duì)等待 | 防刷、防過載 |
| 熔斷規(guī)則 (Degrade) | 依賴穩(wěn)定性 (響應(yīng)時(shí)間/異常) | 調(diào)用第三方接口超時(shí)、數(shù)據(jù)庫慢查詢 | 暫停請求,快速失?。ㄈ蹟啵?/td> | 防雪崩、防依賴故障 |
| 熱點(diǎn)規(guī)則 (Param) | 參數(shù)粒度 (特定參數(shù)值) | 某個(gè)熱門商品被瘋狂刷,其他商品正常訪問 | 限制特定參數(shù)的訪問頻率 | 防熱點(diǎn)數(shù)據(jù)擊穿 |
| 系統(tǒng)規(guī)則 (System) | 整體負(fù)載 (CPU/Load/RT) | 大促期間防止機(jī)器過載,保護(hù)系統(tǒng)基線 | 拒絕部分請求,保護(hù)機(jī)器不掛 | 防機(jī)器掛掉 |
| 授權(quán)規(guī)則 (Auth) | 來源控制 (黑白名單) | 防止某個(gè)惡意 IP 或非法應(yīng)用調(diào)用接口 | 允許或拒絕請求 | 防非法調(diào)用 |
流控規(guī)則(Flow Control)
最常用的規(guī)則,主要用于限流,有如下2種模式
- QPS 模式:每秒允許多少個(gè)請求通過。超過閾值則攔截。
- 線程數(shù)模式:限制同時(shí)處理該資源的線程數(shù)量。
除了簡單的直接拒絕,它還有兩種高級策略:
- Warm Up (預(yù)熱):比如系統(tǒng)剛啟動(dòng),像冷車一樣,不能直接拉滿油門。預(yù)熱模式會(huì)在一定時(shí)間內(nèi)逐漸將閾值從低升到高,防止瞬間流量把剛啟動(dòng)的服務(wù)打掛。
- 排隊(duì)等待 (Queueing):不直接拒絕請求,而是讓請求按照設(shè)定的時(shí)間間隔勻速通過(像檢票口一樣),用于處理突發(fā)的脈沖流量。
熔斷規(guī)則 (Circuit Breaker)
關(guān)注服務(wù)的質(zhì)量。當(dāng)它發(fā)現(xiàn)某個(gè)服務(wù)調(diào)用“不健康”時(shí),會(huì)直接切斷連接,防止連鎖故障(雪崩)。
Sentinel 支持三種策略:
- 慢調(diào)用比例:如果一個(gè)接口的平均響應(yīng)時(shí)間(RT)太長(比如超過 1 秒),且比例達(dá)到閾值,就熔斷。適用于對響應(yīng)速度敏感的場景。
- 異常比例:如果請求中出現(xiàn)的異常(如拋出 RuntimeException)比例過高,就熔斷。
- 異常數(shù):統(tǒng)計(jì)時(shí)間內(nèi)出現(xiàn)的異常總數(shù)超過閾值,直接熔斷。
熔斷是“寧可錯(cuò)殺一百,不可放過一個(gè)”的保護(hù)機(jī)制。觸發(fā)后,所有請求直接走“降級邏輯”(fallback),不再調(diào)用下游真實(shí)服務(wù),直到經(jīng)過一段“冷卻時(shí)間”后嘗試恢復(fù)
熱點(diǎn)規(guī)則 (Hotspot Param)
流控規(guī)則的高級版,它能把限流的粒度細(xì)化到方法參數(shù)級別。
通常情況下,流控是對整個(gè)接口(如 /getProduct)限流。但熱點(diǎn)規(guī)則可以做到:當(dāng)參數(shù) id=1 的時(shí)候限流 100 QPS,而 id=2 的時(shí)候不限流
關(guān)注的是“不均勻”。在實(shí)際場景中,可能只有某個(gè)特定的“爆款”商品(熱點(diǎn) key)流量巨大,導(dǎo)致數(shù)據(jù)庫壓力大。如果對整個(gè)接口限流,會(huì)誤傷其他正常的商品查詢。熱點(diǎn)規(guī)則就是為了解決這種“貧富不均”的問題
系統(tǒng)規(guī)則 (System Protection)
全局視角的規(guī)則,它不針對某個(gè)具體的接口,而是針對整個(gè)應(yīng)用實(shí)例的系統(tǒng)指標(biāo)。
它監(jiān)控的指標(biāo)包括:
- Load(僅 Linux/Unix):系統(tǒng)平均負(fù)載。
- CPU 使用率。
- 入口 QPS。
- 線程數(shù)。
- 平均 RT。
“保底”機(jī)制。通常在單機(jī)的 QPS 或負(fù)載過高時(shí)觸發(fā),目的是讓系統(tǒng)整體保持在一個(gè)穩(wěn)定的水位,防止機(jī)器直接死機(jī)。它是一種兜底的保護(hù),通常配置的閾值會(huì)比機(jī)器的極限處理能力稍微保守一點(diǎn)
授權(quán)規(guī)則 (Authority Rule)
黑白名單機(jī)制,用于控制“誰可以調(diào)用”。
它通過 SentinelContext 中的 origin(來源標(biāo)識)來判斷。通常用來識別調(diào)用方的服務(wù)名、IP 地址等。 關(guān)注的是“身份”,可以使用黑名單 或白名單限制
Spring boot 4如何集成Sentinel?
本次采用@SentinelResource + AOP 方式集成 Sentinel
添加依賴
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-core</artifactId>
<version>1.8.9</version>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-parameter-flow-control</artifactId>
<version>1.8.9</version>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-annotation-aspectj</artifactId>
<version>1.8.9</version>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-transport-simple-http</artifactId>
<version>1.8.9</version>
</dependency>編寫相關(guān)的測試代碼
SentinelConfig類
@Configuration
public class SentinelConfig {
@PostConstruct
public 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(10);
rules.add(rule);
FlowRuleManager.loadRules(rules);
}
@PostConstruct
public void initDegradeRules() {
List<DegradeRule> rules = new ArrayList<>();
DegradeRule rule = new DegradeRule();
rule.setResource("HelloWorld");
rule.setGrade(RuleConstant.DEGRADE_GRADE_RT); // RT threshold degrade strategy
rule.setCount(200); // Max response time (ms)
rule.setTimeWindow(10); // Recovery timeout period in seconds
rules.add(rule);
DegradeRuleManager.loadRules(rules);
}
@Bean
public SentinelResourceAspect sentinelResourceAspect() {
return new SentinelResourceAspect();
}
}HelloWorldService
@Service
public class HelloWorldService {
@SentinelResource(value = "HelloWorld",
entryType = EntryType.IN,
exceptionsToIgnore = {IllegalStateException.class},
blockHandler = "handleBlock",
fallback = "handleFallback")
public String sayHello(String name) {
return "Hello, " + name;
}
public String handleBlock(String name, BlockException ex) {
return "Request blocked by Sentinel: " + ex.getClass().getSimpleName();
}
public String handleFallback(String name, Throwable t) {
return "Request failed and handled by fallback: " + t.getClass().getSimpleName();
}
}HelloWorldController
@RestController
@RequestMapping("/api")
@Tag(name = "登錄接口")
public class HelloWorldController {
@Autowired
private HelloWorldService helloWorldService;
@GetMapping("/hello")
@Operation(summary = "hello")
public String sayHello(@RequestParam(value = "name", defaultValue = "World") String name) {
return helloWorldService.sayHello(name);
}
}@SpringBootTest
@Slf4j
public class SentinelTest {
@Autowired
HelloWorldService helloWorldService;
private AtomicInteger successCount = new AtomicInteger(0);
private AtomicInteger blockCount = new AtomicInteger(0);
private AtomicInteger fallbackCount = new AtomicInteger(0);
@BeforeEach
public void setUp() throws Exception {
// Reset counters before each test
successCount.set(0);
blockCount.set(0);
fallbackCount.set(0);
}
@Test
public void testRateLimitingAndDegradation() throws InterruptedException {
log.info("準(zhǔn)備測試...............");
TimeUnit.SECONDS.sleep(5);
log.info("開始測試...............");
int numberOfThreads = 30; // Number of concurrent threads
ExecutorService executorService = Executors.newFixedThreadPool(numberOfThreads);
CountDownLatch latch = new CountDownLatch(numberOfThreads);
for (int i = 0; i < numberOfThreads; i++) {
executorService.submit(() -> {
try {
String result = helloWorldService.sayHello("TestUser");
if (result.contains("blocked")) {
blockCount.incrementAndGet();
} else if (result.contains("failed")) {
fallbackCount.incrementAndGet();
} else {
successCount.incrementAndGet();
}
} catch (Exception ex) {
System.out.println(ex.getMessage());
fallbackCount.incrementAndGet();
} finally {
latch.countDown();
}
});
}
latch.await(); // Wait until all threads have completed
log.info("Success count: " + successCount.get());
log.info("Blocked count: " + blockCount.get());
log.info("Fallback count: " + fallbackCount.get());
// Assuming the flow rule is set to allow up to 20 requests per second
assert successCount.get() <= 20 : "Number of successful requests should not exceed 20";
assert blockCount.get() > 0 : "Some requests should be blocked due to rate limiting";
assert fallbackCount.get() == 0 : "No requests should go to fallback under normal conditions";
executorService.shutdown();
}
}啟動(dòng)程序
啟動(dòng)sentinel-dashboard
java -Dserver.port=8858 -Dcsp.sentinel.dashboard.server=localhost:8858 -Dproject.name=sentinel-dashboard -Dsentinel.dashboard.auth.username=sentinel -Dsentinel.dashboard.auth.password=123456 -Dserver.servlet.session.timeout=7200 -jar sentinel-dashboard-1.8.9.jar
啟動(dòng)Springboot
注意在啟動(dòng)時(shí)需要添加VM參數(shù)
-Dcsp.sentinel.dashboard.server=localhost:8858
界面展示
通過界面可以針對規(guī)則進(jìn)行修改,保存后可以立即生效



附錄
限流常見配置參數(shù)速查表
| 概念 | 說明 | 適用場景 |
|---|---|---|
| QPS | 每秒查詢率 | 大促搶購、防止刷單 |
| 線程數(shù) | 并發(fā)占用線程數(shù) | 保護(hù)慢接口不占用所有線程池 |
| 快速失敗 | 超過閾值直接報(bào)錯(cuò) | 默認(rèn)策略,簡單粗暴 |
| Warm Up | 預(yù)熱模式,閾值緩慢升高 | 系統(tǒng)剛啟動(dòng),防止瞬間高流量壓垮 |
| 排隊(duì)等待 | 請求勻速通過,處理不急的請求 | 訂單創(chuàng)建等需要削峰填谷的場景 |
Token Server Cluster 部署方式對比
| 特性 | 嵌入模式 (Embedded) | 獨(dú)立模式 (Alone) |
|---|---|---|
| 部署成本 | 低 (利用現(xiàn)有資源) | 高 (需要獨(dú)立機(jī)器) |
| 隔離性 | 差 (與業(yè)務(wù)爭搶資源) | 好 (完全隔離) |
| 適用場景 | 中小規(guī)模集群、對成本敏感 | 超大規(guī)模集群、核心中間件、全局限流 |
| 容災(zāi)能力 | 依賴應(yīng)用集群的穩(wěn)定性 | 強(qiáng) (通常有主從熱備) |
| 運(yùn)維難度 | 簡單 | 較復(fù)雜 (需維護(hù) Server 集群) |
與springboot及springcloud版本對應(yīng)關(guān)系
| Spring Boot 版本 | 對應(yīng)的 Spring Cloud Alibaba (SCA) 版本 | 對應(yīng)的 Sentinel 版本 | 狀態(tài) |
|---|---|---|---|
| 2.3.x | 2.2.x.RELEASE | 1.7.x / 1.8.0 | 舊版,已不再主推 |
| 2.4.x, 2.5.x, 2.6.x, 2.7.x | 2021.x (如 2021.0.5.0) | 1.8.5 / 1.8.6 | 目前最主流的生產(chǎn)環(huán)境組合 |
| 3.0.x, 3.1.x | 2022.0.0.0 (or 2022.0.0.0-RC2) | 1.8.6 (有限支持) | 注意:原生 Web 適配器不支持,需用 Gateway 或特定適配 |
- Sentinel(通過 Spring Cloud Alibaba)實(shí)際上支持 Spring Boot 2.x 的全系版本
- Spring Boot 3.0 的變化:Spring Boot 3.0 強(qiáng)制要求 Java 17+,并且將底層的
javax.servlet(Java EE) 遷移為了jakarta.servlet(Jakarta EE)。 - Sentinel 對 Spring Boot 的支持在 3.0 上遇到了“斷層”,這才是目前版本選擇的核心痛點(diǎn)
- Sentinel 的現(xiàn)狀:
- Sentinel-core / sentinel-web-servlet:目前的主流穩(wěn)定版本(如 1.8.x)底層依然使用的是
javax.servlet.Filter。 - sentinel-spring-webmvc-adapter 目前使用的 springboot 2.5.x版本,servlet.api版本是3.1.0
- 不兼容:這意味著,如果你直接使用原生的
sentinel-web-servlet依賴,它是無法運(yùn)行在 Spring Boot 3.0 環(huán)境下的,會(huì)報(bào)ClassNotFoundException(找不到 javax 包)
- Sentinel-core / sentinel-web-servlet:目前的主流穩(wěn)定版本(如 1.8.x)底層依然使用的是
到此這篇關(guān)于Spring Boot4使用Sentinel進(jìn)行限流的操作方法的文章就介紹到這了,更多相關(guān)springboot sentinel限流內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- 詳解Springboot集成sentinel實(shí)現(xiàn)接口限流入門
- SpringBoot2.0+阿里巴巴Sentinel動(dòng)態(tài)限流實(shí)戰(zhàn)(附源碼)
- SpringBoot基于Sentinel在服務(wù)上實(shí)現(xiàn)接口限流
- Springboot?中使用Sentinel的詳細(xì)步驟
- 在SpringBoot項(xiàng)目中使用Spring Cloud Sentinel實(shí)現(xiàn)流量控制
- SpringBoot實(shí)現(xiàn)接口限流的常用方案
- SpringBoot實(shí)現(xiàn)API接口限流
- SpringBoot接口限流的實(shí)現(xiàn)方法小結(jié)
- Springboot項(xiàng)目接口限流實(shí)現(xiàn)方案
- SpringBoot高并發(fā)下控制限流的幾種實(shí)現(xiàn)方法
相關(guān)文章
spring框架中的本地緩存之spring cache基本使用詳解
Spring Cache 是 Spring 提供的一整套的緩存解決方案,它提供了一整套的接口和代碼規(guī)范、配置、注解等,這樣它就可以整合各種緩存方案了,本文給大家介紹spring框架中的本地緩存之spring cache基本使用,感興趣的朋友一起看看吧2025-05-05
如何在Java中調(diào)用python文件執(zhí)行詳解
豐富的第三方庫使得python非常適合用于進(jìn)行數(shù)據(jù)分析,最近在項(xiàng)目中就涉及到j(luò)ava調(diào)用python實(shí)現(xiàn)的算法,下面這篇文章主要給大家介紹了關(guān)于如何在Java中調(diào)用python文件執(zhí)行的相關(guān)資料,需要的朋友可以參考下2022-05-05
java數(shù)據(jù)結(jié)構(gòu)基礎(chǔ):棧
這篇文章主要介紹了Java的數(shù)據(jù)解構(gòu)基礎(chǔ),希望對廣大的程序愛好者有所幫助,同時(shí)祝大家有一個(gè)好成績,需要的朋友可以參考下,希望能給你帶來幫助2021-07-07
Java如何導(dǎo)出包含多個(gè)Sheet的Excel文件
這篇文章主要為大家詳細(xì)介紹了Java如何導(dǎo)出包含多個(gè)Sheet的Excel文件,文中一共介紹了兩種實(shí)現(xiàn)方法,有需要的小伙伴可以跟隨小編一起學(xué)習(xí)一下2025-07-07
解決springboot服務(wù)注冊到Eureka,端口總是默認(rèn)8080,自己配置端口不生效問題
作者接手一個(gè)SpringCloud項(xiàng)目時(shí)發(fā)現(xiàn)Eureka注冊的服務(wù)端口與實(shí)際Ribbon調(diào)用的實(shí)例端口不一致,通過查閱資料發(fā)現(xiàn)是Eureka讀取server.port不生效,通過在配置文件里添加nonSecurePort參數(shù)即可強(qiáng)制綁定端口2026-05-05
SpringBoot集成Swagger2生成接口文檔的方法示例
我們提供Restful接口的時(shí)候,API文檔是尤為的重要,它承載著對接口的定義,描述等,本文主要介紹了SpringBoot集成Swagger2生成接口文檔的方法示例,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2018-12-12

