我们的 Node.js 生产堆栈中出现了类似的问题。我们有两台使用 WebSockets 的服务器,它们适用于正常用例,但偶尔负载均衡器会在两台服务器之间反弹这些连接,这会导致问题。(我们在后端有会话代码应该已经修复它,但没有正确处理它。)
我们尝试在这些服务器前的梭子鱼负载均衡器上启用 Sticky Session,但发现由于其运行方式,它会阻止 WebSocket 流量。我没有研究确切原因,因为在线可用的信息很少,但似乎这是由于平衡器如何剥离 HTTP 请求的标头,获取 cookie,并将请求转发到正确的后端服务器。由于 WebSockets 以 HTTP 开始,但随后升级,负载均衡器没有注意到连接的差异,并会尝试执行相同的 HTTP 处理。这将导致 WebSocket 连接失败,从而断开用户连接。
以下是我们目前所拥有的,运行良好。我们仍然在后端服务器前使用梭子鱼负载均衡器,但我们没有在负载均衡器上启用粘性会话。在我们的后端服务器上,我们的应用服务器前面是 HAProxy,它确实支持 WebSocket,并且可以以“迂回”的方式提供粘性会话。
请求流列表
- 传入的客户端请求命中主梭子鱼负载均衡器
- 负载均衡器转发到任一活动后端服务器
- HAProxy 接收请求并检查新的“粘性 cookie”
- 基于 cookie,HAProxy 转发到正确的后端应用服务器
请求流程图
WebSocket Request /--> Barracuda 1 -->\ /--> Host 1 -->\ /--> App 1
-------------------> --> -->
\--> Barracuda 2 -->/ \--> Host 2 -->/ \--> App 1
当箭头返回一个请求时,这意味着请求可以流向流中的任一点。
HAProxy 配置详细信息
backend app_1
cookie ha_app_1 insert
server host1 10.0.0.101:80011 weight 1 maxconn 1024 cookie host_1 check
server host2 10.0.0.102:80011 weight 1 maxconn 1024 cookie host_2 check
在上面的配置中:
cookie ha_app_1 insert
是实际使用的 cookie 名称
cookie host_1 check
或cookie host_2 check
设置 cookie 值