最常见原因是资源埋点没对上:sentinel.Entry()未在主goroutine调用,或resourceName与规则不匹配;系统级限流认"default",接口级需用"GET:/api/order"格式,且Entry必须在Gin handler主流程中调用并判空e再defer Exit。

为什么 Gin + Sentinel 的限流中间件不生效
最常见原因是资源埋点没对上——sentinel.Entry() 没在主 goroutine 调用,或 resourceName 和系统规则不匹配。
系统级限流(如 CPU、Load)只认 resourceName: "default",且必须传 sentinel.WithTrafficType(base.Inbound);而接口级限流(比如单个路由)要用 "GET:/api/order" 这类格式,不能写成 "/api/order" 或带 query 参数的完整 URL。
-
Entry()必须在 Gin handler 主流程里调用,不能丢进go func() {}里 -
e := sentinel.Entry(...)返回值可能为nil,直接defer e.Exit()会 panic,得先判空:if e != nil { defer e.Exit() } - 规则加载必须在服务启动早期完成,不能每次请求都调
system.LoadRules(),否则规则引擎会被锁死
BBR 自适应限流和 InboundQPS 固定阈值怎么选
BBR(Bottleneck Bandwidth and RT)不是简单限 QPS,而是根据当前系统负载(CPU、RT、并发数)动态调整允许的入口流量。它适合流量波动大、硬件资源不均的生产环境;但调试难度高,初期容易误判。
InboundQPS 是固定阈值,配置直观,适合秒杀、导出等明确知道安全上限的场景。但它不管服务器是不是快挂了——CPU 95% 时照样放行 200 QPS,可能直接压垮 DB。
- 用 BBR:需搭配
system.Load或system.CPU规则,且TriggerCount填的是软阈值(比如 Load > 8.0 就开始降流),不是硬拒绝值 - 用
InboundQPS:建议配合Strategy: system.Throughput(吞吐优先)或system.Adaptive(自适应窗口),比纯 BBR 更稳 - 两者不能共存:同一时间只生效最先满足的规则,
system.Load和system.InboundQPS同时配,只有前者起作用
Concurrency 并发数限流为什么能防慢接口堆积
它限制的是“同时正在处理的请求数”,不是每秒多少个。比如一个导出接口平均耗时 10s,QPS=100 时,理论上并发数是 1000;如果数据库连接池只有 200,剩下的 800 请求就会卡在等待连接,最终超时或 OOM。
设 Concurrency: 50 后,第 51 个请求进来就立刻被拦截,不会进入 handler,也就不会占连接、不会排队、不会拖垮下游。
- 适用场景:文件生成、报表导出、批量同步、长事务接口
- 注意:它对短平快请求(如鉴权、缓存查询)几乎无感,因为它们并发数天然低
- 别和
InboundQPS混用——QPS 高但并发低(如大量轻量请求)时,并发规则不触发,QPS 规则又可能放太多请求进来
sentinel.SentinelMiddleware 中的 block fallback 容易漏什么
默认 fallback 是返回 429,但生产中往往要记录日志、打监控、甚至触发告警。更关键的是:这个函数运行在被限流的请求上下文中,ctx.AbortWithStatusJSON() 后,后续中间件仍可能执行(比如日志中间件没判 ctx.IsAborted())。
- 务必在 fallback 函数里手动
ctx.Abort(),否则 Gin 可能继续走后续 handler - 不要在 fallback 里做耗时操作(如写 DB、发 HTTP),它本身就在限流路径上,加延迟会恶化响应
- 返回体结构最好和正常接口一致,避免前端解析失败;错误码建议用 429(Too Many Requests)而非 200 + code=500
实际部署时,system.LoadRules() 加载顺序、resourceName 字符串一致性、以及 Entry/Exit 是否严格配对,这三点出错率最高,且问题现象隐蔽——看起来规则写了,但就是不触发。











