Sentinel流控规则检查源码级分析

Sentinel(阿里巴巴开源的流量控制组件)FlowRuleChecker 类用于执行 流控规则(Flow Control Rules)检查。它的作用是在每次请求进入受保护资源时,判断是否应该放行(pass)还是拒绝(block)。

下面我将从 整体架构、关键方法、核心逻辑和设计思想 四个层面帮你深入理解。


🧩 一、整体功能概览

目标 :根据配置的流控规则(FlowRule),决定当前请求是否被限流(抛出 BlockException)。

核心流程:

  1. 获取当前资源(如 /api/order)对应的流控规则列表。
  2. 遍历每条规则,逐个检查是否满足通过条件。
  3. 如果任意一条规则 不通过 → 抛出 FlowException(限流)。
  4. 所有规则都通过 → 请求继续执行。

🔑 二、关键方法解析

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);
    }
  • 执行 本地限流
  • 关键步骤:
    1. 调用 selectNodeByRequesterAndStrategy(...) 选择要检查的统计节点(可能是 origin 节点、关联资源节点等)。
    2. 调用 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. 无侵入式集成

  • 通过 ContextNode 解耦业务逻辑与限流逻辑。

🧪 四、举个实际例子

假设你配置了一条规则:

java 复制代码
FlowRule rule = new FlowRule("order_create")
    .setCount(10)                    // QPS 阈值 10
    .setLimitApp("web")              // 只限制来自 "web" 的请求
    .setStrategy(RuleConstant.STRATEGY_DIRECT);

当请求到来时:

  1. context.getOrigin() 返回 "web" → 匹配 limitApp
  2. strategy = DIRECT → 使用 context.getOriginNode() 统计 "web" 的 QPS。
  3. 如果 "web" 的 QPS > 10 → canPass 返回 false → 抛出 FlowException

✅ 总结:如何理解这段代码?

层面 说明
作用 Sentinel 的流控核心检查器,决定请求是否被限流。
核心逻辑 遍历规则 → 选择统计节点 → 调用限流算法 → 决策放行/拒绝。
关键抽象 FlowRule(规则)、Node(统计)、Controller(算法)、Context(上下文)。
扩展性 支持本地/集群、多种策略、自定义 origin。
容错 集群失败可降级,避免系统不可用。

💡 一句话总结
FlowRuleChecker 是 Sentinel 的"交通警察",根据预设规则(限速牌)和实时车流量(Node 统计),决定是否让当前"车辆"(请求)通行。

如果你正在使用 Sentinel,理解这段代码有助于你:

  • 正确配置流控规则;
  • 排查限流不生效的问题;
  • 自定义限流策略或降级逻辑。
相关推荐
lang2015092813 小时前
Sentinel限流核心:ThrottlingController设计详解
服务器·网络·sentinel
lang2015092820 小时前
Sentinel预热限流:WarmUpController原理详解
java·spring·sentinel
lang2015092820 小时前
Sentinel流量整形控制器全解析
sentinel
lang2015092820 小时前
Sentinel三大流控策略全解析
网络·sentinel
lang2015092820 小时前
Sentinel限流核心逻辑解析
java·python·sentinel
lang201509281 天前
Sentinel核心统计节点:滑动窗口与指标计算
sentinel
lang201509281 天前
深入解析Sentinel核心类StatisticSlot
sentinel
lang201509281 天前
Sentinel核心机制:Context与EntranceNode解析
网络·sentinel
lang201509281 天前
Alibaba Sentinel核心类CtSph深入分析
sentinel