sentinel go热点参数限流必须显式配置paramindex/paramkey、metrictype和controlbehavior三项,缺一不可,否则规则被静默丢弃;paramkey比paramindex更健壮,qps模式下threshold与durationinsec共同决定限流窗口,concurrency模式限制的是并发goroutine数而非qps。

直接上结论:Sentinel Go 的热点参数限流不是“打开开关就能用”的功能,它必须显式配置 ParamIndex 或 ParamKey、MetricType、ControlBehavior 三项,缺一不可;否则规则加载失败,且静默跳过——你根本收不到错误提示,流量照常打穿。
为什么 sentinel.LoadRules() 不报错但限流不生效
常见现象是调用 hotspot.LoadRules 返回 nil,日志也无异常,但实际请求从未被拒绝。根本原因是规则结构体字段缺失或类型错配:
-
MetricType和ControlBehavior是强制字段,漏设会导致规则被 Sentinel Go 直接丢弃(不存入内存),连日志都不会打 -
ParamIndex设为0,但实际入参是 struct(如func getProduct(req ProductReq)),此时提取结果为空,规则对所有请求都无效 - 用
ParamKey时字段名拼写错误(比如写成"userId"但 struct 实际是UserID),Go 的反射无法匹配,同样静默失败 - 参数值类型不是基础类型(
int/string/int64等)且未实现ParamFlowArgument接口,提取失败后跳过计数,不报错也不限流
ParamIndex 和 ParamKey 怎么选才稳
二者互斥,选错一个就导致参数提取失败。关键看参数结构和长期维护成本:
- 如果方法签名固定且参数顺序不会变(如
func getUser(id int, name string)),用ParamIndex=0简单直接 - 但只要涉及 struct 或 map 入参(比如
func createOrder(req OrderCreateReq)),必须用ParamKey="ProductID"—— 否则靠索引拿不到嵌套字段,且后续加字段易错位 - 优先用
ParamKey,哪怕多写几个字;它不依赖位置,字段名改了也能通过编译器提前发现,比运行时静默失效强得多 - 若用 map,
ParamKey对应 key 名必须完全一致(区分大小写),且 map 值不能为nil,否则提取返回空字符串,被当成统一参数值统计
QPS 模式下 BurstCount 和 DurationInSec 怎么配
这不是“越大越好”的参数,配错会直接让限流形同虚设:
-
DurationInSec必须设为正整数(如1),设0或负数会导致规则加载失败,但hotspot.LoadRules仍返回nil -
BurstCount只在ControlBehavior=Reject且MetricType=QPS时生效;它是“突发容量”,不是阈值——真正起作用的是Threshold+DurationInSec的组合 - 举例:想限制
productID=1001每秒最多 100 次,设Threshold=100、DurationInSec=1即可;BurstCount设 20 是为了允许短时脉冲(如 100+20=120 请求在 1 秒内打进来,前 100 放行,后 20 拒绝) - 若把
DurationInSec设成60,Threshold=6000,看起来等价,但实际窗口拉长后统计延迟增加,热点识别滞后,秒杀场景下可能刚发现已打爆 DB
Concurrency 模式容易被忽略的并发语义
很多人以为 MetricType=Concurrency 就是“每秒多少请求”,其实它统计的是**同时正在执行的 goroutine 数**,和 QPS 完全不是一回事:
-
Threshold=5表示:当同一productID的请求有 5 个 goroutine 同时在跑(比如都在查 DB、都在调第三方),第 6 个进来就直接拒绝 - 适合防慢 SQL 或阻塞 IO,不适合控制吞吐量;设高了没用(goroutine 占用的是内存和调度开销,不是时间片)
- 千万别在
ControlBehavior=Throttling下用 Concurrency 模式——排队逻辑只对 QPS 有效,Concurrency 下设MaxQueueingTimeMs会被忽略 - 真实压测时,用
go tool pprof看 goroutine 数,比看 QPS 更能验证 Concurrency 限流是否生效
最常被绕过的点:规则加载后,没检查 sentinel.GetNode("your-resource").Resource.Name 是否真对应你定义的资源名;名字不一致,规则就挂在空节点上,永远不触发。别信“写了就生效”,得用 sentinel.GetNode 或控制台实时监控确认节点存在且有 metric 数据。











