Skip to content

Sentinel 是怎么实现限流的? ​

  • 标签:Spring Cloud、微服务、后端、服务容灾

🏛 业务架构师 ​

Sentinel 的限流实现核心是**"责任链插槽 + 滑动窗口统计 + 令牌桶/匀速排队控制"**三件套:

1. 资源模型与插槽链(Slot Chain):

每个调用(方法、URL、@SentinelResource 标注的资源)进入时穿过一条ProcessorSlot 责任链:NodeSelectorSlot(构建统计节点树)→ ClusterBuilderSlot → StatisticSlot(滑动窗口计数)→ FlowSlot(限流判断)→ DegradeSlot(熔断)→ SystemSlot(系统自适应保护)→ ParamFlowSlot(热点参数)……责任链让限流、熔断、热点防护在同一入口按序生效,各插槽独立演化——这是它架构上最优雅的部分。

2. 滑动窗口统计:

时间线切成多个窗口(默认 1 秒 = 2 个 500ms 窗格),基于 LongAdder 高并发计数(比 AtomicLong 争用低),按窗口统计 QPS/RT/线程数——限流与熔断判断的实时数据来源。

3. 流控效果(三种模式):

  • 快速失败:超阈值直接抛 FlowException(默认)——保护优先;
  • Warm Up(预热):冷启动时阈值从低爬升(令牌桶冷启动因子)——应对 JVM 预热/缓存未热,避免刚启动的实例被打死;
  • 匀速排队(漏桶):请求按间隔匀速通过,超出排队等待——削峰填谷,适合可等待的后台任务与 MQ 消费限速。

4. 规则动态化:规则从 Nacos 配置中心加载,控制台改规则秒级推送——大促调参不发版。

架构师视角:Sentinel 把"限流熔断"从编码劳动变成控制台运营能力(规则可视化、监控大盘、实时生效),这是它国内流行超过 Resilience4j 的根本原因——治理能力的产品化程度决定推广速度。

🏗 系统架构师 ​

两块核心:滑动窗口统计加责任链处理。

  1. 数据结构:LeapArray 滑动窗口——时间切 sample(默认 1s 窗口 2 个 500ms 格),每格独立统计通过、拒绝、异常、RT;LongAdder 无锁累加,统计开销纳秒级;
  2. Slot Chain(责任链):NodeSelectorSlot(构建调用树)→ ClusterBuilderSlot → AuthoritySlot(黑白名单)→ SystemSlot(系统自适应)→ ParamFlowSlot(热点参数)→ FlowSlot(流控) → DegradeSlot(熔断)——一次调用顺序过链,各管一类规则;
  3. 流控效果:直接拒绝;Warm Up(冷启动因子 3,缓存类服务缓坡放量预热);排队等待(漏桶匀速,适合削峰);
  4. 规则来源:内存规则加控制台推送;生产用 Nacos 数据源持久化——控制台改规则写 Nacos,客户端监听生效,规则可审计可回滚。

架构评价:单机限流零外部依赖(Sentinel 是 SDK 不是 Server,不存在自身宕机问题);调用树上下文让「按调用链路限流」成为可能,这是它比简单注解限流强的地方。代价:集群维度需要 Token Server。

💻 全栈开发专家 ​

两块核心:滑动窗口统计 + Slot 责任链。

Slot 链:Sentinel 把一次资源访问包成 Entry,依次过一串 ProcessorSlot:

  1. NodeSelectorSlot:构建调用树(谁调用谁)
  2. ClusterBuilderSlot:建统计节点
  3. StatisticSlot:业务执行前后埋点——请求/成功/异常/RT 全记
  4. FlowSlot:流控检查(QPS/线程数阈值、流控效果)
  5. AuthoritySlot:黑白名单
  6. DegradeSlot:熔断检查(异常比例/慢调用比例)
  7. SystemSlot:系统级保护(Load、入口 QPS、平均 RT)

滑动窗口(LeapArray):每秒切成 2 个 500ms 样本,环形数组复用,统计只累加当前窗口的 MetricBucket(LongAdder 计数),读取时聚合最近窗口——避免固定窗口"边界双倍突刺",内存开销极小。

流控效果三种:快速失败(直接 block)、Warm Up(冷启动斜坡放量)、匀速排队(漏桶思路,漏速 = QPS 阈值)。

生产铁律:规则默认存内存,必须接 Nacos/Apollo 数据源持久化(ReadableDataSource 推送),否则重启全丢——Sentinel Dashboard 本身只是个内存规则编辑器,这个坑新团队必踩。