- Sentinel简介
- Sentinel 入门 demo
- 限流入门示例|done
- 结束语
- Reference
摘要 介绍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阈值 为 3rules.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|classification1765786892000|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
- https://github.com/alibaba/Sentinel/wiki/How-to-Use
- https://sentinelguard.io/zh-cn/docs/introduction.html
Buy me a coffee. ☕Get red packets.