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

.NET Core集群中使用WebSocket时HttpContext丢失问题求助

求助:SignalR+Rebus+Cloudflare负载均衡下HttpContext为空问题

配置情况

  • 三台配置完全一致的Windows服务器,部署多个基于.NET 8和IIS的C# API,同时部署RabbitMQ集群
  • 使用Cloudflare作为负载均衡器,未启用会话亲和性(因不想使用代理)

问题描述

API通过Rebus以localhost方式连接本地RabbitMQ实例,集群消息自动分发。核心配置代码如下:

[...]

services
  .AddSignalR( _ => {
    _.EnableDetailedErrors = true;
  } )
  .AddMessagePackProtocol( _ => {
    _.SerializerOptions = MessagePackSerializerOptions.Standard
      .WithSecurity( MessagePackSecurity.UntrustedData );
   } )
  .AddRebusBackplane<myhub>(); // 已脱敏

[...]

string rabbitMqConnectionString = $"amqp://rabbit:carrot@localhost:5672/myvhost"; // 已脱敏

services.AddRebus( configure => configure
  .Transport( x => {
    x.UseRabbitMq( rabbitMqConnectionString, GenerateTransientQueueName( "queuename" ) )
      .InputQueueOptions( o => {
        o.SetAutoDelete( true );
        o.SetDurable( false );
      } );
  } ) );

services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();

[...]

app.UseEndpoints( endpoints => {
  endpoints.MapControllers();
  endpoints.MapHub<myhub>( "/myhub" ); // 已脱敏
} );

[...]

通过NextJS应用的SignalR Hub访问API时,经负载均衡器刷新几次后,即使目标主机未改变,HttpContextAccessor.HttpContext突然为空。报错触发代码片段:

[...]
 
_httpContextAccessor = httpContextAccessor;
_context = context;
_securityService = securityService;

Claim[]? claims = _httpContextAccessor.HttpContext?.User.Claims.ToArray();

if (_httpContextAccessor == null) throw new Exception( "Httpcontextaccessor is null" );
if (_httpContextAccessor.HttpContext == null) throw new Exception( "Httpcontextaccessor => Httpcontext is null" ); // <-- 触发此异常
if (_httpContextAccessor.HttpContext.User == null) throw new Exception( "Httpcontextaccessor => Httpcontext => User is null" );

if (claims == null) {
  throw new Exception( "Cant access Http Context!" );
}

[...]

排查信息:

  • 未使用Rebus、RabbitMQ或SignalR的API运行正常,无此问题,怀疑问题出在Rebus或RabbitMQ环节
  • RabbitMQ日志和管理界面无异常,三台API服务器均已正常连接
  • 绕开负载均衡器直接访问时,问题不再出现

更新内容

定位到SignalR客户端协商请求环节:负载均衡器在协商后返回不同服务器(因未启用粘性会话,高流量时会重定向流量)。通过客户端关闭协商后,问题无法复现,JS配置代码如下:

const connection = new HubConnectionBuilder()
.withUrl(`${process.env.NEXT_PUBLIC_API_BASEURI}/${global.endpoints.myhub}`, {
    accessTokenFactory: () => mytoken,
    skipNegotiation: true, // 新增配置
    transport: HttpTransportType.WebSockets, // 新增配置
})
.withHubProtocol(new MessagePackHubProtocol())
.withAutomaticReconnect()
.build();

注:关闭协商前需参考微软官方安全建议。

现寻求针对该问题的进一步专业技术建议。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 22:48:17