直接用Stream模块做WebSocket四层转发是绕过HTTP层、逼近TCP原生性能的方案,不解析HTTP头、不处理Upgrade升级,仅透传TCP流,需启用stream模块、配置so_keepalive、长超时及内核参数调优。

直接用 Stream 模块做 WebSocket 四层转发,是绕过 HTTP 层、逼近 TCP 原生性能的方案。它不解析 HTTP 头、不处理 Upgrade 协议升级,把连接当纯 TCP 流透传,天然规避了七层代理中缓冲、超时、头重写等开销。适合对延迟极度敏感、连接数极高(如万级并发)、且后端已自行完成 TLS 终结或使用自定义协议封装的场景。
Stream 模块启用与基础转发配置
确保 Nginx 编译时启用了 stream 模块(主流发行版二进制包通常默认包含)。在主配置文件顶部(http 块之外)添加:
stream {
upstream ws_backend {
server 10.0.1.10:8080 max_fails=3 fail_timeout=30s;
server 10.0.1.11:8080 max_fails=3 fail_timeout=30s;
}
server {
listen 8080 so_keepalive=on;
proxy_pass ws_backend;
proxy_timeout 1d;
proxy_responses 1;
}
}
关键点说明:
- so_keepalive=on:内核级 TCP Keepalive 开关,比应用层心跳更轻量,避免连接被中间设备静默断开
- proxy_timeout 1d:设为 1 天(86400 秒),覆盖绝大多数长连接生命周期,防止空闲断连
- proxy_responses 1:仅等待上游建立一次连接即认为成功,不校验响应内容(WebSocket 不需要 HTTP 响应体)
- 不配置
proxy_http_version或Upgrade头——四层不关心这些
系统级连接资源与内核参数硬调优
Stream 模块吞吐直接受操作系统网络栈限制,必须同步调整:
- 提升文件描述符上限:
echo '* soft nofile 2097152' >> /etc/security/limits.conf && echo '* hard nofile 2097152' >> /etc/security/limits.conf,并确认 Nginx 启动用户(如www-data)生效 - 增大连接队列:
net.core.somaxconn = 65535(监听队列长度) - 复用 TIME_WAIT 连接:
net.ipv4.tcp_tw_reuse = 1(客户端主动发起连接时有效) - 缩短 FIN 超时:
net.ipv4.tcp_fin_timeout = 15,加速连接回收 - 禁用 SYN Cookie(若非高防场景):
net.ipv4.tcp_syncookies = 0,降低握手延迟
执行 sysctl -p 生效,并在 Nginx 主配置中匹配:worker_rlimit_nofile 2097152; 与 events { use epoll; worker_connections 1048576; }
连接保活与健康检查的务实设计
Stream 层无法识别 WebSocket ping/pong 帧,因此不能依赖应用层心跳做健康检测。需采用更底层、更可靠的机制:
- 开启
tcp_check(需编译时加--with-stream_upstream_check_module):check interval=3 rise=2 fall=3 timeout=1 type=tcp;
每 3 秒发一次 TCP SYN 探测,连续 2 次成功视为健康,3 次失败下线 - 避免使用 HTTP 健康检查(如
type=http)——Stream 不解析 HTTP,会失败 - 若后端支持 TLS,建议在后端终结 TLS,Nginx Stream 只做纯 TCP 转发;否则需用
ssl_preread模块提取 SNI 分流,但会增加少量解析开销
监控与压测验证要点
调优后必须验证是否真正承载住目标连接规模:
- 用
ss -s查看tcp状态统计,重点关注estab(已建立)和tw(TIME_WAIT)数量 - 运行
nginx -T | grep worker_connections确认配置加载无误 - 使用
wrk或专用 WebSocket 压测工具(如wstest)模拟真实连接行为,观察 Nginx 进程 CPU 和内存是否平稳 - 抓包验证:在 Nginx 入口侧
tcpdump -i any port 8080,确认流量不经 HTTP 解析、直接透传到后端 IP:Port
这种模式不处理协议语义,所以没有“握手失败”概念——连得上就是通,连不上就查网络链路或后端状态。它简单、高效、可预期,是 WebSocket 极致性能的底层基石。



















