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

React与.NET Core集成SignalR数分钟后无响应问题求助

SignalR连接异常(持续发送心跳但无响应、onclose不触发)问题解决方案

问题本质

你看到的Trace: (WebSockets transport) sending data. String data of length 11.是SignalR的心跳Ping帧(默认每30秒发送一次),持续输出说明前端一直在尝试维持连接,但后端已无响应或连接已静默断开,而前端未检测到状态变化,导致onclose事件不触发。


1. 后端.NET Core配置优化

调整SignalR的超时与心跳参数,确保后端主动检测死连接并触发关闭:

// Startup.cs 或 Program.cs
services.AddSignalR(options =>
{
    // 缩短心跳间隔,加快异常检测
    options.KeepAliveInterval = TimeSpan.FromSeconds(15);
    // 客户端超时时间需大于心跳间隔,避免误判
    options.ClientTimeoutInterval = TimeSpan.FromSeconds(30);
});
  • 同时排查后端所在服务器/负载均衡器(如Nginx)的长连接限制:
    • Nginx需设置proxy_read_timeout 300s;(至少大于SignalR的超时时间),并开启WebSocket支持:
      location /hub {
          proxy_pass http://your-backend;
          proxy_http_version 1.1;
          proxy_set_header Upgrade $http_upgrade;
          proxy_set_header Connection "upgrade";
          proxy_read_timeout 300s;
      }
      

2. 前端React侧连接状态修复

手动添加心跳检测与主动重连逻辑,弥补默认机制的不足:

import { HubConnectionBuilder } from "@microsoft/signalr";

let connection;
let lastPingReceived = Date.now();

const startConnection = async () => {
    connection = new HubConnectionBuilder()
        .withUrl("/your-hub-url")
        .withAutomaticReconnect([0, 2000, 5000, 10000]) // 配置自动重连间隔
        .build();

    // 订阅后端自定义Ping响应(需后端配合实现)
    connection.on("pingResponse", () => {
        lastPingReceived = Date.now();
    });

    // 定时检查心跳是否正常
    setInterval(() => {
        const now = Date.now();
        // 超过1分钟未收到心跳响应,主动断开重连
        if (now - lastPingReceived > 60000) {
            connection.stop();
        }
    }, 10000);

    // 完善连接状态监听
    connection.onclose((error) => {
        console.error("连接已关闭:", error);
        setTimeout(startConnection, 5000); // 延迟重连
    });

    connection.onreconnected((connectionId) => {
        console.log("重新连接成功,新连接ID:", connectionId);
        // 重新订阅业务事件
        setupEventListeners();
    });

    try {
        await connection.start();
        console.log("连接成功");
        setupEventListeners();
    } catch (err) {
        console.error("连接失败:", err);
        setTimeout(startConnection, 5000);
    }
};

const setupEventListeners = () => {
    // 订阅你的业务事件
    connection.on("your-event", (data) => {
        console.log("接收数据:", data);
    });
};

// 初始化连接
startConnection();
  • 关键注意点:确保前端@microsoft/signalr版本与后端.NET Core版本完全匹配(如.NET Core 6对应SignalR客户端6.x版本),版本不兼容会导致连接状态异常。

3. 后端日志排查

在Hub类中添加连接日志,确认后端是否收到心跳或主动断开连接:

using Microsoft.AspNetCore.SignalR;
using Microsoft.Extensions.Logging;

public class YourHub : Hub
{
    private readonly ILogger<YourHub> _logger;

    public YourHub(ILogger<YourHub> logger)
    {
        _logger = logger;
    }

    public override async Task OnConnectedAsync()
    {
        _logger.LogInformation("客户端连接: {ConnectionId}", Context.ConnectionId);
        // 定时向前端发送Ping响应
        _ = SendPingLoop();
        await base.OnConnectedAsync();
    }

    public override async Task OnDisconnectedAsync(Exception exception)
    {
        _logger.LogInformation("客户端断开: {ConnectionId}, 异常: {Msg}", 
            Context.ConnectionId, exception?.Message ?? "无异常");
        await base.OnDisconnectedAsync(exception);
    }

    private async Task SendPingLoop()
    {
        while (Context.ConnectionId != null)
        {
            await Clients.Client(Context.ConnectionId).SendAsync("pingResponse");
            await Task.Delay(TimeSpan.FromSeconds(15));
        }
    }
}

查看后端日志,确认是否有连接超时、线程死锁或进程崩溃的异常信息。


4. 网络层排查

  • 打开浏览器DevTools的网络面板,筛选WebSocket类型,查看帧交互:如果只有前端发送Ping,没有后端的Pong响应,说明后端已静默断开连接。
  • 用隐私模式测试,排除浏览器缓存或插件干扰。

内容的提问来源于stack exchange,提问作者BHARTI SAH

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 00:45:13