nginx stream模块tcp转发需协同nginx、内核与系统资源:先确认模块启用且stream块平级置于nginx.conf顶层;严格设置文件描述符限制、内核连接队列参数(somaxconn、tcp_max_syn_backlog等);启用epoll、so_keepalive及合理proxy_timeout。

Stream 模块做 TCP 转发时,优化不是调大几个参数就完事——它本质是让 Nginx、内核网络栈、系统资源三者协同咬合。关键不在“怎么配”,而在“为什么这么配”。
确保 stream 模块已启用且配置位置正确
很多问题卡在第一步:模块没加载或配置写错地方。
- 运行 nginx -V | grep --with-stream,有输出才说明编译时启用了模块;若无,需重装 nginx-full(Debian/Ubuntu)或安装 nginx-mod-stream(RHEL/CentOS),或自行编译加 --with-stream
- stream 块必须与 http、events 平级,放在 nginx.conf 最外层,不能缩进、不能嵌套在 http 内;常见错误是把 server 块写进 http { } 里,导致 "stream" directive is not allowed here
- proxy_pass 后只接受 IP:PORT 或 upstream 名,绝不能带 http:// 或路径,否则启动失败
对齐系统级资源上限
worker_connections 是软限制,真起作用的是操作系统允许 Nginx 打开的文件描述符数量。
- 在 /etc/security/limits.conf 中为 Nginx 运行用户(如 www-data、nginx)设置:
www-data soft nofile 2097152
www-data hard nofile 2097152 - 在 nginx.conf 主配置块中写:worker_rlimit_nofile 2097152;
- 验证方式:cat /proc/$(pgrep nginx)/limits | grep "Max open files",soft 和 hard 值都应 ≥ worker_connections × worker_processes
调优内核连接队列与网络参数
哪怕 Nginx 和系统资源充足,内核队列太小也会在建连高峰丢包,现象是客户端连接超时、Nginx 日志却无记录。
- 设 net.core.somaxconn = 65535(已完成三次握手等待 accept 的队列长度),建议 ≥ worker_connections ÷ worker_processes,并留余量
- 同步设 net.ipv4.tcp_max_syn_backlog = 131070(SYN 半连接队列),一般为 somaxconn 的 2 倍
- 开启 net.ipv4.tcp_tw_reuse = 1 加速 TIME_WAIT 连接复用(客户端主动建连场景有效)
- 关闭 net.ipv4.tcp_syncookies = 0(非高防场景),降低握手延迟
- 所有参数写入 /etc/sysctl.conf 并执行 sysctl -p 生效
启用高效事件模型并设合理超时
stream 模块不走 HTTP 流程,对事件驱动更敏感,低效模型会直接触发硬限制。
- events 块中必须显式写:use epoll;(Linux)、multi_accept on;(一次收多个连接)、accept_mutex on;(默认开启可不写)
- stream server 中启用 so_keepalive=on,由内核维持长连接,避免中间设备静默断连
- 设 proxy_timeout 1d(86400 秒)应对 WebSocket 或 MQTT 等长连接;对数据库类短连接,可设为 30s~300s
- proxy_responses 1 表示只要上游成功建立 TCP 连接即认为转发成功,不等待应用层响应(四层无需解析内容)











