Java Sentinel流量控制与熔断降级框架详解
- [1. Sentinel简介与基本概念](#1. Sentinel简介与基本概念)
- [1.1 Sentinel概述](#1.1 Sentinel概述)
- [1.2 微服务面临的稳定性挑战](#1.2 微服务面临的稳定性挑战)
- [1.3 Sentinel的核心特性](#1.3 Sentinel的核心特性)
- [1.4 Sentinel与其他框架对比](#1.4 Sentinel与其他框架对比)
- [1.5 Sentinel的应用场景](#1.5 Sentinel的应用场景)
1. Sentinel简介与基本概念
1.1 Sentinel概述
Sentinel是阿里巴巴开源的一款面向分布式服务架构的高可用流量控制与熔断降级组件,主要用于解决微服务架构下的流量控制、熔断降级、系统负载保护等问题。Sentinel以"流量为切入点",从流量控制、熔断降级、系统负载保护、热点参数限流和授权控制等多个维度保护服务的稳定性。
Sentinel最初是为了解决阿里巴巴内部系统的稳定性问题而开发的,经过多年的迭代和实战考验,于2018年开源,并成为Apache软件基金会的孵化项目。Sentinel的设计理念是"简单易用、高扩展性、实时监控",它提供了丰富的规则配置能力和实时监控界面,帮助开发者快速实现服务的稳定性保障。
Sentinel的主要功能包括:
- 流量控制:对进入系统的流量进行控制,防止流量突增导致系统崩溃
- 熔断降级:当服务出现异常时,自动熔断,避免级联故障
- 系统负载保护:保护系统不被过载的请求压垮
- 热点参数限流:对热点参数进行精准限流
- 授权控制:基于请求来源的黑白名单控制
- 实时监控:提供实时的监控数据和可视化界面
1.2 微服务面临的稳定性挑战
随着微服务架构的普及,系统的稳定性面临着越来越多的挑战:
-
流量突增:
- 秒杀、促销等活动导致流量突发增长
- 热点事件导致某一服务请求量剧增
- 网络爬虫等恶意流量攻击
-
服务依赖故障:
- 服务间调用链长,任一环节故障都可能导致整个系统不可用
- 慢调用导致线程池耗尽,服务响应延迟
- 依赖服务不可用或响应超时
-
系统资源限制:
- CPU、内存、磁盘、网络等资源有限
- 数据库连接池、线程池等中间件资源耗尽
- 缓存击穿/穿透导致数据库压力过大
-
其他问题:
- 代码bug导致服务异常
- 硬件故障或网络抖动
- 配置错误或版本发布问题
这些问题如果不加以控制,可能会导致服务雪崩、系统崩溃等严重后果,影响用户体验和业务连续性。
1.3 Sentinel的核心特性
Sentinel具有以下核心特性:
1.3.1 流量控制
流量控制是Sentinel的核心功能之一,它通过监控资源的访问QPS(每秒请求数)或并发线程数,对流量进行控制,防止服务被瞬时的流量冲击所击垮。
- 多种限流策略:支持基于QPS、并发线程数、响应时间等多种限流策略
- 灵活的限流模式:支持直接拒绝、冷启动、匀速排队等多种限流模式
- 细粒度控制:支持对URL、方法、服务等进行细粒度的限流控制
1.3.2 熔断降级
熔断降级是指当服务出现异常或响应超时等情况时,自动将该服务熔断,避免故障扩散到其他服务。
- 多种熔断策略:支持基于异常比例、异常数、慢调用比例等多种熔断策略
- 自动恢复机制:熔断后自动进入半开状态,试探服务是否恢复正常
- 自定义降级逻辑:支持自定义降级后的处理逻辑
1.3.3 系统负载保护
系统负载保护是指从系统的整体负载出发,保护系统不被过载的请求压垮。
- 系统维度保护:基于系统的CPU使用率、平均RT、入口QPS等指标进行保护
- 自适应保护:根据系统的实时负载自动调整保护策略
- 防止雪崩:避免因局部故障导致整个系统崩溃
1.3.4 热点参数限流
热点参数限流是指对访问频率高的参数值进行精准限流。
- 参数级限流:支持对指定参数的特定值进行限流
- 灵活配置:支持基于参数索引或参数值的限流配置
- 防护热点问题:有效防止热点商品、热点用户等导致的服务过载
1.3.5 授权控制
授权控制是指基于请求来源的黑白名单控制,防止恶意访问。
- 来源识别:支持自定义请求来源识别逻辑
- 黑白名单控制:支持对不同来源的请求进行黑白名单过滤
- 灵活扩展:支持通过SPI机制扩展来源识别方式
1.3.6 实时监控与控制台
Sentinel提供了丰富的监控数据和可视化控制台,帮助开发者实时了解系统的运行状态。
- 实时监控:实时展示资源的QPS、响应时间、异常数等指标
- 规则管理:支持在控制台动态配置和管理规则
- 实时统计:提供秒级的实时统计数据
- 可视化界面:直观的图形界面,便于操作和分析
1.3.7 高扩展性
Sentinel提供了灵活的扩展机制,支持开发者自定义各种规则和处理逻辑。
- SPI扩展点:提供丰富的SPI扩展点,支持自定义限流策略、熔断策略等
- 规则扩展:支持自定义规则的加载和持久化方式
- 适配各种框架:支持与Spring Cloud、Dubbo、gRPC等主流框架集成
1.4 Sentinel与其他框架对比
与其他流量控制和熔断降级框架相比,Sentinel具有以下优势:
| 特性 | Sentinel | Hystrix | Resilience4j |
|---|---|---|---|
| 流量控制 | 支持QPS、并发线程数、热点参数等多种限流 | 支持线程池隔离 | 支持基于时间窗口的限流 |
| 熔断降级 | 支持多种熔断策略,自动恢复机制完善 | 基于断路器模式,配置复杂 | 基于断路器模式,支持多种熔断策略 |
| 系统保护 | 提供系统维度的负载保护 | 不支持 | 不支持 |
| 实时监控 | 提供丰富的监控指标和可视化控制台 | 监控功能较弱,需要整合其他工具 | 监控功能较弱,需要整合其他工具 |
| 扩展性 | 提供丰富的SPI扩展点 | 扩展能力有限 | 基于函数式编程,扩展灵活 |
| 性能 | 采用无锁设计,性能优异 | 基于线程池隔离,性能开销较大 | 性能较好 |
| 易用性 | 配置简单,控制台操作友好 | 配置复杂,学习成本高 | 配置简单,API友好 |
| 生态集成 | 支持Spring Cloud、Dubbo等主流框架 | 支持Spring Cloud,但维护停止 | 支持Spring Cloud、Micronaut等 |
从对比中可以看出,Sentinel在功能完整性、性能、易用性等方面都具有明显优势,是微服务架构下保障系统稳定性的理想选择。
1.5 Sentinel的应用场景
Sentinel适用于以下场景:
1.5.1 秒杀/大促场景
在秒杀、大促等流量突增的场景下,Sentinel可以通过流量控制功能,将流量控制在系统可承受的范围内,防止系统崩溃。
1.5.2 微服务架构
在微服务架构下,Sentinel可以对服务间的调用进行保护,防止某一服务故障导致整个系统雪崩。
1.5.3 API网关
在API网关层,Sentinel可以对外部请求进行限流和授权控制,保护后端服务的安全和稳定。
1.5.4 热点资源保护
对于热点资源(如热点商品、热点用户),Sentinel可以通过热点参数限流功能,对热点参数进行精准限流,防止热点资源导致系统过载。
1.5.5 系统容量规划
通过Sentinel的监控数据,可以了解系统的真实容量和瓶颈,为系统容量规划提供依据。
1.5.6 服务治理
Sentinel可以与服务注册中心、配置中心等结合,实现服务的动态治理和保护。
通过本章的介绍,我们对Sentinel有了基本的了解。在接下来的章节中,我们将详细介绍Sentinel的安装配置、核心原理以及各种功能的使用方法。
2. Sentinel安装与环境配置
2.1 系统要求
在安装Sentinel之前,需要确保系统满足以下要求:
2.1.1 硬件要求
- CPU:至少2核
- 内存:至少2GB
- 磁盘:至少1GB可用空间
2.1.2 软件要求
- JDK:Java 8及以上版本
- Maven:Maven 3.2.0及以上版本(用于构建客户端项目)
- 操作系统:支持Windows、Linux、macOS等主流操作系统
2.1.3 网络要求
- 控制台与客户端之间需要网络连通
- 控制台默认端口为8080,确保该端口未被占用
2.2 Sentinel控制台下载与安装
Sentinel控制台是一个基于Spring Boot的Web应用,用于实时监控Sentinel的运行状态、配置规则等。
2.2.1 下载方式
有两种方式可以获取Sentinel控制台:
-
从GitHub Releases下载 :
访问Sentinel的GitHub Releases页面(https://github.com/alibaba/Sentinel/releases),下载最新版本的sentinel-dashboard JAR包。
-
从Maven中央仓库下载 :
可以使用Maven的依赖管理功能获取Sentinel控制台,或者直接从Maven中央仓库下载JAR包。
2.2.2 安装步骤
Sentinel控制台是一个可执行的JAR包,无需复杂的安装过程,只需下载即可使用。
-
选择一个合适的目录用于存放Sentinel控制台,例如:
bashmkdir -p /opt/sentinel cd /opt/sentinel -
下载最新版本的Sentinel控制台JAR包:
bashwget https://github.com/alibaba/Sentinel/releases/download/v1.8.6/sentinel-dashboard-1.8.6.jar(注:请根据实际情况选择最新版本的下载链接)
2.3 Sentinel控制台配置
Sentinel控制台支持通过命令行参数或配置文件进行配置。
2.3.1 命令行参数配置
以下是一些常用的命令行参数:
| 参数名 | 说明 | 默认值 |
|---|---|---|
server.port |
控制台服务端口 | 8080 |
csp.sentinel.dashboard.server |
控制台地址(客户端配置用) | - |
sentinel.dashboard.auth.username |
控制台登录用户名 | sentinel |
sentinel.dashboard.auth.password |
控制台登录密码 | sentinel |
sentinel.transport.ip |
控制台绑定的IP地址 | - |
sentinel.transport.port |
控制台接收客户端心跳的端口 | 8719 |
logging.file.name |
日志文件路径 | - |
2.3.2 配置文件配置
除了命令行参数外,还可以通过创建application.properties或application.yml文件来配置Sentinel控制台。
创建application.properties文件,内容如下:
properties
# 服务器端口
server.port=8080
# 控制台登录用户名和密码
sentinel.dashboard.auth.username=sentinel
sentinel.dashboard.auth.password=sentinel
# 日志配置
logging.file.name=/opt/sentinel/logs/sentinel-dashboard.log
logging.level.root=INFO
# 控制台接收客户端心跳的端口
sentinel.transport.port=8719
2.4 启动Sentinel控制台
2.4.1 直接启动
使用以下命令直接启动Sentinel控制台:
bash
java -jar sentinel-dashboard-1.8.6.jar
2.4.2 指定端口启动
如果需要使用自定义端口,可以通过server.port参数指定:
bash
java -jar sentinel-dashboard-1.8.6.jar --server.port=8888
2.4.3 使用配置文件启动
如果使用配置文件,可以通过--spring.config.location参数指定配置文件路径:
bash
java -jar sentinel-dashboard-1.8.6.jar --spring.config.location=/opt/sentinel/application.properties
2.4.4 在后台启动(Linux/Mac)
在Linux或Mac系统上,可以使用以下命令将Sentinel控制台作为后台服务启动:
bash
nohup java -jar sentinel-dashboard-1.8.6.jar > sentinel.log 2>&1 &
2.4.5 验证控制台启动
启动成功后,可以通过浏览器访问Sentinel控制台:
http://localhost:8080
使用默认的用户名和密码(均为sentinel)登录控制台。
2.5 客户端配置
要使用Sentinel的功能,需要在应用程序中集成Sentinel客户端。
2.5.1 添加依赖
在Maven项目的pom.xml文件中添加Sentinel的依赖:
xml
<!-- Sentinel核心依赖 -->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-core</artifactId>
<version>1.8.6</version>
</dependency>
<!-- Sentinel注解支持 -->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-annotation-aspectj</artifactId>
<version>1.8.6</version>
</dependency>
<!-- Sentinel传输模块(用于与控制台通信) -->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-transport-simple-http</artifactId>
<version>1.8.6</version>
</dependency>
<!-- Sentinel控制台客户端 -->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-dashboard-client</artifactId>
<version>1.8.6</version>
</dependency>
2.5.2 配置JVM参数
在启动应用程序时,需要添加以下JVM参数,指定Sentinel控制台的地址:
bash
-Dcsp.sentinel.dashboard.server=localhost:8080
-Dcsp.sentinel.app.type=1
-Dproject.name=sentinel-demo
参数说明:
csp.sentinel.dashboard.server:Sentinel控制台的地址csp.sentinel.app.type:应用类型,1表示Web应用project.name:应用名称,用于在控制台中标识
2.5.3 配置文件配置
除了JVM参数外,还可以通过配置文件csp.properties来配置Sentinel客户端。该文件需要放在项目的根目录下。
properties
# Sentinel控制台地址
csp.sentinel.dashboard.server=localhost:8080
# 应用名称
project.name=sentinel-demo
# 客户端IP
csp.sentinel.client.ip=127.0.0.1
# 客户端端口
csp.sentinel.port=8719
# 日志目录
csp.sentinel.log.dir=/opt/sentinel/logs
# 日志级别
csp.sentinel.log.level=info
2.6 验证安装
安装完成后,需要验证Sentinel控制台和客户端是否正常工作。
2.6.1 验证控制台
- 打开浏览器,访问
http://localhost:8080 - 使用用户名和密码
sentinel登录 - 登录成功后,应该能够看到Sentinel控制台的主页面
2.6.2 验证客户端
- 启动集成了Sentinel客户端的应用程序
- 访问应用程序的某个接口,触发Sentinel的监控
- 在Sentinel控制台中,可以看到应用程序的监控数据
- 尝试配置一条规则(如流量控制规则),验证规则是否生效
2.6.3 常见问题排查
-
控制台无法访问:
- 检查控制台是否已经启动
- 检查端口是否被占用
- 检查防火墙设置
-
客户端无法连接到控制台:
- 检查控制台地址和端口是否配置正确
- 检查网络连接是否正常
- 检查客户端是否已经启动
-
控制台中看不到客户端数据:
- 检查客户端是否已经有流量产生
- 检查客户端的应用名称是否配置正确
- 检查客户端的日志,查看是否有错误信息
通过以上步骤,我们可以完成Sentinel的安装和配置,为后续的使用做好准备。在接下来的章节中,我们将深入介绍Sentinel的核心原理和各种功能的使用方法。
3. Sentinel核心原理和架构
3.1 Sentinel的核心概念
Sentinel有几个核心概念,理解这些概念对于正确使用Sentinel至关重要。
3.1.1 资源
资源是Sentinel的核心概念,它可以是任何我们需要保护的代码或服务。在Sentinel中,资源可以是:
- 一个HTTP接口
- 一个Java方法
- 一个Dubbo服务
- 任何可被调用的代码块
Sentinel通过对资源的定义和保护,实现流量控制、熔断降级等功能。
3.1.2 规则
规则是Sentinel进行流量控制和熔断降级的依据。Sentinel支持多种规则类型:
- 流量控制规则(FlowRule):定义资源的流量控制策略
- 熔断降级规则(DegradeRule):定义资源的熔断降级策略
- 系统保护规则(SystemRule):定义系统级别的保护策略
- 热点参数规则(ParamFlowRule):定义热点参数的限流策略
- 授权规则(AuthorityRule):定义请求来源的黑白名单控制
规则可以通过控制台动态配置,也可以通过代码或配置文件静态配置。
3.1.3 插槽链(Slot Chain)
插槽链是Sentinel的核心骨架,所有的流量控制、熔断降级等功能都是通过插槽链实现的。
Sentinel的插槽链采用责任链模式,每个插槽负责不同的功能:
- NodeSelectorSlot:负责收集资源的路径,并将这些资源的调用路径以树状结构存储起来
- ClusterBuilderSlot:负责存储资源的统计信息和调用者信息
- StatisticSlot:负责统计资源的实时运行指标
- FlowSlot:负责流量控制
- DegradeSlot:负责熔断降级
- SystemSlot:负责系统负载保护
- AuthoritySlot:负责授权控制
- ParamFlowSlot:负责热点参数限流
3.1.4 流量指标(Metrics)
流量指标是Sentinel进行决策的基础,包括:
- QPS:每秒请求数
- 并发线程数:当前正在处理请求的线程数
- 响应时间:请求的处理时间
- 异常数:处理请求时发生的异常数量
- 异常比例:异常数占总请求数的比例
这些指标通过滑动时间窗口(Sliding Window)进行统计,确保数据的实时性和准确性。
3.2 Sentinel的工作原理
Sentinel的工作原理可以分为以下几个步骤:
3.2.1 资源定义与埋点
要使用Sentinel保护资源,首先需要对资源进行定义和埋点。Sentinel支持两种埋点方式:
-
显式埋点:通过Sentinel提供的API手动定义资源
javatry (Entry entry = SphU.entry("resourceName")) { // 被保护的业务逻辑 } catch (BlockException ex) { // 资源访问被拒绝的处理逻辑 } -
隐式埋点:通过注解或框架集成自动定义资源
java@SentinelResource(value = "resourceName", blockHandler = "handleBlock") public String doSomething(String param) { // 被保护的业务逻辑 return "result"; }
3.2.2 流量统计
当资源被访问时,Sentinel会通过插槽链中的StatisticSlot对流量指标进行统计。Sentinel采用滑动时间窗口进行流量统计,确保统计数据的实时性和准确性。
滑动时间窗口的实现原理:
- 将时间窗口划分为多个小的时间片段(Bucket)
- 每个Bucket记录该时间段内的流量指标
- 当时间窗口滑动时,移除过期的Bucket,并添加新的Bucket
- 通过聚合当前时间窗口内的所有Bucket数据,得到实时的流量统计
3.2.3 规则检查与执行
在流量统计完成后,Sentinel会通过各个功能插槽(FlowSlot、DegradeSlot等)对流量进行检查:
- FlowSlot:根据流量控制规则检查是否需要限流
- DegradeSlot:根据熔断降级规则检查是否需要熔断
- SystemSlot:根据系统保护规则检查是否需要系统保护
- AuthoritySlot:根据授权规则检查请求是否被允许
- ParamFlowSlot:根据热点参数规则检查是否需要参数限流
如果任何一个插槽检查不通过,就会抛出相应的BlockException,中断请求的处理。
3.2.4 规则动态配置
Sentinel支持规则的动态配置,规则可以通过以下方式进行配置:
- 控制台配置:通过Sentinel控制台动态配置和管理规则
- API配置:通过Sentinel提供的API编程式配置规则
- 配置文件:通过本地配置文件静态配置规则
- 分布式配置中心:集成Nacos、Apollo等配置中心,实现规则的分布式管理
规则的动态配置可以实现实时的流量控制和熔断降级策略调整,无需重启应用。
3.3 Sentinel的架构设计
Sentinel采用分层架构设计,从下到上分为核心层、适配层和接入层。
3.3.1 核心层
核心层是Sentinel的核心实现,包括:
- 核心骨架:插槽链的实现
- 规则引擎:规则的存储、加载和执行
- 统计引擎:流量指标的统计和分析
- 核心API:对外提供的核心功能接口
核心层采用无锁设计,确保高性能的同时保证线程安全。
3.3.2 适配层
适配层负责与各种框架和组件的集成,包括:
- Web适配:支持Servlet、Spring MVC等Web框架
- RPC适配:支持Dubbo、gRPC等RPC框架
- 消息队列适配:支持RocketMQ、Kafka等消息队列
- 框架集成:支持Spring Boot、Spring Cloud等框架
适配层通过SPI机制进行扩展,方便集成新的框架和组件。
3.3.3 接入层
接入层是用户直接使用的接口,包括:
- 注解API:通过注解方式定义资源
- 控制台API:与Sentinel控制台交互的接口
- 规则API:规则配置和管理的接口
接入层提供了简单易用的接口,降低了用户使用Sentinel的门槛。
3.3.4 控制台架构
Sentinel控制台采用前后端分离架构:
- 后端:基于Spring Boot的Web应用,提供RESTful API
- 前端:基于React的单页应用,提供可视化界面
控制台的主要功能包括:
- 实时监控:显示资源的实时运行指标
- 规则配置:动态配置和管理各种规则
- 集群管理:管理和监控集群中的所有客户端
- 权限管理:控制用户的访问权限
3.4 Sentinel的SPI扩展机制
Sentinel提供了丰富的SPI(Service Provider Interface)扩展点,允许用户自定义各种功能。
3.4.1 SPI扩展点
Sentinel的主要SPI扩展点包括:
- Slot扩展:允许用户自定义插槽,扩展Sentinel的功能
- Rule扩展:允许用户自定义规则类型和处理逻辑
- Statistic扩展:允许用户自定义流量统计方式
- Transport扩展:允许用户自定义客户端与控制台的通信方式
- Datasource扩展:允许用户自定义规则的存储和加载方式
3.4.2 扩展实现步骤
实现Sentinel的SPI扩展通常需要以下步骤:
-
实现扩展接口:实现Sentinel提供的扩展接口
javapublic class CustomDataSource implements ReadableDataSource<String, List<FlowRule>> { // 实现接口方法 } -
创建SPI配置文件:在META-INF/services目录下创建以扩展接口全类名为名的配置文件
META-INF/services/com.alibaba.csp.sentinel.datasource.ReadableDataSource -
配置扩展实现:在配置文件中指定扩展实现类的全类名
com.example.sentinel.CustomDataSource -
使用扩展:在应用中使用自定义的扩展
javaReadableDataSource<String, List<FlowRule>> ds = new CustomDataSource(); FlowRuleManager.register2Property(ds.getProperty());
3.4.3 扩展示例
以下是一个自定义数据源的示例:
java
public class FileDataSource implements ReadableDataSource<String, List<FlowRule>> {
private final File file;
private final Converter<String, List<FlowRule>> parser;
public FileDataSource(String filePath, Converter<String, List<FlowRule>> parser) {
this.file = new File(filePath);
this.parser = parser;
// 注册文件监听
registerFileWatch();
}
@Override
public List<FlowRule> loadConfig() throws Exception {
String content = Files.readString(file.toPath());
return parser.convert(content);
}
@Override
public Property<List<FlowRule>> getProperty() {
// 返回可监听的属性
}
// 实现文件监听逻辑
private void registerFileWatch() {
// ...
}
}
通过SPI扩展机制,Sentinel可以灵活地适应各种场景和需求,提高了框架的可扩展性和灵活性。
4. Sentinel流量控制实践
4.1 流量控制概述
流量控制(Flow Control)是Sentinel的核心功能之一,它通过监控资源的访问流量,对流量进行控制,防止系统被瞬时的高流量冲击所击垮。
4.1.1 流量控制的作用
- 防止系统过载:通过限制请求的速率或并发数,防止系统资源耗尽
- 保障系统稳定性:确保系统在高负载情况下仍能正常运行
- 平滑流量曲线:通过冷启动、匀速排队等策略,使流量更加平滑
- 防止雪崩效应:避免单个服务故障导致整个系统崩溃
4.1.2 流量控制的维度
Sentinel支持从多个维度进行流量控制:
- 资源维度:对特定资源进行流量控制
- 调用者维度:对特定调用者进行流量控制
- 参数维度:对特定参数值进行流量控制
- 系统维度:从系统整体负载出发进行流量控制
4.2 流量控制规则
流量控制规则(FlowRule)是Sentinel进行流量控制的依据,它定义了资源的流量控制策略。
4.2.1 规则的主要属性
| 属性名 | 说明 | 默认值 |
|---|---|---|
resource |
资源名称 | - |
count |
阈值 | - |
grade |
限流阈值类型(QPS或并发线程数) | 0(QPS) |
limitApp |
调用来源 | default(不区分来源) |
strategy |
流量控制策略 | 0(直接) |
controlBehavior |
流量控制效果(直接拒绝、冷启动、匀速排队) | 0(直接拒绝) |
clusterMode |
是否集群限流 | false |
4.2.2 规则的配置方式
Sentinel支持多种规则配置方式:
- 控制台配置:通过Sentinel控制台动态配置
- API配置:通过代码编程式配置
- 配置文件:通过本地配置文件静态配置
- 配置中心:集成Nacos、Apollo等配置中心
4.3 流量控制策略
Sentinel支持多种流量控制策略:
4.3.1 直接拒绝
**直接拒绝(Reject)**是默认的流量控制策略,当请求超过阈值时,直接拒绝新的请求并抛出FlowException。
特点:
- 实现简单,性能开销小
- 对短时间内的突发流量比较敏感
- 适用于对响应时间要求不高的场景
4.3.2 冷启动
**冷启动(Warm Up)**也称为预热模式,它通过控制请求速率的增长速度,使系统在启动后有一个预热的过程。
冷启动的实现基于令牌桶算法,通过设置一个冷启动因子(默认3),初始的阈值为count / coldFactor,然后随着时间的推移,阈值逐渐增加到count。
特点:
- 防止系统在启动初期因大量请求而崩溃
- 适用于系统需要预热的场景(如缓存加载)
- 可以平滑流量曲线
4.3.3 匀速排队
**匀速排队(Rate Limiting)**模式严格控制请求的通过速率,确保请求以均匀的速度通过。
匀速排队的实现基于漏桶算法,它会维护一个队列,当请求到达时,如果队列未满,则将请求放入队列;否则,拒绝请求。队列中的请求会按照固定的速率被处理。
特点:
- 确保请求以均匀的速度通过
- 适用于对响应时间稳定性要求较高的场景
- 可以有效应对突发流量
4.4 流量控制模式
Sentinel支持多种流量控制模式:
4.4.1 直接模式
直接模式是默认的流量控制模式,它直接对当前资源进行流量控制。
配置示例:
java
FlowRule rule = new FlowRule();
rule.setResource("resourceName");
rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
rule.setCount(10); // QPS阈值为10
rule.setStrategy(RuleConstant.STRATEGY_DIRECT);
FlowRuleManager.loadRules(Collections.singletonList(rule));
4.4.2 关联模式
关联模式是指当关联的资源达到阈值时,对当前资源进行流量控制。
适用场景:
- 当两个资源之间存在依赖关系时,如订单服务和支付服务
- 当一个资源的访问会影响另一个资源的性能时
配置示例:
java
FlowRule rule = new FlowRule();
rule.setResource("orderService");
rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
rule.setCount(100);
rule.setStrategy(RuleConstant.STRATEGY_RELATE);
rule.setRefResource("paymentService"); // 关联的资源
FlowRuleManager.loadRules(Collections.singletonList(rule));
4.4.3 链路模式
链路模式是指只对特定调用链路的请求进行流量控制。
适用场景:
- 当需要对不同调用路径的请求进行不同的流量控制时
- 当需要精确控制某个服务的入口流量时
配置示例:
java
FlowRule rule = new FlowRule();
rule.setResource("serviceA");
rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
rule.setCount(50);
rule.setStrategy(RuleConstant.STRATEGY_CHAIN);
rule.setRefResource("serviceB"); // 调用链的入口资源
FlowRuleManager.loadRules(Collections.singletonList(rule));
4.5 实战示例
4.5.1 基于QPS的流量控制
- 定义资源:
java
@RestController
public class FlowController {
@GetMapping("/hello")
@SentinelResource(value = "hello", blockHandler = "handleBlock")
public String hello() {
return "Hello, Sentinel!";
}
// 限流处理方法
public String handleBlock(BlockException ex) {
return "请求过于频繁,请稍后重试!";
}
}
- 配置规则:
java
@Configuration
public class SentinelConfig {
@PostConstruct
public void initRules() {
List<FlowRule> rules = new ArrayList<>();
FlowRule rule = new FlowRule();
rule.setResource("hello");
rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
rule.setCount(5); // QPS阈值为5
rule.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_DEFAULT);
rules.add(rule);
FlowRuleManager.loadRules(rules);
}
}
- 测试 :
- 使用压测工具(如JMeter)模拟6个并发请求
- 观察结果,应该有1个请求被限流
4.5.2 基于并发线程数的流量控制
- 定义资源:
java
@GetMapping("/concurrent")
@SentinelResource(value = "concurrent", blockHandler = "handleBlock")
public String concurrent() throws InterruptedException {
Thread.sleep(1000); // 模拟耗时操作
return "Concurrent test";
}
- 配置规则:
java
FlowRule rule = new FlowRule();
rule.setResource("concurrent");
rule.setGrade(RuleConstant.FLOW_GRADE_THREAD);
rule.setCount(3); // 并发线程数阈值为3
rules.add(rule);
- 测试 :
- 使用压测工具模拟5个并发请求
- 观察结果,应该有2个请求被限流
4.5.3 冷启动模式
- 配置规则:
java
FlowRule rule = new FlowRule();
rule.setResource("hello");
rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
rule.setCount(100);
rule.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_WARM_UP);
rule.setWarmUpPeriodSec(10); // 预热时间为10秒
rules.add(rule);
- 测试 :
- 启动应用后立即发送大量请求
- 观察QPS的变化,应该从33(100/3)逐渐增加到100
4.5.4 匀速排队模式
- 配置规则:
java
FlowRule rule = new FlowRule();
rule.setResource("hello");
rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
rule.setCount(10);
rule.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_RATE_LIMITER);
rule.setMaxQueueingTimeMs(500); // 最大排队时间为500毫秒
rules.add(rule);
- 测试 :
- 发送突发请求
- 观察请求的响应时间,应该比较均匀
- 超过排队时间的请求会被拒绝
-
[3. Sentinel核心原理和架构](#3. Sentinel核心原理和架构)
- [3.1 Sentinel的核心概念](#3.1 Sentinel的核心概念)
- [3.2 Sentinel的工作原理](#3.2 Sentinel的工作原理)
- [3.3 Sentinel的架构设计](#3.3 Sentinel的架构设计)
- [3.4 Sentinel的SPI扩展机制](#3.4 Sentinel的SPI扩展机制)
-
[4. Sentinel流量控制实践](#4. Sentinel流量控制实践)
- [4.1 流量控制概述](#4.1 流量控制概述)
- [4.2 流量控制规则](#4.2 流量控制规则)
- [4.3 流量控制策略](#4.3 流量控制策略)
- [4.4 流量控制模式](#4.4 流量控制模式)
- [4.5 实战示例](#4.5 实战示例)
5. Sentinel熔断降级实践
5.1 熔断降级概述
熔断降级(Circuit Breaking & Degradation)是Sentinel的另一个核心功能,它通过监控资源的错误率、响应时间等指标,在资源出现异常时进行熔断或降级处理,防止局部故障扩散到整个系统。
5.1.1 熔断降级的作用
- 防止级联故障:避免一个服务的故障导致整个调用链崩溃
- 保护调用方:当被调用服务不可用时,快速失败并返回降级结果
- 自动恢复:在故障修复后自动恢复正常调用
- 提高系统可用性:确保系统在部分服务故障时仍能提供基本功能
5.1.2 熔断与降级的区别
| 特性 | 熔断 | 降级 |
|---|---|---|
| 触发条件 | 服务不可用(错误率、响应时间等) | 系统负载高、资源不足 |
| 恢复方式 | 自动恢复(半开状态试探) | 人工或配置恢复 |
| 作用范围 | 特定服务或资源 | 通常是核心功能降级为非核心功能 |
| 执行时机 | 调用前检查 | 调用时或调用后执行 |
5.2 熔断降级规则
熔断降级规则(DegradeRule)定义了资源的熔断降级策略,它基于资源的错误率、响应时间等指标进行熔断或降级。
5.2.1 规则的主要属性
| 属性名 | 说明 | 默认值 |
|---|---|---|
resource |
资源名称 | - |
count |
阈值 | - |
grade |
熔断降级策略(慢调用比例、异常比例、异常数) | 0(慢调用比例) |
timeWindow |
熔断时长(单位:秒) | - |
minRequestAmount |
熔断触发的最小请求数 | 5 |
slowRatioThreshold |
慢调用比例阈值(仅对慢调用比例策略有效) | - |
statIntervalMs |
统计时长(单位:毫秒) | 1000ms |
rtSlowRequestAmount |
慢调用定义的RT阈值(仅对慢调用比例策略有效) | - |
5.2.2 规则的配置方式
同流量控制规则一样,Sentinel支持多种熔断降级规则配置方式:
- 控制台配置:通过Sentinel控制台动态配置
- API配置:通过代码编程式配置
- 配置文件:通过本地配置文件静态配置
- 配置中心:集成Nacos、Apollo等配置中心
5.3 熔断策略
Sentinel支持三种熔断降级策略:
5.3.1 慢调用比例
慢调用比例(Slow Request Ratio):当资源的慢调用比例超过阈值时,触发熔断。
慢调用是指响应时间超过rtSlowRequestAmount的请求。
配置示例:
java
DegradeRule rule = new DegradeRule();
rule.setResource("resourceName");
rule.setGrade(RuleConstant.DEGRADE_GRADE_RT);
rule.setCount(200); // RT阈值为200ms
rule.setSlowRatioThreshold(0.5); // 慢调用比例阈值为50%
rule.setTimeWindow(10); // 熔断时长为10秒
rule.setMinRequestAmount(5); // 最小请求数为5
rule.setStatIntervalMs(1000); // 统计时长为1秒
5.3.2 异常比例
异常比例(Exception Ratio):当资源的异常比例超过阈值时,触发熔断。
异常比例是指异常请求数占总请求数的比例。
配置示例:
java
DegradeRule rule = new DegradeRule();
rule.setResource("resourceName");
rule.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_RATIO);
rule.setCount(0.3); // 异常比例阈值为30%
rule.setTimeWindow(10); // 熔断时长为10秒
rule.setMinRequestAmount(5); // 最小请求数为5
rule.setStatIntervalMs(1000); // 统计时长为1秒
5.3.3 异常数
异常数(Exception Count):当资源在统计时长内的异常数超过阈值时,触发熔断。
配置示例:
java
DegradeRule rule = new DegradeRule();
rule.setResource("resourceName");
rule.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_COUNT);
rule.setCount(10); // 异常数阈值为10
rule.setTimeWindow(10); // 熔断时长为10秒
rule.setMinRequestAmount(5); // 最小请求数为5
rule.setStatIntervalMs(60000); // 统计时长为60秒
5.4 实战示例
5.4.1 基于慢调用比例的熔断
- 定义资源:
java
@RestController
public class DegradeController {
@GetMapping("/slow")
@SentinelResource(value = "slow", blockHandler = "handleBlock", fallback = "handleFallback")
public String slow() throws InterruptedException {
// 随机延迟,模拟慢调用
long delay = (long) (Math.random() * 500);
Thread.sleep(delay);
return "Slow response with delay: " + delay + "ms";
}
// 限流处理方法
public String handleBlock(BlockException ex) {
return "请求被熔断,请稍后重试!";
}
// 降级处理方法
public String handleFallback(Throwable t) {
return "服务降级,返回默认结果!";
}
}
- 配置规则:
java
@Configuration
public class SentinelConfig {
@PostConstruct
public void initDegradeRules() {
List<DegradeRule> rules = new ArrayList<>();
DegradeRule rule = new DegradeRule();
rule.setResource("slow");
rule.setGrade(RuleConstant.DEGRADE_GRADE_RT);
rule.setCount(200); // RT阈值为200ms
rule.setSlowRatioThreshold(0.5); // 慢调用比例阈值为50%
rule.setTimeWindow(10); // 熔断时长为10秒
rule.setMinRequestAmount(5); // 最小请求数为5
rules.add(rule);
DegradeRuleManager.loadRules(rules);
}
}
- 测试 :
- 发送多个请求,观察慢调用比例
- 当慢调用比例超过50%时,资源被熔断
- 10秒后,资源自动恢复
5.4.2 基于异常比例的熔断
- 定义资源:
java
@GetMapping("/exception")
@SentinelResource(value = "exception", blockHandler = "handleBlock", fallback = "handleFallback")
public String exception() {
// 随机抛出异常,模拟服务异常
if (Math.random() > 0.7) {
throw new RuntimeException("服务内部异常");
}
return "正常响应";
}
- 配置规则:
java
DegradeRule rule = new DegradeRule();
rule.setResource("exception");
rule.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_RATIO);
rule.setCount(0.5); // 异常比例阈值为50%
rule.setTimeWindow(10); // 熔断时长为10秒
rule.setMinRequestAmount(5); // 最小请求数为5
rules.add(rule);
- 测试 :
- 发送多个请求,观察异常比例
- 当异常比例超过50%时,资源被熔断
- 10秒后,资源自动恢复
5.4.3 基于异常数的熔断
- 配置规则:
java
DegradeRule rule = new DegradeRule();
rule.setResource("exception");
rule.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_COUNT);
rule.setCount(5); // 异常数阈值为5
rule.setTimeWindow(10); // 熔断时长为10秒
rule.setMinRequestAmount(5); // 最小请求数为5
rule.setStatIntervalMs(60000); // 统计时长为60秒
rules.add(rule);
- 测试 :
- 在1分钟内发送多个请求,使异常数超过5个
- 当异常数达到阈值时,资源被熔断
- 10秒后,资源自动恢复
5.4.4 自定义降级逻辑
- 定义资源:
java
@GetMapping("/custom-degrade")
@SentinelResource(value = "customDegrade", blockHandler = "handleBlock", fallback = "handleCustomFallback")
public Map<String, Object> customDegrade() {
// 模拟调用第三方服务
if (Math.random() > 0.5) {
throw new RuntimeException("第三方服务不可用");
}
Map<String, Object> result = new HashMap<>();
result.put("success", true);
result.put("data", "第三方服务返回的数据");
return result;
}
// 自定义降级处理方法
public Map<String, Object> handleCustomFallback(Throwable t) {
Map<String, Object> fallbackResult = new HashMap<>();
fallbackResult.put("success", false);
fallbackResult.put("message", "服务降级,返回默认数据");
fallbackResult.put("data", "默认数据");
return fallbackResult;
}
- 测试 :
- 发送请求,观察正常响应和降级响应
- 正常响应包含第三方服务数据
- 降级响应返回默认数据
- [5. Sentinel熔断降级实践](#5. Sentinel熔断降级实践)
- [5.1 熔断降级概述](#5.1 熔断降级概述)
- [5.2 熔断降级规则](#5.2 熔断降级规则)
- [5.3 熔断策略](#5.3 熔断策略)
- [5.4 实战示例](#5.4 实战示例)
6. Sentinel热点参数限流与系统保护
6.1 热点参数限流
热点参数限流是Sentinel的一个重要特性,它可以对资源请求中的热点参数进行精确的流量控制,防止因某个参数值的请求量过大而导致系统过载。
6.1.1 热点参数限流的作用
- 针对特定参数值限流:可以对请求中某个参数的特定值进行限流
- 精确控制热点流量:防止热点数据(如热门商品ID、热点用户ID)导致系统过载
- 灵活的参数索引:支持对方法的多个参数进行限流
- 结合其他限流策略:可以与流量控制、熔断降级等策略结合使用
6.1.2 热点参数限流规则
热点参数限流规则(ParamFlowRule)定义了资源的热点参数限流策略。
规则的主要属性:
| 属性名 | 说明 | 默认值 |
|---|---|---|
resource |
资源名称 | - |
count |
阈值 | - |
grade |
限流模式(QPS或并发线程数) | 0(QPS) |
paramIdx |
参数索引(从0开始) | - |
durationInSec |
统计窗口时长(秒) | 1 |
controlBehavior |
流量控制效果 | 0(直接拒绝) |
paramFlowItemList |
参数例外项列表 | - |
clusterMode |
是否集群限流 | false |
6.1.3 热点参数限流的实现原理
Sentinel的热点参数限流基于滑动窗口算法实现,它通过以下步骤进行限流:
- 参数提取:从请求中提取指定索引的参数值
- 参数统计:为每个参数值维护一个滑动窗口计数器
- 阈值检查:检查参数值的请求数是否超过阈值
- 限流执行:如果超过阈值,则拒绝请求
6.1.4 参数例外项
参数例外项允许为特定的参数值设置不同的阈值,例如:
- 对大多数商品ID设置较低的阈值
- 对热门商品ID设置较高的阈值
6.2 系统保护规则
系统保护规则是从系统整体负载的角度出发,对系统进行保护,防止系统因整体过载而崩溃。
6.2.1 系统保护的作用
- 防止系统整体崩溃:从系统负载、CPU使用率等全局指标进行保护
- 动态调整限流阈值:根据系统的实时负载动态调整限流策略
- 避免雪崩效应:防止局部故障导致系统整体不可用
6.2.2 系统保护规则的类型
Sentinel支持以下几种系统保护规则:
- RT(响应时间):当系统的平均响应时间超过阈值时,触发系统保护
- 线程数:当系统的线程数超过阈值时,触发系统保护
- 入口QPS:当系统的入口QPS超过阈值时,触发系统保护
- CPU使用率:当系统的CPU使用率超过阈值时,触发系统保护
6.2.3 系统保护规则的属性
| 属性名 | 说明 | 默认值 |
|---|---|---|
resource |
资源名称(系统规则中为"system") | - |
count |
阈值 | - |
grade |
规则类型(RT、线程数、入口QPS、CPU使用率) | - |
highestSystemLoad |
系统负载阈值(仅对CPU使用率规则有效) | - |
avgRt |
平均响应时间阈值(仅对RT规则有效) | - |
maxThread |
最大线程数阈值(仅对线程数规则有效) | - |
qps |
入口QPS阈值(仅对入口QPS规则有效) | - |
highestCpuUsage |
CPU使用率阈值(仅对CPU使用率规则有效) | - |
6.3 授权规则
授权规则用于对资源的访问进行黑白名单控制,它可以根据请求的来源IP或其他标识进行授权控制。
6.3.1 授权规则的作用
- 控制资源访问权限:允许或拒绝特定来源的请求访问资源
- 防止恶意访问:拒绝来自黑名单IP的请求
- 实现访问控制策略:根据业务需求灵活配置授权规则
6.3.2 授权规则的属性
| 属性名 | 说明 | 默认值 |
|---|---|---|
resource |
资源名称 | - |
limitApp |
授权策略(白名单或黑名单)和授权对象 | - |
strategy |
授权策略(白名单或黑名单) | 0(白名单) |
6.3.3 授权规则的实现原理
Sentinel的授权规则通过RequestOriginParser接口实现请求来源的解析,然后根据配置的授权策略进行访问控制:
- 解析请求来源:通过RequestOriginParser解析请求的来源
- 检查授权策略:根据配置的白名单或黑名单检查请求来源
- 执行授权控制:允许或拒绝请求访问资源
6.4 实战示例
6.4.1 热点参数限流示例
- 定义资源:
java
@RestController
public class HotParamController {
@GetMapping("/product/{id}")
@SentinelResource(value = "product", blockHandler = "handleBlock")
public String getProduct(@PathVariable Long id) {
return "Product ID: " + id;
}
// 限流处理方法
public String handleBlock(Long id, BlockException ex) {
return "商品查询过于频繁,请稍后重试!";
}
}
- 配置热点参数限流规则:
java
@PostConstruct
public void initHotParamRules() {
List<ParamFlowRule> rules = new ArrayList<>();
ParamFlowRule rule = new ParamFlowRule();
rule.setResource("product");
rule.setParamIdx(0); // 第一个参数
rule.setCount(5); // QPS阈值为5
rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
// 添加参数例外项(商品ID为1001的请求QPS阈值为20)
ParamFlowItem item = new ParamFlowItem();
item.setClassType(String.class.getName());
item.setValue("1001");
item.setCount(20);
rule.setParamFlowItemList(Collections.singletonList(item));
rules.add(rule);
ParamFlowRuleManager.loadRules(rules);
}
- 测试 :
- 频繁访问
/product/1,观察是否被限流 - 频繁访问
/product/1001,观察是否有更高的阈值
- 频繁访问
6.4.2 系统保护规则示例
- 配置系统保护规则:
java
@PostConstruct
public void initSystemRules() {
List<SystemRule> rules = new ArrayList<>();
SystemRule rule = new SystemRule();
rule.setHighestCpuUsage(0.8); // CPU使用率阈值为80%
rule.setAvgRt(100); // 平均响应时间阈值为100ms
rule.setMaxThread(200); // 最大线程数阈值为200
rule.setQps(2000); // 入口QPS阈值为2000
rules.add(rule);
SystemRuleManager.loadRules(rules);
}
- 测试 :
- 模拟高CPU使用率或高QPS场景
- 观察系统是否触发保护
6.4.3 授权规则示例
- 实现RequestOriginParser:
java
@Component
public class IpRequestOriginParser implements RequestOriginParser {
@Override
public String parseOrigin(HttpServletRequest request) {
// 从请求头或其他地方获取请求来源
String origin = request.getHeader("X-Real-IP");
if (origin == null) {
origin = request.getRemoteAddr();
}
return origin;
}
}
- 配置授权规则:
java
@PostConstruct
public void initAuthorityRules() {
List<AuthorityRule> rules = new ArrayList<>();
AuthorityRule rule = new AuthorityRule();
rule.setResource("product");
rule.setStrategy(RuleConstant.AUTHORITY_WHITE); // 白名单
rule.setLimitApp("127.0.0.1,192.168.1.0/24"); // 允许访问的IP
rules.add(rule);
AuthorityRuleManager.loadRules(rules);
}
- 测试 :
- 从白名单IP访问资源,应该允许访问
- 从非白名单IP访问资源,应该被拒绝
- [6. Sentinel热点参数限流与系统保护](#6. Sentinel热点参数限流与系统保护)
- [6.1 热点参数限流](#6.1 热点参数限流)
- [6.2 系统保护规则](#6.2 系统保护规则)
- [6.3 授权规则](#6.3 授权规则)
- [6.4 实战示例](#6.4 实战示例)
7. Sentinel与Spring Cloud的集成
7.1 Spring Cloud环境准备
在将Sentinel与Spring Cloud集成之前,需要准备好Spring Cloud环境。
7.1.1 版本要求
| Spring Cloud版本 | Sentinel版本 | Spring Boot版本 |
|---|---|---|
| Hoxton.x | 1.7.x+ | 2.2.x+ |
| Greenwich.x | 1.6.x+ | 2.1.x+ |
| Finchley.x | 1.5.x+ | 2.0.x+ |
7.1.2 环境依赖
- 创建Spring Boot项目:使用Spring Initializr创建一个Spring Boot项目
- 添加Spring Cloud依赖:在pom.xml中添加Spring Cloud依赖管理
- 添加Sentinel依赖:添加Sentinel相关依赖
xml
<!-- Spring Cloud依赖管理 -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Hoxton.SR12</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
7.2 Sentinel与Spring Cloud整合
7.2.1 添加依赖
在Spring Boot项目的pom.xml中添加Sentinel相关依赖:
xml
<!-- Spring Cloud Alibaba Sentinel -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
<version>2.2.8.RELEASE</version>
</dependency>
<!-- Sentinel数据源持久化(可选) -->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
<version>1.8.6</version>
</dependency>
<!-- Spring Boot Actuator(可选,用于监控) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
7.2.2 配置Sentinel
在application.yml中配置Sentinel:
yaml
spring:
application:
name: sentinel-demo
cloud:
sentinel:
transport:
dashboard: localhost:8080 # Sentinel控制台地址
port: 8719 # 与控制台通信的端口
datasource:
ds1:
nacos:
server-addr: localhost:8848
dataId: sentinel-demo-flow-rules
groupId: DEFAULT_GROUP
rule-type: flow
# 暴露Actuator端点
management:
endpoints:
web:
exposure:
include: '*'
7.2.3 定义资源
使用@SentinelResource注解定义资源:
java
@RestController
public class ProductController {
@GetMapping("/product/{id}")
@SentinelResource(value = "product", blockHandler = "handleBlock", fallback = "handleFallback")
public String getProduct(@PathVariable Long id) {
if (id == 1) {
throw new RuntimeException("商品不存在");
}
return "Product ID: " + id;
}
// 限流处理
public String handleBlock(Long id, BlockException ex) {
return "请求过于频繁,请稍后重试!";
}
// 降级处理
public String handleFallback(Long id, Throwable t) {
return "服务异常,返回默认结果!";
}
}
7.3 Sentinel与Spring Cloud Gateway集成
Spring Cloud Gateway是Spring Cloud生态中的API网关,Sentinel提供了与Spring Cloud Gateway的集成支持。
7.3.1 添加依赖
xml
<!-- Spring Cloud Gateway -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!-- Sentinel Gateway适配器 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
<version>2.2.8.RELEASE</version>
</dependency>
7.3.2 配置Gateway路由
yaml
spring:
cloud:
gateway:
routes:
- id: product_route
uri: http://localhost:8081
predicates:
- Path=/api/product/**
filters:
- StripPrefix=1
7.3.3 配置Sentinel Gateway规则
java
@Configuration
public class GatewaySentinelConfig {
@PostConstruct
public void initGatewayRules() {
Set<GatewayFlowRule> rules = new HashSet<>();
GatewayFlowRule rule = new GatewayFlowRule();
rule.setResourceMode(SentinelGatewayConstants.RESOURCE_MODE_ROUTE_ID);
rule.setResource("product_route");
rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
rule.setCount(10); // QPS阈值为10
rule.setIntervalSec(1);
rules.add(rule);
GatewayRuleManager.loadRules(rules);
}
}
7.3.4 自定义Gateway限流响应
java
@Component
public class CustomGatewayBlockExceptionHandler implements WebExceptionHandler {
@Override
public Mono<Void> handle(ServerWebExchange exchange, Throwable ex) {
if (ex instanceof BlockException) {
exchange.getResponse().setStatusCode(HttpStatus.TOO_MANY_REQUESTS);
exchange.getResponse().getHeaders().setContentType(MediaType.APPLICATION_JSON);
String body = "{\"code\":429,\"message\":\"请求过于频繁,请稍后重试\"}";
DataBuffer buffer = exchange.getResponse().bufferFactory().wrap(body.getBytes());
return exchange.getResponse().writeWith(Mono.just(buffer));
}
return Mono.error(ex);
}
}
7.4 整合Feign
Feign是Spring Cloud中的声明式HTTP客户端,Sentinel可以与Feign集成,为Feign客户端提供限流和降级保护。
7.4.1 添加依赖
xml
<!-- Spring Cloud OpenFeign -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
7.4.2 启用Feign Sentinel支持
在application.yml中启用Feign Sentinel支持:
yaml
feign:
sentinel:
enabled: true # 启用Feign的Sentinel支持
7.4.3 定义Feign客户端
java
@FeignClient(name = "product-service", fallback = ProductFeignClientFallback.class)
public interface ProductFeignClient {
@GetMapping("/product/{id}")
String getProduct(@PathVariable("id") Long id);
}
// 降级实现
@Component
class ProductFeignClientFallback implements ProductFeignClient {
@Override
public String getProduct(Long id) {
return "Product service is unavailable, return default product";
}
}
7.4.4 使用Feign客户端
java
@RestController
public class OrderController {
@Autowired
private ProductFeignClient productFeignClient;
@GetMapping("/order/{productId}")
@SentinelResource(value = "order")
public String createOrder(@PathVariable Long productId) {
String product = productFeignClient.getProduct(productId);
return "Create order for " + product;
}
}
7.5 完整实战示例
7.5.1 项目结构
spring-cloud-sentinel-demo
├── gateway-service # API网关服务
├── product-service # 商品服务
├── order-service # 订单服务
└── sentinel-dashboard # Sentinel控制台
7.5.2 商品服务实现
- 添加依赖:同7.2.1
- 配置文件:同7.2.2
- 控制器:同7.2.3
7.5.3 订单服务实现
- 添加依赖:同7.2.1 + Feign依赖
- 配置文件:同7.2.2 + Feign Sentinel配置
- Feign客户端:同7.4.3
- 控制器:同7.4.4
7.5.4 网关服务实现
- 添加依赖:同7.3.1
- 配置文件:同7.3.2 + Sentinel配置
- Sentinel规则配置:同7.3.3
7.5.5 测试
-
启动服务:
- 启动Nacos(如果使用)
- 启动Sentinel控制台
- 启动商品服务
- 启动订单服务
- 启动网关服务
-
测试流程:
- 访问
http://localhost:8080/api/product/1,测试商品服务降级 - 频繁访问
http://localhost:8080/api/product/2,测试限流 - 访问
http://localhost:8080/api/order/1,测试Feign集成和降级
- 访问
- [7. Sentinel与Spring Cloud的集成](#7. Sentinel与Spring Cloud的集成)
- [7.1 Spring Cloud环境准备](#7.1 Spring Cloud环境准备)
- [7.2 Sentinel与Spring Cloud整合](#7.2 Sentinel与Spring Cloud整合)
- [7.3 Sentinel与Spring Cloud Gateway集成](#7.3 Sentinel与Spring Cloud Gateway集成)
- [7.4 整合Feign](#7.4 整合Feign)
- [7.5 完整实战示例](#7.5 完整实战示例)
8. Sentinel高级特性、最佳实践与监控
8.1 规则持久化
Sentinel默认将规则保存在内存中,重启后规则会丢失。为了解决这个问题,Sentinel提供了规则持久化的支持。
8.1.1 持久化方式
Sentinel支持多种规则持久化方式:
- 文件持久化:将规则保存到本地文件
- Nacos持久化:将规则保存到Nacos配置中心
- Apollo持久化:将规则保存到Apollo配置中心
- ZooKeeper持久化:将规则保存到ZooKeeper
8.1.2 Nacos持久化配置
添加依赖:
xml
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
<version>1.8.6</version>
</dependency>
配置文件:
yaml
spring:
cloud:
sentinel:
datasource:
ds1:
nacos:
server-addr: localhost:8848
dataId: sentinel-demo-flow-rules
groupId: DEFAULT_GROUP
rule-type: flow # 规则类型
namespace: public # Nacos命名空间
在Nacos中创建规则:
json
[
{
"resource": "product",
"limitApp": "default",
"grade": 1,
"count": 10,
"strategy": 0,
"controlBehavior": 0,
"clusterMode": false
}
]
8.1.3 文件持久化配置
配置文件:
yaml
spring:
cloud:
sentinel:
datasource:
ds2:
file:
file: classpath:flow-rules.json
rule-type: flow
refresh-interval-ms: 3000 # 刷新间隔
flow-rules.json:
json
[
{
"resource": "order",
"limitApp": "default",
"grade": 1,
"count": 5,
"strategy": 0,
"controlBehavior": 0,
"clusterMode": false
}
]
8.2 自定义规则源
Sentinel支持自定义规则源,可以从任何数据源加载规则。
8.2.1 实现DataSource接口
java
public class CustomDataSource implements ReadableDataSource<String, List<FlowRule>> {
private final String config; // 模拟配置源
public CustomDataSource(String config) {
this.config = config;
}
@Override
public List<FlowRule> loadConfig() {
// 从自定义源加载规则
return JSON.parseArray(config, FlowRule.class);
}
@Override
public Map<String, PropertyChangeListener<?>> getPropertyChangeListeners() {
return Collections.emptyMap();
}
@Override
public void addPropertyChangeListener(String key, PropertyChangeListener<?> listener) {
// 实现监听逻辑
}
@Override
public void removePropertyChangeListener(String key) {
// 实现移除监听逻辑
}
}
8.2.2 注册自定义数据源
java
@Configuration
public class SentinelConfig {
@PostConstruct
public void initCustomDataSource() {
// 模拟从数据库加载的规则配置
String config = "[{\"resource\":\"test\",\"count\":10,\"grade\":1}]";
CustomDataSource dataSource = new CustomDataSource(config);
FlowRuleManager.register2Property(dataSource.getProperty());
}
}
8.3 监控与指标
Sentinel提供了丰富的监控指标,可以帮助我们了解系统的运行状态。
8.3.1 监控指标类型
- 资源指标:QPS、响应时间、异常数等
- 规则指标:限流次数、降级次数、热点参数拦截次数等
- 系统指标:CPU使用率、内存使用率、线程数等
8.3.2 使用Actuator查看指标
添加依赖:
xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
访问监控端点:
http://localhost:8080/actuator/sentinel:查看Sentinel监控信息http://localhost:8080/actuator/metrics:查看所有指标
8.3.3 自定义指标
java
@Component
public class CustomMetrics implements InitFunc {
@Override
public void init() {
// 注册自定义指标
MetricExtensionRegistry.register(new MetricExtension() {
@Override
public List<MetricNode> collect() {
List<MetricNode> metrics = new ArrayList<>();
// 收集自定义指标
MetricNode node = new MetricNode();
node.setName("custom_metric");
node.setValue(System.currentTimeMillis());
metrics.add(node);
return metrics;
}
});
}
}
8.4 最佳实践
8.4.1 资源命名规范
- 使用有意义的名称 :如
order_create、user_login - 包含业务上下文 :如
payment_alipay、payment_wechat - 避免过长:建议不超过50个字符
8.4.2 规则配置建议
-
流量控制:
- 根据实际业务场景选择限流策略
- 设置合理的阈值,避免影响正常业务
- 优先使用Warm Up模式应对突发流量
-
熔断降级:
- 设置合理的慢调用比例阈值(建议50%以上)
- 熔断时长不宜过长(建议5秒到1分钟)
- 为关键业务设置降级逻辑
-
热点参数限流:
- 对频繁访问的参数进行限流
- 使用参数例外项处理特殊情况
8.4.3 部署建议
- 独立部署Sentinel控制台
- 配置高可用的规则数据源
- 定期备份规则配置
- 监控Sentinel控制台的运行状态
8.4.4 性能优化
- 减少不必要的埋点
- 使用异步埋点
- 合理设置统计窗口大小
- 关闭不需要的规则类型
8.5 常见问题与排查
8.5.1 控制台看不到数据
可能原因:
- 客户端与控制台网络不通
- 客户端未正确配置控制台地址
- 客户端未触发任何资源
排查步骤:
- 检查客户端日志是否有连接错误
- 验证控制台地址配置是否正确
- 手动访问客户端接口触发资源
8.5.2 规则不生效
可能原因:
- 规则配置错误
- 资源名称不匹配
- 规则数据源问题
排查步骤:
- 检查规则配置是否符合规范
- 确认资源名称是否完全一致
- 查看规则数据源是否正常加载
8.5.3 性能问题
可能原因:
- 埋点过多
- 规则数量过多
- 统计窗口设置不合理
优化建议:
- 减少不必要的埋点
- 合并相似规则
- 调整统计窗口大小
8.6 未来发展与总结
8.6.1 Sentinel的优势
- 轻量级:核心库只有几十KB
- 高性能:单机支持几十万QPS
- 易用性:提供丰富的API和注解
- 扩展性:支持SPI扩展
- 生态丰富:与Spring Cloud、Dubbo等生态无缝集成
8.6.2 未来发展方向
- 更强大的规则引擎:支持更复杂的规则表达式
- 更完善的监控系统:提供更丰富的指标和可视化
- 更好的集群支持:优化集群限流算法
- 更智能的流量控制:引入机器学习算法
8.6.3 总结
Sentinel是一款功能强大的流量控制、熔断降级框架,它提供了丰富的功能和灵活的配置,可以帮助我们构建高可用的分布式系统。通过合理使用Sentinel,我们可以有效地保护系统免受流量冲击,提高系统的稳定性和可靠性。
在实际项目中,我们应该根据业务需求选择合适的功能和配置,遵循最佳实践,并不断优化和调整,以达到最佳的保护效果。
- [8. Sentinel高级特性、最佳实践与监控](#8. Sentinel高级特性、最佳实践与监控)
- [8.1 规则持久化](#8.1 规则持久化)
- [8.2 自定义规则源](#8.2 自定义规则源)
- [8.3 监控与指标](#8.3 监控与指标)
- [8.4 最佳实践](#8.4 最佳实践)
- [8.5 常见问题与排查](#8.5 常见问题与排查)
- [8.6 未来发展与总结](#8.6 未来发展与总结)