第1章:Sentinel 概述与核心概念
1.1 什么是 Sentinel
| 概念名称 | 说明 | 注意事项 |
|---|---|---|
| Sentinel | 阿里巴巴开源的面向分布式服务架构的流量治理组件,主要用于保障系统在高并发场景下的稳定性。 | Sentinel 是轻量级、高可用的,适用于微服务架构中的流量控制、熔断降级等场景。 |
| 开源项目 | 由阿里巴巴于2018年开源,现为 Apache 顶级项目(孵化中),社区活跃,支持多语言(Java、Go等)。 | Java 版本功能最完整,Go 版本仍在持续演进中。 |
| 核心目标 | 在系统面临突发流量时,通过流量控制、熔断降级、系统保护等手段防止系统雪崩。 | 不仅限于”限流”,更强调”智能防护”和”自适应保护”。 |
1.2 Sentinel 的核心功能
| 功能名称 | 说明 | 注意事项 |
|---|---|---|
| 流量控制(Flow Control) | 控制资源的访问频率,防止系统被突发流量冲垮。支持 QPS 或线程数维度控制。 | 可配置多种流控模式和策略,如直接拒绝、Warm Up、排队等待。 |
| 熔断降级(Circuit Breaking) | 当依赖服务不稳定(如响应慢、异常多)时,自动熔断调用,避免连锁故障。 | 支持基于 RT、异常比例、异常数的降级策略。 |
| 热点参数限流(Hotspot Parameter Flow Control) | 对带有特定参数的请求进行精细化限流,例如限制某个用户 ID 或商品 ID 的访问频率。 | 适用于防止”热点数据”引发系统瓶颈。 |
| 系统自适应保护(System Protection) | 基于系统整体状态(如 Load、CPU 使用率)进行入口流量控制,防止系统过载。 | 从系统维度提供最后一道防线,适合微服务集群环境。 |
| 实时监控与可视化 | 提供 Dashboard 控制台,实时查看运行时指标(QPS、线程数、RT 等)。 | 需接入 transport 模块上报数据至控制台。 |
| 规则动态配置 | 支持通过控制台或配置中心(如 Nacos)动态修改规则,无需重启应用。 | 生产环境建议结合配置中心实现持久化。 |
1.3 流控、降级、熔断、热点参数的基本概念
| 概念名称 | 说明 | 注意事项 |
|---|---|---|
| 资源(Resource) | Sentinel 中的”资源”是流量控制的基本单位,可以是一个方法、一个 URL、一个服务等。 | 所有控制规则都作用于资源之上。 |
| 流控(Flow Control) | 限制资源在单位时间内的访问次数或并发线程数,防止系统过载。 | 常见策略:QPS 限流、线程数限流。 |
| 降级(Degradation) | 在系统压力大或依赖不稳定时,暂时关闭某些非核心功能,保证主流程可用。 | 是一种”牺牲局部保整体”的容错机制。 |
| 熔断(Circuit Breaking) | 当服务调用失败率超过阈值时,自动切断调用链路,一段时间后尝试恢复(半开状态)。 | 熔断器有三种状态:关闭(Closed)、打开(Open)、半开(Half-Open)。 |
| 热点参数(Hotspot Parameter) | 指某些请求参数值访问频率极高,容易成为系统瓶颈的数据(如热门商品 ID)。 | 热点参数限流可对特定参数值进行精准限流。 |
| 上下文(Context) | 表示一次调用链路的运行环境,用于跟踪资源调用路径和统计信息。 | 同一个请求链路共享一个 Context。 |
| Slot Chain | Sentinel 内部处理请求的插槽链,每个 Slot 负责不同职责(如统计、流控、降级等)。 | 可扩展自定义 Slot 实现个性化逻辑。 |
1.4 Sentinel 与 Hystrix 的对比
| 对比维度 | Sentinel | Hystrix |
|---|---|---|
| 开发公司 | 阿里巴巴 | Netflix |
| 核心理念 | 流量治理 + 系统自适应保护 | 熔断器模式为主 |
| 流控能力 | 强大,支持 QPS、线程数、热点参数、关联流控等多种模式 | 仅支持线程池或信号量隔离,流控能力弱 |
| 熔断降级 | 支持 RT、异常比例、异常数等多种策略 | 支持基于异常比例的熔断 |
| 系统保护 | 支持基于系统 Load、CPU 使用率的自适应保护 | 不支持系统维度保护 |
| 实时监控 | 提供 Dashboard 控制台,支持实时监控和规则配置 | 需整合 Turbine 才能实现聚合监控 |
| 动态规则 | 支持通过控制台或配置中心动态修改规则 | 配置修改需代码或属性刷新,不够灵活 |
| 扩展性 | 基于 Slot Chain 可扩展性强 | 扩展性一般,主要依赖 HystrixCommand |
| 性能开销 | 更轻量,基于滑动窗口统计,性能更高 | 使用线程池隔离时有额外线程开销 |
| 社区活跃度 | 国内活跃,集成 Spring Cloud Alibaba 方便 | Netflix 已宣布 Hystrix 进入维护模式 |
| 适用场景 | 微服务全链路流量治理 | 传统熔断降级场景 |
第2章:环境搭建与快速入门
2.1 引入 Sentinel 依赖(Maven 配置)
| 依赖名称 | Maven 坐标 | 用途 | 注意事项 |
|---|---|---|---|
| sentinel-core | com.alibaba.csp:sentinel-core:1.8.6 | 核心依赖,提供流量控制、熔断降级等基础功能 | 所有使用 Sentinel 的项目都必须引入 |
| sentinel-annotation-aspectj | com.alibaba.csp:sentinel-annotation-aspectj:1.8.6 | 支持 @SentinelResource 注解切面 | 使用注解方式定义资源时需要引入 |
| sentinel-web-servlet | com.alibaba.csp:sentinel-web-servlet:1.8.6 | 为传统 Servlet 项目提供 Web 适配 | 用于非 Spring Boot Web 项目 |
| sentinel-datasource-nacos | com.alibaba.csp:sentinel-datasource-nacos:1.8.6 | 支持从 Nacos 加载规则 | 实现规则持久化时使用 |
| sentinel-transport-simple-http | com.alibaba.csp:sentinel-transport-simple-http:1.8.6 | 与 Sentinel 控制台通信模块 | 应用需上报监控数据或接收规则时使用 |
示例:最简 Maven 配置(Spring Boot 项目)
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-core</artifactId>
<version>1.8.6</version>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-transport-simple-http</artifactId>
<version>1.8.6</version>
</dependency>
2.2 启动 Sentinel 控制台
| 操作步骤 | 说明 | 注意事项 |
|---|---|---|
| 下载控制台 | 官方 GitHub 仓库 releases 页面下载 sentinel-dashboard-x.x.x.jar | 确保版本与客户端一致,避免兼容问题 |
| 启动命令 | java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080 -jar sentinel-dashboard-1.8.6.jar | 可指定端口、用户名密码等参数 |
| 默认登录 | 用户名:sentinel,密码:sentinel | 登录后可修改密码,生产环境务必更改 |
| 客户端连接 | 客户端需引入 transport 模块并配置 dashboard 地址 | 通过 -Dcsp.sentinel.dashboard.server 参数或配置文件指定 |
| JVM 参数 | -Dserver.port=8080:控制台端口;-Dcsp.sentinel.dashboard.server=localhost:8080:注册地址;-Dproject.name=my-service:服务名 | 服务启动后会在控制台自动注册 |
示例:完整启动命令
java -Dserver.port=8080 \
-Dcsp.sentinel.dashboard.server=localhost:8080 \
-Dproject.name=sentinel-demo \
-jar sentinel-dashboard-1.8.6.jar
2.3 定义资源与最简单的流控规则
| 方法名称 | 语法 | 用途 | 注意事项 |
|---|---|---|---|
SphU.entry() | Entry entry = SphU.entry("resourceName"); | 定义一个资源入口,开始统计和规则判断 | 必须配对使用 entry 和 exit,否则会导致统计错误或内存泄漏 |
entry.exit() | entry.exit(); | 退出资源调用,释放上下文 | 必须在 finally 块中调用,确保释放资源 |
Tracer.trace() | Tracer.trace(e); | 记录异常,用于降级统计 | 仅用于记录异常,不影响流控判断 |
代码示例
Entry entry = null;
try {
entry = SphU.entry("HelloWorld");
// 业务逻辑
System.out.println("Hello World");
} catch (BlockException e) {
System.out.println("Blocked!");
} finally {
if (entry != null) {
entry.exit();
}
}
注:
SphU是 Sentinel 提供的底层 API,用于手动定义资源。
2.4 查看实时监控数据
| 指标名称 | 说明 | 注意事项 |
|---|---|---|
| QPS(Queries Per Second) | 每秒请求数,分为通过 QPS 和被拦截 QPS | 控制台中可查看实时曲线 |
| 平均响应时间(RT) | 请求的平均处理时间,单位毫秒 | RT 骤升可能意味着系统瓶颈 |
| 并发线程数 | 当前正在处理请求的线程数量 | 可用于设置线程数流控 |
| 资源名称 | 在 SphU.entry() 中定义的字符串标识 | 控制台中按资源名聚合数据 |
| Block 异常数 | 被流控或降级规则拦截的请求次数 | 反映规则生效情况 |
| 操作步骤 | 说明 | 注意事项 |
|---|---|---|
| 登录控制台 | 访问 http://localhost:8080,使用默认账号密码登录 | 确保客户端已连接 |
| 查看机器列表 | 在”簇点链路”或”实时监控”页面查看已注册服务 | 若无数据,检查 transport 配置 |
| 查看实时指标 | 进入”实时监控”页面,选择服务和时间范围 | 数据每秒上报一次 |
| 查看簇点链路 | 在”簇点链路”页面查看当前应用的所有资源 | 可对未配置规则的资源快速添加流控 |
注意: 首次访问资源后才会在”簇点链路”中显示,需确保有实际调用触发。
第3章:流量控制(Flow Control)
3.1 流控规则基本参数说明
| 参数名称 | 语法(Java 类字段) | 用途 | 注意事项 |
|---|---|---|---|
| resource | String resource | 指定规则作用的资源名称,必须与 SphU.entry() 中的名称一致 | 资源名区分大小写,建议使用有意义的命名 |
| count | double count | 限流阈值,具体含义取决于 mode 和 grade | 支持小数,如 Warm Up 场景下可设 0.5 QPS |
| grade | int grade | 限流阈值类型:0=QPS,1=线程数 | 默认为 QPS 模式(0) |
| limitApp | String limitApp | 流控针对的调用者,default 表示不区分调用者 | 可实现按调用方限流 |
| strategy | int strategy | 流控模式:0=直接拒绝,1=关联资源,2=链路模式 | 默认为直接拒绝 |
| controlBehavior | int controlBehavior | 流控效果(策略):0=快速失败,1=Warm Up,2=排队等待 | 影响限流后的处理方式 |
代码示例(规则配置片段)
FlowRule rule = new FlowRule();
rule.setResource("HelloWorld");
rule.setCount(10); // 每秒最多10次
rule.setGrade(RuleConstant.FLOW_GRADE_QPS); // QPS 模式
rule.setLimitApp("default");
rule.setStrategy(RuleConstant.STRATEGY_DIRECT);
rule.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_DEFAULT);
3.2 QPS 与线程数流控模式
| 模式名称 | grade 值 | 用途 | 注意事项 |
|---|---|---|---|
| QPS 模式 | RuleConstant.FLOW_GRADE_QPS(0) | 基于每秒请求数进行限流,适用于控制接口访问频率 | 最常用模式,适合大多数接口限流场景 |
| 线程数模式 | RuleConstant.FLOW_GRADE_THREAD(1) | 基于并发线程数进行限流,防止资源被长时间占用 | 适用于响应时间较长的服务,防止线程堆积 |
代码示例:QPS 模式
FlowRule rule = new FlowRule();
rule.setResource("GET_ORDER");
rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
rule.setCount(20); // 每秒最多20次
代码示例:线程数模式
FlowRule rule = new FlowRule();
rule.setResource("SLOW_SERVICE");
rule.setGrade(RuleConstant.FLOW_GRADE_THREAD);
rule.setCount(5); // 最多5个线程同时执行
3.3 直接拒绝、Warm Up、排队等待流控策略
| 策略名称 | controlBehavior 值 | 用途 | 注意事项 |
|---|---|---|---|
| 直接拒绝(快速失败) | RuleConstant.CONTROL_BEHAVIOR_DEFAULT(0) | 超过阈值直接拒绝请求,抛出 FlowException | 默认策略,简单粗暴,适合核心服务 |
| Warm Up(预热) | RuleConstant.CONTROL_BEHAVIOR_WARM_UP(1) | 初始阈值较低,逐步上升至设定值,防止突发流量冲击 | 适用于系统启动后需要预热的场景,如缓存冷启动 |
| 排队等待(匀速器) | RuleConstant.CONTROL_BEHAVIOR_RATE_LIMITER(2) | 请求超过阈值时排队等待,按固定间隔放行 | 需设置 maxQueueingTimeMs,适合削峰填谷 |
代码示例:Warm Up
rule.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_WARM_UP);
rule.setCount(100);
// 默认冷启动时间10秒
代码示例:排队等待
rule.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_RATE_LIMITER);
rule.setMaxQueueingTimeMs(5000); // 最大等待5秒
3.4 资源维度与关联流控
| 模式名称 | strategy 值 | 用途 | 注意事项 |
|---|---|---|---|
| 直接流控 | RuleConstant.STRATEGY_DIRECT(0) | 对当前资源自身进行限流 | 默认模式 |
| 关联流控 | RuleConstant.STRATEGY_RELATE(1) | 当关联资源达到阈值时,限流当前资源 | 适用于”写强依赖读”的场景,如支付成功后更新订单 |
| 链路流控 | RuleConstant.STRATEGY_CHAIN(2) | 基于调用链路入口(context)进行限流 | 需结合 ContextUtil.enter() 使用,控制入口流量 |
代码示例:关联流控规则
FlowRule rule = new FlowRule();
rule.setResource("UPDATE_INVENTORY");
rule.setStrategy(RuleConstant.STRATEGY_RELATE);
rule.setRefResource("PLACE_ORDER");
rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
rule.setCount(5);
第4章:熔断降级(Circuit Breaking & Degradation)
4.1 降级规则触发条件(RT、异常比例、异常数)
| 触发方式 | grade 值 | 用途 | 注意事项 |
|---|---|---|---|
| 基于 RT(响应时间) | RuleConstant.DEGRADE_GRADE_RT(0) | 当资源平均响应时间超过阈值时触发降级 | 需统计周期内请求数达到最小阈值才生效 |
| 基于异常比例 | RuleConstant.DEGRADE_GRADE_EXCEPTION_RATIO(1) | 当异常请求比例超过阈值时触发降级 | count 取值范围 [0.0, 1.0] |
| 基于异常数 | RuleConstant.DEGRADE_GRADE_EXCEPTION_COUNT(2) | 当单位时间异常数超过阈值时触发降级 | 适用于异常数绝对值敏感的场景 |
代码示例
// 基于 RT
DegradeRule rule = new DegradeRule();
rule.setResource("GET_USER");
rule.setGrade(RuleConstant.DEGRADE_GRADE_RT);
rule.setCount(100); // RT > 100ms
rule.setTimeWindow(10); // 熔断10秒
// 基于异常比例
rule.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_RATIO);
rule.setCount(0.5); // 异常比例 > 50%
// 基于异常数
rule.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_COUNT);
rule.setCount(5); // 每分钟异常数 > 5
4.2 熔断状态机:半开、开、闭
| 状态名称 | 说明 | 触发条件 | 持续时间 | 注意事项 |
|---|---|---|---|---|
| 关闭(Closed) | 正常调用,统计指标 | 初始状态或熔断恢复后 | 持续到触发降级条件 | 所有请求正常通过 |
| 打开(Open) | 拒绝所有请求,直接降级 | 达到降级条件(如 RT 超时、异常比例高) | 持续 timeWindow 秒 | 不处理业务,直接抛出 DegradeException |
| 半开(Half-Open) | 允许部分请求通过,试探资源是否恢复 | Open 状态持续 timeWindow 后自动进入 | 短暂状态 | 若请求成功则回到 Closed,失败则回到 Open |
配置参数
| 配置字段 | 语法(DegradeRule 字段) | 用途 | 示例 |
|---|---|---|---|
| timeWindow | int timeWindow | 熔断持续时间,单位为秒 | rule.setTimeWindow(10); // 熔断10秒后尝试恢复 |
4.3 降级策略配置与响应行为
| 方法/字段 | 语法 | 用途 | 注意事项 |
|---|---|---|---|
DegradeRuleManager.loadRules() | DegradeRuleManager.loadRules(List<DegradeRule> rules) | 加载降级规则 | 应在应用启动时初始化规则 |
Tracer.trace() | Tracer.trace(Throwable e) | 记录异常,用于异常比例/异常数统计 | 必须调用,否则异常不会被统计 |
| BlockException 处理 | catch (BlockException e) | 捕获降级触发的异常 | 可结合 fallback 返回友好提示 |
代码示例
// 加载降级规则
List<DegradeRule> rules = new ArrayList<>();
rules.add(rule);
DegradeRuleManager.loadRules(rules);
// 记录异常
try {
// 调用依赖服务
} catch (Exception e) {
Tracer.trace(e);
throw e;
}
// 处理降级异常
if (e instanceof DegradeException) {
// 返回降级结果,如缓存数据
}
第5章:热点参数限流(Hotspot Parameter Flow Control)
5.1 热点参数限流原理
| 概念名称 | 说明 | 注意事项 |
|---|---|---|
| 热点参数 | 指在一段时间内被频繁访问的特定参数值,如热门商品ID、用户ID等 | 热点数据可能导致缓存击穿、数据库压力过大 |
| 参数索引(paramIdx) | 指定方法参数列表中参与限流的参数位置(从0开始) | 必须准确指定,否则无法正确提取参数值 |
| 参数类型 | 支持基本类型(int, long, String等)和包装类型 | 不支持复杂对象,需提取简单类型字段 |
| 实时统计 | Sentinel 使用 LRU 或 CountMinSketch 结构实时统计各参数值的访问频次 | 内存占用与热点参数数量相关,需合理设置 |
| 局部限流 | 可对特定参数值设置独立的限流阈值,实现精细化控制 | 例如:对爆款商品ID限制更严格的QPS |
5.2 ParamFlowRule 配置详解
| 字段名称 | 语法(ParamFlowRule 字段) | 用途 | 注意事项 |
|---|---|---|---|
| resource | String resource | 指定规则作用的资源名称 | 必须与 SphU.entry() 中资源名一致 |
| paramIdx | int paramIdx | 指定参与限流的参数在方法参数列表中的索引 | 索引从0开始,必须为有效位置 |
| grade | int grade | 限流模式:0=QPS模式 | 目前仅支持QPS模式 |
| count | long count | 基础限流阈值(QPS) | 所有参数值共享的基础阈值 |
| durationInSec | int durationInSec | 统计窗口时长,单位秒 | 通常设为1 |
| controlBehavior | int controlBehavior | 流控效果:0=快速失败,1=Warm Up | 支持 Warm Up 模式 |
| maxQueueingTimeMs | int maxQueueingTimeMs | 排队等待最大时间,单位毫秒 | 仅当 controlBehavior=2 时生效 |
| paramFlowItemList | List<ParamFlowItem> paramFlowItemList | 特定参数值的局部限流配置列表 | 用于实现”局部限流” |
代码示例
ParamFlowRule rule = new ParamFlowRule();
rule.setResource("getUserOrder");
rule.setParamIdx(0); // 第一个参数
rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
rule.setCount(10); // 默认每秒最多10次
rule.setDurationInSec(1); // 1秒窗口
rule.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_DEFAULT);
List<ParamFlowItem> items = new ArrayList<>();
ParamFlowItem item = new ParamFlowItem();
item.setObject("10086"); // 商品ID
item.setClassType(String.class.getName());
item.setCount(5); // 单独限流5QPS
items.add(item);
rule.setParamFlowItemList(items);
5.3 参数值限流与局部限流策略
| 策略类型 | 说明 | 注意事项 |
|---|---|---|
| 全局参数限流 | 对所有参数值统一限流,使用基础 count 阈值 | 最基础的参数限流方式 |
| 局部参数限流 | 对特定参数值设置独立的限流阈值 | 需添加到 paramFlowItemList |
| Warm Up 局部限流 | 对热点参数启用预热模式,防止突发流量 | 适用于新上架爆款商品 |
| 多参数支持 | 可对多个参数建立热点规则(需分别定义资源) | Sentinel 不支持单规则多参数索引 |
代码示例:全局参数限流
ParamFlowRule rule = new ParamFlowRule();
rule.setResource("queryProduct");
rule.setParamIdx(0);
rule.setCount(20); // 所有商品ID共用20QPS
代码示例:局部参数限流
ParamFlowItem item = new ParamFlowItem();
item.setObject("hot_product_001");
item.setClassType(String.class.getName());
item.setCount(5); // 热门商品单独限流5QPS
rule.setParamFlowItemList(Collections.singletonList(item));
代码示例:完整热点规则配置
ParamFlowRule rule = new ParamFlowRule();
rule.setResource("queryProduct");
rule.setParamIdx(0);
rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
rule.setCount(10);
rule.setDurationInSec(1);
rule.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_DEFAULT);
List<ParamFlowItem> items = new ArrayList<>();
ParamFlowItem hotItem = new ParamFlowItem();
hotItem.setObject("P1001");
hotItem.setClassType(String.class.getName());
hotItem.setCount(3); // 爆款商品限流3QPS
items.add(hotItem);
rule.setParamFlowItemList(items);
ParamFlowRuleManager.loadRules(Collections.singletonList(rule));
第6章:系统自适应保护(System Rule)
6.1 系统规则的作用维度(load、CPU、RT、线程数、入口 QPS)
| 维度名称 | 对应字段 | 说明 | 适用场景 | 注意事项 |
|---|---|---|---|---|
| 系统负载(Load) | highestSystemLoad | 基于系统的 Load1(1分钟平均负载)进行保护 | Linux/Unix 系统,多核CPU环境 | 仅对 Linux 生效,单核CPU需调整阈值 |
| CPU 使用率 | highestCpuUsage | 基于 JVM 获取的 CPU 使用率(0.0~1.0) | 所有操作系统 | 当 CPU 使用过高时拒绝新请求 |
| 平均 RT | averageRt | 基于入口流量的平均响应时间 | 防止慢请求拖垮系统 | 需统计周期内请求数达到最小阈值 |
| 并发线程数 | maxThread | 基于入口资源的并发处理线程数 | 防止线程资源耗尽 | 与线程池限流不同,是系统维度控制 |
| 入口 QPS | qps | 基于入口 Context 的总 QPS | 控制系统整体吞吐量 | 防止系统被整体打满 |
6.2 系统规则的触发条件与保护策略
| 配置字段 | 语法(SystemRule 字段) | 用途 | 注意事项 |
|---|---|---|---|
| highestSystemLoad | double highestSystemLoad | 设置 Load 阈值,超过则触发保护 | 单核CPU建议设为1.0,多核可设为核数*2.5 |
| highestCpuUsage | double highestCpuUsage | 设置 CPU 使用率阈值(0.0~1.0) | 获取的是 JVM 进程的 CPU 使用率 |
| averageRt | long averageRt | 设置平均响应时间阈值,单位毫秒 | 需持续一段时间才生效 |
| maxThread | int maxThread | 设置最大并发线程数阈值 | 防止线程池耗尽 |
| qps | double qps | 设置入口总 QPS 阈值 | 作用于所有入口资源总和 |
| highestOccupiedRatio | double highestOccupiedRatio | 堆内存占用比例阈值(0.0~1.0) | 防止频繁 GC |
保护策略说明
| 保护策略 | 说明 | 注意事项 |
|---|---|---|
| 自适应流控 | 当任一维度超过阈值,自动拒绝部分入口请求 | 无需配置具体资源,作用于整个应用 |
| 优先级最高 | 系统规则优先级高于其他规则(流控、降级) | 是最后一道防线 |
| 实时生效 | 规则变更后立即生效,无需重启 | 可动态调整阈值 |
| 全局生效 | 一个应用实例只允许设置一组系统规则 | 不支持按资源或调用方区分 |
代码示例:系统规则配置
SystemRule rule = new SystemRule();
rule.setHighestSystemLoad(3.0); // Load > 3.0 触发
rule.setHighestCpuUsage(0.85); // CPU > 85% 触发
rule.setAverageRt(100); // RT > 100ms 触发
rule.setMaxThread(1000); // 线程 > 1000 触发
rule.setQps(1000); // QPS > 1000 触发
rule.setHighestOccupiedRatio(0.7); // 堆 > 70% 触发
List<SystemRule> rules = new ArrayList<>();
rules.add(rule);
SystemRuleManager.loadRules(rules);
第7章:规则持久化与动态数据源
7.1 原生内存规则存储的局限性
| 问题名称 | 说明 | 注意事项 |
|---|---|---|
| 应用重启丢失 | 规则存储在内存中,应用重启后所有规则消失 | 控制台配置的规则无法保留 |
| 多实例不一致 | 每个实例需单独配置规则,难以保证一致性 | 在集群环境下维护成本高 |
| 无法审计追溯 | 规则变更无记录,难以追踪谁在何时修改了规则 | 不符合生产环境安全要求 |
| 依赖控制台 | 必须连接控制台才能配置规则,离线环境不可用 | 生产环境可能不允许直连控制台 |
| 动态性不足 | 虽然支持运行时修改,但缺乏版本管理和回滚机制 | 修改错误后难以快速恢复 |
7.2 支持的动态数据源(Nacos、Zookeeper、Apollo 等)
| 数据源类型 | Maven 依赖 | 用途 | 注意事项 |
|---|---|---|---|
| Nacos | sentinel-datasource-nacos | 将规则存储在 Nacos 配置中心 | 需启动 Nacos 服务,推荐用于 Spring Cloud Alibaba 环境 |
| Zookeeper | sentinel-datasource-zookeeper | 将规则存储在 Zookeeper | 适合已有 Zookeeper 基础设施的项目 |
| Apollo | sentinel-datasource-apollo | 集成携程 Apollo 配置中心 | 支持 Apollo 的命名空间和环境隔离 |
| Redis | sentinel-datasource-redis | 使用 Redis 存储规则 | 需自行实现读写逻辑,适合缓存场景 |
| File(本地文件) | sentinel-datasource-extension | 从本地文件加载规则 | 适用于测试或离线环境,不推荐生产使用 |
注: 所有数据源均需实现
ReadableDataSource接口,支持规则的自动加载与监听。
7.3 集成 Nacos 实现规则持久化
| 配置项 | 语法 / 步骤 | 用途 | 注意事项 |
|---|---|---|---|
| Nacos Server 地址 | -Dcsp.sentinel.nacos.serverAddr=127.0.0.1:8848 | 指定 Nacos 服务器地址 | 确保网络可达 |
| 命名空间 | -Dcsp.sentinel.nacos.namespace=public | 指定 Nacos 命名空间 | 多环境隔离时使用 |
| dataId | -Dcsp.sentinel.nacos.dataId=${spring.application.name}-${server.port}-flow-rules | 规则数据的 dataId | 建议按服务+端口命名 |
| groupId | -Dcsp.sentinel.nacos.groupId=SENTINEL_GROUP | 指定 Nacos group | 默认为 DEFAULT_GROUP |
| ruleType | -Dcsp.sentinel.nacos.ruleType=flow | 指定规则类型(flow, degrade, param_flow, system, authority) | 必须匹配规则类别 |
代码示例(Java 配置)
ReadableDataSource<String, List<FlowRule>> dataSource = new NacosDataSource<>(
"127.0.0.1:8848",
"public",
"my-service-flow",
source -> JSON.parseObject(source, new TypeReference<List<FlowRule>>() {})
);
FlowRuleManager.register2Property(dataSource.getProperty());
注意: 需在应用启动时执行,引入
sentinel-datasource-nacos依赖。
Nacos 中配置 Flow Rule JSON 示例
[
{
"resource": "GET_USER",
"limitApp": "default",
"grade": 1,
"count": 20,
"strategy": 0,
"controlBehavior": 0
}
]
第8章:Sentinel 与 Spring Cloud Alibaba 集成
8.1 @SentinelResource 注解详解
| 属性名称 | 语法 | 用途 | 注意事项 |
|---|---|---|---|
| value | String value | 资源名称,必填 | 必须唯一标识资源 |
| entryType | EntryType entryType | 入口类型:EntryType.IN / OUT | IN 表示入口流量,OUT 表示出口 |
| blockHandler | String blockHandler | 配置阻塞异常处理方法名 | 方法必须在同一类中,参数一致 |
| blockHandlerClass | Class<?> blockHandlerClass | 指定 blockHandler 所在类 | 用于跨类复用处理逻辑 |
| fallback | String fallback | 异常降级方法名(包括业务异常) | 可捕获非 BlockException |
| defaultFallback | String defaultFallback | 默认降级方法,适用于所有未指定 fallback 的异常 | 最后兜底的 fallback 方法 |
| exceptionsToIgnore | Class<? extends Throwable>[] exceptionsToIgnore | 指定忽略的异常类型,不触发 fallback | 忽略的异常将直接抛出 |
代码示例:基本用法
@SentinelResource(value = "api", blockHandler = "handleBlock")
public String api() {
// 业务逻辑
return "OK";
}
public String handleBlock(BlockException e) {
return "Blocked";
}
代码示例:跨类 BlockHandler
@SentinelResource(blockHandlerClass = ExceptionHandlers.class, blockHandler = "commonBlock")
public String api() { ... }
public class ExceptionHandlers {
public static String commonBlock(String id, BlockException e) {
return "Blocked globally";
}
}
代码示例:Fallback 使用
@SentinelResource(value = "api", fallback = "apiFallback")
public String api(String id) {
throw new RuntimeException();
}
public String apiFallback(String id, Throwable e) {
return "Fallback due to: " + e.getMessage();
}
代码示例:完整注解用法
@SentinelResource(
value = "queryOrder",
entryType = EntryType.IN,
blockHandler = "orderBlockHandler",
fallback = "orderFallback",
exceptionsToIgnore = {IllegalArgumentException.class}
)
public String queryOrder(String orderId) {
if ("error".equals(orderId)) throw new IllegalArgumentException();
return "Order Data";
}
8.2 Spring Cloud Gateway 中的 Sentinel 集成
| 配置项 | 说明 | 注意事项 |
|---|---|---|
| 依赖引入 | 引入 spring-cloud-starter-gateway + sentinel-spring-cloud-gateway-adapter | 必须引入适配器模块 |
| 自动配置 | GatewayRuleManager 自动加载网关规则 | Sentinel 自动注册网关插槽 |
| 规则类型 | ApiDefinition 和 GatewayFlowRule,支持基于 path、host、header 匹配 | 定义 API 分组和流控规则 |
| 自定义 API 分组 | PredicateItem 配置,将多个路径归为一个 API 组 | matchStrategy: 0 精确匹配,1 正则 |
| 限流响应 | 默认返回 429 状态码 | 可通过自定义 BlockRequestHandler 修改 |
配置示例(application.yml)
# API 分组与流控规则配置示例
gateway:
sentinel:
api-definitions:
- api-name: user-api
predicate-items:
- pattern: /user/**
match-strategy: 0
flow-rules:
- resource: user-api
count: 10
grade: 1
代码示例:Java 配置网关规则
Set<ApiDefinition> definitions = new HashSet<>();
ApiDefinition api = new ApiDefinition("user-api")
.setPredicateItems(new HashSet<>(Arrays.asList(
new PredicateItem().setPattern("/user/info")
)));
definitions.add(api);
GatewayApiDefinitionManager.loadApiDefinitions(definitions);
Set<GatewayFlowRule> rules = new HashSet<>();
rules.add(new GatewayFlowRule("user-api")
.setCount(5)
.setGrade(RuleConstant.FLOW_GRADE_QPS));
GatewayRuleManager.loadRules(rules);
8.3 Feign 整合 Sentinel 实现服务熔断
| 配置项 | 语法 / 步骤 | 用途 | 注意事项 |
|---|---|---|---|
| 启用 Sentinel | spring.cloud.openfeign.sentinel.enabled=true | 开启 Feign 对 Sentinel 的支持 | 必须设置为 true |
| Fallback 类 | @FeignClient(fallback = UserClientFallback.class) | 指定熔断后的降级实现类 | Fallback 类需声明为 Spring Bean |
| FallbackFactory | @FeignClient(fallbackFactory = UserClientFallbackFactory.class) | 可获取异常信息的工厂模式 fallback | 适合需要日志记录的场景 |
| 规则配置 | DegradeRule,资源名为接口全限定名+方法签名 | 配置熔断规则 | 如 UserClient#getUser() |
代码示例:Fallback 实现
@FeignClient(name = "user-service", fallback = UserClientFallback.class)
public interface UserClient {
String getUser();
}
@Component
public class UserClientFallback implements UserClient {
public String getUser() {
return "Default User";
}
}
代码示例:FallbackFactory 实现
@FeignClient(name = "user-service", fallbackFactory = UserClientFallbackFactory.class)
public interface UserClient { ... }
public class UserClientFallbackFactory implements FallbackFactory<UserClient> {
public UserClient create(Throwable cause) {
return () -> "Default User, cause: " + cause.getMessage();
}
}
代码示例:Feign 熔断规则配置
DegradeRule rule = new DegradeRule();
rule.setResource("UserClient#getUser()");
rule.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_RATIO);
rule.setCount(0.5);
DegradeRuleManager.loadRules(Collections.singletonList(rule));
注意: Feign 整合后,当远程调用失败或超时,将自动触发 Sentinel 熔断并执行 fallback 逻辑。
第9章:自定义异常处理与回调
9.1 BlockExceptionHandler 自定义
| 方法/字段 | 语法 | 用途 | 注意事项 |
|---|---|---|---|
| handle() | void handle(HttpServletRequest request, HttpServletResponse response, BlockException e) | 处理被 Sentinel 规则拦截的请求 | 必须实现 BlockExceptionHandler 接口 |
| 注册处理器 | WebServletConfig.setBlockExceptionHandler() | 将自定义处理器注册到 Sentinel | 通常在应用初始化时执行 |
| 支持的异常类型 | FlowException, DegradeException, ParamFlowException, SystemBlockException, AuthorityException | 不同规则触发的不同异常 | 可根据不同异常返回不同响应 |
代码示例:JSON 格式 BlockExceptionHandler
public class JsonBlockExceptionHandler implements BlockExceptionHandler {
public void handle(HttpServletRequest req, HttpServletResponse resp, BlockException e) {
resp.setStatus(429);
resp.getWriter().write("{\"code\":429,\"msg\":\"Request blocked by Sentinel\"}");
}
}
代码示例:注册自定义处理器
@Component
public class SentinelConfig {
@PostConstruct
public void init() {
WebServletConfig.setBlockExceptionHandler(new JsonBlockExceptionHandler());
}
}
9.2 Fallback 和 BlockHandler 方法定义
| 回调类型 | 语法要求 | 用途 | 注意事项 |
|---|---|---|---|
| BlockHandler | 方法参数列表与原方法一致,并追加 BlockException 参数 | 处理被流控、降级等规则拦截的异常 | 必须在同一类或指定 blockHandlerClass 中 |
| BlockHandlerClass | 静态或实例方法,参数同上 | 跨类复用 BlockHandler | 类必须有无参构造或为 Spring Bean |
| Fallback | 参数列表与原方法一致,可追加 Throwable 参数 | 处理业务异常和 Sentinel 异常(除 BlockException 外) | 可捕获非 BlockException 的所有异常 |
| defaultFallback | 无参数或仅 Throwable 参数 | 默认兜底降级方法 | 当未指定 fallback 时使用 |
注意: BlockHandler 优先级高于 Fallback。若请求被规则拦截,先走 BlockHandler;若抛出业务异常,则走 Fallback。
9.3 异常分类与响应定制
| 异常类型 | 对应类 | 触发条件 | 建议响应 | 注意事项 |
|---|---|---|---|---|
| FlowException | com.alibaba.csp.sentinel.slots.block.flow.FlowException | 流控规则触发(QPS/线程数超限) | HTTP 429 Too Many Requests | 可细分为直接拒绝、Warm Up 拒绝等 |
| DegradeException | com.alibaba.csp.sentinel.slots.block.degrade.DegradeException | 降级规则触发(RT、异常比例、异常数) | HTTP 503 Service Unavailable | 表示服务不稳定 |
| ParamFlowException | com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowException | 热点参数限流触发 | HTTP 429 或自定义提示 | 针对特定参数值的限制 |
| SystemBlockException | com.alibaba.csp.sentinel.slots.block.system.SystemBlockException | 系统保护规则触发(Load、CPU、RT等) | HTTP 503 或降级页面 | 系统整体过载 |
| AuthorityException | com.alibaba.csp.sentinel.slots.block.authority.AuthorityException | 黑白名单规则触发 | HTTP 403 Forbidden | 权限控制场景 |
| UnknownException | com.alibaba.csp.sentinel.slots.block.SentinelRpcException | Sentinel 内部错误或未知异常 | HTTP 500 Internal Server Error | 需记录日志排查 |
定制方式
| 定制方式 | 说明 | 示例 |
|---|---|---|
| BlockExceptionHandler | 统一处理所有 BlockException 子类 | 根据 e.getClass() 判断类型并返回不同 JSON 响应 |
| Fallback 方法 | 按业务逻辑返回友好提示 | 返回缓存数据、默认值或提示”服务繁忙,请稍后重试” |
| 日志记录 | 结合 Tracer.trace() 记录异常 | 在 catch 块中 Tracer.trace(e) 并打日志 |
代码示例:按异常类型返回不同响应
public void handle(HttpServletRequest req, HttpServletResponse resp, BlockException e) {
int code = 503;
String msg = "Service unavailable";
if (e instanceof FlowException) {
code = 429;
msg = "Request rate exceeded";
} else if (e instanceof SystemBlockException) {
msg = "System overload protection";
}
resp.setStatus(code);
resp.getWriter().write(String.format("{\"code\":%d,\"msg\":\"%s\"}", code, msg));
}
第10章:监控与可视化
10.1 Sentinel 控制台功能介绍
| 功能模块 | 说明 | 注意事项 |
|---|---|---|
| 实时监控 | 查看每秒 QPS、成功数、异常数、平均 RT 等指标 | 数据每秒上报一次,延迟较低 |
| 簇点链路 | 显示当前应用中所有被 Sentinel 保护的资源 | 可查看资源的调用路径和统计信息 |
| 流控规则 | 管理流量控制规则,支持新增、修改、删除 | 修改后实时生效,无需重启应用 |
| 降级规则 | 配置熔断降级规则(RT、异常比例、异常数) | 可设置熔断时间窗口 |
| 热点规则 | 配置热点参数限流规则 | 支持局部参数值限流 |
| 系统规则 | 设置系统自适应保护阈值(Load、CPU、RT等) | 作用于整个应用入口流量 |
| 授权规则 | 配置黑白名单,控制资源访问权限 | 基于 limitApp 字段判断调用方 |
| 集群流控 | 配置集群模式下的流量控制 | 需搭建 Token Server |
| 机器列表 | 查看已接入的客户端应用实例 | 显示 IP、端口、版本、心跳状态 |
10.2 实时指标数据查看(QPS、线程数、响应时间)
| 指标名称 | 说明 | 单位 | 查看位置 | 注意事项 |
|---|---|---|---|---|
| 通过 QPS | 每秒成功通过的请求数 | 次/秒 | 实时监控图表、簇点链路表格 | 不包含被拦截或异常的请求 |
| 拦截 QPS | 每秒被规则拦截的请求数 | 次/秒 | 实时监控图表 | 包括流控、降级、系统保护等拦截 |
| 异常 QPS | 每秒发生业务异常的请求数 | 次/秒 | 实时监控图表 | 需调用 Tracer.trace() 才会计入 |
| 平均 RT | 请求的平均响应时间 | 毫秒(ms) | 实时监控图表、资源详情 | RT 骤升可能表示性能瓶颈 |
| 并发线程数 | 当前正在处理请求的线程数量 | 个 | 簇点链路表格 | 可用于线程数流控参考 |
| 资源名称 | 被保护的资源标识 | - | 簇点链路列表 | 点击可查看该资源的详细指标 |
| 最小/最大 RT | 请求响应时间的最小值和最大值 | 毫秒(ms) | 资源详情页面 | 反映响应时间波动情况 |
10.3 接入监控数据上报(Transport 模块)
| 配置项 | 语法 / 参数 | 用途 | 注意事项 |
|---|---|---|---|
| 控制台地址 | -Dcsp.sentinel.dashboard.server=127.0.0.1:8080 | 指定 Sentinel 控制台地址 | 必须配置,否则无法注册 |
| 客户端端口 | -Dcsp.sentinel.api.port=8719 | 指定客户端接收命令的端口 | 默认 8719,冲突时可修改 |
| 应用名称 | -Dproject.name=my-service | 指定应用名称 | 建议使用小写字母和连字符 |
| 心跳间隔 | -Dcsp.sentinel.heartbeat.interval.ms=10000 | 心跳发送间隔 | 默认 10 秒,不建议频繁修改 |
| 传输模块依赖 | sentinel-transport-simple-http | 提供与控制台通信能力 | 必须引入该依赖 |
| Jetty 内嵌服务器 | 内置 SimpleHttpCommandCenter | 接收控制台指令(如规则查询) | 启动时监听 8719 端口 |
| 上报模式 | 拉模式(Pull) | 控制台主动从客户端拉取监控数据 | 客户端定时上报,控制台定时拉取 |
Maven 依赖配置
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-transport-simple-http</artifactId>
<version>1.8.6</version>
</dependency>
示例:完整启动命令
java -Dproject.name=user-service \
-Dcsp.sentinel.dashboard.server=localhost:8080 \
-Dcsp.sentinel.api.port=8720 \
-jar user-service.jar
注意: 确保客户端与控制台网络互通,防火墙开放相应端口。首次访问资源后才会在控制台显示。
第11章:扩展与高级用法
11.1 自定义 Context 和 EntryType
| 概念 | 语法 / 方法 | 用途 | 注意事项 |
|---|---|---|---|
| Context | ContextUtil.enter(contextName) | 创建独立的调用上下文,用于链路隔离或自定义统计维度 | 必须成对调用 enter 和 exit,建议使用 try-finally |
| 自定义 Context 名称 | String contextName | 区分不同调用链路,影响流控规则匹配 | 常用于网关、Feign 调用等场景 |
| EntryType | EntryType.IN / EntryType.OUT | 指定资源入口类型:IN 表示流入流量,OUT 表示流出流量 | 影响系统规则的统计 |
| Context + EntryType 组合 | 结合使用 | 实现精细化的流量控制 | 可用于区分内部调用与外部访问 |
| 异步 Context 传播 | ContextUtil.getContext() | 在异步线程中传递上下文 | 异步场景需手动传递 Context |
代码示例:创建独立 Context
ContextUtil.enter("order-service-call");
try {
Entry entry = SphU.entry("placeOrder");
// 业务逻辑
entry.exit();
} finally {
ContextUtil.exit();
}
代码示例:异步 Context 传播
final Context ctx = ContextUtil.getContext();
CompletableFuture.runAsync(() -> {
ContextUtil.setContext(ctx);
// 异步执行资源
});
代码示例:Web 过滤器中创建 Context
public class SentinelContextFilter implements Filter {
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
String contextName = req.getHeader("X-Context-Name");
if (contextName == null || contextName.isEmpty()) {
contextName = "DEFAULT";
}
try {
ContextUtil.enter(contextName, req.getRemoteAddr()); // 第二个参数为 origin,用于黑白名单
chain.doFilter(request, response);
} finally {
ContextUtil.exit();
}
}
}
11.2 Slot Chain 扩展机制
| Slot 类型 | 作用 | 执行顺序 | 是否可扩展 | 说明 |
|---|---|---|---|---|
| NodeSelectorSlot | 构建调用链路的节点树 | 1 | 否 | 记录资源的调用路径 |
| ClusterBuilderSlot | 构建 ClusterNode,统计总体指标 | 2 | 否 | 用于统计 QPS、RT 等 |
| LogSlot | 记录热点参数日志 | 3 | 否 | 支持热点参数限流 |
| StatisticSlot | 统计实时指标,触发降级/系统规则 | 4 | 否 | 核心统计逻辑 |
| AuthoritySlot | 根据黑白名单校验权限 | 5 | 是 | 可自定义访问控制逻辑 |
| SystemSlot | 检查系统保护规则 | 6 | 是 | 可自定义系统指标判断 |
| FlowSlot | 检查流控规则 | 7 | 是 | 可实现自定义流控算法 |
| DegradeSlot | 检查熔断降级规则 | 8 | 是 | 可扩展降级策略 |
扩展机制说明
| 扩展机制 | 说明 | 注意事项 |
|---|---|---|
| SPI(Service Provider Interface) | Sentinel 使用 Java SPI 机制加载自定义 Slot | 在 META-INF/services/com.alibaba.csp.sentinel.slotchain.SlotChainBuilder 中声明 |
| SlotChainBuilder | 自定义构建 Slot 链的逻辑 | 可插入、替换、移除 Slot |
| Order 值 | 控制 Slot 的加载优先级 | 数值越小,优先级越高 |
11.3 注册自定义 Slot 实现业务拦截
| 步骤 | 说明 | 注意事项 |
|---|---|---|
| 1. 实现 AbstractLinkedProcessorSlot | 创建自定义 Slot 类,继承 AbstractLinkedProcessorSlot<T> | 必须调用 fireEntry 和 fireExit 以保证链式调用 |
| 2. 实现 SlotChainBuilder | 构建包含自定义 Slot 的链 | 必须返回完整的 Slot 链 |
| 3. SPI 配置 | 在 META-INF/services/ 下注册 | 文件编码为 UTF-8,无 BOM |
| 4. 依赖引入 | 确保类路径正确 | 不要与 Sentinel 内部类冲突 |
代码示例:自定义 Slot
public class CustomBusinessSlot extends AbstractLinkedProcessorSlot<DefaultNode> {
public void entry(Context context, ResourceWrapper resourceWrapper, DefaultNode node,
int count, boolean prioritized, Object... args) throws Throwable {
// 拦截前逻辑:如权限校验、日志记录
if (isBlockedByBusinessRule(context, resourceWrapper)) {
throw new BlockException("BUSINESS_LIMIT");
}
fireEntry(context, resourceWrapper, node, count, prioritized, args); // 继续执行下一个 Slot
}
public void exit(Context context, ResourceWrapper resourceWrapper, int count, Object... args) {
// 拦截后逻辑:如清理资源
fireExit(context, resourceWrapper, count, args); // 继续执行上一个 Slot
}
private boolean isBlockedByBusinessRule(Context context, ResourceWrapper resource) {
// 自定义业务拦截逻辑
return false;
}
}
代码示例:自定义 SlotChainBuilder
public class CustomSlotChainBuilder implements SlotChainBuilder, SpiOrder {
public ProcessorSlotChain build() {
ProcessorSlotChain chain = new DefaultProcessorSlotChain();
// 在 FlowSlot 之前插入自定义 Slot
chain.addLast(new NodeSelectorSlot());
chain.addLast(new ClusterBuilderSlot());
chain.addLast(new LogSlot());
chain.addLast(new StatisticSlot());
chain.addLast(new CustomBusinessSlot()); // 插入自定义 Slot
chain.addLast(new AuthoritySlot());
chain.addLast(new SystemSlot());
chain.addLast(new FlowSlot());
chain.addLast(new DegradeSlot());
return chain;
}
public int getOrder() {
return 100; // 优先级高于默认 builder (1000)
}
}
SPI 配置示例
创建文件 META-INF/services/com.alibaba.csp.sentinel.slotchain.SlotChainBuilder,内容:
com.example.sentinel.CustomSlotChainBuilder
注意事项:
- 自定义 Slot 的性能影响需评估,避免在
entry方法中执行耗时操作。 - 抛出
BlockException会中断请求,触发 fallback 或 blockHandler。 - 可结合 Context 和 Entry 实现复杂的业务拦截逻辑,如灰度发布、流量染色等。