Blazor Server在Firefox中偶现WebSocket未处于OPEN状态错误
Blazor Server应用在Firefox中偶尔无法加载的问题
问题现象
- 我们开发的基于.NET 7.0的Blazor Server应用部署在Windows Server 2019的IIS 10上,在最新版Chrome或Edge中运行正常,但部分使用最新版Firefox的用户会偶尔出现页面加载失败的情况,且使用时间越长,触发该问题的概率越高。
- 页面加载失败时,开发者控制台会出现以下错误:
Uncaught (in promise) WebSocket is not in the OPEN stateUncaught (in promise) Error: cannot send data if the connection is not in the 'Connected' State.
- 偶尔在Chrome开发者控制台中会看到发送
101 Switching Protocols请求,响应头包含Upgrade: websocket但状态码显示为200。不确定这是否意味着SignalR出现故障后,Chrome自动切换到“原生WebSocket”作为降级方案,而Firefox在尝试降级时失败。
已完成的排查操作
- 通过Firefox的
about:config确认network.http.http2.websockets设置为true - 重启过IIS服务器
- 确认IIS已安装WebSocket组件
背景与疑问
- 这是我们首个Blazor Server应用,对SignalR和WebSocket技术不熟悉,通过谷歌搜索及Stack Overflow查询均未找到相关解决方案。
- 我们的理解是应该使用SignalR(其底层基于WebSocket),而非微软所说的“原生WebSocket”。原本以为Blazor Server无需额外配置即可正常使用SignalR,但现在怀疑可能存在配置错误,导致应用一直依赖降级方案运行。
现有Program.cs代码
using Microsoft.EntityFrameworkCore; using miniDARTS.Data; using MudBlazor.Services; using Microsoft.AspNetCore.Authentication.Negotiate; using miniDARTS.Services; var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.AddRazorPages(); builder.Services.AddServerSideBlazor(); // Blazor Server doesn't include HttpClient service by default. builder.Services.AddHttpClient(); builder.Services.AddAuthentication(NegotiateDefaults.AuthenticationScheme).AddNegotiate(); builder.Services.AddAuthorization(options => { options.FallbackPolicy = options.DefaultPolicy; }); // Configure the database connection. string connectionString = ""; if (Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") == "Production") { connectionString = builder.Configuration.GetConnectionString("miniDARTSContext"); } else if (Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") == "Development") { connectionString = builder.Configuration.GetConnectionString("testing"); } var serverVersion = new MySqlServerVersion(new Version(8, 0, 28)); builder.Services.AddDbContextFactory<miniDARTSContext>(options => options.UseMySql(connectionString, serverVersion), ServiceLifetime.Scoped); // Only run cron jobs if they are in a production environment. if (Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") == "Production") { IHost host = Host.CreateDefaultBuilder(args) .ConfigureServices(services => { services.AddHostedService<ScopedBackgroundService>(); services.AddScoped<IScopedProcessingService, PhaseChangeReportService>(); }) .Build(); host.RunAsync(); } // Add MudBlazor services. builder.Services.AddMudServices(); var app = builder.Build(); // Configure the HTTP request pipeline. if (!app.Environment.IsDevelopment()) { app.UseExceptionHandler("/Error"); // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. app.UseHsts(); } app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseRouting(); app.UseAuthentication(); app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapRazorPages(); }); app.MapBlazorHub(); app.MapFallbackToPage("/_Host"); app.Run();
内容的提问来源于stack exchange,提问作者Neil Wehneman
相关产品推荐
相关产品推荐

