bbr限流器必须显式配置cputhreshold(如800),否则fallback为0导致限流失效;禁止复用limiter实例;挂载位置决定作用域,需http/grpc分别配置;验证需查cpu平台期、stats指标及响应头。

BBR限流器怎么配才不踩CPU阈值坑
直接上结论:Kratos默认的BBR限流器不是开箱即用的“傻瓜模式”,它依赖实时CPU使用率触发动态限流,若不显式配置CPUThreshold,会 fallback 到 0,导致限流逻辑永远不生效。
常见错误现象是——明明加了ratelimit.Server中间件,压测时QPS飙到崩溃,日志里却看不到任何ErrLimitExceed提示。
-
bbr.NewLimiter()必须显式传入bbr.WithCPUThreshold(800)(单位是千分比,即80%) - 低于该阈值时,BBR只做观测,不限流;超过后才基于
MaxPass * MinRt * windows / 1000公式判断是否丢弃请求 - 不要复用同一个
limiter实例给多个服务——BBR内部按服务维度维护滑动窗口,共享会导致指标污染
令牌桶限流适合什么场景
BBR适合流量波动大、资源争抢频繁的网关或聚合层;而令牌桶更适合低频但强一致性的核心接口,比如支付确认、库存扣减。
它的行为更可预测:固定速率填充令牌,每次请求消耗1个,无CPU依赖,也不会因瞬时RT抖动误判。
- 用
github.com/go-kratos/aegis/ratelimit/tokenbucket替代bbr包 - 关键参数:
tokenbucket.WithRate(100)(每秒100个令牌)、tokenbucket.WithBurst(200)(最大突发200) - 注意
WithBurst不能小于WithRate,否则启动时panic报"burst must be >= rate"
限流中间件挂载位置影响全局还是局部
挂载位置决定作用域,错一层就全白配。Kratos中间件链是洋葱模型,顺序和层级都关键。
- 全局限流:在
http.NewServer()或grpc.NewServer()的Middlewares(...)里传入,覆盖所有路由 - 分组限流:用
srv.Group("/api")后调用Group.Middleware(...),只对子路由生效 - 单路由限流:目前Kratos不支持单个
HandleFunc单独挂中间件,需拆成独立Group或改用自定义中间件包裹handler
特别注意:HTTP Server和gRPC Server的中间件不互通,ratelimit.Server必须分别挂载。
如何验证限流是否真生效
别只看日志有没有ErrLimitExceed,那只是结果。要确认机制跑通,得查三项指标:
- 压测时用
top或pidstat -u 1观察CPU是否稳定在配置的CPUThreshold附近(BBR模式下应有明显平台期) - 在代码中注入
log打印limiter.Stats()返回的inflight、pass、rt值,确认它们在持续更新 - 触发限流后检查响应头:
http.Server会自动带X-RateLimit-Limit和X-RateLimit-Remaining,但仅当使用ratelimit.Server且未被外层中间件吞掉error时才可见
最容易被忽略的是:BBR的滑动窗口默认采样5秒、50个桶,意味着从CPU超阈值到首次触发限流,存在最多1秒延迟(取决于当前窗口位置)。高敏业务需评估这个“反应滞后”是否可接受。











