要让 limit_req_zone 在百万级并发场景下稳定运行,关键是精准控制每个客户端内存开销并确保共享内存容纳活跃IP状态;Nginx通过毫秒级令牌桶+共享内存管理真实请求频率,10MB zone约支持8万个活跃IPv4 IP,256MB zone可支撑50万+活跃IP,需结合分层建模、合理key设计与实时监控。

要让 limit_req_zone 在百万级并发场景下稳定运行,关键不是盲目扩大内存,而是精准控制每个客户端占用的内存开销,并确保共享内存区域能容纳活跃 IP 的状态数据。Nginx 本身不直接处理“百万并发请求”,而是通过毫秒级令牌桶 + 共享内存状态管理,实现对海量连接中真实请求频率的高效约束。
理解 limit_req_zone 的内存占用模型
每个客户端 IP(以 $binary_remote_addr 为例)在 zone 中对应一个 state 结构体:
- IPv4 地址固定占 4 字节,IPv6 占 16 字节;
- state 本身在 64 位系统上占 128 字节(含计数器、时间戳、锁等);
- 1MB zone 约可存储 8000 个 IPv4 客户端状态(1048576 ÷ 128 ≈ 8192);
- 因此 10MB zone ≈ 支持约 8 万个活跃 IP 的限流状态。
注意:zone 存储的是“最近访问过且尚未过期”的客户端状态,不是所有历史 IP。Nginx 会自动淘汰最久未用的 state,但若活跃 IP 数远超 zone 容量,会导致频繁驱逐和重建,增加 CPU 开销并削弱限流精度。
面向百万并发的 zone 规划策略
百万并发 ≠ 百万活跃限流 IP。实际生产中需按业务特征分层建模:
- 区分冷热流量:核心接口(如登录、下单)IP 活跃度高,可单独配 zone;静态资源、开放 API 可共用轻量 zone 或不启用;
-
按地域/代理聚合:对使用 CDN 或 NAT 网关的用户,改用
$http_x_forwarded_for需谨慎,推荐结合geo+map对可信 CDN IP 段跳过限流,或按$server_name或$host做虚拟主机维度限速; - 合理设置 zone 大小:若预估峰值有 20 万真实客户端 IP 需限流,建议 zone ≥ 256MB(200000 × 128B ≈ 25.6MB,再乘以 10 倍冗余),避免抖动;
-
避免 key 过宽:不用
$request或长 cookie 值作 key,防止单个客户端生成多个 state,快速耗尽内存。
高性能配置示例(支撑 50 万+ 活跃 IP)
以下配置兼顾内存效率与限流弹性:
http {
# 主限流区:按二进制 IP,支持约 50 万活跃客户端
limit_req_zone $binary_remote_addr zone=api_limit:256m rate=10r/s;
<pre class="brush:php;toolbar:false;"># 补充区:针对高频爬虫特征(如无 UA、固定 header)
map $http_user_agent $is_bot {
~*(?i)python-requests|curl|httpie 1;
default 0;
}
limit_req_zone $binary_remote_addr$is_bot zone=bot_limit:64m rate=2r/s;
server {
location /api/ {
# 正常用户走主区,突发允许 30 请求缓冲
limit_req zone=api_limit burst=30 nodelay;
# 疑似爬虫额外叠加更严限制
limit_req zone=bot_limit burst=5;
}
}}
说明:256MB zone 在 64 位系统下理论支持约 200 万个 state(256×1024² ÷ 128 ≈ 2,097,152),远超 50 万需求,留出充足空间应对 IP 快速轮换或扫描探测。
必须配合的运维保障措施
光靠配置不够,还需实时监控与响应:
- 开启
stub_status,定期采集ngx_http_limit_req_module的 rejected、delayed 计数; - 用
limit_req_status 429替代默认 503,便于前端识别限流并退避; - 设置
limit_req_log_level warn,当拒绝率持续 > 1% 时触发告警; - 滚动重启前执行
nginx -t && nginx -s reload,避免 reload 导致 zone 状态重置引发瞬时放行。
真正支撑百万并发的不是单点参数调大,而是把限流变成可观测、可分级、可灰度的基础设施能力。










