首页/新闻资讯/正文详情

Ocelot WebSockets 代理实战指南:从基础配置、SignalR 到自定义缓冲中间件

发布时间:2026/9/25 2:13:33 来源:云帆数科 栏目:资讯中心
Ocelot WebSockets 代理实战指南:从基础配置、SignalR 到自定义缓冲中间件
API网关后端微服务【免费下载链接】Ocelot.NET API Gateway项目地址https://gitcode.com/gh_mirrors/oc/Ocelot点击查看免费下载导读本文是 Ocelot.NET API Gateway官方文档 docs/features/websockets.rst 的深度实战解读系统讲解如何在 Ocelot 网关中启用 WebSocket 与 SignalR 代理包括最小可运行的Program.cs与ocelot.json配置、ws/wss协议与 SSL 证书处理、与负载均衡/服务发现等功能的兼容边界以及通过继承WebSocketsProxyMiddleware定制 64 KB 高吞吐缓冲区的完整样例。读完本文你将能独立为现有 Ocelot 网关接入 WebSocket 实时通道并掌握其底层代理实现消息泵、握手、头转发的原理细节。WebSockets 代理Ocelot 做什么Ocelot 基于 src/WebSockets/WebSocketsProxyMiddleware.cs 提供 WebSocket 反向代理能力其工作方式与普通 HTTP 路由完全不同收到来自上游浏览器/客户端的 WebSocket 升级请求后Ocelot 先与下游服务建立ClientWebSocket连接再与上游客户端完成AcceptWebSocketAsync握手随后进入**双向消息泵Pump**阶段PumpAsync(client, server)把下游消息转发给上游PumpAsync(server, client)把上游消息转发给下游两者以Task.WhenAll并发运行见 Proxy 方法整个过程中 Ocelot 扮演纯透传角色——接收上游消息、代理到下游服务、接收下游响应、再代理回上游客户端。Ocelot 的 WebSockets 功能最初由 issue #212 提出于 5.3.0 版本引入。基础配置让一条路由代理 WebSocket 流量第一步启用 ASP.NET Core WebSocket 中间件在Program.cs中启用var app builder.Build(); app.UseWebSockets(); // required for Ocelot 24.x and earlier; called automatically since version 25.0 await app.UseOcelot(); await app.RunAsync();版本差异重要从 Ocelot 25.0 开始app.UseWebSockets()会在 Ocelot 构建管道时被内部调用无需再手动注册24.x 及更早版本则必须显式调用。从源码看OcelotPipelineExtensions.cs 中的BuildOcelotPipeline会先app.UseWebSockets()添加原生WebSocketMiddleware这是完成 CONNECT 方法与 WS 握手、使IsWebSocketRequest为真的关键随后通过app.MapWhen(context context.WebSockets.IsWebSocketRequest, app app.ConfigureWebSockets(configuration))把 WebSocket 升级请求分流到独立的 WS 专用管道与普通 HTTP 管道分离。第二步配置 ocelot.json 路由{ UpstreamPathTemplate: /, DownstreamPathTemplate: /ws, DownstreamScheme: ws, DownstreamHostAndPorts: [ { Host: localhost, Port: 5001 } ] }配置要点DownstreamScheme必须为wsWebSocket 明文协议这是识别 WebSocket 路由的核心标记上述配置的含义是所有进入/的 WebSocket 流量将被代理到localhost:5001/wsDownstreamHostAndPorts可配置多个下游地址此时配合负载均衡器见下文支持的功能即可在多实例间分发 WS 连接。真实的可运行示例可参考 samples/WebSocket/ocelot.json其中同时演示了ws与wss两种路由分别代理到corefx-net-http11.azurewebsites.net的 Echo 服务与echo.websocket.org。底层原理WebSocketsProxyMiddleware 的四个关键机制深入 WebSocketsProxyMiddleware.cs 源码可看到代理过程的四个核心细节1. 不转发的 WebSocket 专用头public static readonly string[] NotForwardedWebSocketHeaders new[] { Connection, Host, Upgrade, Sec-WebSocket-Accept, Sec-WebSocket-Protocol, Sec-WebSocket-Key, Sec-WebSocket-Version, Sec-WebSocket-Extensions, };源码位置这些头由握手双方自行协商代理转发会导致握手失败因此在把上游请求头复制到ClientWebSocket.Options时会被显式排除其余请求头如 Cookie、自定义头则被转发。需要说明的是转发过程会捕获ArgumentException——.NET Framework 下某些被误认为受限的头会触发该异常属预期行为。2. 可覆写的缓冲区大小public const int Default4KBufferSize 4096; protected virtual int BufferSize Default4KBufferSize;源码位置PumpAsync每次ReceiveAsync使用该缓冲区接收数据并原样SendAsync到对端BufferSize是virtual属性这正是官方样例通过子类将其放大到 64 KB 的扩展点见下文自定义中间件。3. 下游 Scheme 自动修正Proxy 方法 中只有ws:///wss://才是ClientWebSocket支持的 URI 前缀。若配置的下游 scheme 是http/httpsOcelot 会记录一条警告Invalid scheme has detected which will be replaced!并自动改写为ws/wss避免连接失败。4. 连接异常与关闭处理捕获OperationCanceledException以EndpointUnavailable关闭对端输出后直接返回不重新抛出避免取消/超时污染错误管道捕获WebSocketExceptionConnectionClosedPrematurely时关闭对端其余情况仅记录Warning 级别日志后吞掉错误——该级别从 Error 降为 Warning是因为不稳定网络中 WebSocket 频繁断连会产生大量噪音源码注释收到Close消息时把来源的CloseStatus与描述透传给对端TryCloseOutputAsync仅在状态为Open/CloseReceived时执行关闭。此外WebSocketsFactory.cs 通过代理模式创建客户端连接ClientWebSocket→ClientWebSocketConnector→ ClientWebSocketProxy.cs后者把所有WebSocket抽象方法委托给真实套接字这一抽象让中间件对底层连接具备可测试性与可替换性。代理 SignalR网关后挂实时应用Ocelot 同样支持代理 SignalR功能由 issue #344 提出8.0.7 版本发布。步骤如下第一步安装 SignalR 客户端包dotnet add package Microsoft.AspNetCore.SignalR.Client注意SignalR 是 ASP.NET Core 框架的一部分。在类库项目中可通过FrameworkReference直接引用无需 NuGet 包ItemGroup FrameworkReference IncludeMicrosoft.AspNetCore.App / /ItemGroup第二步注册服务builder.Services.AddOcelot(builder.Configuration); builder.Services.AddSignalR();注意务必关注 SignalR 的传输层配置——只有正确配置允许的传输方式TransportsWebSockets 连接才能建立。第三步配置路由{ UpstreamPathTemplate: /gateway/{catchAll}, DownstreamPathTemplate: /{catchAll}, DownstreamScheme: ws, DownstreamHostAndPorts: [ { Host: localhost, Port: 5001 } ] }标准 Ocelot 路由规则在此完全适用关键仍是DownstreamScheme: ws。{catchAll}占位符用于把/gateway/hub/xxx的路径后缀原样透传给下游 SignalR Hub解决 SignalR 协议路径如协商、连接端点必须完整保留的问题。安全通道wss 与自签名证书处理使用 wss 协议需要加密 WebSocket 连接时将路由 scheme 改为wssDownstreamScheme: wss,wss://即 WebSocket over TLS可同时用于上文所述 SignalR 场景与普通 WebSocket 场景即 docs/features/websockets.rst 文档中ws-secure小节所述you can use WebSocket SSL for both SignalR and websockets。忽略 SSL 校验强烈不建议若下游使用自签名证书且确实需要绕过验证可以配置DownstreamScheme: wss, DangerousAcceptAnyServerCertificateValidator: true,该开关在 Proxy 方法 中把RemoteCertificateValidationCallback设置为恒返回true并输出一条格式化警告日志IgnoredSslWarningFormatYou have ignored all SSL warnings...。强烈不建议在生产使用此开关该life hack由 PR #1377 引入涉及 issue #1375、#1237 等自 20.0 版本可用但官方明确表示将在未来版本移除或重构。关于 SSL 错误处理的最佳实践请参阅 docs/features/configuration.rst 中的ssl-errors章节。功能矩阵哪些 Ocelot 特性可与 WebSockets 协同支持的特性4 项路由docs/features/routing.rst——上游路径模板、catchAll 等标准路由能力完整可用负载均衡docs/features/loadbalancer.rst——可在路由中配置多个DownstreamHostAndPorts由负载均衡器选择下游实例安全选项IP 白/黑名单Security Optionsrouting-security-options小节——自 25.0 版本起IP 允许/禁止列表会在 WebSocket 升级请求上强制执行这是修复 bug #2403 的 PR #2406 的成果。从源码看WS 专用管道 ConfigureWebSockets 中同样注册了 SecurityMiddleware且其 HandleWebSocketErrors 专门处理升级请求的校验失败——因为 WS 管道没有普通 HTTP 管道中的ResponderMiddleware负责把错误翻译成状态码否则升级会以 200 OK 错误完成服务发现docs/features/servicediscovery.rst——可将路由接入服务发现提供者从而对 WebSocket 请求做负载均衡分发。即你可以让下游服务运行 WebSocket既可在路由中列出多个DownstreamHostAndPorts也可对接服务发现提供者——这是官方文档中颇为得意的组合场景。不支持的特性12 项官方明确列出以下特性在 WebSocket 场景下不会生效追踪 docs/features/tracing.rst日志中的请求 ID 关联 docs/features/logging.rstlg-request-id小节请求聚合 docs/features/aggregation.rst限流 docs/features/ratelimiting.rstQoS / 熔断 docs/features/qualityofservice.rst中间件注入 docs/features/middlewareinjection.rst——例外OcelotPipelineConfiguration的WebSocketsMiddlewareType与WebSocketsMiddleware两个属性可用见下文样例头变换 docs/features/headerstransformation.rst委托处理器 docs/features/delegatinghandlers.rstClaims 变换 docs/features/claimstransformation.rst缓存 docs/features/caching.rst认证 docs/features/authentication.rst——官方注明若社区提出需求可能会探索实现基础认证的方案授权 docs/features/authorization.rst原因很直接很多 Ocelot 特性并非针对 WebSocket 设计如头处理、HTTP 客户端功能等它们在升级/双工场景下没有对应执行点。官方同时提醒由于该特性尚未被大规模验证强烈建议在使用前做充分测试。定制中间件调整缓冲区与管道注入官方样例项目 samples/WebSocket位于Ocelot.Samples.slnx解决方案中演示了如何通过子类化WebSocketsProxyMiddleware自定义缓冲大小并以两种方式注册到 Ocelot 管道。第一步子类化中间件放大缓冲区public class MyWebSocketsProxyMiddleware : WebSocketsProxyMiddleware { protected override int BufferSize 65536; // 64 KB for high-throughput streams (e.g. HTTP.sys video streaming) public MyWebSocketsProxyMiddleware(RequestDelegate next, IOcelotLoggerFactory logging, IWebSocketsFactory factory) : base(next, logging, factory) { } }完整实现见 samples/WebSocket/MyWebSocketsProxyMiddleware.cs。默认缓冲为 4 KBDefault4KBufferSize64 KB 适用于 HTTP.sys 视频流等高吞吐场景。源码中PumpAsync还会对BufferSize做非正数校验ThrowIfNegativeOrZero因此覆写值必须大于 0。第二步通过WebSocketsMiddlewareType注册推荐var wsPipeline new OcelotPipelineConfiguration { WebSocketsMiddlewareType typeof(MyWebSocketsProxyMiddleware), }; await app.UseOcelot(wsPipeline);第三步等价方案——通过WebSocketsMiddleware委托注册var wsPipeline new OcelotPipelineConfiguration { WebSocketsMiddleware (context, next) { Task Next(HttpContext ctx) next(); var loggerFactory context.RequestServices.GetRequiredServiceIOcelotLoggerFactory(); var wsFactory context.RequestServices.GetRequiredServiceIWebSocketsFactory(); var middleware new MyWebSocketsProxyMiddleware(Next, loggerFactory, wsFactory); return middleware.Invoke(context); }, }; await app.UseOcelot(wsPipeline);优先级规则当同时设置WebSocketsMiddlewareType时它优先于WebSocketsMiddleware委托会被忽略。这一点在 OcelotPipelineExtensions.ConfigureWebSockets 中体现类型注入调用UseIfNotNullWebSocketsProxyMiddleware(configuration.WebSocketsMiddlewareType)还会校验其基类型必须是WebSocketsProxyMiddleware否则抛异常而委托仅在WebSocketsMiddlewareType is null时才注册。这两个属性定义于 OcelotPipelineConfiguration.cs完整参考见 docs/features/middlewareinjection.rst 的OcelotPipelineConfiguration章节。25.0 版本提示上述样例工程 samples/WebSocket/Program.cs 面向 25.0代码中注释了IF Ocelot version is 24.1 and lower需手动app.UseWebSockets()。该样例对应 issue #2386、PR #2387随 25.0 版本发布。测试验证仓库中的 WebSocket 测试用例仓库在 acceptance/WebSockets 目录下提供了三类验收测试可用于验证代理行为ClientWebSocketTests.cs覆盖 HTTP/1.1SSLWebSocket 栈的 Echo 回显测试含对corefx-net-http11.azurewebsites.net外网服务的 InlineData并针对 bug #930 断言WebSocketException when WebSocketErrorCode is ConnectionClosedPrematurely只被记录一次且不抛出同时标注 HTTP/2WebSocket 组合是 Ocelot 当前不支持的场景ConnectAsync对:protocol伪头的处理缺失官方留了 TODODiscoveryWebSocketTests.cs验证 WebSocket 路由对接服务发现后多个下游服务实例间可正确分发/回显WebSocketsFactoryTests.cs验证WebSocketsFactory创建连接的能力。注意部分用例标记了Assert.SkipWhen(IsCiCd(), ...)即 CI/CD 中跳过、建议本地运行这与文档充分测试后再上生产的提醒一致。版本历史与路线图能力引入版本来源WebSockets 代理5.3.0issue #212SignalR 代理8.0.7issue #344wss假验证器DangerousAcceptAnyServerCertificateValidator20.0PR #1377issue #1375、#1237内部自动调用app.UseWebSockets()、Security Options 支持 WS 升级请求、自定义中间件样例25.0issue #2386/PR #2387、bug #2403/PR #2406关于未来官方在文档 Roadmap 小节明确表示WebSocket 与 SignalR 正由 .NET 社区积极演进建议持续关注 ASP.NET Core 官方 WebSockets 与 SignalR 文档了解新版本动态。同时 Ocelot 团队认为当前 WebSockets 特性已过时——它基于自研WebSocketsProxyMiddleware而 ASP.NET Core 框架本身已提供原生WebSocketMiddleware团队有意对该特性进行迁移或重新设计跟踪 issue #1707。这提示读者长期方案应关注 Ocelot 主仓库的后续发布并在升级网关时回归验证 WS 场景。参考链接汇总本文来源文档docs/features/websockets.rst核心中间件源码src/WebSockets/WebSocketsProxyMiddleware.cs连接工厂与代理src/WebSockets/WebSocketsFactory.cs、src/WebSockets/ClientWebSocketProxy.cs管道配置src/Middleware/OcelotPipelineConfiguration.cs、src/Middleware/OcelotPipelineExtensions.cs样例工程samples/WebSocket/Program.cs、samples/WebSocket/MyWebSocketsProxyMiddleware.cs、samples/WebSocket/ocelot.json验收测试acceptance/WebSockets/ClientWebSocketTests.cs、acceptance/WebSockets/DiscoveryWebSocketTests.cs协议规范RFC 6455与 WebSockets Standard、ASP.NET Core WebSockets 支持等外部资料详见原文档 docs/features/websockets.rst 的 Handy Links 部分赞分享API网关后端微服务【免费下载链接】Ocelot.NET API Gateway项目地址https://gitcode.com/gh_mirrors/oc/Ocelot点击查看免费下载相关推荐3个实战场景高效掌握Graylog日志管理的进阶应用3个实战场景高效掌握Graylog日志管理的进阶应用 面对海量日志数据时如何从杂乱无章的信息中提取价值Graylog作为专业的开源日志管理平台能够帮助技日志分析运维观测终极sanitize-html实战教程从基础配置到高级自定义轻松净化用户提交的HTML终极sanitize html实战教程从基础配置到高级自定义轻松净化用户提交的HTML sanitize html是一款强大的HTML净化工具能够帮助开发应用安全开发工具Places365终极指南10分钟掌握场景识别AI模型Places365终极指南10分钟掌握场景识别AI模型 Places365是一款强大的场景识别AI模型能够快速准确地识别图像中的场景类型。本文将为你提供一个人工智能计算机视觉深度学习预训练上一篇Headlamp终极指南如何用这款强大的Kubernetes仪表板提升集群管理效率下一篇OfficeCLI渲染引擎揭秘如何在无Office环境下生成HTML/PNG预览创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关推荐

React 拖拽实战指南:beautiful-react-hooks 中 useDrag 的用法、自定义拖拽图像与数据传递
React 拖拽实战指南:beautiful-react-hooks 中 useDrag 的用法、自定义拖拽图像与数据传递

前端开发工具 【免费下载链接】beautiful-react-hooks 🔥 A collection of beautiful and (hopefully) useful React hooks to speed-up your components and hooks development 🔥 项目地址: https://gitcode.com/gh_mirrors/be/beautiful-r… · 2026/9/25 2:13:33

VS2017 MFC源码包实战:从编译到修改的完整指南
VS2017 MFC源码包实战:从编译到修改的完整指南

简介:这份资源是任哲《MFC Windows应用程序设计(第3版)》配套的VS2017源码包,面向正在学习Windows桌面开发、希望从理论走向动手实践的C开发者与高校学生。内容围绕MFC框架展开,涵盖CWinApp应用类、CFrameWnd主框架窗口… · 2026/9/25 2:13:27

CMake 3.24.4 Windows x86_64 官方二进制包深度解析
CMake 3.24.4 Windows x86_64 官方二进制包深度解析

简介:本资源为CMake 3.24.4官方Windows x64版本完整安装包,面向C开发者、跨平台项目构建工程师及高校计算机专业学生,用于替代系统自带或旧版CMake,解决现代C项目(如支持C20/23、CUDA、Apple Silicon交叉编译等&#x… · 2026/9/25 2:13:27

从零手写Transformer:原理拆解与PyTorch实现
从零手写Transformer:原理拆解与PyTorch实现

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 2:38:29

OpenChamber 的 pr-review 命令:基于 OpenCode 的维护者式 PR 评审工作流
OpenChamber 的 pr-review 命令:基于 OpenCode 的维护者式 PR 评审工作流

AI Agent人工智能代码智能体交互助手 【免费下载链接】openchamber Agentic Development Environment based on OpenCode AI agent 项目地址: https://gitcode.com/gh_mirrors/op/openchamber 点击查看 免费下载 导读 本文讲解 OpenChamber 仓库中用于单条 Pull R… · 2026/9/25 2:38:23

百万卡架构解析:Nested BSP与Unified Bus如何实现超节点计算
百万卡架构解析:Nested BSP与Unified Bus如何实现超节点计算

1. 从「百万卡」这个数字说起:为什么规模本身就是一道架构题第一次看到「百万卡还算一台计算机」这个说法,我的反应是:这不就是堆机器吗?但仔细想一下,如果只是把一百万张加速卡插上电、连上网,它大概率跑不… · 2026/9/25 2:38:23

F´ 框架中的 Utils::LockGuard:基于 Os::Mutex 的 RAII 作用域锁守卫实战指南
F´ 框架中的 Utils::LockGuard:基于 Os::Mutex 的 RAII 作用域锁守卫实战指南

嵌入式系统编程 【免费下载链接】fprime F - A flight software and embedded systems framework 项目地址: https://gitcode.com/gh_mirrors/fp/fprime 点击查看 免费下载 导读 Utils::LockGuard 是 F(F Prime,飞行软件与嵌入式系统框架&a… · 2026/9/25 2:38:23

鸿蒙应用内日志组件升级:从不可见到可查可分享
鸿蒙应用内日志组件升级:从不可见到可查可分享

做鸿蒙应用开发,最磨人的不是写业务逻辑,而是排查问题。尤其当应用发到别人手里,用户回你一句“点了没反应”,或者“崩了,啥也没干就崩了”,而你手里连一行有效日志都没有,那种感觉真的很难受。… · 2026/9/25 2:38:23

MLX90614积木使用完全指南:3块积木搞定初始化、物体温度与环境温度读取
MLX90614积木使用完全指南:3块积木搞定初始化、物体温度与环境温度读取

MLX90614积木使用完全指南:3块积木搞定初始化、物体温度与环境温度读取 【免费下载链接】CupCode_MLX90614红外测温模块 源师兄的红外测试模块扩展 项目地址: https://gitcode.com/yuanshixiong/mlx0614 本指南带你快速上手 MLX90614 积木——源师兄的红外测… · 2026/9/25 2:38:17

数值优化(Numerical Optimization)学习系列-03-共轭梯度方法(Conjugate Gradient)
数值优化(Numerical Optimization)学习系列-03-共轭梯度方法(Conjugate Gradient)

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:00:31

创维E900V22D刷机全攻略:S905L3SB芯片兼容性解析与救砖实战
创维E900V22D刷机全攻略:S905L3SB芯片兼容性解析与救砖实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:00:31

MQTT协议原理与Broker服务器搭建实战:从Mosquitto到EMQX
MQTT协议原理与Broker服务器搭建实战:从Mosquitto到EMQX

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:00:37

了解更多?预约专属演示

我们的顾问将为您一对一讲解产品与方案

企业微信二维码