求助:.NET Core SignalR部署Azure App Service后连接频繁断开
我之前帮团队排查过几乎一模一样的问题,当时折腾了好几天,整理几个最可能的原因和解决办法,你可以挨个试试:
1. 检查Azure App Service的WebSocket配置
首先确认在Azure门户的App Service -> 配置 -> 通用设置里,WebSocket选项是处于开启状态的。另外,如果你的App Service用的是Free/Basic层,这类层级对WebSocket连接数和超时限制很严格,建议临时升级到Standard层测试,排除层级限制的问题。
2. 调整SignalR的超时参数
本地环境没有代理或负载均衡,但Azure App Service前面有ARR(Application Request Routing)代理,默认超时比本地短很多。你需要在服务端的配置里调整SignalR的心跳和超时设置,确保服务端主动发送心跳的间隔比Azure的默认超时短:
// Program.cs(.NET 6+)或者Startup.cs(.NET 5及更早) builder.Services.AddSignalR(options => { // 设置客户端超时为5分钟 options.ClientTimeoutInterval = TimeSpan.FromMinutes(5); // 每2分钟发送一次心跳 options.KeepAliveInterval = TimeSpan.FromMinutes(2); });
3. 覆盖Azure App Service的ARR超时设置
除了SignalR本身的配置,ARR代理也有自己的超时限制。你可以在项目根目录添加web.config文件(即使是.NET Core项目也支持),添加代理超时配置:
<?xml version="1.0" encoding="utf-8"?> <configuration> <system.webServer> <webSocket enabled="true" /> <aspNetCore processPath="%LAUNCHER_PATH%" arguments="%LAUNCHER_ARGS%" hostingModel="inprocess" /> <!-- 把ARR代理超时设置为10分钟 --> <proxy enabled="true" timeout="00:10:00" /> </system.webServer> </configuration>
这个配置会覆盖Azure默认的2分钟超时,避免代理主动断开长连接。
4. 多实例部署必须用Azure SignalR Service背板
如果你的App Service部署了多个实例,默认的SignalR内存存储无法在实例间同步连接状态,会导致连接随机断开。这种情况必须配置Azure SignalR Service作为背板,让所有实例共享连接信息。配置起来也很简单,只需要安装NuGet包Microsoft.Azure.SignalR,然后在Program.cs里添加:
builder.Services.AddSignalR() .AddAzureSignalR(builder.Configuration["AzureSignalR:ConnectionString"]);
同时在Azure门户创建Azure SignalR Service实例,把连接字符串添加到App Service的应用设置里。
5. 客户端添加自动重连逻辑
最后,确保前端客户端配置了自动重连,即使连接断开也能自动恢复:
const connection = new signalR.HubConnectionBuilder() .withUrl("/yourHubEndpoint") .withAutomaticReconnect() // 启用内置自动重连 .build(); // 手动监听断开事件,做额外处理 connection.onclose(() => { console.log("连接断开,正在尝试重连..."); connection.start().catch(err => console.error(err)); });
这些方法里,我当时是因为多实例没配置Azure SignalR Service导致的问题,你可以先排查这个点,再依次试其他方案。
内容的提问来源于stack exchange,提问作者Stephen

