nginx 稳定代理 websocket 集群需三要素:启用协议升级头(proxy_http_version 1.1、upgrade 和 connection 头)、延长超时(read/send/keepalive_timeout ≥ 心跳间隔)、按场景选会话保持(ip_hash/cookie/共享状态),并配合后端健康检查与系统调优。

要让 Nginx 稳定代理 WebSocket 集群、避免连接频繁断开,关键不在“转发”本身,而在于**维持长连接不被中间层切断、确保请求路由一致性、适配协议升级机制**。Nginx 从 1.3.13 起原生支持,但默认 HTTP 负载配置会直接导致 WebSocket 连接秒断。
必须启用的协议升级头和 HTTP/1.1
WebSocket 握手本质是一次带特殊头部的 HTTP 请求,Nginx 必须透传并参与升级流程:
- proxy_http_version 1.1:强制使用 HTTP/1.1(HTTP/1.0 不支持持久连接与 Upgrade)
-
proxy_set_header Upgrade $http_upgrade:把客户端发来的
Upgrade: websocket头原样传给后端 - proxy_set_header Connection "upgrade":显式告知后端“这不是普通 HTTP 请求,要升级协议”
缺一不可。漏掉任一字段,后端收不到升级信号,返回 200 而非 101,连接建立失败。
超时设置必须大幅延长
WebSocket 是空闲时仍保持活跃的长连接,Nginx 默认 proxy_read_timeout 为 60 秒,空闲超时即主动断连:
- proxy_read_timeout 86400(24 小时):控制 Nginx 等待后端响应数据的最大时间,适用于心跳间隔较长场景
- proxy_send_timeout 86400:控制 Nginx 向后端发送请求后等待确认的时间
- keepalive_timeout 86400:保持客户端与 Nginx 之间 keep-alive 连接的时长
这些值应大于你后端服务的 ping/pong 心跳间隔(如后端设 30 秒心跳,则 timeout 至少设为 60 秒以上)。
会话保持策略要按场景选型
WebSocket 连接一旦建立,后续帧都走同一 TCP 连接;若负载均衡随机分发,新帧可能打到无状态的另一台后端,导致消息丢失或连接拒绝:
- ip_hash:最简单,按客户端 IP 哈希固定后端。适合公网直连、IP 分散的场景;但局域网用户会扎堆一台,且宕机后不自动迁移
- sticky cookie(需 nginx plus 或第三方模块):通过 Set-Cookie 绑定会话,支持故障转移,适合 Web 页面内嵌 WS 的场景
- 权衡方案:不强绑定 + 后端共享状态:用加权轮询(weight),但后端改用 Redis 存储 session 和连接映射,实现无状态部署
后端健康与连接稳定性校验
光配对前端没用,后端也得配合:
- 在 upstream 块中加入 health_check interval=10s fails=3 passes=2,及时剔除失联节点
- 后端服务自身需正确响应 ping 帧(不丢弃、不超时),否则 Nginx 可能因无响应误判连接死亡
- 检查系统级限制:
net.core.somaxconn、fs.file-max、Nginx worker_connections,防止连接数打满后新建连接被拒
常见断连现象如“重连几次才成功”“某台机器连接总失败”,大概率是超时不匹配或健康检查未生效。











