“too many concurrent sessions”是后端服务连接超限的提示,Nginx Stream需用limit_conn_zone与limit_conn按IP限制并发连接,并配合proxy_timeout等参数防假限流,通过stream日志和ss命令验证生效。

“too many concurrent sessions”不是 Nginx 原生错误提示,而是后端服务(如 MySQL、Redis、PostgreSQL 或自研 TCP 服务)在连接数超限时返回给客户端的典型响应。它表明当前客户端或该 IP 已建立的活跃连接数超过了后端设定的上限。在 Nginx Stream 模块代理场景中,这个报错往往意味着限流没起作用,或者限流配置与后端能力不匹配。
为什么 Stream 层要主动限制连接数
后端服务的并发连接数有限制,例如:
- MySQL 默认
max_connections = 151,单 IP 无硬限但受全局池约束; - Redis 默认
maxclients = 10000,可按 IP 细粒度控制; - 某些数据库中间件或云服务会直接对源 IP 做连接数配额(如 50 连接/IP)。
若 Nginx 不做前置拦截,大量客户端直连会快速耗尽后端连接池,导致新连接被拒绝,并抛出 “too many concurrent sessions” 类似提示。此时错误实际发生在后端,Nginx 只是透传了失败结果。
用 limit_conn_zone + limit_conn 拦在入口
Stream 模块通过 ngx_stream_limit_conn_module 实现连接级限流,核心是两步:
- 在
stream块顶层定义共享内存区:limit_conn_zone $binary_remote_addr zone=per_ip:10m;
——基于客户端二进制 IP 地址计数,10MB 内存约支持 16 万个独立 IP 的状态记录; - 在具体
server块中启用限制:limit_conn per_ip 5;
——每个 IP 最多维持 5 条并发连接,超出则立即 RST 断开,不转发也不排队。
注意:stream 不支持 limit_req(请求速率),只认并发连接数;变量必须是 stream 上下文可用的,如 $binary_remote_addr、$server_addr,不能用 HTTP 模块里的 $host 或 $request。
配合关键参数防止“假限流”
仅设 limit_conn 不够,还需调整关联行为,否则连接可能长期滞留、绕过统计:
-
proxy_timeout 30s;—— 客户端空闲超时,避免长连接占位不释放; -
proxy_connect_timeout 5s;—— 向后端建连失败快速失败,不卡住连接槽位; -
worker_connections 4096;(写在events块)—— 确保单 worker 能承载足够连接; - 系统级调优:
ulimit -n 65536、fs.file-max = 2097152,避免 OS 层面文件描述符不足。
验证是否真正生效
限流行为默认不记入 HTTP access log,需主动开启 stream 日志并观察状态:
- 在
stream块中添加:log_format connlog '$remote_addr [$time_local] $protocol $status $limit_conn_status';access_log /var/log/nginx/stream.log connlog; - 触发限流时,日志中
$limit_conn_status显示 REJECTED,$status为 503; - 用
ab -n 1000 -c 200 telnet://ip:port或weighttp -n 1000 -c 200 -t 4 -k ip:port压测,检查失败率和日志中 REJECTED 出现频次; - 运行
ss -tn state established '( dport = :3306 )' | wc -l查看真实 ESTABLISHED 连接数,对比限流阈值是否吻合。


















