Lazy loaded image
🗒️Sentinel
Words 5227Read Time 14 min
2025-11-7
2025-11-12
type
status
date
slug
summary
tags
category
icon
password
原文
 

Slot Chain

Sentinel 使用责任链模式将不同的模块串联起来,每个 功能点由一个独立的 Slot实现,如流量控制、熔断降级、系统保护、流量统计等。
请求在各个 Solt之间顺序传递,每个 slot 负责特定的功能处理。
Client code (SphU.entry)
SlotChain (责任链) 1. NodeSelectorSlot
为当前请求选择/创建对应的 DefaultNode,挂到 Context的 curNode。 2. ClusterBuilderSlot
为当前 DefaultNode 绑定/创建全局 ClusterNode(全局聚合统计或集群限流相关)
  1. LogSlot
    1. 调用链路日志、埋点、Trace 信息或将监控事件推送到上层系统(如埋点、日志、链路追踪)
  1. StatisticSlot
    1. 将请求的相关事件 如通过/异常/拒绝等事件写入到 Node 的统计容器,提供 QPS、RT、exection等指标的写入入口
  1. AuthoritySlot
    1. 按来源(调用者 App 名称、IP、来源标识)做鉴权/白名单/黑名单处理(来源限流)。
  1. SystemSlot
    1. 全局系统保护,基于系统指标(CPU、load、平均 RT、全局线程数)做兜底保护。
  1. FlowSlot
    1. 真正实现流量控制的入口——根据流控规则(FlowRule)判断是否放行(QPS/线程数/关联/优先级等),并触发相应的控制行为(直接拒绝/排队/预热等)。
  1. DefaultCircuitBreakerSlot
    1. 系统默认的熔断机制
  1. DegradeSlot
    1. 处理用户自定义的降级规则和熔断逻辑
Exit → metric update

数据统计

Node 是一个资源调用的单位,每个被 Sentinel保护的资源 如接口、方法、RPC 调用都有一个或多个 Node 与之关联。

Node的类型和组成顺序

DefaultNode
每个具体资源对应的统计节点(最常见)
ClusterNode
同一资源的全局聚合节点(所有调用的汇总统计)
EntranceNode
Context 的根节点,用于构建调用树
Node的组成可以理解为一个 N叉树,EntranceNode为根节点
使用这种数据结构和组织方式是为了可以构建调用链统计,支持全局聚合和局部统计分离。
Node接口中定义了统计指标的相关方法。
DefaultNode
rollingCounterInSecond
[window][window]
rollingCounterInMinute
[window]…[window]
 
notion image
请求的统计信息使用的滑动窗口统计算法。
rollingCounterInSecond 每秒的请求统计信息
这里默认会分为2个时间窗口,也就是说1个时间窗口统计500ms内的信息。
rollingCounterInMinute 每分钟的统计信息
默认将一分钟分为 60 个窗口。
每个时间窗口都是数组中的一个元素,每个元素都是当前时间窗口中的统计信息。
rollingCounterInSecond 中的统计数据为例。
rollingCounterInSecondrollingCounterInMinute 内部维护了一个数组,数组的每个元素都为当前时间窗口的统计数据。
时间窗口的组成
WindowWrap T value (MetricBucket) 当前时间窗口的具体统计信息
private long windowStart; // 当前时间窗口的起始时间戳
private final long windowLengthInMs; 当前时间窗口的长度
MetricBucket 内部维护了一个 LongAdder[]数组,用于保存各类事件的统计。为了并发安全这里使用的 LongAdder 类。
例如 统计 PASS 请求通过事件的次数,通过LongAdder[PASS].add(n)就可以完成该类事件的次数递增。获取此类事件的次数只要执行LongAdder[PASS].sum()。
 

具体示例

假设一个创建订单的接口,里面调用了支付 api 和 发送消息的 api,那么该接口组成的Node 的顺序如下。
notion image
 
在Sentinel的 Dashboard 面板上会有如下展示
notion image

如何统计请求数据

进入被保护的资源方法时会构建一个责任链,在执行到StatisticSlot该条责任链时会执行统计行为。
notion image

流控规则

Sentinel 的流控是基于规则(FlowRule)、控制器、统计数据(Node的 LeapArray/MetricBucket)来实现的。

流控规则的数据模型

流控的规则由 FlowRule 类来构建。
  • resource 规则对应的资源名
  • count 阀值 QPS 或 并发线程数
  • grade 模式 QPS 或 线程 ,默认为 QPS
  • controlBehavior 行为 直接拒绝/预热/排队
  • strategy 流控模式 流控的判断条件即什么时候触发流控。可选值有以下
    • 直接:直接限制当前资源的请求,默认策略
      关联:当关联资源触发阀值时,限制当前资源的请求。
      链路: 只限制从特定调用链路进入当前资源的请求,其他链路不受影响。
  • clusterNode 是否为集群模式
  • controlBehavior 流量整形控制器 流控的处理行为即触发流控后应该怎么做,
    • 判断请求是否能通过以及超过流量阀值的处理方式。
  • limitApp 默认值为 default,标识请求来源。
一个资源的流控规则可以有多条,例如对于不同的请求来源有不同的限流策略。
 

如何创建流控规则

Sentinel 的流控规则可以通过硬编码 FlowRuleManager.loadRules() 或动态数据源(DataSource/Dashboard 推送/配置中心)来创建和加载。
 
  1. 通过代码形式加载流控规则。可以借助 SpringBoot 的扩展点,容器初始化完成后加载流控的相关规则。
  1. 可视化操作
    1. 通过 Sentinel 的 Dashboard 来创建或更改流控规则。
      前提是需要部署 Sentinel-Dashboard,集成的相关应用需要配置dashboard 的地址端口等简单参数。
notion image
  1. 配置方式
    1. 本地配置文件、配置中心。
通过 Sentinel 的 Dashboard 或配置中心可动态调整配置。

流控具体是怎么做的

在项目启动时 FlowRuleManager 会将流控规则全部加载内存中,由 flowRules 属性维护所有资源的流控规则。如果配置中心或控制台变更了资源的流控规则,这里会自动更新流控规则。
请求过来的时,执行到FlowSolt这个责任链,根据资源名称获取对应的流控规则后交由FlowRuleChecker.checkFlow方法来校验请求是否需要流控,流控的主要依据除了之前定义的资源的流控规则,还有依赖资源的统计信息(统计信息直接从当前资源的 Node 中获取)。
FlowSolt.entry()
→FlowRuleChecker.checkFlow() 取出当前资源的所有流控规则
→FlowRuleChecker.canPassCheck() 根据当前规则判断当前请求是否能通过
→TrafficShapingController.canPass() 确认请求是否能够通过
FlowRuleChecker.checkFlow()
一个受保护的资源可以有多条流控规则(FlowRule),这里每条规则都会去进行检查,如果其中一条未通过会抛出异常。
FlowRuleChecker.canPassCheck()
  • 校验当前请求和规则是否能够通过。
  • 根据流控规则的isClusterMode参数来判断是走集群校验还是本地校验(单机限流)。

单机限流

选择Node

sentinel中有关联、链路、全局、来源等限流规则或策略,选择 Node 就是选择所需的Node 的中的统计数据,一个请求是否能通过依赖这些统计数据来判定。
默认为流控策略为直接,它只要当前资源关联的 Node。如果是关联、链路则需要找到当前资源关联的 Node。
例如有 2 个服务 ServiceA、ServiceB ,当 ServiceA达到限流,ServiceB也需要限流。
在 调用 ServiceB时,则需要获取到 ServiceA这个资源的 Node 中的统计数据来判断到达请求 ServiceB的请求是否能够通过。

寻找关联节点

流量控制器

Node节点选择完成后,流控规则中所选定的流量控制器会去判断当前请求是否能通过。
在定义一个流控规则时,可以选择一个流量控制器,用于当前请求超过流量阀值时的处理行为。
选择一个流量控制器 for example
Sentinel 定义了一个流量控制器的通用接口 TrafficShapingController。
interface TrafficShapingController
DefaultController
默认的限流规则,根据窗口内的请求数量来决定请求是否pass
ThrottlingController
允许排队模式处理请求
WarmUpController
预热/冷启动模式
WarmUpRateLimiterController
在预热/冷启动模式上增加了超时控制

默认流量控制

DefaultController类实现
Sentinel 默认的限流实现,采用的是立即拒绝策略。
支持高优先级请求预占未来机制,抢占未来时间窗口,当前请求线程会休眠。
 
DefaultController 核心参数如下:取决于流控规则的设定
 

canPass

当前Node的 passQps 这个数据来判断当前请求是否能够通过。
如果当前请求有更高优先级且当前窗口的令牌已经用尽,则会尝试占用未来时间窗口的令牌。

抢占未来时间窗口

只有流控规则中定义为 QPS 模式且调用保护资源的方式为优先级的情况下才会生效。

冷启动/预热

冷启动/预热流量控制策略控制器,用于处理系统初期或长时间空闲后突然迎来大流量的场景。
预热限流是一种渐进式扩容,在初始阶段较低的通过率,随着预热逐渐提升。
面对突发流量时,有效防止系统过载。
 
由WarmUpController类实现。核心参数
首先会在构造器中根据流控规则计算出这些值。
 
 
上一篇
MySQL、Redis缓存一致性问题
下一篇
JDK线程池源码分析

Comments
Loading...