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

ASP.NET Core 5中SignalR的negotiate请求是否会导致503服务不可用错误?

问题根因分析
  • 重连重试策略过于激进:你自定义的reconnectFunc前100ms内重试间隔仅为50ms,单客户端单次重连失败每秒最多会触发20次negotiate请求,双Hub场景下就是40次/秒,和你观测到的每分钟50次的量级完全吻合。一旦出现网络波动、服务端短暂不可用的情况,大量客户端同时高频重试会直接打满IIS请求队列,触发503 Service Unavailable错误。
  • loginHub缺少鉴权配置:如果你的loginHub接口开启了JWT鉴权,当前代码中loginHub初始化时没有配置accessTokenFactory传递令牌,negotiate请求会直接返回401状态码,触发客户端自动重连逻辑,形成无限请求循环。
  • IIS未开启WebSockets协议:如果站点没有启用WebSockets,SignalR会自动降级为长轮询、SSE等传输方式,这类传输方式会频繁发起negotiate请求维持连接,进一步放大请求量。
  • 令牌过期触发循环重连:你配置的refreshToken间隔为24小时,如果JWT有效时长小于24小时,token过期后roomHub的请求会返回401,触发自动重连,也会产生大量无效negotiate请求。
修复方案
  • 调整重连重试策略:把最低重试间隔调整到1000ms以上,避免短时间内高频重试引发的惊群效应,示例修改如下:
function reconnectFunc(retryContext) {
    // 首次重试至少间隔1秒
    if (retryContext.elapsedMilliseconds < 10000) {
        return 1000;
    } 
    // 后续按原有梯度拉长间隔即可
    else if (retryContext.elapsedMilliseconds < 45000) {
        return 5 * 1000;
    }
    else if (retryContext.elapsedMilliseconds < 2 * 60 * 1000) {
        return 10 * 1000;
    }
    else if (retryContext.elapsedMilliseconds < 5 * 60 * 1000) {
        return 60 * 1000;
    }
    else if (retryContext.elapsedMilliseconds < 10 * 60 * 1000) {
        return 3 * 60 * 1000;
    }
    else if (retryContext.elapsedMilliseconds < 15 * 60 * 1000) {
        return 5 * 60 * 1000;
    }
    else {
        return 10 * 60 * 1000;
    }
}
  • 补全loginHub鉴权配置:如果loginHub需要鉴权,初始化时和roomHub一样添加accessTokenFactory配置传递有效令牌。
  • 开启IIS WebSockets功能:进入服务器管理器的「添加角色和功能」向导,在「Web服务器(IIS)- Web服务器 - 应用程序开发」中勾选「WebSocket协议」安装,安装后重启站点即可生效。
  • 优化令牌刷新逻辑:把refreshToken的执行间隔调整为比JWT有效时长小10~15分钟,确保token过期前完成刷新,避免因令牌过期触发无效重连。
  • 临时兜底限流:可以在IIS中给negotiate接口添加请求限流规则,避免短时间内异常请求量过高打垮服务。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.19 23:57:01