limit_conn 通过定义共享内存区、指定限流键(推荐$binary_remote_addr)、在server或location中启用三步实现单ip并发连接限制,统计established连接数,适用于下载及长连接场景。

直接用 limit_conn 限制单个 IP 并发连接数,核心就三步:定义共享内存区域、指定限流键、在目标位置启用限制。它统计的是当前 ESTABLISHED 的 TCP 连接数,不是请求数,对下载、长接口、HTTP/2 场景更贴合。
在 http 块中定义连接统计区域
必须放在 http{} 最外层,不能写在 server 或 location 内:
- 推荐用
$binary_remote_addr作键:IPv4 固定 4 字节,IPv6 固定 16 字节,比$remote_addr更省内存、抗哈希冲突 -
zone=perip:10m表示创建名为perip的共享内存区,大小 10MB,约可存 16 万个独立 IP 的连接状态 - 若出现
limit_conn: cannot add connection错误,说明内存不够,可调大 size(如20m)
在 server 或 location 中启用限制
引用上面定义的 zone 名,并设每个 IP 允许的最大并发连接数:
- 放在
server块:整台虚拟主机生效,适合全局防护 - 放在
location /api/download/这类路径下:只限制该接口,不影响静态资源或轻量 API - 数值建议设 3~10:太小(如 1)易误伤正常多标签页用户;太大(如 50)起不到防护作用
- 超出立即返回 503(可改用
limit_conn_status 429便于前端识别)
代理环境下必须还原真实 IP
如果 Nginx 前有 CDN、SLB 或反向代理,$binary_remote_addr 默认是上一跳地址,会导致所有请求被当成同一个 IP 限流或完全失效:
- 确保已加载
http_realip_module - 配置可信上游:
set_real_ip_from 192.168.1.0/24;(替换成你的真实代理网段) - 指定头字段:
real_ip_header X-Forwarded-For;,并开启递归解析:real_ip_recursive on; - 之后改用
$realip_remote_addr定义 zone,或确保$remote_addr已被正确覆盖
搭配使用效果更稳
limit_conn 是连接层防御,单独用可能不够:
- 加
limit_rate 200k;控制单连接带宽,防止单个连接拖慢整体 - 加
limit_req zone=req_per_ip burst=10 nodelay;防高频短连接刷小文件 - 设
limit_conn_log_level error;避免日志刷屏,只在真超限时记 error 级别 - 配合
proxy_read_timeout 30;和后端熔断,避免慢响应卡死连接池











