摘要 介绍Spring Boot 4 如何集成流量治理神器Sentinel实现QPS限流。
目录
- Sentinel简介
- [启动 Sentinel 控制台](#启动 Sentinel 控制台)
- 下载sentinel
- [访问 Sentinel 控制台](#访问 Sentinel 控制台)
- 注解@SentinelResource使用方法
- 用@SentinelResource限流
- 统一处理Sentinel异常|done
- 结束语
- Reference
Sentinel简介
什么是Sentinel?随着微服务的流行,服务和服务之间的稳定性变得越来越重要。Sentinel 是面向分布式、多语言异构化服务架构的流量治理组件,主要以流量为切入点,从流量路由/调度、流量控制、流量整形、熔断降级、系统自适应过载保护/实例摘除、热点流量防护等多个维度来帮助开发者保障微服务的稳定性。
同一个资源可以创建多条限流规则。Sentinel底层中的 FlowSlot 会对该资源的所有限流规则依次遍历,直到有规则触发限流或者所有规则遍历完毕。
在实际的项目开发中,一般不会直接写类似《Spring Boot整合Sentinel之流量控制入门》中那段限流入门演示代码,通常需要将Sentinel集成到应用框架中。本文以《一步步搭建JDK 21 Spring Boot项目》搭建的Spring Boot项目为基础,展示如何将Sentinel集成到Spring Boot项目中,并基于注解 @SentinelResource 进行限流。demo中只介绍了qps限流策略,它有多种策略备选,请根据业务需要自行选定。
启动 Sentinel 控制台
Sentinel 的使用可以分为两个部分:
-
控制台(Dashboard):控制台主要负责管理规则推送、监控、集群限流、分配管理、机器发现等。
-
核心库(Java 客户端):不依赖任何框架/库,能够运行于 Java 7 及以上版本的运行时环境,同时对 Dubbo / Spring Cloud 等框架也有较好的支持。
下载sentinel
从sentinel控制台传送门下载需要的sentinel jar。

我下载了当前最新版v1.8.9 。下载后在Mac 终端进入jar包存放目录后,执行命令 java -Dserver.port=8080 -jar sentinel-dashboard-1.8.9.jar 即可启动控制台。默认端口是8080,为了避免端口好冲突,可以设置为诸如9000等。

访问 Sentinel 控制台
在浏览器访问sentinel控制台地址http://localhost:8080或者http://127.0.0.1:8080/即可进入如下登录页面,默认账号密码都是 sentinel。恭喜你!此时此刻sentinel下载运行成功。

Sentinel 开源控制台支持实时监控和规则管理。接入控制台的步骤如下:
java
spring.cloud.sentinel.transport.dashboard=localhost:8080
spring.cloud.sentinel.transport.heartbeat-interval-ms=500
spring.cloud.sentinel.eager=true
配置 heartbeat-interval-ms 用于指定应用与 Sentinel 控制台之间的心跳上报间隔,单位是毫秒。配置为 500 表示
👉 应用每 500ms(0.5 秒) 向 Sentinel Dashboard 发送一次心跳,用于上报实例存活状态和基础运行信息。
应用启动时 立即初始化 Sentinel 核心组件并向控制台发起连接,而不是等到第一次流量进入时再初始化。
配置 spring.cloud.sentinel.eager=true表示应用启动时 立即初始化 Sentinel 核心组件并向控制台发起连接,而不是等到流量第一次进入时再初始化。两者组合使用的整体业务含义:
✅ Sentinel 在应用启动阶段即完成初始化,服务一上线就受到限流与熔断保护;
✅ 应用与控制台之间保持高频心跳,同步实例状态更及时;
✅ 更有利于稳定性监控、规则推送和快速问题预警;
注解@SentinelResource使用方法
简单介绍下注解@SentinelResource中各个属性:
- value - 指定资源的名称
- blockHandler - 服务限流后会抛出BlockException异常,此属性用来指定一个函数(方法)来处理BlockException异常的。
- 注意: 这个方法必须是public的,且返回类型需要与原方法相匹配,参数类型默认与原方法一致,且最后加一个额外的参数,类型为BlockException
- blockHandlerClass - 若属性blockHandler指定的函数与原方法不在一个类中,则需要使用该属性指定所在的类
- 注意:必须配合blockHandler属性一起使用,且blockHandler属性指定的方法必须为static静态函数,否则无法解析
- fallback - 用于抛出异常时,执行处理逻辑,可以针对所有类型的异常进行处理
- 注意:Sentinel 1.6.0 之前,fallback函数只针对降级异常(DegradeException)进行处理,不能处理业务异常
- 返回值类型必须与原函数一致,且方法参数也要与原函数一致,可以在最后加一个额外的参数,类型为Throwable类型
- fallbackClass - 若属性fallback指定的函数与原方法不在一个类中,则需要使用该属性指定所在的类
- 注意:必须配合fallback属性一起使用,且fallback属性指定的方法必须为static静态函数,否则无法解析
- defaultFallback - 默认的fallback函数名称,用于通用的fallback逻辑
- exceptionsToIgnore - 用于指定哪些异常被排除掉,不会计入异常统计中,也不会进入fallback逻辑中,而是会原样抛出
用@SentinelResource限流
pom配置如下:
java
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>4.0.0</version>
<relativePath/>
</parent>
<groupId>com.cactus</groupId>
<artifactId>wiener</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>wiener</name>
<description>wiener</description>
<properties>
<java.version>21</java.version>
<sentinel.version>1.8.9</sentinel.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.42</version>
</dependency>
<!-- Sentinel核心服务 -->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-core</artifactId>
<version>${sentinel.version}</version>
</dependency>
<!-- Sentinel本地应用接入控制台,版本需要与控制台保持一致 -->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-transport-simple-http</artifactId>
<version>${sentinel.version}</version>
</dependency>
<!-- Sentinel提供注解无侵入定义资源 https://mvnrepository.com/artifact/com.alibaba.csp/sentinel-annotation-aspectj -->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-annotation-aspectj</artifactId>
<version>${sentinel.version}</version>
</dependency>
</dependencies>
<!-- 如果希望在项目级别使用阿里云镜像,就添加alimaven -->
<repositories>
<repository>
<id>alimaven</id>
<name>aliyun maven</name>
<url>https://maven.aliyun.com/repository/central</url>
</repository>
</repositories>
</project>
先定义一个测试用例getFlow1,验证注解 @SentinelResource限流是否生效:
java
@RestController
@RequestMapping("/sentinel")
public class SentinelTestController {
/**
* 只添加blockHandler属性 指定getFlowBlockHandler方法处理异常
*/
@GetMapping(value = "getFlow1")
@SentinelResource(value = SentinelRuleConfig.RESOURCE_QPS_LIMIT, blockHandler = "getFlowBlockHandler")
public String getFlow1() {
// 返回值
return "流量正常";
}
/**
* getFlow1 处理异常逻辑
*/
public String getFlowBlockHandler(BlockException ex) {
log.info("触发限流");
if (ex instanceof FlowException) {
return "getFlow1限流-流控";
} else if (ex instanceof DegradeException) {
return "getFlow1限流-降级";
}
return "getFlow1限流";
}
}
其中,@SentinelResource(value = SentinelRuleConfig.RESOURCE_QPS_LIMIT, blockHandler = "getFlowBlockHandler")表示对函数 getFlow1 进行限流监控,资源名是my_resource。我们可以通过编写代码或使用 Sentinel 控制台来设置规则。例如,以下是一个定义限流QPS=3的Java代码片段:
java
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 java.util.ArrayList;
import java.util.List;
/**
* @Author Wiener
* @Date 2025-12-11
* @Description: 设置限流规则
*/
public class FlowRules {
/**
* 入门版限流规则
* @param resourceName
*/
public static void initFlowRules(String resourceName) {
List<FlowRule> rules = new ArrayList<>();
FlowRule rule = new FlowRule();
rule.setResource(resourceName);
rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
rule.setCount(3); // 设置 QPS 为 3
rules.add(rule);
FlowRuleManager.loadRules(rules);
}
}
其中,resource表示资源名,grade表示降级策略。
java
import com.alibaba.csp.sentinel.annotation.aspectj.SentinelResourceAspect;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @Author Wiener
* @Description: 加载全局限流配置类
*/
@Configuration
public class SentinelRuleConfig implements InitializingBean {
public final static String RESOURCE_QPS_LIMIT = "my_resource";
@Bean
public SentinelResourceAspect sentinelResourceAspect(){
return new SentinelResourceAspect();
}
@Override
public void afterPropertiesSet() {
FlowRules.initFlowRules(RESOURCE_QPS_LIMIT);
}
}
类SentinelResourceAspect是让 @SentinelResource 从"注解装饰品"变成"真正限流熔断入口"的关键引擎。如果没有它,@SentinelResource 只是个普通注解,不会做任何限流、熔断或者降级处理,使得Sentinel 只是"库";如果有了它,Sentinel 才是流量"治理工具"。
检查效果。在 Spring Boot 应用启动之前,从下图中 Modify options 找到 Add VM options设置JVM 启动参数:

java
-Dcsp.sentinel.dashboard.server=127.0.0.1:8080 -Dproject.name=wiener
本示例是用于给服务打开限流和监控能力的启动配置。它通过 JVM 启动参数为 Spring Boot 本地服务注入 Sentinel 配置,-Dcsp.sentinel.dashboard.server 指定控制台地址(127.0.0.1:8080),-Dproject.name 于定义当前 Spring Boot 应用在 Sentinel 中的唯一标识名称(指定应用名为 wiener)。控制台通过该名称区分不同服务实例,并按应用维度进行指标统计和流控规则管理。通过上述 JVM 启动参数,Spring Boot 应用即可完成与 Sentinel 控制台的集成,实现服务运行状态可视化和流量治理能力。
在服务启动后,多次访问接口 /getFlow1 后可以看到下图所示监控数据:

从流控规则页面可以查到服务端通过代码配置的限流阈值:

我把QPS阈值改为1再刷新Api,限流效果如下:

图中【通过QPS】为1,说明控制台配置的限流规则已经下发到服务端。至此,已经完成Spring Boot整合Sentinel 注解@SentinelResource进行限流并从控制台查看限流效果。
统一处理Sentinel异常|done
Sentinel 支持以下几种规则:流量控制规则、熔断降级规则、系统保护规则、来源访问控制规则和热点参数规则。其所有规则都可以在内存态中动态地查询及修改,修改之后立即生效。默认情况下,触发上述规则时,都会抛出异常到调用方。如果要自定义异常的返回结果,需要实现BlockExceptionHandler接口:
java
public interface BlockExceptionHandler {
/**
* 处理请求被限流、降级、授权拦截时抛出的异常:BlockException
*/
void handle(HttpServletRequest request, HttpServletResponse response, BlockException e) throws Exception;
}
BlockException包含很多个子类,分别对应不同的限流场景:
| 异常 | 说明 |
|---|---|
| FlowException | 限流异常 |
| ParamFlowException | 热点参数限流的异常 |
| DegradeExceptionn | 熔断降级异常 |
| AuthorityExceptionn | 授权规则异常 |
| SystemBlockException | 系统保护规则异常 |
注意,实现BlockExceptionHandler接口的类必须用@Component注解注入到Spring Boot中。统一处理Sentinel异常的代码示例如下:
java
@Component
public class SentinelExceptionHandler implements BlockExceptionHandler {
@Override
public void handle(HttpServletRequest request, HttpServletResponse response, BlockException e) throws Exception {
String msg = "未知异常";
int status = 429;// 请求过多
//异常处理逻辑:根据e异常的类型判断是触发了限流还是降级等,进一步做出不同的处理逻辑
if (e instanceof FlowException) {
msg = "请求被限流";
} else if (e instanceof ParamFlowException) {
msg = "请求被热点参数限流";
} else if (e instanceof DegradeException) {
msg = "请求被熔断降级";
} else if (e instanceof AuthorityException) {
msg = "没有访问权限";
status = 401;
}
response.setContentType("application/json;charset=utf-8");
response.setStatus(status);
response.getWriter().write(msg);
response.getWriter().println("{\"msg\":\""+msg+"\", \"status\":" + status + "}");
}
}
结束语
以上就是这篇文章的全部内容了,希望本文对道友的学习或者工作能带来一定的帮助,如有疑问请留言交流。Wiener在此祝各位生活愉快!工作顺利!