Sentinel
Java 高级 · 阿里中间件
Sentinel 是分布式系统的"流量防卫兵"。它不止是"加个注解就限流",真正的能力在于:用滑动窗口做高精度实时统计、用责任链(ProcessorSlot)把限流/熔断/系统保护串成可扩展管线、用状态机管理熔断的恢复探测。本文把统计内核、责任链、熔断状态机与热点/集群流控讲透。
一、资源与规则:一切皆"资源"
Sentinel 的保护对象是 Resource(资源)——任意逻辑单元(方法、URL、RPC 接口、代码块)。通过 @SentinelResource 或框架适配(Spring MVC、Dubbo、Gateway)自动定义。对资源施加的约束就是 Rule:
- FlowRule(限流):基于 QPS 或线程数限制访问速率。
- DegradeRule(熔断降级):基于慢调用比例 / 异常比例 / 异常数,触发后熔断。
- ParamFlowRule(热点参数限流):对方法参数粒度限流(如某 userId 被刷)。
- SystemRule(系统保护):按 Load、CPU、平均 RT 做自适应保护。
- AuthorityRule(黑白名单):来源 IP/来源应用控制。
二、统计内核:LeapArray 滑动窗口
限流/熔断的"决策依据"是实时统计值(QPS、RT、异常数),而统计的核心是 LeapArray(滑动窗口)。它把时间切成多个 Window(时间槽),每个槽存一小段时间内的统计:
// LeapArray 本质: 环形数组 + 时间映射
public class LeapArray<T> {
int windowLengthInMs; // 单窗口时长(如 500ms)
int sampleCount; // 窗口数(如 2) → 总窗长 1s
AtomicReferenceArray<WindowWrap<T>> array; // 环形数组
}为什么用滑动窗口而非固定窗口? 固定窗口在"窗口边界"会出现两倍流量穿透:例如限流 100/s,第 1 秒后 500ms 来 100 个、第 2 秒前 500ms 又来 100 个,固定窗口各自放行,但实际 1 秒内来了 200 个。滑动窗口统计"过去 N 秒"的连续区间,边界处也平滑准确。
LeapArray 用原子数组 + CAS 重置过期窗口实现无锁高性能;WindowWrap 内用 LongAdder 累加(高并发下分段计数,减少 CAS 争用)。
三、责任链:ProcessorSlotChain
一次资源访问会穿过一条 ProcessorSlot 责任链(类似 Netty 的 Pipeline):
NodeSelectorSlot:为每个资源建DefaultNode(调用树节点),支撑按调用链路限流。ClusterBuilderSlot:建ClusterNode(资源维度的全局统计,跨 EntranceNode 共享)。StatisticSlot:核心统计点——在entry通过前/后记录 pass、block、RT、exception,喂给LeapArray。FlowSlot:依据FlowRule+ 实时统计做限流判断(rule.passQpsvs 当前窗口 pass 数)。DegradeSlot:依据DegradeRule判断是否需要熔断(慢调用/异常比例超阈值)。SystemSlot:系统级保护(Load/CPU 超阈值直接拒)。AuthoritySlot:黑白名单。
TIP
责任链设计的妙处:每个 Slot 只关心自己那一小段逻辑,新增一种保护策略只需加一个 Slot。限流/熔断的"规则"和"统计"解耦——StatisticSlot 沉淀数据,FlowSlot/DegradeSlot 只做决策。这也解释了为什么规则可以动态推送:改 FlowRuleManager 的规则集合即可,责任链结构不动。
四、限流效果与调用关系
FlowRule 不只是"超了就拒",还有丰富的语义:
- 流控效果:
DIRECT(快速失败):超阈值立即抛FlowException,由blockHandler兜底。WARM_UP(预热):冷启动时阈值从threshold / 3缓缓升到阈值,应对缓存预热(如令牌桶)。RATE_LIMITER(排队等待):以匀速处理,超过则排队,超时则拒,用于削峰填谷。
- 调用关系:
STRATEGY_DIRECT(对本身限流)、STRATEGY_RELATE(关联资源,如"支付接口忙时限制查询")、STRATEGY_CHAIN(链路:仅对特定调用入口限流,靠NodeSelectorSlot的调用树)。
五、熔断状态机:closed / open / half-open
熔断降级用经典状态机,避免"上游慢/错 → 自身线程堆积 → 雪崩":
- Closed(关闭):正常放行,持续统计。当慢调用比例(
RT > slowRtMs的请求占比)或异常比例超阈值,且请求数达最小采样,转 Open。 - Open(打开):拒绝所有请求(直接抛
DegradeException),给上游fallback兜底。经过timeWindow休眠期后进入 HalfOpen。 - HalfOpen(半开):放少量探测请求,成功则恢复 Closed,失败则回到 Open 重新计时。
5.1 代码示例
@SentinelResource(value = "createOrder",
blockHandler = "blockHandler", // 限流/熔断触发时兜底(参数末位加 BlockException)
fallback = "fallback") // 业务异常时兜底(参数末位加 Throwable)
public Order createOrder(Long userId) { return orderSvc.create(userId); }
// 限流/熔断兜底: 返回降级响应, 防止雪崩扩散
public Order blockHandler(Long userId, BlockException ex) {
throw new BizException("系统繁忙,请稍后再试");
}
// 代码/配置中心推送规则
List<FlowRule> rules = new ArrayList<>();
rules.add(new FlowRule("createOrder").setCount(200).setGrade(RuleConstant.FLOW_GRADE_QPS));
FlowRuleManager.loadRules(rules);WARNING
- 只配限流不配熔断:上游故障时会因线程堆积拖垮自己。限流防"过载",熔断防"雪崩",二者配合。
- blockHandler / fallback 签名必须正确:必须是"原方法参数 +
BlockException/Throwable",否则不生效且报错。 - 规则只存内存,重启丢失:生产必须接 Nacos/ZK/Apollo 做规则持久化(
DynamicRulePublisher/DynamicRuleSource),否则重启即"裸奔"。 - 热点参数未设例外项:对 VIP 用户误伤,应配置
ParamFlowItem例外项(如某 userId 阈值放宽)。
六、热点参数与集群流控
- 热点参数限流(ParamFlowRule):对
@SentinelResource方法的某个参数(如 userId/skuId)单独限流,配合ParamFlowItem对特定参数值设例外阈值。底层用滑动窗口 + 参数维度的 LRU 统计(只统计 Top N 热点参数,避免内存爆炸)。 - 集群流控(ClusterFlowConfig):单机限流在集群多实例下会"各限各的",总阈值不可控。Sentinel 引入 Token Server(令牌服务器) 模式:各实例向 Token Server 申请令牌,由 Server 做全局配额(
ClusterStrategy)。Token Server 可独立部署或 embed 在某一节点(需指定flowId与 namespace)。
七、生产落地
- 接入 Dashboard 统一管控,规则持久化到 Nacos,变更经评审。
- 核心接口配置"限流 + 熔断 + 系统保护"三层防护;流控优先
WARM_UP(冷启动)与RATE_LIMITER(削峰)。 - 监控
pass/block/rt/exception指标(Sentinel 暴露到 Micrometer/Prometheus),设容量告警。
📚 官方文档与参考资料
- Sentinel 官方文档:https://sentinelguard.io/zh-cn/docs/introduction.html
- Sentinel GitHub:https://github.com/alibaba/Sentinel
- Sentinel 流量控制文档:https://sentinelguard.io/zh-cn/docs/flow-control.html
✏️ 练习与自测
- 为下单接口设计"QPS 限流 200 + 异常比例熔断 50%"组合规则,画出触发逻辑与
DegradeSlot的判断依据。 - 用
@SentinelResource写一个有blockHandler与fallback的示例,区分两者触发时机(BlockException vs Throwable)。 - 解释
LeapArray滑动窗口相比固定窗口限流精度优势,并画出窗口环形复用结构。 - 如何用集群流控保证 10 个实例的总 QPS 不超过 2000?说明 Token Server 的角色。
本节小结
Sentinel 用"资源定义 + LeapArray 滑动窗口实时统计"支撑限流、熔断、热点、系统保护;ProcessorSlot 责任链把各种保护串成可扩展管线(StatisticSlot 沉淀数据,FlowSlot/DegradeSlot 决策);熔断用 closed/open/half-open 状态机做故障隔离与自愈。落地三件事:限流防过载、熔断防雪崩、规则持久化防重启丢失,配合 Dashboard 实现可视化治理。