Spring Boot整合Sentinel之流量控制入门
摘要 介绍Spring Boot 4 如何整合流量治理神器Sentinel,入门案例以实现流量控制为切入点。
Sentinel简介
什么是Sentinel?随着微服务的流行,服务和服务之间的稳定性变得越来越重要。Sentinel 是面向分布式、多语言异构化服务架构的流量治理组件,主要以流量为切入点,从流量路由/调度、流量控制、流量整形、熔断降级、系统自适应过载保护/实例摘除、热点流量防护等多个维度来帮助开发者保障微服务的稳定性。
Sentinel 具有以下特征:
♥丰富的应用场景:Sentinel 承接了阿里巴巴近 10 年的双十一大促流量的核心场景,例如秒杀(即突发流量控制在系统容量可以承受的范围)、消息削峰填谷、集群流量控制、实时熔断下游不可用应用等。
♥完备的实时监控:可以在控制台中看到接入应用的单台机器秒级数据,甚至 500 台以下规模集群的汇总运行情况。
♥广泛的开源生态:Sentinel 提供开箱即用的与其它开源框架/库的整合模块,例如与 Spring Cloud、Apache Dubbo、gRPC、Quarkus 的整合。您只需要引入相应的依赖并进行简单的配置即可快速地接入 Sentinel。同时 Sentinel 提供 Java/Go/C++ 等多种语言的原生实现。
♥完善的 SPI 扩展机制:Sentinel 提供简单易用、完善的 SPI 扩展接口。您可以通过实现扩展接口来快速地定制逻辑。例如定制规则管理、适配动态数据源等。
流量控制(flow control)原理是监控应用流量的 QPS 或并发线程数等指标,当达到指定的阈值时对流量进行控制,以避免被瞬时的流量高峰冲垮,从而保障应用的高可用性。限流的直接表现是在执行 Entry nodeA = SphU.entry(resourceName) 的时候抛出 FlowException 异常。FlowException 是 BlockException 的子类,您可以捕捉 BlockException 来自定义被限流之后的处理逻辑。
『资源』是 Sentinel 的关键概念,只要通过 Sentinel API 定义的代码,就是资源,能够被 Sentinel 保护起来。它可以是 Java 应用程序中的任何内容,例如,由应用程序提供的服务,或由应用程序调用的其它应用提供的服务,甚至可以是一段代码。
『规则』围绕资源的实时状态设定的规则,可以包括「流量控制规则」、「熔断降级规则」以及「系统保护规则」。对于同一个资源,我们通过规则定义如何程序保护资源,所有规则可以动态实时调整。
Sentinel 的「设计理念」是让编码人员自由选择控制的角度,并进行灵活组合,从而达到想要的效果。它的流量控制规则由下表的关键属性组成:
| 字段名 | 说明 | 默认值 |
|---|---|---|
| resource | 资源名 | |
| count | 限流阈值 | |
| grade | 限流机制,1 QPS,0 并发线程数 | QPS 模式 |
| limitApp | 流控针对的调用来源 | default,代表不区分调用来源 |
| strategy | 调用关系限流,包括资源自身、其它关联资源 (refResource)和链路入口等 | 根据资源本身 |
| controlBehavior | 流量控制效果(直接拒绝、预热和匀速排队等) | 直接拒绝 |
限流的直接表现是在执行Entry nodeA = SphU.entry(resourceName)的时候抛出FlowException异常。FlowException是BlockException的子类,您可以捕捉BlockException来自定义被限流之后的处理逻辑。
本文以《一步步搭建JDK 21 Spring Boot项目》搭建的Spring Boot项目为基础,演示Sentinel 限流功能。
Sentinel 入门 demo
使用 Sentinel 来进行资源保护,主要分为几个步骤:
- 定义资源
- 设置规则
- 验证规则
定义需要保护的资源后配置限流规则。我们可以理解为只要有了资源,就可以在任何时候灵活地定义各种流量控制规则。在编码之前考虑此代码片段是否需要保护,如果需要保护,就将其定义为一个资源。今天咱们就把Sentinel限流掰开揉碎讲清楚怎么对流量洪峰限流保证服务稳定性。
- 引入 Sentinel 依赖
如果您的应用使用了 Maven,则从maven仓库地址中找适合的sentinel版本并加入 pom.xml 文件中。我使用的是 JDK 21 + Spring Boot 4.0.0,故引入以下Sentinel依赖包:
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-core</artifactId>
<version>1.8.9</version>
</dependency>
限流入门示例|done
定义资源。我们一般会将 Java 中的方法定义为资源,也可以更灵活地对资源进行定义。在下面的例子中,我们定义的资源名是【my_resource】,将System.out.println("Hello Sentinel");这个代码片段作为被保护的资源,把它用Sentinel API SphU.entry("my_resource")和entry.exit()包裹起来。见如下代码中的函数sentinelDemo(String resourceName):
import com.alibaba.csp.sentinel.Entry;
import com.alibaba.csp.sentinel.SphU;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.cactus.wiener.config.FlowRules;
/**
* @Author 楼兰胡杨
* @Description: 简单的限流示例
*/
public class SimpleSentinelDemo {
public static void main(String[] args) {
// 定义资源名称
String resourceName = "my_resource";
//加载流控规则
FlowRules.initFlowRules(resourceName);
// 启动测试示例
sentinelDemo(resourceName);
}
public static void sentinelDemo(String resourceName) {
Entry entry1 = null;
for (int i = 1; i <= 16; i++) {
try {
// 资源名可使用任意有业务语义的字符串,比如方法名、接口名或其它可唯一标识的字符串。
entry1 = SphU.entry(resourceName);
// 被保护的资源
System.out.println(i + " Hello Sentinel");
} catch (BlockException ex) {
// 处理被流控的逻辑
System.out.println(i + " blocked!");
// 通过休眠使Sentinel进入下一限流统计周期
try {
TimeUnit.MILLISECONDS.sleep(300L);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
} finally {
// 释放资源许可证
if (entry1 != null) {
entry1.exit();
}
}
}
}
}
我们可以通过编写代码或使用 Sentinel 控制台来设置规则。例如,以下是一个定义限流QPS=3的代码片段:
import com.alibaba.csp.sentinel.Entry;
import com.alibaba.csp.sentinel.SphU;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.cactus.wiener.config.FlowRules;
import java.util.concurrent.TimeUnit;
/**
* @Author 楼兰胡杨
* @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);
}
}
在执行函数 sentinelDemo(String resourceName)之前,调用函数FlowRules.initFlowRules(resourceName) 即可将规则应用到受保护的资源。
检查效果。Demo 运行之后,可以在控制台看到某一次执行后打印的如下日志:
1 Hello Sentinel
2 Hello Sentinel
3 Hello Sentinel
4 blocked!
5 blocked!
6 blocked!
7 blocked!
8 Hello Sentinel
9 Hello Sentinel
10 Hello Sentinel
11 blocked!
12 blocked!
13 blocked!
14 Hello Sentinel
15 Hello Sentinel
16 Hello Sentinel
每次打印结果可能不一样。由日志得知系统每秒稳定的接收三个请求,和规则中预先设定的QPS阈值一模一样,且限流和放行交替进行。我们还可以在日志~/logs/csp/${appName}-metrics.log.xxx里找到下面的输出结果:
|--timestamp-|------date time----|--resource-| p |block|s |e|rt|occupiedPassQps|concurrency|classification
1765786892000|2025-12-15 16:21:32|my_resource|3|1|3|0|2|0|0|0
1765786893000|2025-12-15 16:21:33|my_resource|3|3|3|0|1|0|0|0
其中p代表通过请求(获取了令牌entry)的QPS,block代表被阻塞请求的QPS,s代表成功执行完成的请求个数,e代表触发了用户自定义异常的QPS,rt代表从获取令牌(entry)到释放的响应时间,即平均响应时长。occupiedPassQps 代表本时间窗口容量已满,占用未来时间窗口的QPS,默认为false不开启。concurrency 指代并发度,未使用;classification 指资源类型,0 common,1 common_web,2common_rpc,3 common_api_gateway,4 common_db等。
不管是通过什么样的机制进行流量控制,其核心原理都是监控应用流量的qps或者并发线程数,然后判断这些指标的阈值并对流量进行控制,防止瞬时流量高峰导致系统被压垮。
结束语
生活没有倒车档,世事没有后悔药。但愿这次分享的Sentinel流量控制入门示例能与你产生共鸣,祝你今天技术判断更笃定,少踩坑、快进阶!🚀。认同的老铁别忘了关注点赞,提醒身边每一个正在寻求突破技术瓶颈的人。
Reference
Buy me a coffee. ☕Get red packets.
浙公网安备 33010602011771号