Article

微服务 Sentinel

更新于:2026-07-14

第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 ChainSentinel 内部处理请求的插槽链,每个 Slot 负责不同职责(如统计、流控、降级等)。可扩展自定义 Slot 实现个性化逻辑。

1.4 Sentinel 与 Hystrix 的对比

对比维度SentinelHystrix
开发公司阿里巴巴Netflix
核心理念流量治理 + 系统自适应保护熔断器模式为主
流控能力强大,支持 QPS、线程数、热点参数、关联流控等多种模式仅支持线程池或信号量隔离,流控能力弱
熔断降级支持 RT、异常比例、异常数等多种策略支持基于异常比例的熔断
系统保护支持基于系统 Load、CPU 使用率的自适应保护不支持系统维度保护
实时监控提供 Dashboard 控制台,支持实时监控和规则配置需整合 Turbine 才能实现聚合监控
动态规则支持通过控制台或配置中心动态修改规则配置修改需代码或属性刷新,不够灵活
扩展性基于 Slot Chain 可扩展性强扩展性一般,主要依赖 HystrixCommand
性能开销更轻量,基于滑动窗口统计,性能更高使用线程池隔离时有额外线程开销
社区活跃度国内活跃,集成 Spring Cloud Alibaba 方便Netflix 已宣布 Hystrix 进入维护模式
适用场景微服务全链路流量治理传统熔断降级场景

第2章:环境搭建与快速入门

2.1 引入 Sentinel 依赖(Maven 配置)

依赖名称Maven 坐标用途注意事项
sentinel-corecom.alibaba.csp:sentinel-core:1.8.6核心依赖,提供流量控制、熔断降级等基础功能所有使用 Sentinel 的项目都必须引入
sentinel-annotation-aspectjcom.alibaba.csp:sentinel-annotation-aspectj:1.8.6支持 @SentinelResource 注解切面使用注解方式定义资源时需要引入
sentinel-web-servletcom.alibaba.csp:sentinel-web-servlet:1.8.6为传统 Servlet 项目提供 Web 适配用于非 Spring Boot Web 项目
sentinel-datasource-nacoscom.alibaba.csp:sentinel-datasource-nacos:1.8.6支持从 Nacos 加载规则实现规则持久化时使用
sentinel-transport-simple-httpcom.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 类字段)用途注意事项
resourceString resource指定规则作用的资源名称,必须与 SphU.entry() 中的名称一致资源名区分大小写,建议使用有意义的命名
countdouble count限流阈值,具体含义取决于 mode 和 grade支持小数,如 Warm Up 场景下可设 0.5 QPS
gradeint grade限流阈值类型:0=QPS,1=线程数默认为 QPS 模式(0)
limitAppString limitApp流控针对的调用者,default 表示不区分调用者可实现按调用方限流
strategyint strategy流控模式:0=直接拒绝,1=关联资源,2=链路模式默认为直接拒绝
controlBehaviorint 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 字段)用途示例
timeWindowint 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 字段)用途注意事项
resourceString resource指定规则作用的资源名称必须与 SphU.entry() 中资源名一致
paramIdxint paramIdx指定参与限流的参数在方法参数列表中的索引索引从0开始,必须为有效位置
gradeint grade限流模式:0=QPS模式目前仅支持QPS模式
countlong count基础限流阈值(QPS)所有参数值共享的基础阈值
durationInSecint durationInSec统计窗口时长,单位秒通常设为1
controlBehaviorint controlBehavior流控效果:0=快速失败,1=Warm Up支持 Warm Up 模式
maxQueueingTimeMsint maxQueueingTimeMs排队等待最大时间,单位毫秒仅当 controlBehavior=2 时生效
paramFlowItemListList<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 使用过高时拒绝新请求
平均 RTaverageRt基于入口流量的平均响应时间防止慢请求拖垮系统需统计周期内请求数达到最小阈值
并发线程数maxThread基于入口资源的并发处理线程数防止线程资源耗尽与线程池限流不同,是系统维度控制
入口 QPSqps基于入口 Context 的总 QPS控制系统整体吞吐量防止系统被整体打满

6.2 系统规则的触发条件与保护策略

配置字段语法(SystemRule 字段)用途注意事项
highestSystemLoaddouble highestSystemLoad设置 Load 阈值,超过则触发保护单核CPU建议设为1.0,多核可设为核数*2.5
highestCpuUsagedouble highestCpuUsage设置 CPU 使用率阈值(0.0~1.0)获取的是 JVM 进程的 CPU 使用率
averageRtlong averageRt设置平均响应时间阈值,单位毫秒需持续一段时间才生效
maxThreadint maxThread设置最大并发线程数阈值防止线程池耗尽
qpsdouble qps设置入口总 QPS 阈值作用于所有入口资源总和
highestOccupiedRatiodouble 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 依赖用途注意事项
Nacossentinel-datasource-nacos将规则存储在 Nacos 配置中心需启动 Nacos 服务,推荐用于 Spring Cloud Alibaba 环境
Zookeepersentinel-datasource-zookeeper将规则存储在 Zookeeper适合已有 Zookeeper 基础设施的项目
Apollosentinel-datasource-apollo集成携程 Apollo 配置中心支持 Apollo 的命名空间和环境隔离
Redissentinel-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 注解详解

属性名称语法用途注意事项
valueString value资源名称,必填必须唯一标识资源
entryTypeEntryType entryType入口类型:EntryType.IN / OUTIN 表示入口流量,OUT 表示出口
blockHandlerString blockHandler配置阻塞异常处理方法名方法必须在同一类中,参数一致
blockHandlerClassClass<?> blockHandlerClass指定 blockHandler 所在类用于跨类复用处理逻辑
fallbackString fallback异常降级方法名(包括业务异常)可捕获非 BlockException
defaultFallbackString defaultFallback默认降级方法,适用于所有未指定 fallback 的异常最后兜底的 fallback 方法
exceptionsToIgnoreClass<? 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 自动注册网关插槽
规则类型ApiDefinitionGatewayFlowRule,支持基于 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 实现服务熔断

配置项语法 / 步骤用途注意事项
启用 Sentinelspring.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 异常分类与响应定制

异常类型对应类触发条件建议响应注意事项
FlowExceptioncom.alibaba.csp.sentinel.slots.block.flow.FlowException流控规则触发(QPS/线程数超限)HTTP 429 Too Many Requests可细分为直接拒绝、Warm Up 拒绝等
DegradeExceptioncom.alibaba.csp.sentinel.slots.block.degrade.DegradeException降级规则触发(RT、异常比例、异常数)HTTP 503 Service Unavailable表示服务不稳定
ParamFlowExceptioncom.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowException热点参数限流触发HTTP 429 或自定义提示针对特定参数值的限制
SystemBlockExceptioncom.alibaba.csp.sentinel.slots.block.system.SystemBlockException系统保护规则触发(Load、CPU、RT等)HTTP 503 或降级页面系统整体过载
AuthorityExceptioncom.alibaba.csp.sentinel.slots.block.authority.AuthorityException黑白名单规则触发HTTP 403 Forbidden权限控制场景
UnknownExceptioncom.alibaba.csp.sentinel.slots.block.SentinelRpcExceptionSentinel 内部错误或未知异常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

概念语法 / 方法用途注意事项
ContextContextUtil.enter(contextName)创建独立的调用上下文,用于链路隔离或自定义统计维度必须成对调用 enter 和 exit,建议使用 try-finally
自定义 Context 名称String contextName区分不同调用链路,影响流控规则匹配常用于网关、Feign 调用等场景
EntryTypeEntryType.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 机制加载自定义 SlotMETA-INF/services/com.alibaba.csp.sentinel.slotchain.SlotChainBuilder 中声明
SlotChainBuilder自定义构建 Slot 链的逻辑可插入、替换、移除 Slot
Order 值控制 Slot 的加载优先级数值越小,优先级越高

11.3 注册自定义 Slot 实现业务拦截

步骤说明注意事项
1. 实现 AbstractLinkedProcessorSlot创建自定义 Slot 类,继承 AbstractLinkedProcessorSlot<T>必须调用 fireEntryfireExit 以保证链式调用
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 实现复杂的业务拦截逻辑,如灰度发布、流量染色等。