SignalR客户端每小时连接断开且服务端同期返回404如何解决?
根因分析
固定1小时断开+服务端返回404的原因
- 绝大多数反向代理(包括IIS、Nginx、公有云负载均衡)的默认空闲TCP连接超时为3600秒(1小时),当SignalR连接长时间无业务数据传输时,代理会主动切断连接,触发客户端抛出对应连接关闭异常。
- 当前服务端SignalR配置未针对代理场景优化保活策略,连接被代理切断后,服务端会在你配置的
ClientTimeoutInterval(1分钟)之后清理失效的连接ID,后续客户端携带旧连接ID发起的POST请求(通常是长轮询传输模式的后续请求,或是WebSocket断开后的降级请求),服务端找不到对应连接实例,就会返回404状态码。
重连过程中消息发送失败的原因
- SignalR客户端的
WithAutomaticReconnect仅负责连接的重建,没有内置消息缓存、补发能力。当连接处于Reconnecting状态时,直接调用SendAsync/InvokeAsync方法会直接抛出异常,消息无法正常发送。
解决方案
解决固定1小时断开问题
- 调整服务端SignalR保活配置,显式设置小于反向代理空闲超时的心跳间隔,确保在代理判定连接空闲前有心跳包传输,避免被主动切断。修改服务端配置如下:
services.AddSignalR(options => { options.MaximumReceiveMessageSize = null; options.EnableDetailedErrors = true; options.ClientTimeoutInterval = TimeSpan.FromMinutes(1); options.HandshakeTimeout = TimeSpan.FromMinutes(1); // 新增:设置15分钟一次保活心跳,远小于1小时的代理默认空闲超时 options.KeepAliveInterval = TimeSpan.FromMinutes(15); });
- 调整反向代理/负载均衡的空闲连接超时配置,将对应站点的WebSocket、HTTP长连接超时设置为2小时以上,从代理层面避免主动切断正常的SignalR连接。如果使用IIS托管,需要同时开启站点的WebSocket功能,调整IIS站点的连接超时配置。
解决重连过程中消息发送失败问题
- 封装客户端发送方法,发送前先判断
HubConnection.State是否为Connected,如果处于重连/断开状态,先将消息存入本地内存队列或持久化存储。 - 监听客户端的
Reconnected事件,连接重建完成后,批量补发之前缓存的未发送消息。 - 可以搭配Polly等重试框架,对发送方法添加异常重试逻辑,遇到连接未激活类异常时自动重试,直到重连成功或达到最大重试次数。
内容的提问来源于stack exchange,提问作者Dennis Kiesel
相关产品推荐
相关产品推荐

