Nginx通过limit_conn_zone基于变量(如$binary_remote_addr)创建共享内存区以全局统计并发连接数,再由limit_conn指令引用该zone实现每IP最多10个TCP连接的限制,适用于防爬等场景。

通过 limit_conn_zone 指令,Nginx 可以基于指定变量(如客户端 IP)定义一个共享内存区域,用于在 worker 进程间**全局共享连接计数状态**,从而实现真正意义上的并发连接数限制。
核心原理:共享内存 + 变量键值映射
limit_conn_zone 不是直接限流,而是创建一块所有 worker 进程都能读写的共享内存(shared memory zone),把每个唯一变量值(比如 $binary_remote_addr)作为 key,记录其当前活跃连接数。后续用 limit_conn 指令引用该 zone 才真正触发检查和拒绝逻辑。
- zone 名称必须全局唯一,且需指定大小(如
10m),过小会导致哈希冲突或无法新增 key - 推荐用
$binary_remote_addr替代$remote_addr,节省内存(4 字节 vs 字符串长度) - 不支持复合变量(如
$server_name:$binary_remote_addr),但可通过 map 模块间接构造
基本配置示例(按 IP 限并发)
以下配置限制**每个客户端 IP 最多 10 个并发 TCP 连接**(非请求数),适用于防爬、防连接耗尽等场景:
http {
limit_conn_zone $binary_remote_addr zone=conn_per_ip:10m;
server {
location /api/ {
limit_conn conn_per_ip 10;
proxy_pass http://backend;
}
}
}
注意:limit_conn 必须放在具体作用域(server / location),且仅对新建立的连接生效;已建立连接不会被中断,但新连接会返回 503 Service Temporarily Unavailable。
常见误区与关键细节
很多人误以为 limit_conn_zone 自动生效,或混淆连接数与请求数。实际使用中需注意:
- HTTP/2 或 WebSocket 场景下,单个连接可复用,
limit_conn限制的是底层 TCP 连接数,不是请求频次 - 若后端是长连接代理(如 keepalive),需配合
proxy_http_version 1.1和proxy_set_header Connection ''避免干扰 - 无 SSL 时,
$binary_remote_addr是真实客户端 IP;有前置 LB 时,需先用real_ip模块还原,再基于还原后的地址建 zone - 可通过
stub_status模块或 Prometheus exporter(如 nginx-lua-prometheus)监控 zone 使用率与拒绝数
扩展:按 server_name 或自定义维度限连
若需按域名、URI 前缀或用户标识限连,可用 map 构造复合键:
map $host:$binary_remote_addr $conn_key {
default $host:$binary_remote_addr;
}
limit_conn_zone $conn_key zone=conn_per_host_ip:10m;
这样就能实现“每个域名下每个 IP 最多 N 连接”。注意 map 的 key 长度会影响 zone 内存占用,建议控制总长(如截取前 64 字符)。










