在 nginx 多实例集群中保持 websocket 会话,核心做法是配置 proxy_pass 时启用 http/1.1 并显式传递 connection 和 upgrade 头部,同时利用 ip_hash 或 sticky 模块确保同一客户端的请求始终路由到同一个后端节点。

Nginx 如何配置 WebSocket 代理以支持长连接?
要实现 WebSocket 升级,必须在 location 块中设置 proxy_http_version 1.1; 并将 Upgrade 和 Connection 头传递给上游服务器。默认情况下,Nginx 使用 HTTP/1.0 且会清除这些头部,导致握手失败。

server {
listen 80;
server_name ws.example.com;
location /ws {
proxy_pass http://backend_cluster;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_read_timeout 86400s;
}
}
上述配置中,$http_upgrade 变量用于处理非 WebSocket 请求(此时值为空),而 Connection 被强制设为 upgrade。proxy_read_timeout 设置为 86400 秒以防止空闲连接被断开。此配置确保了从客户端到 Nginx 再到后端的通道能够维持双向通信。
多实例集群中如何解决会话粘滞问题?
由于 WebSocket 是基于 TCP 的长连接,一旦建立,后续消息必须发送到同一后端节点。因此,需要在 upstream 块中使用 ip_hash 指令,根据客户端 IP 地址进行哈希分配,保证会话粘性。

upstream backend_cluster {
ip_hash;
server 192.168.1.10:8080;
server 192.168.1.11:8080;
server 192.168.1.12:8080;
}
ip_hash 算法会将来自同一 IP 的请求始终指向同一个 server。如果某个节点宕机,Nginx 会自动将流量转移到其他健康节点,但新建立的连接可能会分配到不同节点,旧连接则中断。对于高可用场景,建议结合后端应用的会话同步机制或使用 Redis Session 存储来弥补连接迁移带来的状态丢失。
当后端节点重启时,现有 WebSocket 连接会发生什么?
当集群中的某个后端节点重启或下线时,所有已建立在该节点上的 WebSocket 连接会被立即切断。客户端会收到 close 事件,通常伴随状态码 1006(异常关闭)。此时,客户端需要实现自动重连逻辑,重新发起握手请求。由于使用了 ip_hash,重连后的请求可能会被分配到另一个健康的后端节点,前提是应用层能识别该用户并恢复其上下文。











