nginx 用 limit_conn_zone 限制单个 ip 并发连接数,需先在 http 块定义共享内存区域(如 zone=perip:10m),再在 server 或 location 中用 limit_conn perip n 启用;它统计当前活跃 tcp 连接(含 keepalive、http/2 多路复用),非请求数;代理环境下需配合 real_ip_module 使用 $realip_remote_addr 确保真实 ip 识别。

Nginx 用 limit_conn_zone 限制单个 IP 并发连接数,核心是两步:先在 http 块中定义共享内存区域记录 IP 连接状态,再在 server 或 location 中用 limit_conn 启用该限制。它统计的是当前活跃的 TCP 连接(含 keepalive、HTTP/2 多路复用),不是请求数。
必须在 http 块中定义共享内存区域
这是前提,不能写在 server 或 location 里:
http {
limit_conn_zone $binary_remote_addr zone=perip:10m;
}
-
$binary_remote_addr是客户端 IP 的二进制格式,比$remote_addr更省内存(IPv4 固定 4 字节,IPv6 固定 16 字节) -
zone=perip:10m表示创建名为perip的共享内存区,大小 10MB;约可存储 16 万~32 万个独立 IP 的连接计数 - 内存不足时,Nginx 日志会报
limit_conn: cannot add connection,此时需增大 size(如20m)
在 server 或 location 中启用限制
引用上面定义的 zone 名,并设定每个 IP 最大并发数:
server {
limit_conn perip 10;
}
或只对 API 路径限制:
location /api/ {
limit_conn perip 5;
}
-
perip必须与limit_conn_zone中的 zone 名完全一致 -
10表示该作用域下,每个 IP 最多维持 10 个同时打开的 TCP 连接 - 若
server和location都配置了limit_conn,以数值更小的那个为准
代理环境要识别真实 IP
如果 Nginx 前有 CDN、SLB 或 WAF,$binary_remote_addr 默认是代理节点 IP,需配合 real_ip_module:
- 确保已加载
http_realip_module - 配置
set_real_ip_from指定可信上游地址段 - 使用
$realip_remote_addr作为 key(推荐),或从$http_x_forwarded_for提取第一个非空 IP 并去空格
建议补充实用配置
-
limit_conn_log_level error;—— 把超限日志设为 error 级,避免刷屏 -
limit_conn_status 429;—— 返回429 Too Many Requests,语义更明确 -
limit_rate 200k;—— 对已放行的连接限速,防止单连接持续占带宽 -
keepalive_timeout 15;—— 及时释放空闲长连接,避免无效占用配额











