核心是连接级粘滞而非请求分发:WebSocket为有状态长连接,必须确保同一条连接始终路由至同一后端,否则导致消息丢失、重连、Session失效;需用ip_hash或sticky cookie实现会话保持,并配置proxy_http_version 1.1、Upgrade/Connection头透传、proxy_read_timeout 86400等超时与保活参数。

Linux 下用 Nginx 的 upstream 实现 WebSocket 集群负载均衡,核心不是“把请求分出去”,而是“让同一条连接始终落在同一台后端”。WebSocket 是有状态长连接,轮询或 least_conn 这类无状态策略会直接导致消息丢失、重连、Session 找不到——必须做连接级粘滞。
必须启用的 upstream 与 proxy 配置
先确认 Nginx 已内置 upstream 模块:nginx -V 2>&1 | grep -o with-http_upstream_module
有输出才可继续。配置需放在 http 块内(推荐新建 /etc/nginx/conf.d/ws-balance.conf):
- 定义 upstream 组,禁用默认轮询,显式启用
ip_hash或配合 sticky cookie - 在
location中设置proxy_http_version 1.1、Upgrade和Connection头,这是协议升级识别的关键 - 关闭缓冲和缓存:
proxy_buffering off; proxy_cache off;,避免 WebSocket 帧被截断或延迟
两种主流会话粘滞方案选型
ip_hash 方案(最常用)
适合客户端 IP 分布较均匀、且不处于大规模 NAT 环境(如企业出口统一公网 IP)的场景:
- 配置简单,Nginx 原生支持,无需改业务
- 扩缩容时哈希重分布,已有连接会断开;IPv6 下更稳定
- 示例:
upstream ws_backend { ip_hash; server 10.0.0.1:8080; server 10.0.0.2:8080; }
sticky cookie 方案(更精准)
需要编译安装 nginx-sticky-module-ng,但能按客户端粒度绑定,不受 NAT 影响:
- 后端首次响应中写入
Set-Cookie: srv_id=...;,后续请求自动路由 - 客户端禁用 Cookie 时失效,需兜底逻辑
- 示例:
upstream ws_backend { sticky cookie srv_id expires=1h domain=.example.com path=/; server 10.0.0.1:8080; server 10.0.0.2:8080; }
超时与连接保活关键参数
WebSocket 连接空闲时,Nginx 默认 60 秒就断开,必须显式调大:
Linux系统管理专家,覆盖12大模块:用户权限、SSH、存储、网络、systemd、防火墙、日志监控、备份恢复、TLS证书、Ansible、容器、IaC。提供配置、验证、加固、监控、备份、自动化、故障排查、回滚闭环。关键词:useradd、sudo、sshd_config、chmod、SEL...
-
proxy_read_timeout 86400;(24 小时):控制后端无数据返回时的等待上限 -
proxy_send_timeout 86400;:控制 Nginx 向后端发数据失败前的等待时间 -
proxy_connect_timeout 30;:建立 TCP 连接超时,建议保持 30 秒以内 -
upstream ... { keepalive 32; }:为每个 worker 保持最多 32 条空闲长连接,降低后端建连压力
验证与排障要点
配置完成后执行 nginx -t && nginx -s reload,再测试:
- 用
wscat -c ws://your-domain.com/ws测试握手是否成功(看响应头是否有Upgrade: websocket) - 观察 Nginx error.log,重点排查
upstream prematurely closed connection(后端主动断连)或no live upstreams(健康检查全挂) - 若频繁 502,检查后端服务是否真正监听并接受 WebSocket 升级请求(如 Spring Boot 需配
AllowedOrigins,Node.js 的ws库需正确处理upgrade事件)

















