通过Ocelot网关连接.NET Core SignalR Hub时出现404错误「No Connection with that ID」的技术求助
你遇到的核心问题是Ocelot路由配置没有正确区分SignalR的HTTP请求(协商、长轮询)和WebSocket请求,导致后续连接请求无法被正确转发到Hub服务器,从而出现连接ID不匹配的错误。下面是针对性的解决方案:
1. 修正Ocelot路由配置
SignalR的请求分为两类:
- HTTP请求:包括
negotiate协商请求、长轮询的POST/GET请求 - WebSocket请求:需要协议升级的握手请求
你之前的路由统一使用了ws作为DownstreamScheme,这会导致HTTP类请求(比如长轮询)被错误地按WebSocket协议转发,从而失效。需要拆分路由:
完整路由配置示例
[ // 处理带路径参数的HTTP请求(如negotiate、长轮询的后续请求) { "DownstreamPathTemplate": "/bookingCancelNotificationHub/{everything}", "ReRouteIsCaseSensitive": false, "DownstreamScheme": "https", // 对应Hub服务器的HTTP协议(http/https) "DownstreamHostAndPorts": [ { "Host": "localhost", "Port": 5009 } ], "UpstreamPathTemplate": "/bookingCancelNotificationHub/{everything}", "UpstreamHttpMethod": ["GET", "POST", "OPTIONS"] }, // 处理根路径的HTTP请求 { "DownstreamPathTemplate": "/bookingCancelNotificationHub", "ReRouteIsCaseSensitive": false, "DownstreamScheme": "https", "DownstreamHostAndPorts": [ { "Host": "localhost", "Port": 5009 } ], "UpstreamPathTemplate": "/bookingCancelNotificationHub", "UpstreamHttpMethod": ["GET", "POST", "OPTIONS"] }, // 处理WebSocket协议升级请求 { "DownstreamPathTemplate": "/bookingCancelNotificationHub", "ReRouteIsCaseSensitive": false, "DownstreamScheme": "wss", // 对应Hub服务器的WebSocket协议(ws/wss) "DownstreamHostAndPorts": [ { "Host": "localhost", "Port": 5009 } ], "UpstreamPathTemplate": "/bookingCancelNotificationHub", "UpstreamHttpMethod": ["GET"], // 确保WebSocket升级头正确转发 "UpstreamHeaderTransform": { "Connection": "Upgrade", "Upgrade": "websocket" } } ]
2. 确认Ocelot中间件顺序
确保UseWebSockets中间件在UseOcelot之前执行,这是WebSocket协议升级的必要条件:
Configure(app => { app.UseCors("CorsPolicy"); app.UseWebSockets(); // 必须在UseOcelot之前 app.UseOcelot().Wait(); });
3. 排除自定义DelegatingHandler干扰
你添加的NoGzipDelegatingHandler可能会修改请求的内容或头信息,导致SignalR的连接验证失败。建议暂时移除这个Handler测试:
// 替换原代码 services.AddOcelot(); // 去掉.AddDelegatingHandler<NoGzipDelegatingHandler>(true)
4. 理解SignalR客户端的正常行为
你提到协商返回的connectionToken被用作请求URL的id参数,这其实是SignalR的正常行为——connectionToken是客户端用来向服务器验证身份的令牌,而非connectionId。出现「No Connection with that ID」错误,本质是Ocelot没有正确转发请求,导致Hub服务器无法关联到这个令牌对应的连接会话。
5. 检查Hub服务器的CORS配置
确保Hub服务器的CORS策略允许携带凭证(AllowCredentials()),并且你的React域名在允许列表内:
options.AddPolicy("CorsPolicy", builder => builder .WithOrigins("https://xxxx.se") // 替换为你的React实际域名 .AllowAnyMethod() .AllowAnyHeader() .AllowCredentials() );
完成以上配置后,重新启动网关和Hub服务器,尝试建立SignalR连接。如果问题仍然存在,可以利用你已开启的EnableDetailedErrors = true查看Hub服务器的详细错误日志,进一步定位问题。
内容的提问来源于stack exchange,提问作者Mustafa Javid

