burst是超额请求的信用额度而非队列长度,单位为等效请求(1请求=1000单位),其值与rate共同决定突发容忍窗口(≈burst/rate秒),nodelay仅改变调度策略而不消除缓冲区,过大burst会导致精度下降和上游并发压力。

burst 参数不是队列长度,而是“超额请求容量”
很多人误以为 burst=20 表示能排队 20 个请求——其实它定义的是「允许累积的超额请求数」,单位是「等效请求」,不是真实并发数。Nginx 内部用 excess 变量动态跟踪当前超出速率的“信用额度”,这个值会随时间衰减(按 rate 比例释放),而 burst 是它的硬上限。
常见错误现象:burst=5 却发现第 6 个请求没被限,第 11 个才 503 ——这是因为前 5 个请求之间间隔大于令牌填充周期,excess 已部分归零。
-
excess初始为 0,每次请求到来时:先按时间差扣减已有的 excess(模拟“漏”),再加 1000(即 1 个请求的“信用”) - 判断是否超限:仅当
excess > limit->burst * 1000才返回NGX_BUSY(503) - 所以
burst=1实际对应 1000 单位,burst=10对应 10000 单位
burst 和 rate 共同决定突发容忍窗口大小
真正决定你能扛住多大“脉冲”的,是 burst / rate 的比值,它近似等于缓冲区可撑住的**最大空闲等待时间(秒)**。比如 rate=10r/s、burst=30,理论缓冲窗口 ≈ 3 秒 —— 这意味着:只要这 30 个请求在 3 秒内打进来,它们都能进缓冲区;超过 3 秒,就可能因 excess 衰减而提前触发限流。
使用场景:秒杀预热阶段用户频繁刷新,你希望允许短时密集点击但不压垮后端,这时设 burst=50 + rate=5r/s(10 秒缓冲窗),比单纯提高 rate 更安全。
- rate 太小 + burst 太大 → 缓冲区长期积压,请求延迟不可控
- rate 太大 + burst=0 → 回退成严格漏桶,拒绝所有微小抖动
- 典型搭配:
rate=20r/s+burst=40(2 秒突发容错)
nodelay 不跳过排队,而是跳过等待
加了 nodelay 并不会让 burst 缓冲区消失,它只是把本该阻塞等待的请求,改为立即通过(但依然会计入 excess)。也就是说:burst 定义容量,nodelay 改变调度策略。
容易踩的坑:在日志里看到大量 200 却仍触发后端超时 —— 很可能是开了 nodelay 后,burst 区内的请求被瞬间打到上游,相当于把“延迟压力”转嫁成了“并发压力”。
- 不加
nodelay:超速请求在 Nginx 内排队,按固定节奏放行(Traffic Shaping) - 加
nodelay:超速请求立刻转发,但后续请求若导致excess > burst,仍会 503(Traffic Policing 倾向) - 生产环境慎用
nodelay,除非你确认上游能扛住 burst 内的瞬时并发
burst 值不是越大越好,内存和精度损耗要算清
burst 值最终影响的是 excess 变量的取值范围,而该变量在源码中是 ngx_msec_int_t 类型(有符号整型)。虽然日常配置 burst=1000 不会溢出,但要注意:Nginx 每次计算都涉及毫秒级时间差与 rate 的乘除,burst 越大,excess 累积误差越明显,可能导致限流边界漂移。
更实际的限制来自共享内存:每个客户端 IP 在 limit_req_zone 中只占约 64 字节,但 burst 本身不额外占空间;真正吃内存的是 zone 大小(如 10m)和 key 粒度($binary_remote_addr vs $uri)。
- 不要为“保险起见”盲目设
burst=10000,测试表明burst>200后对大多数 Web API 的突发吸收收益急剧下降 - 若需更大缓冲,优先考虑业务层队列(如 Redis List + worker 消费),而非在 Nginx 层堆 burst
- 调试时用
log_format记录$limit和$limit_rate变量,比猜更可靠
物理意义最易被忽略的一点:burst 不是时间或请求数的绝对刻度,它是 Nginx 在毫秒级精度下维护的一个动态“信用余额”。它的行为更接近水桶里不断蒸发又缓慢注水的液体,而不是一个静态队列。











