ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

基于 .NET 6 + YARP 的多种应用场景:从反向代理到负载均衡的 API 网关落地大纲

基于 .NET 6 + YARP 的多种应用场景:从反向代理到负载均衡的 API 网关落地大纲 1. 从单体到网关.NET 6 YARP 到底解决什么问题如果你手上有一堆 .NET 6 的 Web API 项目每个服务各自监听不同端口前端调用时要在http://localhost:5001、http://localhost:5002之间来回切换那 API 网关就是绕不过去的一环。YARPYet Another Reverse Proxy是微软官方开源的反向代理库它不是一个独立进程而是一组可以塞进 ASP.NET Core 管道的中间件。这意味着你可以用写 Controller 的方式去写代理逻辑路由、集群、转换规则都能用 C# 或 JSON 配置。它适合谁适合已经在用 .NET 6、想给微服务加统一入口、又不想引入 Nginx 或 Envoy 这类外部组件的团队。YARP 的核心概念只有两个Route路由负责匹配进来的请求Cluster集群负责决定转发到哪些后端。一个 Route 绑定一个 ClusterCluster 里可以放多个 Destination负载均衡策略就作用在这些 Destination 上。我试过把三个本地 API 服务挂到同一个 YARP 网关后面前端只需要记住http://localhost:8000一个地址剩下的路径分发、后端选择全部由网关处理。下面从零开始把反向代理、负载均衡、多后端路由三类场景的配置和验证步骤完整走一遍最后再把上游 endpoint 切到 TaoToken 的统一通道方便后续按场景扩展。2. TaoToken 前置准备统一 Key 与 API 通道在把 YARP 的上游地址指向 TaoToken 之前需要先拿到可用的 API Key 和 Base URL。TaoToken 的 API 入口是https://taotoken.net/api控制台里可以创建和管理 Key。这一步不复杂但有几个细节容易踩坑。首先注册或登录后进入控制台找到 API Keys 页面新建一个 Key。建议按用途命名比如yarp-gateway-dev这样后面在 YARP 配置里看到这个 Key 就知道是给网关用的。Key 只在创建时完整显示一次复制后先存到本地环境变量或密钥管理工具里不要直接硬编码进appsettings.json提交到仓库。其次确认你要调用的模型 ID。TaoToken 的模型对话页面可以查看当前可用的模型列表选一个你打算在网关后面代理的模型记下它的 Model ID。YARP 本身不关心模型它只负责转发 HTTP 请求但你的后端服务或调用方需要知道往请求体里填哪个模型名。然后把 Base URL 和 Key 准备好。YARP 的 Cluster Destination 地址填https://taotoken.net/api认证头通过 Transform 或后端服务自行添加。如果你希望网关统一注入 Authorization 头可以在 YARP 的 Transform 里配置RequestHeader设置把Bearer 你的Key加到转发请求上。这样后端服务不需要各自管理 Key网关层统一处理。最后验证 Key 是否可用。可以用 curl 直接打一次模型对话接口确认返回正常。这一步做完再进入 YARP 的配置环节避免后面排查问题时分不清是网关配置错了还是 Key 本身有问题。3. 可复制配置反向代理、负载均衡与多后端路由这一节给出三套可以直接粘贴的配置片段分别对应反向代理、负载均衡和多后端路由。所有配置都基于 .NET 6 的appsettings.json和Program.cs路径和字段名与 YARP 官方文档一致。3.1 反向代理按路径分发到不同服务先看最基础的反向代理。假设你有两个后端服务用户服务跑在http://localhost:5001订单服务跑在http://localhost:5002。你希望外部访问http://localhost:8000/api/user/...时转发到用户服务访问http://localhost:8000/api/order/...时转发到订单服务。appsettings.json配置如下{ ReverseProxy: { Routes: { user-api: { ClusterId: user-cluster, Match: { Path: api/user/{**catch-all} }, Transforms: [ { PathRemovePrefix: /api/user } ] }, order-api: { ClusterId: order-cluster, Match: { Path: api/order/{**catch-all} }, Transforms: [ { PathRemovePrefix: /api/order } ] } }, Clusters: { user-cluster: { Destinations: { user-service: { Address: http://localhost:5001 } } }, order-cluster: { Destinations: { order-service: { Address: http://localhost:5002 } } } } } }Program.cs里只需要三行核心代码using Yarp.ReverseProxy; var builder WebApplication.CreateBuilder(args); builder.Services.AddReverseProxy() .LoadFromConfig(builder.Configuration.GetSection(ReverseProxy)); var app builder.Build(); app.MapReverseProxy(); app.Run();这里的关键是PathRemovePrefix转换。外部请求/api/user/users进入网关后前缀/api/user被去掉转发到用户服务的路径变成/users。如果你的后端服务本身已经带了/api/user前缀那就不需要这个转换直接转发即可。3.2 负载均衡同一集群多实例分流当同一个服务有多个实例时把它们的地址都放进同一个 Cluster 的 Destinations 里然后指定LoadBalancingPolicy。YARP 内置了RoundRobin、Random、LeastRequests等策略。{ ReverseProxy: { Routes: { default: { ClusterId: backend-cluster, Match: { Path: {**catch-all} } } }, Clusters: { backend-cluster: { Destinations: { server1: { Address: http://localhost:5001 }, server2: { Address: http://localhost:5002 }, server3: { Address: http://localhost:5003 } }, LoadBalancingPolicy: RoundRobin } } } }把LoadBalancingPolicy改成Random就是随机分流。实测下来RoundRobin在实例性能相近时最稳LeastRequests适合实例处理能力不一致的场景。注意 Destination 的 key 名字只是标识不影响转发但建议起有意义的名字方便排查。3.3 多后端路由按请求头选择集群多租户或多环境场景下可以根据请求头来动态选择后端。比如请求里带X-Tenant: tenant1就走租户一的集群带X-Tenant: tenant2就走租户二。{ ReverseProxy: { Routes: { tenant1: { ClusterId: tenant1-cluster, Match: { Headers: { X-Tenant: { Values: [ tenant1 ] } } } }, tenant2: { ClusterId: tenant2-cluster, Match: { Headers: { X-Tenant: { Values: [ tenant2 ] } } } } }, Clusters: { tenant1-cluster: { Destinations: { server1: { Address: http://localhost:5001 } } }, tenant2-cluster: { Destinations: { server2: { Address: http://localhost:5002 } } } } } }这种配置下同一个路径/api/data会根据请求头转发到不同后端。如果你要把上游 endpoint 统一改到 TaoToken只需要把 Cluster 里的 Address 换成https://taotoken.net/api然后在 Transform 里加上 Authorization 头。这样网关层就变成了一个统一的 API 通道入口后面按场景扩展时只需要增删 Route 和 Cluster。4. 验证请求从 curl 到成功结果配置写完后启动网关和各个后端服务用 curl 逐个验证。先确认网关本身在监听http://localhost:8000然后按场景测试。反向代理场景下启动用户服务和订单服务分别监听 5001 和 5002。然后执行curl http://localhost:8000/api/user/users curl http://localhost:8000/api/order/orders如果返回的是用户服务和订单服务的正常响应说明路径匹配和前缀移除都生效了。如果返回 404先检查Match.Path的写法{**catch-all}必须放在路径末尾且前缀不要带多余的斜杠。负载均衡场景下启动三个后端实例每个实例在响应里带上自己的端口号。然后连续请求多次for i in {1..6}; do curl -s http://localhost:8000/api/values; echo; done如果看到端口号按顺序轮换说明RoundRobin生效。如果每次都打到同一个实例检查LoadBalancingPolicy的拼写以及 Destinations 里是否确实配置了多个地址。多后端路由场景下用请求头区分curl -H X-Tenant: tenant1 http://localhost:8000/api/data curl -H X-Tenant: tenant2 http://localhost:8000/api/data两次请求应该返回不同后端的数据。如果不带X-Tenant头YARP 会因为没有任何 Route 匹配而返回 404这是预期行为。你可以加一个默认 Route 来兜底。当上游地址切到 TaoToken 后验证方式类似只是后端变成了https://taotoken.net/api。你可以用模型对话接口做一次端到端测试确认网关转发、认证头注入、响应回传整条链路通畅。5. 常见报错排查401、local proxy failed 与 reading choices这一节整理几个实际会遇到的报错和排查思路。401 Unauthorized如果网关转发到 TaoToken 后返回 401先检查 Authorization 头有没有正确注入。YARP 默认不会自动加认证头你需要在 Transform 里配置RequestHeader或者在后端服务里统一处理。另外确认 Key 没有过期以及请求头格式是Bearer Key中间有一个空格。local proxy failed这个报错通常出现在网关无法连接到后端 Destination。检查 Address 是否可达本地服务是否真的在监听对应端口。如果是 Docker 环境localhost在容器里指向容器自身需要用宿主机的实际 IP 或服务名。另外确认没有防火墙拦截。reading choices 相关报错如果你代理的是模型对话接口返回体里解析choices字段时报错先确认响应体是不是完整的 JSON。YARP 默认会缓冲响应但如果后端返回的是流式数据需要检查是否开启了流式转发。另外确认请求体里的 Model ID 是 TaoToken 支持的模型模型名写错时上游可能返回错误结构导致下游解析失败。OAuth 或认证跳转问题如果后端服务本身有 OAuth 流程经过 YARP 代理后回调地址可能不对。需要在 Transform 里重写Location头或Host头确保回调地址指向网关而不是后端服务。排查时建议先绕过网关直接用 curl 打后端地址确认后端本身正常。然后再经过网关打一次对比两次的请求头和响应体差异。YARP 的日志级别调到Debug可以看到详细的路由匹配和转发信息对定位问题很有帮助。6. 把上游 endpoint 切到 TaoToken统一 Key 与后续扩展前面所有场景的 Cluster Destination 都可以指向 TaoToken 的 API 地址。以反向代理场景为例把user-cluster的 Address 改成https://taotoken.net/api然后在 Route 的 Transforms 里加上认证头{ Transforms: [ { PathRemovePrefix: /api/user }, { RequestHeader: Authorization, Set: Bearer 你的TaoToken Key } ] }这样外部请求进入网关后网关统一加上 Key 再转发到 TaoToken。后端服务不需要各自管理 Key换 Key 时只改网关配置一处。如果你用的是 Coding Plan 或需要长期跑 Agent 任务建议把 Key 放在环境变量里通过builder.Configuration读取避免明文写在 JSON 里。后续按场景扩展时新增一个后端只需要在 Clusters 里加一个 Destination或者在 Routes 里加一条匹配规则。比如你要加一个按模型 ID 分流的场景可以用Match.QueryParameters匹配请求参数里的model字段转发到不同的 Cluster。YARP 的配置是热加载的改完appsettings.json后不需要重启进程网关会自动应用新配置。验证整条链路时用模型对话接口发一次请求确认返回正常。如果遇到问题回到第 5 节的排查步骤先确认 Key 和 Base URL 正确再检查 Transform 有没有生效。接入文档里有更详细的参数说明API Keys 页面可以随时新建或吊销 Key。整套配置跑通后你就有了一个基于 .NET 6 YARP 的 API 网关既能做反向代理和负载均衡也能作为统一的上游通道按场景灵活扩展。
返回列表