部署Blazor应用至Azure Linux应用服务:随机WebSocket连接故障排查
问题现象
采用全InteractiveServer渲染模式的Blazor应用部署到Azure应用服务后,多次执行同一操作会突然触发控制台错误,刷新页面1-5次可恢复。错误信息如下:
Error: Failed to start the transport 'WebSockets': Error: WebSocket failed to connect. The connection could not be found on the server, either the endpoint may not be a SignalR endpoint, the connection ID is not present on the server, or there is a proxy blocking WebSockets. If you have multiple servers check that sticky sessions are enabled.
GET https://app-[removed]-001.azurewebsites.net/blazor?id=f9NSvVeKErKRUaRJWvmrfA&=1724694010721
Error: Failed to start the transport 'LongPolling': Error: No Connection with that ID: Status code '404'
Error: Failed to start the connection: Error: Unable to connect to the server with any of the available transports. Error: WebSockets failed: Error: WebSocket failed to connect. The connection could not be found on the server, either the endpoint may not be a SignalR endpoint, the connection ID is not present on the server, or there is a proxy blocking WebSockets. If you have multiple servers check that sticky sessions are enabled. ServerSentEvents failed: Error: 'ServerSentEvents' does not support Binary. Error: LongPolling failed: Error: No Connection with that ID: Status code '404'
应用配置信息
Program.cs代码
using HelpDesk.Components; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Azure; using HelpDesk.Services; using HelpDesk.Data; using MudBlazor.Services; var builder = WebApplication.CreateBuilder(args); builder.Services.AddMudServices(); // Add services to the container. builder.Services.AddRazorComponents() .AddInteractiveServerComponents(); builder.Services.AddDbContext<SpContext>( opt => opt.UseSqlServer(builder.Configuration.GetConnectionString("StoredProcedureUser")), ServiceLifetime.Transient); builder.Services.AddAzureClients(ab => { ab.AddServiceBusClient(builder.Configuration["AzureWebJobsServiceBus"]); }); builder.Services.AddTransient<IProceduresService, ProceduresService>(); builder.Services.AddTransient<ServiceBusService>(); var app = builder.Build(); // Configure the HTTP request pipeline. if (!app.Environment.IsDevelopment()) { app.UseExceptionHandler("/Error", createScopeForErrors: true); // 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.UseAntiforgery(); app.MapRazorComponents<App>() .AddInteractiveServerRenderMode(); app.Run();
.csproj文件内容
<PropertyGroup> <TargetFramework>net8.0</TargetFramework> <Nullable>enable</Nullable> <ImplicitUsings>enable</ImplicitUsings> <UserSecretsId>foo</UserSecretsId> </PropertyGroup> <PropertyGroup Condition=" '$(RunConfiguration)' == 'https' " /> <PropertyGroup Condition=" '$(RunConfiguration)' == 'http' " /> <ItemGroup> <PackageReference Include="Azure.Messaging.ServiceBus" Version="7.18.1" /> <PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.8" /> <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.8" /> <PackageReference Include="Microsoft.Extensions.Azure" Version="1.7.5" /> <PackageReference Include="MudBlazor" Version="7.6.0" /> </ItemGroup> </Project>
已排查信息
- 应用服务计划为Basic级别,WebSocket连接数无限制
- 不确定是否必须使用SignalR
更新
发现GitHub上有一个Issue描述了完全相同的问题。
故障原因分析及解决方案
SignalR依赖确认
Blazor InteractiveServer渲染模式必须依赖SignalR实现客户端与服务器的实时双向通信,所有交互都通过SignalR连接传递,是核心依赖,无法移除。Azure应用服务配置调整
- 开启粘性会话(ARR Affinity):即使是单实例Basic计划,Azure应用服务的代理配置可能导致连接路由异常。进入Azure门户的应用服务 -> 设置 -> 配置 -> 常规设置,将"ARR Affinity"设为"开启"。
- 确认WebSocket功能启用:进入应用服务 -> 设置 -> 配置 -> WebSocket,确保设置为"开启"。
服务生命周期优化
当前DbContext使用Transient生命周期,不符合EF Core的推荐最佳实践,可能导致不必要的实例创建和资源占用。建议改为Scoped:
builder.Services.AddDbContext<SpContext>( opt => opt.UseSqlServer(builder.Configuration.GetConnectionString("StoredProcedureUser")), ServiceLifetime.Scoped);
框架版本更新
当前使用ASP.NET Core 8.0.8,建议更新到最新的8.0.x补丁版本,修复框架层面可能存在的SignalR连接Bug。应用池回收检查
查看Azure应用服务的应用池回收设置,避免频繁回收导致服务器端连接被强制中断,引发客户端旧连接ID失效问题。
内容的提问来源于stack exchange,提问作者Chris Rockwell

