nginx/HTTP 限流模块

用漏桶状态约束请求速率

limit_req 把漏桶计算、红黑树查状态与队列回收组合起来,按配置的 key 管理请求速率。

release-1.26.3通信与流量核验 2026-10-08
相关概念

工程问题#

需要允许有限突发,又要限制持续请求速率;多 worker 还要共享同一个客户端或业务 key 的计数状态。

实际实现#

共享内存节点记录 excess 和 last;到达时按流逝时间减少 excess,再计入新请求。红黑树定位 key,队列帮助清理旧状态。

处理流程#

  1. 计算 key 并查找共享状态
  2. 按时间衰减超额请求数
  3. 对照 burst 与 delay 决定处理
  4. 更新状态并维护回收顺序

源码片段#

固定版本 · 原文摘录
src/http/modules/ngx_http_limit_req_module.crelease-1.26.3 · L454–L473
查看原文件
454            excess = lr->excess - ctx->rate * ms / 1000 + 1000;455456            if (excess < 0) {457                excess = 0;458            }459460            *ep = excess;461462            if ((ngx_uint_t) excess > limit->burst) {463                return NGX_BUSY;464            }465466            if (account) {467                lr->excess = excess;468469                if (ms) {470                    lr->last = now;471                }472473                return NGX_OK;
ngx_http_limit_req_lookup

excess 随时间按 rate 衰减,并以 1000 为一个请求的定点单位计入本次请求;超过 burst 时返回 NGX_BUSY,允许记账时更新 excess 和 last。速率计算与最终延迟、拒绝、日志响应分别发生在不同环节。

来自已找到现有 key 的分支;共享锁、时间差异常修正、红黑树查找和队列维护在上下文,不是每个请求都进入实体 FIFO。

收益与取舍#

工程分析

带来的收益

  • 状态量无需保存每个历史请求
  • 突发容量与延迟策略可以分别配置

付出的代价

  • 工程分析:共享锁可能成为热点
  • 状态存储有限,粒度由 key 的选择决定

可比较的选择

滑动窗口日志能保留请求的精确时间分布,但每个 key 需要更多存储。

版本与适用范围#

对应 limit_req;是否延迟由配置决定,nodelay 等设置会改变行为,不能把所有请求理解为进入实体 FIFO。

参考来源#

源码、官方文档与原始论文
01
nginx · ngx_http_limit_req_lookup / ngx_http_limit_req_account

src/http/modules/ngx_http_limit_req_module.c · ngx_http_limit_req_lookup / ngx_http_limit_req_account

源码release-1.26.3

相关实现与比较#

4 个相关案例
8 个匹配案例