You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

多服务器Pod负载均衡下SignalR连接协商异常问题

解决.NET SignalR多Pod负载均衡下的连接404问题

核心原因

你的判断完全正确:SignalR协商阶段生成的连接ID和令牌仅存储在处理请求的服务器实例内存中,当负载均衡把后续WebSocket连接请求分发到其他Pod时,目标实例没有对应连接的上下文,就会返回No Connection with that ID的404错误。Redis背板仅用于跨实例的消息广播,不负责共享连接会话数据,因此无法解决这个问题。

解决方案

1. 配置负载均衡会话粘滞(会话亲和性)

让负载均衡器将同一客户端的所有请求(包括协商和WebSocket连接)路由到同一个后端Pod:

  • 云厂商负载均衡配置:
    • AWS ALB:开启「粘性会话」,选择基于Cookie的模式,可自定义Cookie名称
    • Azure App Service:在「配置>常规设置」中开启「ARR 粘性会话」
    • Kubernetes Ingress:添加nginx.ingress.kubernetes.io/affinity: "cookie"注解,配合nginx.ingress.kubernetes.io/session-cookie-name: "signalr-affinity"指定专属Cookie名称
  • 注意:WebSocket是长连接,需确保Cookie有效期覆盖连接生命周期

2. 跳过协商阶段(仅适用于WebSocket传输)

如果前端仅使用WebSocket传输,可直接跳过协商步骤,避免依赖实例内存中的协商数据:

  • 前端代码修改:
    const connection = new signalR.HubConnectionBuilder()
      .withUrl("/yourHubPath", {
        skipNegotiation: true,
        transport: signalR.HttpTransportType.WebSockets
      })
      .build();
    
  • 后端无需额外配置,但要确保负载均衡器已开启WS/WSS协议转发

3. 分布式存储共享连接会话(进阶方案)

如果无法配置会话粘滞,可自定义SignalR连接逻辑,将连接元数据存储到Redis或数据库中:

  • 实现IConnectionIdProvider自定义连接ID生成规则
  • 通过HubFilter或中间件,在协商阶段把连接数据写入分布式存储,在WebSocket握手阶段从存储读取验证
  • 此方案复杂度较高,仅在粘滞会话不可行时考虑

验证步骤

  1. 配置完成后,检查负载均衡器的会话粘滞状态或前端跳过协商的连接日志
  2. 启动多个Pod重复连接测试,确认WebSocket连接不再返回404
  3. 查看后端Pod日志,确认同一客户端的协商和连接请求落到同一个实例

内容的提问来源于stack exchange,提问作者Viniisouza

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 13:58:22