在AWS EKS中启用SignalR的SkipNegotiation的利弊及潜在问题
问题
我们在AWS EKS集群中使用ALB Ingress和Redis缓存处理SignalR连接,当Pod副本数设为3时,连接服务会随机出现404错误。通过设置SkipNegotiation = true并指定Transports = Microsoft.AspNetCore.Http.Connections.HttpTransportType.WebSockets后,问题得到解决。但我们不清楚这个配置的弊端,也不知道SkipNegotiation默认设为false的原因,想咨询启用该设置是否会引发后续问题。
客户端示例代码
Console.WriteLine("Start"); HubConnection connection = new HubConnectionBuilder() .WithUrl("https://<url>/api/v1/taskboard", o => { o.Transports = Microsoft.AspNetCore.Http.Connections.HttpTransportType.WebSockets; o.SkipNegotiation = true; }) .WithAutomaticReconnect() .Build(); await connection.StartAsync(); connection.On<string>("ReceiveMessage", message => { Console.WriteLine(message); }); for (int i = 0; i < 20; i++) { await connection.InvokeAsync("SendMessage", $"Hello {i}"); await Task.Delay(55); } await connection.StopAsync(); await connection.DisposeAsync();
Ingress补充配置
alb.ingress.kubernetes.io/certificate-arn: arn:aws:acm:...... alb.ingress.kubernetes.io/listen-ports: '[{"HTTP": 80}, {"HTTPS":443}]' alb.ingress.kubernetes.io/ssl-redirect: '443' alb.ingress.kubernetes.io/scheme: internet-facing alb.ingress.kubernetes.io/subnets: subnet-..., subnet-... alb.ingress.kubernetes.io/load-balancer-attributes: idle_timeout.timeout_seconds=600 alb.ingress.kubernetes.io/target-group-attributes: stickiness.enabled=true,stickiness.lb_cookie.duration_seconds=600 alb.ingress.kubernetes.io/healthcheck-path: /HealthCheck alb.ingress.kubernetes.io/healthcheck-port: '80'
解答
为什么SkipNegotiation默认是false?
SignalR的协商流程是客户端与服务端的握手步骤,核心作用包括:
- 确认双方支持的传输方式(WebSockets、Server-Sent Events、Long Polling),自动选择最优且兼容的传输方案;
- 交换连接配置信息(如超时时间、连接ID);
- 完成认证、CORS等前置校验。
默认开启协商是为了最大化兼容性,确保在不同客户端环境和网络条件下都能成功建立连接。
启用SkipNegotiation=true+指定WebSockets的潜在问题
- 兼容性受限:若客户端环境不支持WebSockets(比如老旧浏览器、受防火墙限制的网络),连接会直接失败,没有降级到其他传输方式的机会。
- 丢失动态配置同步:协商过程中服务端会返回连接超时、最大重试次数等动态配置,跳过协商后客户端只能使用硬编码的本地设置,无法适配服务端后续的配置变更。
- 服务端变更容错性降低:如果后续服务端禁用WebSockets支持,客户端不会自动感知并切换传输方式,会直接出现连接失败;而协商模式下会自动切换到可用的传输方式。
结合场景分析
之前出现随机404的原因,大概率是协商请求(HTTP)和后续的WebSocket升级请求被ALB路由到了不同的Pod。虽然配置了LB粘性会话,但ALB对HTTP请求和WebSocket升级请求的粘性处理可能存在差异,导致协商得到的连接信息与实际处理WebSocket连接的Pod不匹配,从而触发404。
是否可以长期启用该设置?
如果你的客户端环境是可控的(比如都是现代浏览器、内部系统),且服务端会持续稳定支持WebSockets,那么启用该设置不会有太大问题,还能减少一次握手请求的开销。但如果需要兼容多样化的客户端或网络环境,建议排查ALB粘性会话的配置问题,回归默认的协商模式,避免出现大范围的连接失败。
内容的提问来源于stack exchange,提问作者BendEg
相关产品推荐
相关产品推荐

