gin+sentinel限流中间件必须显式调用sentinel.entry和e.exit(),因sentinel-golang是资源粒度轻量库,不自动织入http handler,且gin本身无限流能力;entry与exit须在主goroutine严格配对、判空defer,resourcename须为"default"并传inbound类型,否则系统规则不生效。

为什么 Gin + Sentinel 的限流中间件必须显式调用 sentinel.Entry 和 e.Exit()
因为 sentinel-golang 是资源粒度的轻量库,不自动织入 HTTP handler;Gin 本身也无熔断/限流能力。你写的中间件若只调用 sentinel.Entry 却没配对 e.Exit(),统计上下文就中断,规则永远不生效。
常见错误现象:
- 配置了
system.InboundQPS规则但完全不触发限流 - 请求返回 200 却没走限流逻辑,
sentinel.SentinelMiddleware看似启用实则空转 - panic 后 recover 中补
e.Exit()—— 无效,goroutine 已中断,指标已丢失
正确做法:
-
e.Exit()必须放在defer中,且紧贴Entry调用之后(不能在c.Next()后或 recover 里) - resourceName 建议统一为
"GET:/api/order"这类格式,避免字符串散落难维护 - 必须传
sentinel.WithTrafficType(base.Inbound),否则系统级规则(如InboundQPS)不计入统计
system.LoadRules 加载后为什么没效果?
system.LoadRules 只是注册规则,不绑定执行上下文。它不监听任何流量,也不自动关联到某个 handler 或资源名。
关键点:
- 系统级规则(如
InboundQPS、Concurrency)要求resourceName必须是"default",否则不触发 - 规则中
MetricType和实际埋点的TrafficType必须匹配:比如用了system.InboundQPS,埋点就必须带base.Inbound - 必须确保
sentinel.InitDefault()已成功调用,且无 error;否则后续所有Entry都静默失败
示例配置(生效前提):
if _, err := system.LoadRules([]*system.Rule{{
MetricType: system.InboundQPS,
TriggerCount: 200,
Strategy: system.BBR,
}}); err != nil {
log.Fatalf("Failed to load system rules: %+v", err)
}
降级规则里 SlowRatioThreshold 和 MinRequestAmount 怎么设才不误杀
这两个参数直接决定熔断是否“敏感过头”或“反应迟钝”。设错会导致小抖动就熔断,或大范围超时还放行。
真实服务建议值:
-
MinRequestAmount至少为20:低于该值统计方差大,5 次请求里 2 次慢就触发,纯噪声 -
SlowRatioThreshold推荐0.3~0.5:即 30%~50% 请求被判定为慢调用才熔断,兼顾灵敏与稳定 -
SlowCallDurationInMs应略高于接口 P90 RT(如 P90 是 300ms,设为400),避免把正常尾部延迟当异常 - 搭配
StatIntervalInMs: 60000(1 分钟窗口),比默认 10s 更抗脉冲干扰
flow.Reject 和 flow.Throttling 行为差异在哪
两者都基于滑动时间窗口,但拒绝策略影响下游重试逻辑和用户体验。
flow.Reject:
- 超阈值立刻返回
TokenResult{Blocked: true} - 适合强实时性接口(如支付下单),不排队、不缓冲
- 下游若盲目重试,可能加剧雪崩
flow.Throttling:
- 允许请求排队等待,直到有 Token 可用
- 适合容忍延迟的场景(如报表导出、异步通知)
- 需配合合理
MaxQueueingTimeMs,否则用户等太久
注意:flow.Throttling 在高并发下会堆积 goroutine,生产环境慎用,优先选 flow.Reject + 前端退避重试。
最易被忽略的一点:所有 degrade.Entry 必须严格配对 Exit,且不能跨 goroutine —— Gin handler 里启的 goroutine 若调用 Entry,必须自己管理 Exit,主 handler 的 defer 不会覆盖它。











