Nginx限流需在http块定义limit_req_zone、location块用limit_req启用;漏桶平滑靠rate+burst+nodelay组合实现,如rate=5r/s、burst=20、nodelay可缓冲突发请求并即时处理,保持平均速率。

直接在 location 块中启用限流,必须配合 limit_req_zone(定义规则)和 limit_req(实际启用)两个指令。漏桶效果由 rate + burst + nodelay 的组合决定,关键不是“有没有限流”,而是“怎么平滑”。
1. 先在 http 块定义漏桶规则
限流状态需要共享内存存储,必须放在 http 级别:
-
$binary_remote_addr是最常用 key,按客户端 IP 统计,内存更省 -
zone=api_limit:10m表示开一块 10MB 内存,约能存 16 万个 IP 的计数状态 -
rate=5r/s是漏出速率:每秒最多处理 5 个请求,即平均 200ms 放行一个
示例配置:
http {limit_req_zone $binary_remote_addr zone=api_limit:10m rate=5r/s;
}
2. 在 location 中调用并设置平滑参数
仅写 limit_req zone=api_limit; 会导致突发请求被大量拒绝——因为漏桶默认严格排队,不缓存也不加速。要真正“平滑”,需补充两个参数:
-
burst=20:开一个容量为 20 的 FIFO 缓冲队列,把暂时无法立即漏出的请求暂存起来 -
nodelay:让进入缓冲队列的请求“不等待漏出时间”,只要入队就立刻执行(但受rate控制总节奏)
这样,即使瞬间来 25 个请求,前 5 个按 200ms 间隔执行,后 20 个进队即执行(无额外延迟),整体节奏仍被压在 5r/s 平均线上,不会打满后端。
location /api/v1/submit {limit_req zone=api_limit burst=20 nodelay;
proxy_pass http://backend;
}
3. 可选但建议加上的优化项
提升可观测性和业务友好度:
-
limit_req_status 429;:把默认的 503 拒绝响应改成标准限流码 429,前端更容易识别 -
limit_req_log_level warn;:将触发限流的日志级别降为warn,避免刷屏 error 日志 - 若需区分用户身份(如登录态),可用
$cookie_uid或$http_x_user_id替代$binary_remote_addr作为 key
4. 验证是否生效
用简单压测快速验证逻辑:
- 并发 10 个请求打
/api/v1/submit:应全部成功,响应时间集中在 0–200ms 区间 - 并发 30 个请求:前 25 个大概率成功(5 + burst=20),第 26 起开始返回 429
- 持续每秒发 6 个请求:长期运行后,约 1/6 的请求会触发 429,符合 5r/s 设定
注意:漏桶是“平均速率”控制,不是硬性窗口计数,所以短时小幅超发是允许的,这也是它比计数器更平滑的原因。

















