实现单IP连接数压制需协同配置worker_connections与limit_conn:前者设worker进程级总连接上限,后者基于$binary_remote_addr在HTTP层限制每IP并发连接数,二者分属不同层级且须合理配比。

要实现单 IP 连接数压制,核心是 worker_connections 与 limit_conn 协同作用:前者限制每个 worker 进程能处理的总连接数,后者在 HTTP 层按 key(如 $binary_remote_addr)精确限制并发连接数。二者不在同一层级,不能互相替代,但必须合理配比,否则会出现“限流失效”或“过早拒绝连接”。
理解两者的分工和作用层级
worker_connections 是全局资源上限,属于事件驱动层(epoll/kqueue),决定一个 worker 能同时管理多少 socket 句柄(含空闲、活跃、等待关闭等状态)。它不区分客户端,只看系统级连接总数。
limit_conn 是 HTTP 模块功能,在请求进入 server 或 location 阶段时触发,基于变量(如 $binary_remote_addr)做内存哈希计数,对同一 key 的并发请求数做硬限制。它不消耗 worker_connections,但所有被 limit_conn 允许的连接最终都要占用 worker_connections。
简单说:worker_connections 是“总闸门”,limit_conn 是“分户水表”。总闸门太小,分户再细也没用;分户不限制,总闸门再大也会被单个恶意 IP 耗尽。
配置 limit_conn 实现单 IP 压制
在 http、server 或 location 块中定义共享内存区并启用限制:
- 先声明共享内存 zone,例如:limit_conn_zone $binary_remote_addr zone=perip:10m; —— 10MB 内存约可存储 16 万 IP 记录,$binary_remote_addr 比 $remote_addr 更省空间且兼容 IPv4/IPv6
- 在需要限流的位置应用:limit_conn perip 10; 表示每个 IP 最多保持 10 个并发连接(注意:是并发连接数,不是请求数)
- 建议搭配 limit_conn_log_level warn; 和 limit_conn_status 503;,便于日志追踪和前端识别
worker_connections 数值设定要点
该值需满足:worker_connections ≥ (预期峰值并发连接数 ÷ worker_processes)+ 安全余量
- 若使用 worker_processes auto;,实际 worker 数等于 CPU 核心数,此时每个 worker 的 connections 应至少为单 IP 限值 × 预估最大活跃 IP 数 + 系统连接(如 upstream、health check)
- 例如:服务器有 4 核,设 limit_conn perip 20,预计最多 500 个不同 IP 同时访问,则建议 worker_connections 3000;(20×500 = 1000,再翻 2–3 倍留余量)
- 务必检查系统级限制:ulimit -n 和 /proc/sys/fs/file-max,确保 nginx 启动用户能打开足够文件描述符
验证与常见陷阱
配置后需实测验证效果,而非仅看语法正确:
- 用 ab 或 wrk 模拟单 IP 多并发(如 wrk -t1 -c 50 -d10s http://your.site/),观察是否在第 11 个连接开始返回 503
- 注意:HTTPS 场景下,如果启用了 keepalive,一个 TLS 连接可能承载多个 HTTP 请求,limit_conn 限制的是连接数,不是请求频次;如需限制请求速率,应叠加 limit_req
- IPv6 地址需确保 $binary_remote_addr 正确截取(Nginx 1.11.0+ 默认支持),旧版本可能需用 $remote_addr 导致哈希冲突
- 代理环境(如 CDN、LB)下,$binary_remote_addr 可能是上一跳地址,此时应改用可信 header(如 X-Real-IP)并配合 set_real_ip_from 设置可信网段

















