You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 01:28:01