文章目录
-
- 第一部分:理论篇
-
- [1. Sentinel 简介](#1. Sentinel 简介)
- [2. Sentinel 核心原理](#2. Sentinel 核心原理)
-
- [2.1 资源与规则](#2.1 资源与规则)
- [2.2 Sentinel 工作主流程](#2.2 Sentinel 工作主流程)
- [2.3 核心类解析](#2.3 核心类解析)
- [3. Sentinel 功能支持与使用流程](#3. Sentinel 功能支持与使用流程)
-
- [3.1 流量控制](#3.1 流量控制)
- [3.2 熔断降级](#3.2 熔断降级)
- [3.3 系统自适应保护](#3.3 系统自适应保护)
- [3.4 热点参数限流](#3.4 热点参数限流)
- [3.5 黑白名单控制](#3.5 黑白名单控制)
- [3.6 使用流程](#3.6 使用流程)
- [4. Sentinel 架构](#4. Sentinel 架构)
-
- [4.1 核心库](#4.1 核心库)
- [4.2 控制台](#4.2 控制台)
- [5. 限流组件对比](#5. 限流组件对比)
-
- [5.1 Sentinel vs Hystrix vs Resilience4j](#5.1 Sentinel vs Hystrix vs Resilience4j)
- [5.2 各组件特点](#5.2 各组件特点)
- [6. Sentinel 优缺点](#6. Sentinel 优缺点)
-
- [6.1 优点](#6.1 优点)
- [6.2 缺点](#6.2 缺点)
- [7. 理论篇总结](#7. 理论篇总结)
- 第二部分:实战篇
-
- [1. Sentinel 本地部署](#1. Sentinel 本地部署)
-
- [1.1 部署 Sentinel Dashboard](#1.1 部署 Sentinel Dashboard)
-
- [1.1.1 下载 Dashboard](#1.1.1 下载 Dashboard)
- [1.1.2 启动 Dashboard](#1.1.2 启动 Dashboard)
- [1.1.3 访问 Dashboard](#1.1.3 访问 Dashboard)
- [1.2 配置开机自启(可选)](#1.2 配置开机自启(可选))
-
- [Linux 系统(使用 systemd)](#Linux 系统(使用 systemd))
- [2. Spring Boot 接入 Sentinel](#2. Spring Boot 接入 Sentinel)
-
- [2.1 添加依赖](#2.1 添加依赖)
- [2.2 配置 Sentinel](#2.2 配置 Sentinel)
- [2.3 定义资源](#2.3 定义资源)
-
- [2.3.1 使用 @SentinelResource 注解](#2.3.1 使用 @SentinelResource 注解)
- [2.3.2 开启 Sentinel 对 Spring MVC 端点的自动保护](#2.3.2 开启 Sentinel 对 Spring MVC 端点的自动保护)
- [2.4 启用 Sentinel 注解支持](#2.4 启用 Sentinel 注解支持)
- [3. Sentinel 核心功能演示](#3. Sentinel 核心功能演示)
-
- [3.1 流量控制(Flow Control)](#3.1 流量控制(Flow Control))
-
- [3.1.1 通过 Dashboard 配置流控规则](#3.1.1 通过 Dashboard 配置流控规则)
- [3.1.2 代码方式配置流控规则](#3.1.2 代码方式配置流控规则)
- [3.2 熔断降级(Circuit Breaking)](#3.2 熔断降级(Circuit Breaking))
-
- [3.2.1 通过 Dashboard 配置熔断规则](#3.2.1 通过 Dashboard 配置熔断规则)
- [3.2.2 代码方式配置熔断规则](#3.2.2 代码方式配置熔断规则)
- [3.3 热点参数限流(Hot Spot)](#3.3 热点参数限流(Hot Spot))
-
- [3.3.1 使用 @SentinelResource 注解定义热点参数资源](#3.3.1 使用 @SentinelResource 注解定义热点参数资源)
- [3.3.2 通过 Dashboard 配置热点规则](#3.3.2 通过 Dashboard 配置热点规则)
- [3.3.3 代码方式配置热点规则](#3.3.3 代码方式配置热点规则)
- [3.4 系统自适应保护(System Adaptive Protection)](#3.4 系统自适应保护(System Adaptive Protection))
-
- [3.4.1 通过 Dashboard 配置系统规则](#3.4.1 通过 Dashboard 配置系统规则)
- [3.4.2 代码方式配置系统规则](#3.4.2 代码方式配置系统规则)
- [4. 规则持久化](#4. 规则持久化)
-
- [4.1 基于文件的规则持久化](#4.1 基于文件的规则持久化)
- [4.2 基于 Nacos 的规则持久化](#4.2 基于 Nacos 的规则持久化)
- [4.3 基于 Consul 的规则持久化](#4.3 基于 Consul 的规则持久化)
- [5. 实际应用案例](#5. 实际应用案例)
-
- [5.1 接口限流保护](#5.1 接口限流保护)
- [5.2 服务调用保护](#5.2 服务调用保护)
- [5.3 网关限流保护](#5.3 网关限流保护)
- [6. 最佳实践](#6. 最佳实践)
-
- [6.1 合理划分资源](#6.1 合理划分资源)
- [6.2 选择合适的限流策略](#6.2 选择合适的限流策略)
- [6.3 合理配置熔断规则](#6.3 合理配置熔断规则)
- [6.4 规则持久化](#6.4 规则持久化)
- [6.5 监控告警](#6.5 监控告警)
- [7. 常见问题与解决方案](#7. 常见问题与解决方案)
-
- [7.1 应用无法注册到 Dashboard](#7.1 应用无法注册到 Dashboard)
- [7.2 规则不生效](#7.2 规则不生效)
- [7.3 @SentinelResource 注解不生效](#7.3 @SentinelResource 注解不生效)
- [8. 实战篇总结](#8. 实战篇总结)
- 参考资料
本文尝试入门 Alibaba Sentinel,一个强大的流量控制组件。我们将从理论出发,涵盖其核心原理、功能特性、架构设计以及与其他主流限流组件的对比,然后进入实战环节,详细介绍 Sentinel 的本地部署、与 Spring Boot 的集成方法,并演示其核心功能的使用。
第一部分:理论篇
1. Sentinel 简介
Sentinel 是阿里巴巴开源的,面向分布式服务架构的轻量级高可用流量控制组件,主要以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。
Sentinel 具有以下特征:
- 丰富的应用场景:Sentinel 承接了阿里巴巴近 10 年的双十一大促流量的核心场景,例如秒杀(即突发流量控制在系统容量可以承受的范围)、消息削峰填谷、集群流量控制、实时熔断下游不可用应用等。
- 完备的实时监控:Sentinel 同时提供实时的监控功能。可以在控制台中看到接入应用的单台机器秒级数据,甚至 500 台以下规模的集群的汇总运行情况。
- 广泛的开源生态:Sentinel 提供开箱即用的与其它开源框架/库的整合模块,例如与 Spring Cloud、Apache Dubbo、gRPC、Quarkus 的整合。您只需要引入相应的依赖并进行简单的配置即可快速地接入 Sentinel。同时 Sentinel 提供 Java/Go/C++ 等多语言的原生实现。
- 完善的 SPI 扩展机制:Sentinel 提供简单易用、完善的 SPI 扩展接口。可以通过实现扩展接口来快速地定制逻辑。例如定制规则管理、适配动态数据源等。
Sentinel 分为两个部分:
- 核心库(Java 客户端):不依赖任何框架/库,能够运行于所有 Java 运行时环境,同时对 Dubbo / Spring Cloud 等框架也有较好的支持。
- 控制台(Dashboard):基于 Spring Boot 开发,打包后可以直接运行,不需要额外的 Tomcat 等应用容器。
2. Sentinel 核心原理
2.1 资源与规则
在 Sentinel 中,资源是保护的基本单位,可以是 Java 应用程序中的任何内容,例如,由应用程序提供的服务,或由应用程序调用的其它应用提供的服务,甚至可以是一段代码。
资源定义的方式主要有几种:
- 通过
SphU.entry("resourceName")
和entry.exit()
方法定义资源 - 通过
@SentinelResource
注解定义资源 - 通过适配器接入(如 Web 适配器、Dubbo 适配器等)
规则是 Sentinel 的核心概念之一,通过规则来指定资源的限流、熔断、系统保护等行为。规则可以动态实时地进行配置和修改,并立即生效。
2.2 Sentinel 工作主流程
在 Sentinel 里面,所有的资源都对应一个资源名称(resourceName
),每次资源调用都会创建一个 Entry
对象。Entry 可以通过对主流框架的适配自动创建,也可以通过注解的方式或调用 SphU
API 显式创建。
Entry 创建的时候,同时也会创建一系列功能插槽(slot chain),这些插槽有不同的职责:
- NodeSelectorSlot:负责收集资源的路径,并将这些资源的调用路径,以树状结构存储起来,用于根据调用路径来限流降级;
- ClusterBuilderSlot:用于存储资源的统计信息以及调用者信息,例如该资源的 RT, QPS, thread count 等等,这些信息将用作为多维度限流,降级的依据;
- StatisticSlot:用于记录、统计不同纬度的 runtime 指标监控信息;
- FlowSlot:用于根据预设的限流规则以及前面 slot 统计的状态,来进行流量控制;
- AuthoritySlot:根据配置的黑白名单和调用来源信息,来做黑白名单控制;
- DegradeSlot:通过统计信息以及预设的规则,来做熔断降级;
- SystemSlot:通过系统的状态,例如 load1 等,来控制总的入口流量。
Sentinel 将 ProcessorSlot
作为 SPI 接口进行扩展,使得 Slot Chain 具备了扩展的能力。用户可以自行加入自定义的 slot 并编排 slot 间的顺序,从而可以给 Sentinel 添加自定义的功能。
2.3 核心类解析
Sentinel 的核心骨架,将不同的 Slot 按照顺序串在一起(责任链模式),从而将不同的功能(限流、降级、系统保护)组合在一起。slot chain 其实可以分为两部分:统计数据构建部分(statistic)和判断部分(rule checking)。
主要核心类包括:
- ProcessorSlotChain:Sentinel 的核心骨架,将不同的 Slot 按照顺序串在一起
- Context :代表调用链路上下文,贯穿一次调用链路中的所有
Entry
- Entry:每一次资源调用都会创建一个 Entry
- Node:各种统计节点,如 StatisticNode、DefaultNode、ClusterNode、EntranceNode 等
- StatisticSlot:Sentinel 最为重要的类之一,用于根据规则判断结果进行相应的统计操作
3. Sentinel 功能支持与使用流程
3.1 流量控制
流量控制在网络传输中是一个常用的概念,它用于调整网络包的发送数据。在 Sentinel 中,我们可以通过流控规则来控制系统的 QPS 或并发线程数等指标。
流量控制的方式包括:
- 直接拒绝:当 QPS 超过阈值时,直接拒绝多余的请求
- 冷启动/预热:当系统长期处于低水位的情况下,当流量突然增加时,直接把系统拉升到高水位可能瞬间把系统压垮。通过"冷启动",让通过的流量缓慢增加,在一定时间内逐渐增加到阈值上限,给冷系统一个预热的时间,避免冷系统被压垮
- 匀速排队:严格控制请求通过的间隔时间,也即是让请求以均匀的速度通过,对应的是漏桶算法
3.2 熔断降级
除了流量控制以外,对调用链路中不稳定的资源进行熔断降级也是保障高可用的重要措施之一。由于调用关系的复杂性,如果调用链路中的某个资源出现了不稳定,最终会导致请求发生堆积。
Sentinel 熔断降级会在调用链路中某个资源出现不稳定状态时(例如调用超时或异常比例升高),对这个资源的调用进行限制,让请求快速失败,避免影响到其它的资源而导致级联错误。
熔断降级支持的模式:
- 慢调用比例:当单位统计时长内请求数目大于设置的最小请求数目,并且慢调用的比例大于阈值,则接下来的熔断时长内请求会自动被熔断
- 异常比例:当单位统计时长内请求数目大于设置的最小请求数目,并且异常的比例大于阈值,则接下来的熔断时长内请求会自动被熔断
- 异常数:当单位统计时长内的异常数目超过阈值之后会自动进行熔断
3.3 系统自适应保护
Sentinel 系统自适应限流从整体维度对应用入口流量进行控制,结合应用的 Load、CPU 使用率、总体平均 RT、入口 QPS 和并发线程数等几个维度的监控指标,通过自适应的流控策略,让系统的入口流量和系统的负载达到一个平衡,让系统尽可能跑在最大吞吐量的同时保证系统整体的稳定性。
3.4 热点参数限流
热点参数限流是一种更细粒度的流量控制,它允许我们针对某个热点参数进行限流,比如针对某个用户 ID 限流。
3.5 黑白名单控制
黑白名单根据资源的请求来源(origin)限制资源是否通过,若配置白名单则只有请求来源位于白名单内时才可通过;若配置黑白名单则请求来源位于黑名单时不通过,其余的请求通过。
3.6 使用流程
Sentinel 的使用流程非常简单,主要包括以下几个步骤:
- 定义资源:通过 API 或注解方式定义资源
- 定义规则:配置规则,包括流控规则、熔断规则、系统规则等
- 检验规则是否生效:通过运行程序并观察监控数据,检验规则是否生效
4. Sentinel 架构
Sentinel 的整体架构分为核心库和控制台两部分:
4.1 核心库
核心库不依赖任何框架/库,能够运行于 Java 8 及以上的版本的运行时环境,同时对 Dubbo / Spring Cloud 等框架也有较好的支持。
核心库主要负责:
- 定义资源
- 规则管理
- 实时统计
- 规则判断
- 扩展点
4.2 控制台
控制台(Dashboard)主要负责:
- 规则管理:配置规则、查看规则
- 监控展示:查看秒级监控,了解系统实时运行情况
- 机器发现:自动发现应用
5. 限流组件对比
5.1 Sentinel vs Hystrix vs Resilience4j
功能 | Sentinel | Hystrix | Resilience4j |
---|---|---|---|
隔离策略 | 信号量隔离(并发线程数限流) | 线程池隔离/信号量隔离 | 信号量隔离 |
熔断降级策略 | 基于响应时间、异常比率、异常数等 | 异常比率模式、超时熔断 | 基于异常比率、响应时间 |
实时统计实现 | 滑动窗口(LeapArray) | 滑动窗口(基于 RxJava) | Ring Bit Buffer |
动态规则配置 | 支持多种配置源 | 支持多种数据源 | 有限支持 |
扩展性 | 丰富的 SPI 扩展接口 | 插件的形式 | 接口的形式 |
基于注解的支持 | 支持 | 支持 | 支持 |
限流 | 基于 QPS,支持基于调用关系的限流 | 有限的支持 | Rate Limiter |
集群流量控制 | 支持 | 不支持 | 不支持 |
流量整形 | 支持预热模式、匀速排队模式等多种复杂场景 | 不支持 | 简单的 Rate Limiter 模式 |
系统自适应保护 | 支持 | 不支持 | 不支持 |
控制台 | 提供开箱即用的控制台,可配置规则、查看秒级监控、机器发现等 | 简单的监控查看 | 不提供控制台,可对接其它监控系统 |
多语言支持 | Java / Go / C++ | Java | Java |
开源社区状态 | 活跃 | 停止维护 | 较活跃 |
5.2 各组件特点
Hystrix
Hystrix 的关注点在于以隔离和熔断为主的容错机制,超时或被熔断的调用将会快速失败,并可以提供 fallback 机制。
Hystrix 的资源模型设计上采用了命令模式,将对外部资源的调用和 fallback 逻辑封装成一个命令对象(HystrixCommand/ HystrixObservableCommand),其底层的执行是基于 RxJava 实现的。
Hystrix 的线程池隔离针对不同的资源分别创建不同的线程池,不同服务调用都发生在不同的线程池中,在线程池排队、超时等阻塞情况时可以快速失败。但是,线程池隔离的代价就是线程上下文切换的 overhead 比较大,特别是对低延时的调用有比较大的影响。
需要注意的是,Netflix 已经宣布 Hystrix 进入维护模式,不再添加新功能,推荐使用 Resilience4j 或 Sentinel。
Resilience4j
Resilience4j 是一个受 Netflix Hystrix 启发的轻量级容错库,但它是为 Java 8 和函数式编程设计的。轻量级,因为库只使用 Vavr,它没有任何其他外部库依赖项。
Resilience4j 提供高阶函数(decorators)来增强任何功能接口、lambda 表达式或方法引用,包括断路器、速率限制器、重试或隔板。可以在任何函数接口、lambda 表达式或方法引用上堆叠多个装饰器。优点是可以选择所需的装饰器,而无需其他任何东西。
Sentinel
Sentinel 的侧重点在于:
- 多样化的流量控制策略,支持预热模式、匀速排队模式等多种复杂场景
- 熔断降级
- 系统负载保护
- 实时监控和控制台
Sentinel 的设计更为简单。相比 Hystrix Command 强依赖隔离规则,Sentinel 的资源定义与规则配置的耦合度更低。Sentinel 并不指定执行模型,也不关注应用是如何执行的。Sentinel 的原则非常简单:根据对应资源配置的规则来为资源执行相应的限流/降级/负载保护策略。
6. Sentinel 优缺点
6.1 优点
- 丰富的应用场景:Sentinel 提供了多样化的流量控制策略,支持预热模式、匀速排队模式等多种复杂场景,能够满足各种业务需求。
- 完备的实时监控:Sentinel 提供了实时的监控功能,可以在控制台中看到接入应用的单台机器秒级数据,甚至集群的汇总运行情况。
- 广泛的开源生态:Sentinel 提供了与 Spring Cloud、Apache Dubbo、gRPC 等框架的整合模块,使得接入变得非常简单。
- 完善的 SPI 扩展机制:Sentinel 提供了简单易用、完善的 SPI 扩展接口,可以通过实现扩展接口来快速地定制逻辑。
- 多语言支持:Sentinel 提供了 Java/Go/C++ 等多语言的原生实现。
- 活跃的社区:Sentinel 拥有活跃的社区,持续更新和维护。
- 阿里巴巴生产环境验证:Sentinel 在阿里巴巴内部经过了大规模的生产环境验证,包括双十一等高并发场景。
6.2 缺点
- 学习曲线:相比于一些简单的限流组件,Sentinel 的功能更加丰富,因此学习曲线可能会更陡峭。
- 配置复杂性:由于功能丰富,Sentinel 的配置相对复杂,需要对各种规则有深入的理解。
- 控制台依赖:虽然核心库不依赖控制台,但要充分发挥 Sentinel 的功能,控制台是必不可少的。
- 规则持久化:默认情况下,规则是存储在内存中的,需要额外配置才能实现规则的持久化。
- 集群限流的复杂性:虽然 Sentinel 支持集群限流,但配置和维护相对复杂。
7. 理论篇总结
Sentinel 作为一个面向分布式服务架构的轻量级高可用流量控制组件,提供了丰富的功能和良好的扩展性,能够满足各种复杂的业务场景。相比于 Hystrix 和 Resilience4j,Sentinel 在流量控制、系统自适应保护、实时监控等方面具有明显的优势。
在选择限流组件时,需要根据具体的业务场景和需求进行选择。如果需要丰富的流量控制策略、系统自适应保护和实时监控,Sentinel 是一个很好的选择;如果更注重轻量级和函数式编程,Resilience4j 可能更适合;而 Hystrix 由于已经进入维护模式,不再推荐使用。
无论选择哪种组件,都需要深入理解其核心原理和使用方法,才能充分发挥其功能,保障系统的稳定性和可用性。
第二部分:实战篇
1. Sentinel 本地部署
1.1 部署 Sentinel Dashboard
Sentinel Dashboard 是 Sentinel 的控制台组件,提供机器发现、监控、规则管理等功能。以下是部署步骤:
1.1.1 下载 Dashboard
首先,从 GitHub 下载最新版本的 Sentinel Dashboard:
https://github.com/alibaba/Sentinel/releases
当前最新的稳定版本是 sentinel-dashboard-1.8.7.jar
。
1.1.2 启动 Dashboard
使用以下命令启动 Sentinel Dashboard:
bash
java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard.jar
参数说明:
-Dserver.port=8080
:指定 Dashboard 的端口号为 8080-Dcsp.sentinel.dashboard.server=localhost:8080
:指定 Dashboard 的地址和端口-Dproject.name=sentinel-dashboard
:指定项目名称
如果需要修改默认的用户名和密码(默认都是 sentinel
),可以添加以下参数:
-Dsentinel.dashboard.auth.username=admin
:设置用户名为 admin-Dsentinel.dashboard.auth.password=123456
:设置密码为 123456
1.1.3 访问 Dashboard
启动成功后,通过浏览器访问:http://localhost:8080
使用默认用户名和密码(都是 sentinel
)登录,或者使用自定义的用户名和密码。
1.2 配置开机自启(可选)
如果需要将 Sentinel Dashboard 设置为开机自启,可以根据不同的操作系统进行配置:
Linux 系统(使用 systemd)
- 创建服务文件:
bash
sudo vim /etc/systemd/system/sentinel-dashboard.service
-
添加以下内容:
[Unit]
Description=Sentinel Dashboard
After=network.target[Service]
Type=simple
User=your_username
ExecStart=/usr/bin/java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080 -Dproject.name=sentinel-dashboard -jar /path/to/sentinel-dashboard.jar
Restart=on-failure[Install]
WantedBy=multi-user.target -
启用服务:
bash
sudo systemctl daemon-reload
sudo systemctl enable sentinel-dashboard
sudo systemctl start sentinel-dashboard
2. Spring Boot 接入 Sentinel
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>
</dependency>
<!-- 引入 Spring Cloud Alibaba 依赖管理 -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2022.0.0.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
注意:请根据的 Spring Boot 版本选择合适的 Spring Cloud Alibaba 版本。例如:
- Spring Boot 3.x 对应 Spring Cloud Alibaba 2022.x.x
- Spring Boot 2.6.x 对应 Spring Cloud Alibaba 2021.x.x
- Spring Boot 2.4.x 对应 Spring Cloud Alibaba 2.2.6.RELEASE
2.2 配置 Sentinel
在 application.yml
或 application.properties
中添加 Sentinel 配置:
yaml
spring:
application:
name: sentinel-demo
cloud:
sentinel:
transport:
# 配置 Sentinel Dashboard 地址
dashboard: localhost:8080
# 指定应用与 Sentinel Dashboard 通信的端口(默认为 8719)
port: 8719
# 饥饿加载模式,项目启动时即初始化 Sentinel
eager: true
2.3 定义资源
在 Spring Boot 中,有多种方式定义 Sentinel 资源:
2.3.1 使用 @SentinelResource 注解
java
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class TestController {
@GetMapping("/hello")
@SentinelResource(value = "hello",
blockHandler = "blockHandlerForHello",
fallback = "fallbackForHello")
public String hello() {
return "Hello Sentinel";
}
// 处理限流或降级
public String blockHandlerForHello(BlockException ex) {
return "Blocked by Sentinel: " + ex.getClass().getSimpleName();
}
// 处理业务异常
public String fallbackForHello(Throwable t) {
return "Fallback: " + t.getMessage();
}
}
2.3.2 开启 Sentinel 对 Spring MVC 端点的自动保护
在 application.yml
中添加:
yaml
spring:
cloud:
sentinel:
web-context-unify: false
这样,所有的 Spring MVC 端点都会自动作为 Sentinel 资源,资源名为请求路径(如 /hello
)。
2.4 启用 Sentinel 注解支持
在启动类或配置类上添加 @EnableSentinel
注解:
java
import com.alibaba.cloud.sentinel.annotation.SentinelRestTemplate;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
@SpringBootApplication
public class SentinelDemoApplication {
public static void main(String[] args) {
SpringApplication.run(SentinelDemoApplication.class, args);
}
@Bean
@LoadBalanced
@SentinelRestTemplate
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
3. Sentinel 核心功能演示
3.1 流量控制(Flow Control)
流量控制是 Sentinel 最基本的功能,用于限制资源的访问量,保障系统稳定性。
3.1.1 通过 Dashboard 配置流控规则
- 访问 Sentinel Dashboard
- 选择应用,进入"流控规则"页面
- 点击"新增流控规则"按钮
- 填写规则信息:
- 资源名:要保护的资源名称,如
hello
- 针对来源:默认为
default
,表示不区分调用来源 - 阈值类型:选择 QPS 或线程数
- 单机阈值:设置限流阈值,如 QPS 为 5
- 流控模式:直接、关联或链路
- 流控效果:快速失败、Warm Up 或排队等待
- 资源名:要保护的资源名称,如
- 点击"新增"按钮保存规则
3.1.2 代码方式配置流控规则
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 org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.List;
@Component
public class SentinelRuleConfig {
@PostConstruct
public void initFlowRules() {
List<FlowRule> rules = new ArrayList<>();
// 创建流控规则
FlowRule rule = new FlowRule();
// 设置资源名
rule.setResource("hello");
// 设置限流阈值类型为 QPS
rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
// 设置 QPS 阈值为 5
rule.setCount(5);
rules.add(rule);
// 加载规则
FlowRuleManager.loadRules(rules);
}
}
3.2 熔断降级(Circuit Breaking)
熔断降级是对调用链路中不稳定的资源进行熔断保护,防止级联故障。
3.2.1 通过 Dashboard 配置熔断规则
- 访问 Sentinel Dashboard
- 选择应用,进入"熔断规则"页面
- 点击"新增熔断规则"按钮
- 填写规则信息:
- 资源名:要保护的资源名称
- 熔断策略:慢调用比例、异常比例或异常数
- 最小请求数:触发熔断的最小请求数
- 统计时长:统计时间窗口,单位为 ms
- 熔断时长:熔断持续时间,单位为 s
- 慢调用比例阈值:慢调用占比超过该值触发熔断(仅慢调用比例模式)
- 异常比例阈值:异常请求占比超过该值触发熔断(仅异常比例模式)
- 异常数阈值:异常请求数超过该值触发熔断(仅异常数模式)
- 点击"新增"按钮保存规则
3.2.2 代码方式配置熔断规则
java
import com.alibaba.csp.sentinel.slots.block.RuleConstant;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.List;
@Component
public class SentinelDegradeConfig {
@PostConstruct
public void initDegradeRules() {
List<DegradeRule> rules = new ArrayList<>();
// 创建熔断规则
DegradeRule rule = new DegradeRule();
// 设置资源名
rule.setResource("hello");
// 设置熔断策略为异常比例
rule.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_RATIO);
// 设置异常比例阈值,取值范围 [0.0, 1.0]
rule.setCount(0.5);
// 设置最小请求数
rule.setMinRequestAmount(5);
// 设置统计时长,单位为 ms
rule.setStatIntervalMs(1000);
// 设置熔断时长,单位为 s
rule.setTimeWindow(10);
rules.add(rule);
// 加载规则
DegradeRuleManager.loadRules(rules);
}
}
3.3 热点参数限流(Hot Spot)
热点参数限流是一种更细粒度的流量控制,它允许我们针对某个热点参数进行限流。
3.3.1 使用 @SentinelResource 注解定义热点参数资源
java
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HotSpotController {
@GetMapping("/product")
@SentinelResource(value = "getProduct",
blockHandler = "getProductBlockHandler")
public String getProduct(@RequestParam Long productId) {
return "Product info: " + productId;
}
public String getProductBlockHandler(Long productId, BlockException ex) {
return "Blocked by hot spot rule: " + productId;
}
}
3.3.2 通过 Dashboard 配置热点规则
- 访问 Sentinel Dashboard
- 选择应用,进入"热点规则"页面
- 点击"新增热点规则"按钮
- 填写规则信息:
- 资源名:要保护的资源名称,如
getProduct
- 参数索引:参数在方法参数列表中的索引,从 0 开始,如
0
表示第一个参数 - 单机阈值:限流阈值
- 统计窗口时长:统计时间窗口,单位为秒
- 资源名:要保护的资源名称,如
- 点击"新增"按钮保存规则
3.3.3 代码方式配置热点规则
java
import com.alibaba.csp.sentinel.slots.block.RuleConstant;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowItem;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowRuleManager;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@Component
public class SentinelHotSpotConfig {
@PostConstruct
public void initParamFlowRules() {
List<ParamFlowRule> rules = new ArrayList<>();
// 创建热点参数规则
ParamFlowRule rule = new ParamFlowRule();
// 设置资源名
rule.setResource("getProduct");
// 设置限流模式为 QPS
rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
// 设置参数索引
rule.setParamIdx(0);
// 设置限流阈值
rule.setCount(5);
// 特例配置:对特定参数值单独设置阈值
ParamFlowItem item = new ParamFlowItem();
// 设置参数值
item.setObject(String.valueOf(1));
// 设置特例阈值
item.setCount(10);
// 设置限流模式为 QPS
item.setClassType(String.class.getName());
rule.setParamFlowItemList(Collections.singletonList(item));
rules.add(rule);
// 加载规则
ParamFlowRuleManager.loadRules(rules);
}
}
3.4 系统自适应保护(System Adaptive Protection)
系统自适应保护从整体维度对应用入口流量进行控制,结合应用的 Load、CPU 使用率等指标,让系统的入口流量和系统的负载达到一个平衡。
3.4.1 通过 Dashboard 配置系统规则
- 访问 Sentinel Dashboard
- 选择应用,进入"系统规则"页面
- 点击"新增系统规则"按钮
- 填写规则信息:
- 系统 Load:当系统 load1 超过阈值,触发系统保护
- CPU 使用率:当系统 CPU 使用率超过阈值,触发系统保护
- 平均 RT:当单台机器所有入口流量的平均 RT 达到阈值,触发系统保护
- 并发线程数:当单台机器所有入口流量的并发线程数达到阈值,触发系统保护
- 入口 QPS:当单台机器所有入口流量的 QPS 达到阈值,触发系统保护
- 点击"新增"按钮保存规则
3.4.2 代码方式配置系统规则
java
import com.alibaba.csp.sentinel.slots.system.SystemRule;
import com.alibaba.csp.sentinel.slots.system.SystemRuleManager;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.List;
@Component
public class SentinelSystemConfig {
@PostConstruct
public void initSystemRules() {
List<SystemRule> rules = new ArrayList<>();
// 创建系统规则
SystemRule rule = new SystemRule();
// 设置 load 阈值
rule.setHighestSystemLoad(3.0);
// 设置 CPU 使用率阈值
rule.setHighestCpuUsage(0.6);
// 设置平均 RT 阈值,单位是毫秒
rule.setAvgRt(500);
// 设置并发线程数阈值
rule.setMaxThread(200);
// 设置入口 QPS 阈值
rule.setQps(300);
rules.add(rule);
// 加载规则
SystemRuleManager.loadRules(rules);
}
}
4. 规则持久化
默认情况下,Sentinel 的规则是存储在内存中的,应用重启后规则会丢失。为了解决这个问题,Sentinel 提供了动态规则源支持,可以将规则持久化到外部存储。
4.1 基于文件的规则持久化
java
import com.alibaba.csp.sentinel.datasource.FileRefreshableDataSource;
import com.alibaba.csp.sentinel.datasource.ReadableDataSource;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.io.File;
import java.util.List;
@Component
public class FileDataSourceInit {
@PostConstruct
public void init() throws Exception {
String ruleDir = System.getProperty("user.home") + "/sentinel/rules";
String flowRulePath = ruleDir + "/flow-rule.json";
// 创建目录
File dir = new File(ruleDir);
if (!dir.exists()) {
dir.mkdirs();
}
// 创建文件数据源
ReadableDataSource<String, List<FlowRule>> flowRuleDataSource = new FileRefreshableDataSource<>(
flowRulePath,
source -> JSON.parseObject(source, new TypeReference<List<FlowRule>>() {})
);
// 注册到 FlowRuleManager
FlowRuleManager.register2Property(flowRuleDataSource.getProperty());
}
}
4.2 基于 Nacos 的规则持久化
首先,添加 Nacos 数据源依赖:
xml
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
然后,在 application.yml
中配置 Nacos 数据源:
yaml
spring:
cloud:
sentinel:
datasource:
flow:
nacos:
server-addr: localhost:8848
dataId: ${spring.application.name}-flow-rules
groupId: SENTINEL_GROUP
rule-type: flow
degrade:
nacos:
server-addr: localhost:8848
dataId: ${spring.application.name}-degrade-rules
groupId: SENTINEL_GROUP
rule-type: degrade
4.3 基于 Consul 的规则持久化
首先,添加 Consul 数据源依赖:
xml
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-consul</artifactId>
<version>1.8.6</version>
</dependency>
然后,在 application.yml
中配置 Consul 数据源:
yaml
spring:
cloud:
sentinel:
datasource:
flow:
consul:
host: localhost
port: 8500
rule-key: sentinel_flow_rule
data-type: json
rule-type: flow
在 Consul 中添加规则配置:
json
[
{
"resource": "/hello",
"limitApp": "default",
"grade": 1,
"count": 5,
"strategy": 0,
"controlBehavior": 0
}
]
5. 实际应用案例
5.1 接口限流保护
以下是一个完整的接口限流保护示例:
java
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/api")
public class ApiController {
@GetMapping("/test")
@SentinelResource(value = "apiTest",
blockHandler = "blockHandlerForApiTest",
fallback = "fallbackForApiTest")
public String apiTest() {
// 模拟业务逻辑
return "API test success";
}
// 处理限流或降级
public String blockHandlerForApiTest(BlockException ex) {
return "API request blocked: " + ex.getClass().getSimpleName();
}
// 处理业务异常
public String fallbackForApiTest(Throwable t) {
return "API request failed: " + t.getMessage();
}
}
5.2 服务调用保护
使用 @SentinelRestTemplate
注解保护 RestTemplate 调用:
java
import com.alibaba.cloud.sentinel.annotation.SentinelRestTemplate;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
@Configuration
public class RestTemplateConfig {
@Bean
@SentinelRestTemplate(blockHandler = "handleBlock", fallback = "handleFallback")
public RestTemplate restTemplate() {
return new RestTemplate();
}
// 处理限流或降级
public static String handleBlock(String url, Exception ex) {
return "RestTemplate request blocked: " + url;
}
// 处理业务异常
public static String handleFallback(String url, Throwable t) {
return "RestTemplate request failed: " + url;
}
}
5.3 网关限流保护
如果使用 Spring Cloud Gateway,可以添加 Sentinel 网关限流支持:
xml
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
</dependency>
在 application.yml
中配置:
yaml
spring:
cloud:
gateway:
routes:
- id: service-route
uri: lb://service-name
predicates:
- Path=/service/**
sentinel:
scg:
fallback:
mode: response
response-body: '{"code":429,"message":"Too many requests"}'
6. 最佳实践
6.1 合理划分资源
资源是 Sentinel 的核心概念,合理划分资源是使用 Sentinel 的基础。建议按照以下原则划分资源:
- 按照业务功能划分资源,而不是技术实现
- 保持资源粒度的一致性,不要过粗或过细
- 为资源命名时使用有意义的名称,便于识别和管理
6.2 选择合适的限流策略
Sentinel 提供了多种限流策略,应根据业务场景选择合适的策略:
- 直接拒绝:适用于大部分场景,直接拒绝超出阈值的请求
- 冷启动(Warm Up):适用于系统刚启动或流量突增的场景,让通过的流量缓慢增加
- 匀速排队:适用于请求需要严格按照时间间隔处理的场景
6.3 合理配置熔断规则
熔断规则的配置应考虑以下因素:
- 最小请求数:设置合理的最小请求数,避免因为少量请求就触发熔断
- 统计时长:根据业务特点设置合适的统计窗口
- 熔断时长:根据故障恢复时间设置合适的熔断时长
- 阈值:根据系统容量和业务容忍度设置合适的阈值
6.4 规则持久化
在生产环境中,建议将规则持久化到外部存储,如 Nacos、ZooKeeper、Apollo 等,避免应用重启后规则丢失。
6.5 监控告警
结合 Sentinel 的监控功能,建立完善的监控告警机制,及时发现和处理系统异常。
7. 常见问题与解决方案
7.1 应用无法注册到 Dashboard
可能的原因和解决方案:
- 检查 Dashboard 地址配置是否正确
- 确保应用有访问量,Sentinel 会在首次调用时初始化
- 检查网络连接,确保应用可以访问 Dashboard
- 查看日志
${user.home}/logs/csp/sentinel-record.log.xxx
排查问题
7.2 规则不生效
可能的原因和解决方案:
- 检查资源名称是否正确
- 确保规则已正确加载
- 检查是否有冲突的规则
- 查看日志排查问题
7.3 @SentinelResource 注解不生效
可能的原因和解决方案:
- 确保已启用 Sentinel 注解支持(
@EnableSentinel
) - 确保方法是 public 的
- 确保不是内部方法调用(内部方法调用不会触发 AOP)
- 检查 blockHandler 和 fallback 方法的签名是否正确
8. 实战篇总结
本实战篇详细介绍了 Sentinel 的本地部署、Spring Boot 接入方法以及核心功能的使用。通过学习和实践,应该能够:
- 部署和配置 Sentinel Dashboard
- 将 Sentinel 集成到 Spring Boot 应用中
- 使用 Sentinel 的流量控制、熔断降级、热点参数限流和系统自适应保护功能
- 实现规则持久化
- 应用 Sentinel 最佳实践
Sentinel 作为一个功能强大的流量控制组件,能够有效保障应用的稳定性和可用性。希望本教程能够帮助快速上手 Sentinel,并在实际项目中发挥其价值。
参考资料
- Sentinel GitHub Wiki: https://github.com/alibaba/Sentinel/wiki
- Sentinel 介绍: https://github.com/alibaba/Sentinel/wiki/介绍
- Sentinel 工作原理: https://github.com/alibaba/Sentinel/wiki/工作原理
- Sentinel 工作主流程: https://github.com/alibaba/Sentinel/wiki/Sentinel工作主流程
- Sentinel 核心类解析: https://github.com/alibaba/Sentinel/wiki/Sentinel-核心类解析
- 常用限流降级组件对比: https://github.com/alibaba/Sentinel/wiki/常用限流降级组件对比
- Sentinel 控制台: https://github.com/alibaba/Sentinel/wiki/控制台
- CSDN - 限流降级组件Sentinel、Hystrix、Resilience4j对比: https://blog.csdn.net/krauser1991/article/details/120293507
- CSDN - SpringBoot 3.1.7 集成Sentinel: https://blog.csdn.net/u010887012/article/details/135694628