nginx的limit_req模块加delay参数后启用“带缓冲区的漏桶”,允许burst内前delay个超限请求被匀速延迟放行而非直接503,delay值表示可延迟处理的最大请求数,需配合burst>0和合理rate使用。

nginx 的 limit_req 模块默认采用“漏桶”限流,当请求超过速率时直接拒绝(503),这对用户体验不友好。而 delay 参数(配合 burst)能将突发请求暂存并匀速释放,实现更平滑的流量缓冲——本质是启用“带缓冲区的漏桶”,让超限请求排队等待而非立即失败。
delay 参数如何改变限流行为
不加 delay 时:limit_req zone=foo burst=10 nodelay 表示最多允许 10 个请求瞬时进入队列,超出即 503;加 delay 后:limit_req zone=foo burst=10 delay=5 表示:前 5 个超限请求会被延迟执行(按 leak rate 匀速放出),其余 5 个才可能被拒绝。
关键点:delay 后的数值不是延迟毫秒数,而是“允许延迟处理的最大请求数”。nginx 会计算每个请求应等待的时间(基于当前队列长度和 rate),自动注入 X-RateLimit-Delay 响应头(需开启 limit_req_status 或自定义日志确认)。
配置中必须配合的参数
-
必须设置
burst:delay 只在 burst > 0 时生效;若 burst=0,delay 无意义 -
推荐显式写
nodelay控制边界:例如burst=20 delay=10表示最多缓存 20 个,但只对其中前 10 个做延迟放行,后 10 个仍直接 503;若希望全部 20 个都尝试延迟,则写burst=20 delay=20 -
rate 要合理:delay 效果依赖于 rate 值。rate 过小会导致排队时间过长(用户感知卡顿),rate 过大则缓冲形同虚设。建议从业务平均响应时间反推:如接口平均耗时 100ms,rate 可设为
10r/s(即 100ms/req)
实际效果与调试建议
启用 delay 后,客户端会观察到部分请求响应时间明显增加(比如从 20ms 升至 300ms),但不再出现突兀的 503。可通过以下方式验证:
- 用
ab -n 100 -c 50压测,对比有无 delay 时的失败率和 P95 延迟 - 在 log_format 中加入
$limit和$limit_rate变量,查看哪些请求被延迟、延迟了多久 - 注意:delay 不影响请求计费逻辑,所有进入 burst 队列的请求都会被计入 limit_req zone 的统计
替代思路:结合 limit_conn 更精细控流
单纯靠 delay 缓冲无法解决慢请求堆积问题(例如一个请求卡住 5 秒,会阻塞后续所有延迟请求)。此时可叠加 limit_conn 限制并发连接数,避免单个慢请求拖垮整条队列。例如:
limit_conn_zone $binary_remote_addr zone=addr:10m;
limit_req zone=api burst=30 delay=15;
limit_conn addr 20;
这样既用 delay 平滑短时脉冲,又用 limit_conn 防止单 IP 占满 worker 连接资源。










