第一章:引言与背景
1.1 微服务架构的兴起与 API 网关的重要性
在过去的十年中,软件架构经历了从单体应用向微服务架构的重大转变。微服务通过将复杂系统拆分为多个独立部署、松耦合的服务单元,显著提升了系统的可维护性、可扩展性和开发效率。
然而,微服务架构也带来了新的挑战:
- 客户端需要与多个服务直接通信,增加了调用复杂度;
- 跨服务的身份认证、限流、熔断、日志追踪等横切关注点难以统一管理;
- 服务发现、负载均衡、协议转换等问题需集中处理。
为解决这些问题,API 网关(API Gateway)应运而生。API 网关作为系统的统一入口,承担了路由转发、安全控制、流量治理、协议适配等核心职责,成为微服务架构中不可或缺的组件。
1.2 Ocelot:.NET 生态中的经典网关
Github:ThreeMammals/Ocelot
在 .NET 生态中,Ocelot是早期最流行的开源 API 网关实现之一。它基于 ASP.NET Core 构建,支持请求路由与重写、身份验证与授权、限流、负载均衡、服务发现集成等功能。
Ocelot 因其配置简单、社区活跃、文档丰富,被广泛应用于中小型 .NET 微服务项目中。
然而,随着微服务规模扩大和性能要求提升,Ocelot 的局限性逐渐显现:
- 性能瓶颈:基于中间件链式调用,高并发下延迟较高;
- 功能扩展困难:插件机制不够灵活;
- 维护活跃度下降:核心团队更新缓慢;
- 缺乏对 HTTP/2、gRPC 等现代协议的原生支持。
1.3 YARP:微软官方推出的下一代反向代理网关
Github:dotnet/yarp
为应对上述挑战,微软于 2020 年正式推出YARP(Yet Another Reverse Proxy),并将其定位为“微软新一代网关”。YARP 并非传统意义上的完整 API 网关,而是一个高性能、可扩展、基于 .NET 的反向代理框架,开发者可在此基础上构建定制化网关。
YARP 的核心优势:
- 极致性能:YARP 直接基于
System.Net.Http 和 Kestrel 构建,绕过传统中间件管道,实现接近原生 HttpClient 的转发性能。官方基准测试显示,YARP 在吞吐量和延迟方面显著优于 Ocelot。
- 高度可定制:YARP 提供丰富的扩展点,允许开发者按需注入业务逻辑。
- 现代化协议支持:原生支持 HTTP/1.1、HTTP/2、WebSocket,未来计划支持 gRPC 代理。
- 微软官方维护:作为 .NET 基金会项目,YARP 获得微软持续投入,版本迭代稳定,安全性有保障。
- 与 .NET 生态无缝集成:支持依赖注入、配置系统、日志、指标等标准 .NET 功能,是现代.NET后端架构的优选组件。
1.4 为什么选择 YARP 替代 Ocelot?
| 对比维度 |
Ocelot |
YARP |
| 性能 |
中等,中间件链式调用 |
高,直接底层网络操作 |
| 可扩展性 |
插件有限,需继承特定类 |
开放扩展点,任意中间件或自定义逻辑 |
| 协议支持 |
主要 HTTP/1.1 |
HTTP/1.1, HTTP/2, WebSocket |
| 社区与维护 |
社区驱动,更新缓慢 |
微软官方维护,持续更新 |
| 学习曲线 |
简单,配置即用 |
需一定 .NET 底层知识 |
| 适用场景 |
中小型项目,快速搭建 |
中大型项目,高性能、高定制需求 |
结论:对于新项目或计划重构网关的现有系统,YARP 是更优选择。
1.5 本书目标与结构预览
本书旨在通过一个完整的电商微服务系统 Demo,教你如何使用 YARP 逐步构建高性能、可扩展的 API 网关。
项目 Demo 概述:
- 前端:React SPA
- 网关层:YARP
- 微服务:用户服务、商品服务、订单服务、支付服务
- 基础设施:Docker + Kubernetes、Consul、Redis、Prometheus + Grafana
第二章:YARP 核心原理与架构解析
2.1 YARP 是什么?——重新定义反向代理
YARP 是微软于 2020 年开源的高性能反向代理框架,其目标不是提供一个“开箱即用”的完整网关产品,而是为开发者提供一个可编程、可扩展、高性能的基础构建块,用于构建自定义的 API 网关、边缘服务或内部流量路由系统。
关键定位:YARP 是一个框架,而非产品。这意味着你需要编写少量代码来“激活”其能力,但换来的是极致的灵活性和性能。
YARP 的设计哲学源于微软内部大规模微服务系统的实践经验,同时完全基于 .NET 生态构建,天然支持云原生场景。
2.2 YARP 的整体架构
YARP 的架构清晰分层,主要由以下核心组件构成:
┌───────────────────────────────────────┐
│ HTTP 请求 (Ingress) │
└──────────────────┬────────────────────┘
▼
┌───────────────────────────────────────┐
│ ASP.NET Core 中间件管道 │
│ ┌─────────────┐ ┌─────────────┐ │
│ │ 自定义中间件 │ → │ YARP 中间件 │ │
│ └─────────────┘ └──────┬──────┘ │
└────────────────────────────┼──────────┘
▼
┌─────────────────────────────────┐
│ 路由匹配引擎 (Matcher) │
└────────────────┬────────────────┘
▼
┌─────────────────────────────────┐
│ 目标集群选择 (Cluster) │
└────────────────┬────────────────┘
▼
┌─────────────────────────────────┐
│ 请求转发器 (HttpProxy) │
│ (基于 HttpClient + Sockets) │
└────────────────┬────────────────┘
▼
┌───────────────────────┐
│ 后端服务 (Destination)│
└───────────────────────┘
核心模块说明:
1. YARP 中间件(YarpMiddleware)
- 注册在 ASP.NET Core 管道中;
- 拦截所有进入的 HTTP 请求;
- 触发路由匹配逻辑;
- 若匹配成功,则交由
HttpProxy 执行转发。
2. 路由配置模型(Route & Cluster)
YARP 使用两层抽象:
- Route(路由):定义如何匹配传入请求(如路径、方法、主机头等)。
- Cluster(集群):定义一组后端目标(Destinations),包含负载均衡策略、健康检查、HTTP 客户端配置等。
3. HttpProxy(核心转发器)
- 直接操作底层
SocketsHttpHandler,支持连接复用、HTTP/2 多路复用、流式传输;
- 实现“零拷贝”转发以提升性能;
- 支持请求/响应头修改、超时控制、重试机制等。
4. 可扩展点
YARP 提供多个接口供开发者注入自定义逻辑,如动态加载路由配置、修改请求/响应内容、自定义健康检查逻辑等。
2.3 YARP 的工作流程详解
当一个 HTTP 请求到达 YARP 网关时,其处理流程如下:
- 请求进入 ASP.NET Core 管道:由 Kestrel 接收,依次经过各类中间件。
- YARP 中间件拦截请求:获取当前生效的路由列表。
- 路由匹配:遍历所有 Route,按优先级或顺序进行匹配。
- 集群选择:根据匹配到的 Route 找到对应的 Cluster,执行负载均衡和健康检查。
- 请求转发:构造新的 HttpRequestMessage,应用转换规则,通过底层 HttpClient 发送到后端,并流式读取响应。
- 错误处理与重试:若后端失败,可配置重试策略。
- 日志与指标上报:自动记录代理延迟、状态码等,可集成分布式追踪。
2.4 YARP 与传统反向代理的对比
| 特性 |
Nginx |
Envoy |
YARP |
| 语言 |
C |
C++ |
C# (.NET) |
| 配置方式 |
静态配置文件 |
动态 xDS API |
JSON / Code / 动态 Provider |
| 扩展性 |
Lua / C 模块 |
WASM / C++ Filter |
C# 接口 / DI / 中间件 |
| 性能 |
极高 |
高 |
高(接近 HttpClient 原生性能) |
| 与 .NET 集成 |
弱 |
弱 |
极强 |
YARP 的独特价值:在 .NET 技术栈内,无需引入外部组件,即可实现高性能网关,且能深度集成业务逻辑。
2.5 本章小结
本章深入剖析了 YARP 的设计哲学、核心架构及其在 .NET 生态中的独特定位。我们明确了 YARP 是一个可编程的反向代理框架,其高性能来源于对底层网络栈的直接操作,通过 Route + Cluster 模型实现灵活路由,丰富的扩展点支持高度定制化需求。在 .NET 微服务场景中,YARP 是替代传统方案的理想选择。
第三章:从零搭建 YARP 网关项目
本章将带领你从空白项目开始,一步步构建一个可运行的 YARP 网关,并实现对后端微服务的代理转发。我们将采用 .NET 8 作为开发框架。
3.1 环境准备
开发环境要求
- 操作系统:Windows / Linux / macOS
- .NET SDK:.NET 8.0(LTS)
- IDE:Visual Studio 2022 或 VS Code
创建解决方案结构
建议采用分层项目结构:
ECommerce.Gateway.Solution/
├── src/
│ ├── ECommerce.Gateway/ ← YARP 网关主项目
│ ├── ECommerce.UserService/ ← 用户微服务(Demo)
│ └── ECommerce.ProductService/ ← 商品微服务(Demo)
└── tests/
3.2 创建 YARP 网关项目
使用 CLI 创建项目
# 创建解决方案
dotnet new sln -n ECommerce.Gateway.Solution
# 创建网关项目
dotnet new webapi -n ECommerce.Gateway -o src/ECommerce.Gateway
# 添加到解决方案
dotnet sln add src/ECommerce.Gateway
安装 YARP NuGet 包
进入网关项目目录,执行:
dotnet add package Yarp.ReverseProxy
3.3 配置 YARP 基础代理功能
修改 Program.cs
打开Program.cs,替换为以下内容:
using Yarp.ReverseProxy;
var builder = WebApplication.CreateBuilder(args);
// 注册 YARP 服务
builder.Services.AddReverseProxy()
.LoadFromConfig(builder.Configuration.GetSection("ReverseProxy"));
var app = builder.Build();
// 启用 YARP 中间件
app.MapReverseProxy();
app.Run();
配置 appsettings.json
在appsettings.json中添加ReverseProxy节点:
{
"ReverseProxy": {
"Routes": {
"user_route": {
"ClusterId": "user_cluster",
"Match": { "Path": "/api/users/{**remainder}" }
},
"product_route": {
"ClusterId": "product_cluster",
"Match": { "Path": "/api/products/{**remainder}" }
}
},
"Clusters": {
"user_cluster": {
"Destinations": { "user1": { "Address": "http://localhost:5001" } }
},
"product_cluster": {
"Destinations": { "product1": { "Address": "http://localhost:5002" } }
}
}
}
}
3.4 创建两个 Demo 微服务(用于测试)
用户服务(UserService)
dotnet new webapi -n ECommerce.UserService -o src/ECommerce.UserService
dotnet sln add src/ECommerce.UserService
修改其Program.cs,监听端口 5001,并定义简单 API 端点。
商品服务(ProductService)
dotnet new webapi -n ECommerce.ProductService -o src/ECommerce.ProductService
dotnet sln add src/ECommerce.ProductService
修改其Program.cs,监听端口 5002,并定义简单 API 端点。
3.5 启动与测试
同时启动三个项目
在三个独立的终端中分别运行三个项目。
发送测试请求
使用 curl 测试网关路由:
# 测试用户服务
curl http://localhost:5000/api/users
# 响应: Hello from User Service!
# 测试商品服务
curl http://localhost:5000/api/products
# 响应: Hello from Product Service!
如果看到上述响应,说明 YARP 网关已成功代理请求。
3.6 关键机制解析
路径重写行为
YARP 默认保留原始路径转发。例如,请求 /api/users/123 会转发到 http://localhost:5001/api/users/123。若需重写路径,可通过 Transforms 实现。
请求头透传
YARP 自动透传大部分请求头,但会添加标准代理头(如 X-Forwarded-For),后端服务可据此获取客户端真实 IP。
错误处理
- 若后端服务未启动,YARP 返回
502 Bad Gateway。
- 若路由不匹配,请求会继续执行后续中间件管道。
3.7 本章小结
本章完成了基于 .NET 8 的 YARP 网关项目创建、静态路由配置,并搭建了测试微服务验证了请求代理功能。你现在拥有了一个可工作的 YARP 网关原型,为后续集成高级功能打下基础。
第四章:路由配置详解——静态路由 vs 动态路由
在 YARP 中,路由是决定请求如何被处理的核心规则。本章将深入讲解 YARP 路由系统的各种匹配机制、配置方式及其适用场景。
4.1 路由的基本结构
YARP 的路由由 Match 条件和 Action 行为两部分组成。在配置中,一个典型路由如下:
"route_id": {
"ClusterId": "backend_cluster",
"Match": {
"Path": "/api/{**catchall}",
"Methods": [ "GET", "POST" ],
"Hosts": [ "api.example.com" ]
}
}
4.2 静态路由配置详解
静态路由指在应用启动时从配置文件加载,运行期间不可变的路由规则。
路径匹配模式
- 精确匹配:
"Path": "/health"
- 参数占位符:
"Path": "/api/users/{id}"
- 通配符捕获:
"Path": "/api/{**remainder}" (必须放在路径末尾)
多条件组合匹配
YARP 支持 AND 逻辑组合多个匹配条件,如同时匹配路径、HTTP 方法、主机头和自定义请求头。
路由优先级控制
当多个路由可能匹配同一请求时,可通过显式设置 Order 字段(数值越小越优先)或依赖配置文件中的声明顺序来决定优先级。
可以配置路由根据特定的请求头(Header)或查询参数(Query Parameter)进行匹配,适用于灰度发布等场景。
4.4 动态路由配置:为什么需要它?
当微服务实例动态扩缩容、需要实时调整路由规则或与服务注册中心集成时,静态配置存在局限,此时动态路由配置成为必需。
4.5 实现动态路由:自定义 IProxyConfigProvider
YARP 通过 IProxyConfigProvider 接口支持动态配置加载。
创建动态配置提供者
创建一个实现 IProxyConfigProvider 接口的类,用于从内存、数据库或 API 加载路由和集群配置。该类需要提供一个 ChangeToken,以便在配置变更时通知 YARP 热更新。
注册动态提供者
在 Program.cs 中注册自定义的 IProxyConfigProvider,并确保 YARP 使用它来获取配置。
添加管理 API
可以暴露一个 API 端点,用于测试动态添加路由,无需重启网关即可生效。
4.6 与服务发现集成
在实际生产中,动态路由通常与 Consul、Kubernetes 等服务发现工具集成,自动根据服务实例的变化更新路由配置。
4.7 静态 vs 动态路由对比总结
| 维度 |
静态路由 |
动态路由 |
| 配置来源 |
appsettings.json |
代码 / 数据库 / 服务注册中心 |
| 更新方式 |
重启应用 |
热更新(无需重启) |
| 适用规模 |
小型、稳定系统 |
中大型、弹性系统 |
| 开发复杂度 |
低 |
中高 |
最佳实践:初期使用静态路由快速验证,上线前切换为动态路由以支持弹性伸缩。
4.8 本章小结
本章全面解析了 YARP 路由系统的配置能力,包括静态路由的多维匹配、动态路由的实现原理,为后续与服务发现集成打下基础。
第五章:身份认证与授权集成
在微服务架构中,统一身份认证与授权是 API 网关的核心职责之一。本章将教你如何在 YARP 网关中集成 JWT Bearer Token 验证。
5.1 认证模型设计:网关 vs 微服务
两种常见模式
- 网关认证 + 透传 Token:网关验证 JWT 合法性,验证通过后将原始 Token 转发给后端。(推荐)
- 网关认证 + 剥离 Token:网关验证后生成内部凭证,后端无需处理 JWT。
YARP 推荐采用第一种模式:网关负责“认证”,微服务负责“授权”。
5.2 在 YARP 中集成 JWT Bearer 认证
YARP 本身不包含认证逻辑,但可无缝集成 ASP.NET Core 的标准认证中间件。
添加认证服务
在 Program.cs 中添加 JWT Bearer 认证服务,配置颁发者(Authority)、受众(Audience)等验证参数。
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options => {
options.Authority = "https://localhost:5005";
options.Audience = "ecommerce_api";
});
并在 HTTP 请求管道中启用认证与授权中间件,顺序必须在 MapReverseProxy() 之前。
配置受保护路由
可以为特定路由配置授权策略(AuthorizationPolicy),要求请求必须经过认证。未配置策略的路由则允许公开访问。
5.3 搭建本地身份提供商(用于测试)
可以快速搭建一个简易的 IdentityServer4 或 OpenIddict 项目,用于颁发测试用的 JWT Token。配置包括定义 API 作用域、客户端和测试用户。
5.4 获取测试 Token 并调用网关
使用工具向身份提供商请求 Token,然后在调用受保护的网关接口时,在 Authorization 头中携带该 Token。网关会验证 Token 的有效性。
5.5 高级场景:Claims 转换与头注入
通过 YARP 的 Transforms 功能,可以在转发请求前,将认证用户的信息(如用户ID、角色)从 JWT Claims 中提取出来,并注入到新的请求头(如 X-User-ID)中传递给后端微服务。这有助于实现安全的上下文传递,避免后端重复解析 Token。
5.6 本章小结
本章完成了在 YARP 网关中集成 JWT 认证、按路由策略控制访问权限,并通过 Transforms 将用户信息注入请求头。你现在拥有了一个具备统一认证能力的安全网关。
第六章:限流与熔断策略实现
在高并发微服务系统中,流量治理是保障系统稳定性的关键手段。YARP 可轻松集成 .NET 生态中的成熟组件实现限流与熔断。
6.1 限流策略设计
为什么需要限流?
防止恶意攻击、保护后端服务不被突发流量压垮、实现多租户配额管理等。
限流维度
包括全局限流、路由限流、客户端限流(按 IP 或 API Key)、用户限流(按用户 ID)。推荐组合使用。
6.2 集成 AspNetCoreRateLimit 实现限流
安装与配置
安装 AspNetCoreRateLimit NuGet 包,并在 Program.cs 中注册所需服务(内存缓存、配置选项等)。在 HTTP 管道中尽早启用限流中间件。
配置限流规则
在 appsettings.json 中配置 IP 或客户端限流规则,可以针对特定端点(路由)设置时间段内的请求次数限制。超出限制的请求将返回 429 状态码。
对于需要结合 JWT Claims 等业务属性的更灵活限流逻辑,可以利用 YARP 的 Request Transform,在转发前执行自定义的限流判断,并通过设置 SuppressProxyPipeline 来阻止转发。
6.4 熔断策略:防止雪崩效应
什么是熔断?
熔断器模式包含三种状态:关闭(正常)、打开(快速失败)、半开(尝试恢复)。当后端服务失败率达到阈值时触发熔断,避免资源耗尽。
集成 Polly 实现熔断
安装 Polly 包。通过 YARP 的 ConfigureHttpClient 方法,为每个集群的 HttpClient 配置 Polly 的熔断策略,例如在连续出现5次失败后熔断30秒。
6.5 限流与熔断的监控与告警
配置限流库和熔断策略的日志记录,并在状态变更时(如触发熔断)上报指标或触发告警,这对于运维至关重要。
6.6 本章小结
本章实现了 YARP 网关的限流与熔断两大核心稳定性机制。你的网关现在不仅能转发请求,还具备了自我保护能力,确保核心服务在高负载或下游异常时的可用性。