ngx_http_limit_conn_module精准连接控制
一、引言
在高并发场景下,客户端可能会发起大量并发连接,导致后端服务资源耗尽、响应变慢甚至宕机。
NGINX 自带的 ngx_http_limit_conn_module
模块可以针对任意“键”(最常见的是客户端 IP)限制并发连接数,让你以最低成本保护后端服务。
本文将以零基础、一步步的方式,讲解如何安装、配置、测试并进阶使用此模块。
二、先决条件
-
NGINX 已编译或安装了
ngx_http_limit_conn_module
-
开源版从 v0.8.4 起即包含该模块;
-
验证命令:
nginx -V 2>&1 | grep --color limit_conn
如输出含
--with-http_limit_conn_module
或limit_conn
,说明模块已启用。
-
-
Linux 环境(如 Ubuntu/CentOS),具备
sudo
或root
权限。 -
测试工具(可选):
ab
(ApacheBench):sudo apt install apache2-utils
h2load
(HTTP/2 测试):可选安装
三、核心指令概览
指令 | 功能 | |
---|---|---|
limit_conn_zone key zone=name:size; | 在共享内存中为指定 key 创建 “连接计数区”,size 建议用 m (兆) | |
limit_conn zone number; | 针对前面定义的 zone ,限制最大并发连接数 | |
`limit_conn_dry_run on | off;` | 干跑模式:只记录超额次数,不实际拒绝请求 |
limit_conn_log_level level; | 设置超额时的日志级别:info 、notice 、warn 、error | |
limit_conn_status code; | 自定义超额时的 HTTP 返回码,默认 503 | |
嵌入变量 $limit_conn_status | 保存本次连接检查结果:PASSED 、REJECTED 、REJECTED_DRY_RUN |
四、基础配置与测试
4.1 在 http
块中定义 Zone
编辑 NGINX 主配置文件(通常为 /etc/nginx/nginx.conf
),在 http { ... }
内新增:
# 以客户端 IP 作为键,分配 10MB 共享内存存储状态
limit_conn_zone $binary_remote_addr zone=addr:10m;
说明:
- 推荐使用
$binary_remote_addr
而非$remote_addr
,它占用固定 4 字节,更高效。- 1MB 大约支持 16K~32K 条不同键记录。
4.2 在 server
或 location
中生效
在同一配置文件中,找到对应的 server
段,添加:
server {listen 80;server_name example.com;# 对 /download/ 路径,每个 IP 同时只允许 1 个连接location /download/ {limit_conn addr 1;limit_conn_log_level notice;limit_conn_status 429;}# 其他 location…
}
limit_conn addr 1;
:每个 IP 同时最多 1 个并发。limit_conn_log_level notice;
:写入 notice 级别日志,便于排查。limit_conn_status 429;
:返回 HTTP 429 (Too Many Requests) 而非默认 503。
4.3 检查并重载配置
sudo nginx -t
# 若语法无误:
sudo systemctl reload nginx
nginx -t
用于检测语法错误;reload
平滑生效,无需中断现有连接。
4.4 使用 ApacheBench 验证
# 模拟 5 个并发,一共 10 个请求
ab -n 10 -c 5 http://example.com/download/
- 若限制为 1,则只有 1 个请求成功(返回 200),其余 4 个返回 429。
- 可在 access.log 中查看返回码分布。
4.5 查看错误日志
sudo tail -f /var/log/nginx/error.log
会看到类似:
2025/05/12 10:00:00 [notice] 1234#0: *56 limiting connections by zone "addr"
五、进阶场景案例
5.1 双重限制:IP + 全局连接
需求:每个 IP 最多 10 个连接,同时整个虚拟主机总连接不超过 200。
http {limit_conn_zone $binary_remote_addr zone=perip:10m;limit_conn_zone $server_name zone=perserver:10m;
}server {listen 80;server_name app.example.com;limit_conn perip 10;limit_conn perserver 200;
}
- 若单个 IP 发起过多连接或整体并发过高,均会触发限流。
5.2 干跑模式(Dry Run)
需求:验证限流策略对线上业务的影响,但不真正拒绝请求。
location /api/ {limit_conn addr 2;limit_conn_dry_run on;
}
- 开启
dry_run
后:所有请求均被允许,但超额次数会记录到共享内存,并在日志中有输出。
5.3 HTTP/2 并发流控制
NGINX 将 HTTP/2 的每条并发流视作独立“连接”来计数。
只需在 listen
中启用 HTTP/2:
server {listen 443 ssl http2;# 限制每个 IP 同时 5 条 HTTP/2 流limit_conn_zone $binary_remote_addr zone=addr:10m;limit_conn addr 5;
}
六、指令参数详解
6.1 limit_conn_zone key zone=name:size;
key
:用于分组的变量,可包含多个变量与文本组合。zone=name:size
:内存区名称和大小,size
建议以m
为单位。- 注意:请求中若
key
为空,则不计入统计。
6.2 limit_conn zone number;
zone
:前面定义的 zone 名称。number
:允许的最大并发连接数。
6.3 limit_conn_dry_run on|off;
on
:只记录,不拒绝。off
(默认):超额时拒绝。
6.4 limit_conn_log_level level;
- 级别:
info
、notice
、warn
、error
(默认)。 - 影响 error.log 中的日志级别。
6.5 limit_conn_status code;
- 自定义拒绝状态码,如
429
、503
(默认)。
6.6 嵌入变量 $limit_conn_status
-
可在日志格式(
log_format
)中引用,值为:PASSED
:未超额REJECTED
:超额并被拒绝REJECTED_DRY_RUN
:干跑模式下超额
示例:
log_format conn '$remote_addr [$time_local] ''zone=$limit_conn_status ''"$request" $status';
access_log /var/log/nginx/conn.log conn;
七、常见问题与排查
问题 | 排查思路 |
---|---|
限制无效 | 1. 确认 limit_conn_zone 在 http 中;limit_conn 在 server /location 中。2. 变量名拼写是否准确。 |
日志中未见限流记录 | 1. 检查 limit_conn_log_level 是否过高。2. 确认 error.log 路径是否正确。 |
zone 存储耗尽报错 | 增大 limit_conn_zone 的 size (如 20m 、50m )。 |
HTTP/2 并发测试不准 | 使用支持 HTTP/2 的测试工具(如 h2load ),并确认 listen 已启用 http2 。 |
八、总结
-
核心思想:基于共享内存,为任意“键”统计并发连接数,并在超过阈值时拒绝请求。
-
关键配置:
limit_conn_zone
—— 定义内存与分组键limit_conn
—— 设定并发阈值- 可结合
dry_run
、log_level
、status
、嵌入变量精细化控制与监控
-
应用价值:保护下载、API、WebSocket、HTTP/2 服务,防止滥用和 DoS 攻击。
掌握了以上内容,您就能在 NGINX 层以最低成本、最高效率地实现精准连接数控制。祝您配置顺利,业务平稳运行!