Blazor Server应用20余用户同时访问时故障求助
Blazor Server 多用户访问故障排查与解决建议
核心问题分析
日志中的Microsoft.JSInterop.JSDisconnectedException表明,Blazor电路已断开并销毁后,RadzenContextMenu组件仍尝试发起JavaScript互操作调用。结合20+用户触发故障的场景,大概率是服务器资源瓶颈导致电路意外终止,或是组件生命周期未正确处理电路断开状态。
一、服务器资源瓶颈排查
内存监控
- 实时跟踪
w3wp.exe的内存占用,确认是否存在内存泄漏(内存持续攀升至接近8GB上限) - 检查应用中未释放的资源:如未取消的异步任务、未Dispose的
IDisposable对象、长期订阅的事件
- 实时跟踪
CPU负载检查
- 查看
w3wp.exe的CPU使用率,若持续超过80%,会导致服务器无法及时处理SignalR心跳包,触发电路超时断开
- 查看
二、Blazor与SignalR配置优化
1. 细化电路与Hub配置
在Program.cs中补充以下配置,优化资源管理与连接稳定性:
builder.Services.AddServerSideBlazor() .AddHubOptions(options => { options.ClientTimeoutInterval = TimeSpan.FromSeconds(60); options.KeepAliveInterval = TimeSpan.FromSeconds(15); // 增大最大接收消息大小,避免大消息导致连接中断 options.MaximumReceiveMessageSize = 10 * 1024 * 1024; // 10MB options.StreamBufferCapacity = 100; }) .AddCircuitOptions(options => { // 缩短断开电路的保留时间,快速释放资源 options.DisconnectedCircuitRetentionPeriod = TimeSpan.FromMinutes(3); // 限制保留的最大电路数,避免内存占用过高 options.MaxRetainedCircuits = 80; });
2. IIS应用池优化
- 配置应用池回收规则:当内存占用超过6GB时自动回收,防止内存泄漏导致的进程崩溃
- 调整应用池队列长度至2000,应对多用户并发请求
- 确认IIS已正确安装
WebSocketModule(在IIS管理器“模块”中检查)
三、组件生命周期修复
针对RadzenContextMenu在Dispose时触发的异常,需处理电路断开后的JS互操作调用:
1. 封装安全的JS互操作方法
替换组件中直接的JS调用,增加电路状态检查:
public static class SafeJSRuntimeExtensions { public static async Task SafeInvokeVoidAsync(this IJSRuntime jsRuntime, string identifier, params object[] args) { if (jsRuntime is RemoteJSRuntime remoteJSRuntime && !remoteJSRuntime.Circuit.IsConnected) { return; } await jsRuntime.InvokeVoidAsync(identifier, args); } }
若使用自定义组件,将InvokeVoidAsync替换为SafeInvokeVoidAsync;若使用Radzen组件,建议升级至最新版本,查看是否已修复该Dispose场景的问题。
2. 监听电路状态
注册CircuitHandler监听电路断开事件,及时取消未完成的异步操作:
public class CircuitConnectionHandler : CircuitHandler { public override Task OnCircuitDisconnectedAsync(Circuit circuit, CancellationToken cancellationToken) { // 可在此处通知全局组件电路已断开,取消相关异步任务 return base.OnCircuitDisconnectedAsync(circuit, cancellationToken); } } // 在Program.cs中注册 builder.Services.AddScoped<CircuitConnectionHandler>(); builder.Services.AddSingleton<CircuitHandler>(sp => sp.GetRequiredService<CircuitConnectionHandler>());
四、日志补充排查
启用SignalR详细日志,定位连接断开的具体原因:
在appsettings.json中添加日志配置:
{ "Logging": { "LogLevel": { "Microsoft.AspNetCore.SignalR": "Debug", "Microsoft.AspNetCore.Http.Connections": "Debug", "Microsoft.AspNetCore.Components.Server.Circuits": "Debug" } } }
通过日志可查看SignalR连接的建立、心跳、断开全流程,判断是客户端网络问题还是服务器端资源不足导致的中断。
内容的提问来源于stack exchange,提问作者Tim Kruger
相关产品推荐
相关产品推荐

