4. 流量控制进阶:基于调用关系的限流、关联限流、链路限流、热点参数限流

流量控制是保障微服务稳定性的第一道防线。在基础 QPS/线程数限流之上,Sentinel 提供了四种面向调用关系的进阶限流策略,能够更精细地控制流量在不同资源、不同调用路径上的分布。本章将逐一剖析关联限流、链路限流、热点参数限流的原理与配置方法,并通过对比表格和架构图帮助理解其适用场景。

4.1 四种限流模式概述

Sentinel 的流量控制规则(FlowRule)除了基础的 grade(限流阈值类型)和 count(阈值)外,核心在于 strategy 字段,它决定了限流生效的调用关系维度。下表总结了四种策略的对比:

策略值 策略名称 核心逻辑 典型场景
0 直接限流(Direct) 对资源自身 QPS/线程数进行限流,不关心调用来源 接口总入口限流、数据库连接池限流
1 关联限流(Associate) 当关联资源达到阈值时,对当前资源进行限流 “写操作”过载时限制“读操作”
2 链路限流(Chain) 只统计从指定入口资源进入的流量,进行限流 区分用户请求与内部定时任务对同一资源的访问
3 热点参数限流(Hot Param) 针对资源的具体参数值进行限流,支持参数例外项 商品 ID 维度限流、用户 ID 维度限流
配置入口:在 Sentinel 控制台的「流量控制」菜单中,新建规则时选择「策略」下拉框即可切换四种模式。关联限流和链路限流需要额外指定关联资源或入口资源名称。

4.2 关联限流:保护上下游依赖

关联限流的核心思想是:当资源 A 的流量过大时,主动限制资源 B 的流量,从而避免资源 A 被完全压垮,导致整个系统雪崩。它常用于“读写分离”或“高优与低优”操作共存的场景。

4.2.1 原理与配置

假设有一个订单系统,包含两个核心资源:createOrder(写订单)和 queryOrder(查订单)。当写操作压力过大时,我们希望优先保障写操作的稳定性,主动对读操作进行限流。

  • 配置方式:在 queryOrder 资源上创建流控规则,策略选择「关联」,关联资源填写 createOrder。当 createOrder 的 QPS 达到阈值时,queryOrder 的请求会被拒绝。
  • 阈值类型:支持 QPS 和线程数两种模式。
代码示例:通过 Sentinel API 配置关联限流规则
// 为 queryOrder 资源创建关联限流规则
FlowRule rule = new FlowRule();
rule.setResource("queryOrder");
rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
rule.setCount(100);          // 关联资源阈值:100 QPS
rule.setStrategy(RuleConstant.STRATEGY_ASSOCIATE);
rule.setRefResource("createOrder");  // 关联资源名
FlowRuleManager.loadRules(Collections.singletonList(rule));

4.2.2 关联限流流程图

下图展示了关联限流的判断逻辑:当关联资源 createOrder 的实时 QPS 超过 100 时,queryOrder 的请求会被直接拒绝,而 createOrder 本身不受影响。

关联限流判断流程 请求 queryOrder 关联资源 QPS > 100? 拒绝请求 放行请求 createOrder 实时 QPS 说明:关联限流只检查关联资源的实时指标,不对当前资源自身做统计。当关联资源恢复正常后,限流自动解除。

4.3 链路限流:区分调用来源

链路限流允许你只对从特定入口资源(origin)发起的调用进行限流,而忽略其他入口的流量。这在同一个资源被多个上游服务或内部任务调用时非常有用。

4.3.1 原理与配置

假设资源 getUserInfo 同时被两个入口调用:userApi(用户请求)和 syncTask(定时同步任务)。我们希望限制同步任务对 getUserInfo 的调用频率,但不影响用户请求。

  • 配置方式:在 getUserInfo 资源上创建流控规则,策略选择「链路」,入口资源填写 syncTask。此时,只有从 syncTask 进入的流量会被统计并限流。
  • 前置条件:必须在代码中显式定义入口资源,使用 SphU.entry("getUserInfo", EntryType.IN) 并指定调用来源。
常见误区:链路限流要求调用链路上必须存在入口上下文。如果所有调用都使用默认入口,链路限流将退化为直接限流。务必在调用入口处使用 ContextUtil.enter("入口名") 创建上下文。

4.3.2 链路限流架构图

下图展示了链路限流如何区分不同入口对同一资源的访问:

链路限流:按入口资源隔离 入口:userApi 入口:syncTask getUserInfo 链路规则 入口: syncTask 说明:虚线表示 syncTask 入口的流量被链路规则限流,实线表示 userApi 入口的流量不受影响。

4.4 热点参数限流:精细化到参数值

热点参数限流是 Sentinel 最精细的限流手段,它针对同一个资源的不同参数值分别统计流量,并允许为特定参数值设置不同的阈值。例如,对商品 ID 为 1001 的查询限流 100 QPS,而对商品 ID 为 1002 的查询限流 50 QPS。

4.4.1 核心概念

  • 参数索引:指定对资源的第几个参数进行限流(从 0 开始)。
  • 统计窗口时长:默认 1 秒,可配置。
  • 参数例外项:允许为特定的参数值设置独立的阈值,覆盖全局阈值。
代码示例:配置热点参数限流规则
// 创建热点参数限流规则
ParamFlowRule rule = new ParamFlowRule("getProduct")
    .setParamIdx(0)           // 对第一个参数(商品ID)限流
    .setCount(50)             // 全局阈值:50 QPS
    .setDurationInSec(1);     // 统计窗口:1秒

// 添加参数例外项:商品ID=1001 的阈值提升到 200 QPS
ParamFlowItem item = new ParamFlowItem()
    .setObject("1001")
    .setClassType(int.class.getName())
    .setCount(200);
rule.getParamFlowItemList().add(item);

ParamFlowRuleManager.loadRules(Collections.singletonList(rule));

4.4.2 热点参数限流效果示意

下表展示了不同商品 ID 在热点规则下的限流效果:

商品 ID 全局阈值 例外项阈值 实际生效阈值 说明
1001 50 QPS 200 QPS 200 QPS 例外项覆盖全局
1002 50 QPS 无 50 QPS 使用全局阈值
1003 50 QPS 无 50 QPS 使用全局阈值
2001 50 QPS 无 50 QPS 使用全局阈值

4.5 四种策略的选择指南

在实际项目中,如何选择合适的限流策略?可以参考以下决策流程:

  1. 是否需要区分调用来源?是 → 链路限流;否 → 下一步。
  2. 是否需要保护关联资源?是 → 关联限流;否 → 下一步。
  3. 是否需要针对参数值差异化限流?是 → 热点参数限流;否 → 直接限流。
最佳实践:建议先使用直接限流兜底,再针对核心链路或热点参数叠加链路/热点规则。关联限流通常用于读写分离架构中的读接口保护。热点参数限流对缓存击穿防护效果显著,建议配合本地缓存使用。

4.6 本章小结

本章深入讲解了 Sentinel 四种进阶限流策略的原理与配置方法。关联限流通过保护关联资源间接稳定系统;链路限流实现了按调用来源的精细化控制;热点参数限流则提供了参数级别的限流能力。掌握这些策略,能够帮助你在复杂微服务架构中构建更精准、更灵活的流量防护体系。