Sentinel(阿里巴巴开源的流量控制组件) 中 FlowRuleChecker 类用于执行 流控规则(Flow Control Rules)检查。它的作用是在每次请求进入受保护资源时,判断是否应该放行(pass)还是拒绝(block)。
下面我将从 整体架构、关键方法、核心逻辑和设计思想 四个层面帮你深入理解。
🧩 一、整体功能概览
目标 :根据配置的流控规则(
FlowRule),决定当前请求是否被限流(抛出BlockException)。
核心流程:
- 获取当前资源(如
/api/order)对应的流控规则列表。 - 遍历每条规则,逐个检查是否满足通过条件。
- 如果任意一条规则 不通过 → 抛出
FlowException(限流)。 - 所有规则都通过 → 请求继续执行。
🔑 二、关键方法解析
1. checkFlow(...)
java
public void checkFlow(Function<String, Collection<FlowRule>> ruleProvider, ResourceWrapper resource,
Context context, DefaultNode node, int count, boolean prioritized) throws BlockException {
if (ruleProvider == null || resource == null) {
return;
}
Collection<FlowRule> rules = ruleProvider.apply(resource.getName());
if (rules != null) {
for (FlowRule rule : rules) {
if (!canPassCheck(rule, context, node, count, prioritized)) {
throw new FlowException(rule.getLimitApp(), rule);
}
}
}
}
- 入口方法 ,由 Sentinel 的 Slot Chain 调用(如
FlowSlot)。 - 参数说明:
ruleProvider: 根据资源名获取流控规则的函数。resource: 当前访问的资源(如 API 路径)。context: 请求上下文(包含 origin、调用链等)。node: 统计节点(记录 QPS、线程数等指标)。count: 本次请求消耗的"令牌"数量(通常为 1)。prioritized: 是否优先级请求(可抢占资源)。
✅ 逻辑 :遍历所有规则,只要有一条 canPassCheck 返回 false,就限流。
2. canPassCheck(...)
java
public boolean canPassCheck(FlowRule rule, Context context, DefaultNode node, int acquireCount, boolean prioritized)
- 判断单条流控规则是否允许通过。
- 支持两种模式:
- 本地限流(Local)
- 集群限流(Cluster)
分支逻辑:
java
if (rule.isClusterMode()) {
return passClusterCheck(...); // 集群模式
}
return passLocalCheck(...); // 本地模式
3. passLocalCheck(...)
java
private static boolean passLocalCheck(FlowRule rule, Context context, DefaultNode node, int acquireCount,
boolean prioritized) {
Node selectedNode = selectNodeByRequesterAndStrategy(rule, context, node);
if (selectedNode == null) {
return true;
}
return rule.getRater().canPass(selectedNode, acquireCount, prioritized);
}
- 执行 本地限流。
- 关键步骤:
- 调用
selectNodeByRequesterAndStrategy(...)选择要检查的统计节点(可能是 origin 节点、关联资源节点等)。 - 调用
rule.getRater().canPass(...)实际判断(基于滑动窗口、令牌桶等算法)。
- 调用
✅
rater是限流算法的具体实现(如DefaultController基于 QPS 或线程数)。
4. selectNodeByRequesterAndStrategy(...)
这是 最复杂的部分 ,决定了"对谁限流?"
java
static Node selectNodeByRequesterAndStrategy(/*@NonNull*/ FlowRule rule, Context context, DefaultNode node) {
// The limit app should not be empty.
String limitApp = rule.getLimitApp();
int strategy = rule.getStrategy();
String origin = context.getOrigin();
if (limitApp.equals(origin) && filterOrigin(origin)) {
if (strategy == RuleConstant.STRATEGY_DIRECT) {
// Matches limit origin, return origin statistic node.
return context.getOriginNode();
}
return selectReferenceNode(rule, context, node);
} else if (RuleConstant.LIMIT_APP_DEFAULT.equals(limitApp)) {
if (strategy == RuleConstant.STRATEGY_DIRECT) {
// Return the cluster node.
return node.getClusterNode();
}
return selectReferenceNode(rule, context, node);
} else if (RuleConstant.LIMIT_APP_OTHER.equals(limitApp)
&& FlowRuleManager.isOtherOrigin(origin, rule.getResource())) {
if (strategy == RuleConstant.STRATEGY_DIRECT) {
return context.getOriginNode();
}
return selectReferenceNode(rule, context, node);
}
return null;
}
流控维度(limitApp):
"default":对所有来源统一限流。"other":对非指定来源限流。- 具体应用名(如
"appA"):只对该来源限流。
流控策略(strategy):
| 策略值 | 含义 |
|---|---|
STRATEGY_DIRECT (0) |
直接对当前资源限流(默认)。 |
STRATEGY_RELATE (1) |
关联限流:当关联资源(refResource)达到阈值,限流当前资源。 |
STRATEGY_CHAIN (2) |
链路限流:只在特定调用链路上限流(需匹配入口资源名)。 |
示例:
- 规则:
limitApp = "mobile",strategy = DIRECT
→ 只限制来自"mobile"应用的请求。 - 规则:
strategy = RELATE,refResource = "order-service"
→ 当"order-service"被大量调用时,限流当前资源(如支付接口)。
5. passClusterCheck(...)
- 处理 集群限流(多个服务实例共享配额)。
- 调用
TokenService向 Token Server 申请令牌。 - 如果集群模式不可用(如网络失败),则:
- 若配置了
fallbackToLocalWhenFail=true→ 降级为本地限流。 - 否则 → 直接放行(fail-open)。
- 若配置了
⚠️ 集群限流需要额外部署 Token Server,适用于分布式场景。
🎯 三、设计亮点
1. 策略模式 + 职责链
- 每条规则独立检查,符合职责链模式。
- 限流算法(
rater)可插拔,支持扩展。
2. 灵活的限流维度
- 支持按 调用方(origin) 、关联资源 、调用链路 进行精细化控制。
3. 容错与降级
- 集群限流失败时自动 fallback 到本地,避免雪崩。
4. 无侵入式集成
- 通过
Context和Node解耦业务逻辑与限流逻辑。
🧪 四、举个实际例子
假设你配置了一条规则:
java
FlowRule rule = new FlowRule("order_create")
.setCount(10) // QPS 阈值 10
.setLimitApp("web") // 只限制来自 "web" 的请求
.setStrategy(RuleConstant.STRATEGY_DIRECT);
当请求到来时:
context.getOrigin()返回"web"→ 匹配limitApp。strategy = DIRECT→ 使用context.getOriginNode()统计"web"的 QPS。- 如果
"web"的 QPS > 10 →canPass返回 false → 抛出FlowException。
✅ 总结:如何理解这段代码?
| 层面 | 说明 |
|---|---|
| 作用 | Sentinel 的流控核心检查器,决定请求是否被限流。 |
| 核心逻辑 | 遍历规则 → 选择统计节点 → 调用限流算法 → 决策放行/拒绝。 |
| 关键抽象 | FlowRule(规则)、Node(统计)、Controller(算法)、Context(上下文)。 |
| 扩展性 | 支持本地/集群、多种策略、自定义 origin。 |
| 容错 | 集群失败可降级,避免系统不可用。 |
💡 一句话总结 :
FlowRuleChecker是 Sentinel 的"交通警察",根据预设规则(限速牌)和实时车流量(Node 统计),决定是否让当前"车辆"(请求)通行。
如果你正在使用 Sentinel,理解这段代码有助于你:
- 正确配置流控规则;
- 排查限流不生效的问题;
- 自定义限流策略或降级逻辑。