如何使用网关为多个SignalR Hub提供单端口访问能力?
SignalR多Hub单端口部署解决方案
核心需求:在仅开放一个端口的前提下,实现多个独立部署的SignalR Hub对外提供服务,保留原有Identity Server身份验证逻辑,无需合并Hub项目。
方案1:IIS同站点多子应用部署(改造成本最低)
- 所有独立Hub项目全部部署到IIS同一个站点下的不同虚拟目录/子应用,例如主站点绑定443端口,Hub1部署到
/hubs/trade路径、Hub2部署到/hubs/notice路径,所有Hub共享同一个端口 - 服务器角色启用「WebSocket协议」功能,IIS站点无需额外配置即可自动透传WebSocket流量
- 原有Hub的Identity Server身份验证逻辑完全不需要修改,请求头、Cookie、查询参数中的身份凭据会自动透传到子应用
- 客户端连接地址直接使用主站域名+子应用路径即可,例如
https://yourdomain.com/hubs/trade/tradeHub - 优势:无需引入额外组件,不改现有架构,兼容后续新增Hub,新增时只需要部署新的子应用即可
方案2:网关层调整:Ocelot跳过WebSocket鉴权,鉴权下放至Hub端
- 保留现有Ocelot网关架构,仅修改Ocelot配置:SignalR Hub对应的路由规则关闭网关层身份验证,只保留流量转发能力
- 原有Hub端的Identity Server身份验证逻辑保持不变,Ocelot会将所有请求头、查询参数原封不动透传给后端Hub,Hub可以正常完成身份校验
- 针对SignalR客户端可能将访问令牌放在查询参数的场景,在Hub的JWT验证配置中添加读取逻辑:
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddJwtBearer(options => { options.Events = new JwtBearerEvents { OnMessageReceived = context => { var accessToken = context.Request.Query["access_token"]; var path = context.HttpContext.Request.Path; if (!string.IsNullOrEmpty(accessToken) && path.StartsWithSegments("/hubs")) { context.Token = accessToken; } return Task.CompletedTask; } }; });
- 优势:不用替换现有网关组件,改造成本极低
方案3:替换网关为YARP(更适合长期维护)
- 替换现有Ocelot网关为微软官方开源反向代理YARP,原生支持WebSocket代理、SignalR专属优化,完全兼容Identity Server身份验证
- 配置不同Hub对应不同路径路由,所有流量统一走网关同一个端口,可选择在网关层统一鉴权或者下放至Hub端鉴权
- 优势:性能优于Ocelot,社区活跃维护无WebSocket相关缺陷,适合后续服务规模持续扩展
内容的提问来源于stack exchange,提问作者Hassan Assaad
相关产品推荐
相关产品推荐

