必须分两步:先在http块用limit_req_zone定义限流规则(如$binary_remote_addr zone=ip_limit:10m rate=5r/s),再在server或location中用limit_req启用;缺一不可,且limit_req_zone仅允许出现在http块。

直接生效的配置必须分两步:先在 http 块定义限流规则,再在 server 或 location 中启用。漏掉任意一步,limit_req 都不会起作用。
limit_req_zone 必须写在 http 块里,否则启动报错
这个指令只允许出现在 http 上下文,写到 server 或 location 里会触发 Nginx 启动失败,错误信息是:"limit_req_zone" directive is not allowed here。
-
$binary_remote_addr比$remote_addr更可靠——前者长度固定(IPv4 是 4 字节,IPv6 是 16 字节),哈希稳定、内存占用小;后者是字符串,长度不一,容易引发哈希冲突或内存浪费 -
zone=ip_limit:10m中的ip_limit必须全局唯一;重复定义同名 zone 会导致 Nginx 拒绝加载配置 -
rate值不能带变量,比如rate=$my_rate是非法的,只能写死为1r/s、30r/m这类静态值
limit_req 的 burst 和 nodelay 参数决定行为差异
同一套 limit_req_zone 规则,配上不同参数,实际效果天差地别:
-
burst=5表示允许最多积压 5 个请求进“桶”,超出部分才被拒绝;不写默认为 0,即严格按速率卡死 -
nodelay表示不排队、不延迟,超速请求立刻返回503 Service Temporarily Unavailable;没加它时,Nginx 会尝试把 burst 内的请求匀速放出(可能造成客户端感知延迟) - 如果既要突发容忍、又要避免延迟堆积,常见组合是
burst=10 nodelay;但注意:这会让所有超限请求立即失败,不适合对用户体验敏感的接口
验证限流是否真在工作,别只看配置 reload 成功
reload 后必须实测 + 查日志,否则很容易误以为生效了:
- 用
curl -I或压测工具(如ab -n 20 -c 10 http://your.site/)快速发一批请求,观察响应状态码是否出现503 - 实时盯住错误日志:
tail -f /var/log/nginx/error.log,真正触发限流时会出现类似limiting requests, excess: 3.123 by zone "ip_limit"或rejected字样 - 注意:如果前端有 CDN、负载均衡或代理(如 Cloudflare),
$binary_remote_addr拿到的可能是代理 IP,此时要配合$http_x_forwarded_for或真实 IP 头做调整,否则限流对象错位
最常被忽略的一点:共享内存区域大小(如 10m)不是随便写的。1MB 约存 16000 个客户端状态,如果你的 rate 设得极细(比如 0.1r/s),又面向海量用户,10m 很快就撑爆,导致新 IP 无法被记录——这时限流反而失效,得按实际并发量预估 zone 容量。











