nginx中limit_conn生效需先配置http块内的limit_conn_zone,key推荐$binary_remote_addr,再在server或location中调用;同时须调大systemd的LimitNOFILE并重载,且代理场景需配合set_real_ip_from获取真实IP。
nginx 里怎么配 limit_conn 才真正生效
配了 limit_conn 却没拦住请求?大概率是漏写了 limit_conn_zone,或者 zone 的 key 选错了。这个指令本身不生效,它只是“调用规则”,真正管用的是前面定义的共享内存 zone。
-
limit_conn_zone必须写在http块里,不能放在server或location里 - key 要慎选:
$binary_remote_addr按客户端 IP 限流最常用;用$server_name是按域名限,$uri按路径限——但后者容易被绕过(比如加随机 query) - zone 大小别太小:
10m最多存约 16 万个 IP(IPv4),高并发站点建议20m起 - 实际生效靠
limit_conn放在server或location块里,例如:limit_conn addr 10;
表示每个 IP 最多 10 个并发连接
Linux 系统级限制:ulimit 和 systemd service 配置冲突怎么办
用户进程连不上、报 Too many open files,光改 nginx 配置没用——系统级文件描述符上限卡死了。nginx worker 进程能打开多少连接,受制于它启动时继承的 ulimit -n 值。
- 查当前值:
ulimit -n(对 shell 会话有效),但 nginx 通常由 systemd 启动,得看 service 文件里的配置 - systemd 服务要显式设:
LimitNOFILE=65536,否则默认可能只有 1024 - 改完必须重载 systemd 配置:
sudo systemctl daemon-reload,再重启 nginx,restart不等于重载配置 - 注意:如果 nginx 是用 root 启动再 drop 权限(如用
user www-data),LimitNOFILE仍需在 service 文件里配,普通用户无法突破这个限制
为什么 limit_conn 对 HTTPS 或代理场景经常失效
因为真实客户端 IP 被代理遮住了,$binary_remote_addr 变成上游代理地址(比如 127.0.0.1),所有请求都算同一个 IP,限流就崩了。
- 先确认是否用了反向代理:检查
X-Forwarded-For或X-Real-IP头有没有传过来 - 在
http块加:set_real_ip_from 10.0.0.0/8;<br>real_ip_header X-Forwarded-For;
(根据你代理网段调整set_real_ip_from) - 然后把
limit_conn_zone的 key 改成$remote_addr(此时它已被real_ip_header替换为真实 IP) - 不推荐直接用
$http_x_forwarded_for当 key——它可能被客户端伪造,且格式不固定(含多个 IP 逗号分隔)
并发连接数和请求数不是一回事:别把 limit_req 当 limit_conn 用
想限制“同时建立的 TCP 连接数”,必须用 limit_conn;用 limit_req 只能控“单位时间内的请求数”(QPS),连接可以复用、长连接不断开,QPS 低但连接数照样爆表。
-
limit_conn数的是 TCP 连接(即ESTABLISHED状态),适用于防慢连接攻击、爬虫建大量空闲连接 -
limit_req数的是 HTTP 请求,依赖limit_req_zone,适合防刷接口,但对 keepalive 连接无效——一个连接发 100 个请求,只算 1 个连接 - 两者可共存,但 zone 名不能重复,且
limit_conn优先级更高:连接数超了,请求根本进不到limit_req那步
真正卡住并发上限的,往往是系统级 ulimit 和 nginx 的 worker_connections 配合问题——前者决定单进程最多开多少 socket,后者决定 nginx 总共能管多少连接。这两个值不一致,再细的 limit_conn 规则也形同虚设。

















