4. 流量控制进阶:基于调用关系的限流、关联限流、链路限流、热点参数限流
流量控制是保障微服务稳定性的第一道防线。在基础 QPS/线程数限流之上,Sentinel 提供了四种面向调用关系的进阶限流策略,能够更精细地控制流量在不同资源、不同调用路径上的分布。本章将逐一剖析关联限流、链路限流、热点参数限流的原理与配置方法,并通过对比表格和架构图帮助理解其适用场景。
4.1 四种限流模式概述
Sentinel 的流量控制规则(FlowRule)除了基础的 grade(限流阈值类型)和 count(阈值)外,核心在于 strategy 字段,它决定了限流生效的调用关系维度。下表总结了四种策略的对比:
| 策略值 | 策略名称 | 核心逻辑 | 典型场景 |
|---|---|---|---|
| 0 | 直接限流(Direct) | 对资源自身 QPS/线程数进行限流,不关心调用来源 | 接口总入口限流、数据库连接池限流 |
| 1 | 关联限流(Associate) | 当关联资源达到阈值时,对当前资源进行限流 | “写操作”过载时限制“读操作” |
| 2 | 链路限流(Chain) | 只统计从指定入口资源进入的流量,进行限流 | 区分用户请求与内部定时任务对同一资源的访问 |
| 3 | 热点参数限流(Hot Param) | 针对资源的具体参数值进行限流,支持参数例外项 | 商品 ID 维度限流、用户 ID 维度限流 |
4.2 关联限流:保护上下游依赖
关联限流的核心思想是:当资源 A 的流量过大时,主动限制资源 B 的流量,从而避免资源 A 被完全压垮,导致整个系统雪崩。它常用于“读写分离”或“高优与低优”操作共存的场景。
4.2.1 原理与配置
假设有一个订单系统,包含两个核心资源:createOrder(写订单)和 queryOrder(查订单)。当写操作压力过大时,我们希望优先保障写操作的稳定性,主动对读操作进行限流。
- 配置方式:在
queryOrder资源上创建流控规则,策略选择「关联」,关联资源填写createOrder。当createOrder的 QPS 达到阈值时,queryOrder的请求会被拒绝。 - 阈值类型:支持 QPS 和线程数两种模式。
// 为 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 本身不受影响。
4.3 链路限流:区分调用来源
链路限流允许你只对从特定入口资源(origin)发起的调用进行限流,而忽略其他入口的流量。这在同一个资源被多个上游服务或内部任务调用时非常有用。
4.3.1 原理与配置
假设资源 getUserInfo 同时被两个入口调用:userApi(用户请求)和 syncTask(定时同步任务)。我们希望限制同步任务对 getUserInfo 的调用频率,但不影响用户请求。
- 配置方式:在
getUserInfo资源上创建流控规则,策略选择「链路」,入口资源填写syncTask。此时,只有从syncTask进入的流量会被统计并限流。 - 前置条件:必须在代码中显式定义入口资源,使用
SphU.entry("getUserInfo", EntryType.IN)并指定调用来源。
ContextUtil.enter("入口名") 创建上下文。
4.3.2 链路限流架构图
下图展示了链路限流如何区分不同入口对同一资源的访问:
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 四种策略的选择指南
在实际项目中,如何选择合适的限流策略?可以参考以下决策流程:
- 是否需要区分调用来源?是 → 链路限流;否 → 下一步。
- 是否需要保护关联资源?是 → 关联限流;否 → 下一步。
- 是否需要针对参数值差异化限流?是 → 热点参数限流;否 → 直接限流。
4.6 本章小结
本章深入讲解了 Sentinel 四种进阶限流策略的原理与配置方法。关联限流通过保护关联资源间接稳定系统;链路限流实现了按调用来源的精细化控制;热点参数限流则提供了参数级别的限流能力。掌握这些策略,能够帮助你在复杂微服务架构中构建更精准、更灵活的流量防护体系。