nginx 限流需先用 limit_req_zone 在 http 块定义共享内存区域(如 zone=ip_limit:10m rate=5r/s),再在 location 中用 limit_req 引用并配置 burst 和 nodelay;注意代理环境应改用 $http_x_forwarded_for 并设置 real_ip。

在 Nginx 中使用 limit_req 限制单个 IP 的请求速率,核心是先定义一个限流区域(zone),再在 server 或 location 块中引用它。关键在于理解 limit_req_zone 和 limit_req 指令的配合逻辑,以及如何避免常见误配置(比如漏掉 burst 导致正常请求被拒)。
定义限流区域(limit_req_zone)
在 http 块中声明共享内存区域,指定依据、大小和速率:
http {
limit_req_zone $binary_remote_addr zone=ip_limit:10m rate=5r/s;
}
-
$binary_remote_addr:用二进制格式存储客户端 IP,比$remote_addr更省内存 -
zone=ip_limit:10m:名为ip_limit的共享内存区,大小 10MB(通常够存约 16 万个 IP) -
rate=5r/s:平均限速为每秒 5 个请求(支持r/m,如30r/m)
在 location 或 server 中启用限流(limit_req)
在需要限流的位置块中调用已定义的 zone:
server {
location /api/ {
limit_req zone=ip_limit burst=10 nodelay;
proxy_pass http://backend;
}
}
-
burst=10:允许突发最多 10 个请求(超出 rate 的部分暂存队列) -
nodelay:不延迟处理 burst 内的请求(立即通过,但会触发“拒绝后续请求”逻辑) - 不加
nodelay时,burst 内请求会被匀速释放(比如 rate=5r/s,burst=10,则最多延后 2 秒发完)
应对真实场景的常用组合
-
防爬虫但放行登录接口:对
/api/限流,但排除/api/login(用单独 location +limit_req off) -
分级限流:为未登录用户设低速(
2r/s),登录用户用 cookie 标识设高速(20r/s) -
返回友好提示:配合
error_page 429返回 JSON 错误页,避免暴露 Nginx 默认 503 -
日志标记限流行为:用
$limit变量(需编译时含--with-http_realip_module)或自定义 log_format 记录是否触发限流
验证与调试技巧
- 用
ab -n 100 -c 20 http://yourdomain/api/test快速压测,观察响应状态码(429 表示触发限流) - 检查 Nginx error log,限流会记录类似
limiting requests, excess: 5.000 by zone "ip_limit" - 注意代理环境:如果前端有 CDN 或负载均衡,
$binary_remote_addr可能是代理 IP,此时应改用$http_x_forwarded_for并配合set_real_ip_from











