limit_req模块需按请求粒度、突发容忍、延迟策略联动设计:key决定限流维度(ip/用户/路径),burst与nodelay协同控制突发(如burst=5 nodelay保支付低延迟),分层配置适配多场景,配合日志、自定义响应和熔断实现可观测与兜底。

直接用 limit_req 模块就能实现令牌桶限流,关键在配置逻辑是否贴合业务真实流量特征——它不是开箱即用的“开关”,而是需要按请求粒度、突发容忍、延迟策略三者联动设计的流量调节器。
明确限流维度与 key 设计
限流效果取决于你用什么做区分标识。key 决定了“谁被限”“谁和谁隔离”:
-
按 IP 限流:适合防御简单爬虫或 CC 攻击,但共享出口 IP(如企业内网、运营商 NAT)时容易误伤;配置示例:
limit_req_zone $binary_remote_addr zone=ip_limit:10m rate=5r/s; -
按用户身份限流:如从 Header 或 Cookie 提取
user_id或X-User-ID,更精准保护后端资源;需配合map指令清洗空值,避免未登录用户挤占额度; -
按接口路径+参数组合限流:例如对
/api/v1/order/create单独设限,或提取商品 ID 做二级分组($request_uri ~* /item/(\d+)),防止热点商品引发雪崩; - 注意:key 越细,内存占用越高;10MB zone 约支持 16 万个唯一 key,超出会触发 LRU 自动淘汰,但可能造成老用户突然被限。
配置 burst 与 nodelay 实现平滑+突发兼容
令牌桶的核心是“允许短暂爆发,但不纵容持续过载”。这靠 burst 和 nodelay 协同控制:
-
burst=20表示桶最多存 20 个令牌,相当于允许最多积压 20 个请求排队; - 不加
nodelay:超速请求进入队列,按令牌生成节奏依次放出,请求延迟升高但后端压力平稳; - 加
nodelay:只要桶里有令牌(哪怕只剩 1 个),就立即处理,不排队;突发流量秒级响应,但瞬时压力上扬; - 推荐组合:高敏感接口(如支付回调)用
burst=5 nodelay,保低延迟;读多写少接口(如商品详情)用burst=30不加 nodelay,换后端稳定。
嵌入业务路径,分层设置速率策略
单一全局限流无法适配多业务场景。应结合 location、if、map 分层挂载不同限流策略:
- 对登录态用户放宽限制:
limit_req zone=user_limit burst=100 nodelay;,对未登录用户收紧:limit_req zone=guest_limit burst=5;; - 按活动生命周期动态调速:秒杀开启时,用
map $arg_activity_id $req_rate { default 1r/s; "seckill2026" 100r/s; },再绑定rate=$req_rate; - 对健康检查、监控探针等内部请求,用
if ($http_user_agent ~* "Prometheus|HealthCheck") { set $limit_key ""; }跳过限流; - 避免在
server块顶层硬编码,优先在location中按路径精细化控制。
可观测与兜底机制不可少
限流生效后必须能感知异常、快速干预:
- 开启日志记录被限请求:
limit_req_log_level warn;,配合log_format输出 $limit_key 和 $limit_rate,便于定位高频 key; - 返回友好提示而非默认 503:用
error_page 503 = @rate_limited;转到自定义响应,返回 JSON 提示“请求过于频繁,请稍后再试”; - 设置紧急熔断开关:通过
geo指令或外部变量(如 Consul KV)控制limit_req是否启用,故障时一键关闭限流保通; - 定期检查
limit_req_status变量或 Nginx stub_status,观察当前 zone 使用率与拒绝率,超过 15% 拒绝率需复核阈值。










