SignalR连接异常:WebSocket握手超时故障排查
SignalR WebSocket握手超时连接失败排查方案
问题现象
客户端无法连接SignalR服务端,始终处于未连接状态:
- 连接初始化日志:
Information: Normalizing '/hub/test' to 'https://localhost:4200/hub/test'. - 超时错误日志:
WebSocket connection to wss://localhost:4200/hub/test?id=MzFJgytPbR9VgqZNeeWYXg failed: WebSocket opening handshake timed out 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.
排查与修复步骤
1. 修正服务端中间件顺序(核心问题)
当前服务端Program.cs的中间件顺序错误,导致请求无法正确路由到SignalR Hub。ASP.NET Core中间件按执行顺序生效,需调整如下:
修改后的服务端代码片段:
var app = builder.Build(); // 开发环境Swagger配置 if (app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(); } // HTTPS跳转必须在路由前执行 app.UseHttpsRedirection(); app.UseRouting(); // 授权逻辑需在路由后、端点映射前执行 app.UseAuthorization(); // WebSocket配置 app.UseWebSockets(new WebSocketOptions { KeepAliveInterval = TimeSpan.FromSeconds(120), }); // 映射Hub和控制器端点 app.UseEndpoints(endpoints => { endpoints.MapHub<TestHub>("/hub/test"); endpoints.MapControllers(); }); app.Run();
2. 配置跨域(客户端与服务端端口不同时)
客户端运行在localhost:4200,若服务端端口不同,需添加跨域配置:
在builder.Services.AddSignalR()前添加跨域服务:
builder.Services.AddCors(options => { options.AddPolicy("AllowAngularClient", policy => { policy.WithOrigins("https://localhost:4200") .AllowAnyHeader() .AllowAnyMethod() .AllowCredentials(); // SignalR必须允许凭证 }); });
在UseRouting()前添加跨域中间件:
app.UseCors("AllowAngularClient");
3. 验证TestHub类实现
确保服务端存在TestHub类且继承自Hub,并实现客户端调用的Register方法:
using Microsoft.AspNetCore.SignalR; public class TestHub : Hub { public async Task Register(string user) { // 示例逻辑:通知所有客户端用户上线 await Clients.All.SendAsync("Notify", user); } }
4. 客户端连接优化
添加自动重试和错误捕获,提升连接稳定性:
initWebSocket() { this.hubconnection = new HubConnectionBuilder() .withUrl('/hub/test', { transport: HttpTransportType.WebSockets | HttpTransportType.ServerSentEvents }) .withAutomaticReconnect() // 自动重试连接 .build(); // 注册接收消息的回调 this.hubconnection.on('Update', (data: CustomData ) => { console.log(data); this.customData = data; }); this.hubconnection.on('Notify', (user: string) => { console.log(user); alert(user + ' updated the data'); }); // 启动连接并处理错误 this.hubconnection.start() .then(() => this.hubconnection.invoke('Register', 'User' + Math.floor(Math.random() * 10001))) .catch(err => { console.error('连接失败:', err); // 手动重试 setTimeout(() => this.initWebSocket(), 5000); }); }
5. 检查WebSocket环境支持
- 确认浏览器未禁用WebSocket功能;
- 若使用代理(如Nginx、IIS),需配置WebSocket支持:
- IIS:确保已安装WebSocket协议;
- Nginx:添加WebSocket代理配置,示例:
location /hub/test { proxy_pass http://your-server-address; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header Host $host; proxy_cache_bypass $http_upgrade; }
- 多服务器部署时,需启用粘性会话,确保同一客户端请求落到同一服务器。
内容的提问来源于stack exchange,提问作者CYL
相关产品推荐
相关产品推荐

