Nginx TCP代理连接数限制是防止后端被打爆的第一道防线,需在stream模块中全局定义limit_conn_zone、server块中配置limit_conn,并配合realip还原真实IP及超时、系统调优。

在 Nginx 的 TCP 代理(stream 模块)场景下,连接数限制不是“可选优化”,而是防止后端服务被打爆的第一道防线。它直接在连接建立阶段计数并拒绝超限请求,不转发、不排队,开销极低,适用于 Redis、MySQL、SSH 等四层代理。
必须启用 stream 模块并正确定义限流区域
limit_conn 在 TCP 代理中只能由 stream 模块提供,且配置位置有严格要求:
- 确认 Nginx 编译时含 --with-stream(主流发行版通常已内置)
- limit_conn_zone 必须写在 http 块之外的全局层级,例如 nginx.conf 顶部,不能嵌套在 http 或 server 内
- 推荐写法:limit_conn_zone $binary_remote_addr zone=conn_per_ip:10m; —— 使用二进制 IP 更省内存,10MB 约支持 16 万个独立客户端
- 若内存不足导致日志出现 limit_conn: cannot add connection,可将 zone 大小调至 20m
在 server 块中绑定并启用连接限制
真正起作用的限流指令必须放在 stream{} 内的具体 server 块中:
- 示例(限制单个 IP 最多 5 个 Redis 连接):limit_conn conn_per_ip 5;
- 支持叠加全局限制:先定义 limit_conn_zone $server_addr zone=addr:10m;,再在 server 中加 limit_conn addr 1000;,控制本机所有监听端口总连接数
- 触发限流时,Nginx 直接发送 TCP RST 包断连,客户端表现为“连接被拒绝”,无 HTTP 状态码
真实客户端 IP 的还原与适配
当流量经过 SLB、云防火墙或四层网关时,$binary_remote_addr 会是代理 IP,需主动提取真实源 IP:
- 启用 ngx_stream_realip_module(主流包已编译)
- 在 stream 块开头配置:set_real_ip_from 10.0.0.0/8; real_ip_header proxy_protocol;
- 上游代理(如 AWS NLB、HAProxy)必须开启 PROXY 协议,Nginx 才能解析真实 IP
- 之后改用 $remote_addr(经 realip 处理后已是真实 IP)作为 key 定义 zone
配合超时、系统资源与可观测性调优
限流只是起点,还需避免连接空转和系统瓶颈:
- 设置合理代理超时:proxy_timeout 30s;(默认 60s),及时释放无数据连接
- 检查系统级限制:fs.file-max ≥ 200000、用户级 ulimit -n ≥ 65536
- events 块中设 worker_connections 4096;,防止单个 worker 过载
- 开启 stream 日志:access_log /var/log/nginx/stream.log main;,状态码为 503 表示限流生效


















