# YARP 配置模型分析 **来源:** [microsoft/reverse-proxy](https://github.com/microsoft/reverse-proxy) **日期:** 2026-03-03 --- ## 核心概念 YARP (Yet Another Reverse Proxy) 的配置模型由三个核心接口/类组成: 1. **IProxyConfigProvider** - 配置数据源接口 2. **IProxyConfig** - 配置快照接口 3. **RouteConfig / ClusterConfig** - 路由和集群配置 ``` ┌─────────────────────────────────────────────────────────────┐ │ IProxyConfigProvider │ │ GetConfig() → IProxyConfig │ └─────────────────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────┐ │ IProxyConfig │ │ ┌─────────────────────┐ ┌─────────────────────┐ │ │ │ RouteConfig[] │ │ ClusterConfig[] │ │ │ │ (路由规则) │ │ (集群配置) │ │ │ └─────────────────────┘ └─────────────────────┘ │ │ ChangeToken: IChangeToken (配置变更通知) │ └─────────────────────────────────────────────────────────────┘ ``` --- ## 1. RouteConfig (路由配置) 路由定义了如何匹配传入请求并将其代理到集群。 ### 核心字段 | 字段 | 类型 | 必填 | 说明 | |------|------|------|------| | `RouteId` | `string` | ✓ | 全局唯一路由标识 | | `Match` | `RouteMatch` | ✓ | 请求匹配规则 | | `ClusterId` | `string` | ○ | 目标集群 ID | | `Order` | `int?` | ○ | 路由优先级 (数值越小优先级越高) | | `AuthorizationPolicy` | `string?` | ○ | 授权策略名称 | | `RateLimiterPolicy` | `string?` | ○ | 限流策略名称 | | `TimeoutPolicy` | `string?` | ○ | 超时策略名称 | | `CorsPolicy` | `string?` | ○ | CORS 策略名称 | | `MaxRequestBodySize` | `long?` | ○ | 请求体最大大小 | | `Metadata` | `IReadOnlyDictionary?` | ○ | 自定义元数据 | | `Transforms` | `IReadOnlyList>?` | ○ | 请求/响应转换规则 | ### RouteMatch (匹配规则) | 字段 | 类型 | 说明 | |------|------|------| | `Methods` | `IReadOnlyList?` | HTTP 方法列表 (GET, POST 等) | | `Hosts` | `IReadOnlyList?` | Host 头匹配 (支持通配符) | | `Path` | `string?` | 路径模式 (如 `/api/{**catch-all}`) | | `Headers` | `IReadOnlyList?` | 请求头匹配规则 | | `QueryParameters` | `IReadOnlyList?` | 查询参数匹配规则 | --- ## 2. ClusterConfig (集群配置) 集群是一组等价的后端服务端点及其相关策略。 ### 核心字段 | 字段 | 类型 | 必填 | 说明 | |------|------|------|------| | `ClusterId` | `string` | ✓ | 全局唯一集群标识 | | `Destinations` | `IReadOnlyDictionary?` | ○ | 目标端点字典 | | `LoadBalancingPolicy` | `string?` | ○ | 负载均衡策略 | | `SessionAffinity` | `SessionAffinityConfig?` | ○ | 会话亲和配置 | | `HealthCheck` | `HealthCheckConfig?` | ○ | 健康检查配置 | | `HttpClient` | `HttpClientConfig?` | ○ | HTTP 客户端配置 | | `HttpRequest` | `ForwarderRequestConfig?` | ○ | 出站请求配置 | | `Metadata` | `IReadOnlyDictionary?` | ○ | 自定义元数据 | ### DestinationConfig (目标端点) | 字段 | 类型 | 必填 | 说明 | |------|------|------|------| | `Address` | `string` | ✓ | 后端地址 (如 `https://127.0.0.1:8080/`) | | `Health` | `string?` | ○ | 主动健康检查端点 | | `Host` | `string?` | ○ | Host 头值 | | `Metadata` | `IReadOnlyDictionary?` | ○ | 自定义元数据 | --- ## 3. 负载均衡策略 YARP 内置以下负载均衡策略: | 策略名称 | 说明 | |----------|------| | `RoundRobin` | 轮询 | | `LeastRequests` | 最少请求 | | `Random` | 随机 | | `PowerOfTwoChoices` | 二选一 (推荐默认) | | `First` | 第一个 | | `WeightedRoundRobin` | 加权轮询 | > **注意:** `WeightedRoundRobin` 需要在 Destination 的 Metadata 中配置 `Weight` 字段。 --- ## 4. 健康检查配置 ### HealthCheckConfig ```csharp public sealed record HealthCheckConfig { public PassiveHealthCheckConfig? Passive { get; init; } // 被动健康检查 public ActiveHealthCheckConfig? Active { get; init; } // 主动健康检查 public string? AvailableDestinationsPolicy { get; init; } // 可用目标策略 } ``` ### ActiveHealthCheckConfig (主动健康检查) | 字段 | 类型 | 说明 | |------|------|------| | `Enabled` | `bool?` | 是否启用 | | `Interval` | `TimeSpan?` | 检查间隔 | | `Timeout` | `TimeSpan?` | 超时时间 | | `Policy` | `string?` | 健康检查策略 | | `Path` | `string?` | 健康检查路径 | ### PassiveHealthCheckConfig (被动健康检查) | 字段 | 类型 | 说明 | |------|------|------| | `Enabled` | `bool?` | 是否启用 | | `Policy` | `string?` | 策略名称 | | `ReactivationPeriod` | `TimeSpan?` | 重新激活周期 | --- ## 5. 会话亲和配置 ### SessionAffinityConfig | 字段 | 类型 | 必填 | 说明 | |------|------|------|------| | `Enabled` | `bool?` | ○ | 是否启用 | | `Policy` | `string?` | ○ | 策略 (Cookie, Header) | | `FailurePolicy` | `string?` | ○ | 失败处理策略 | | `AffinityKeyName` | `string` | ✓ | 亲和键名称 | | `Cookie` | `SessionAffinityCookieConfig?` | ○ | Cookie 配置 | --- ## 6. 动态配置更新 ### IProxyConfig 接口 ```csharp public interface IProxyConfig { string RevisionId { get; } // 配置版本 ID IReadOnlyList Routes { get; } IReadOnlyList Clusters { get; } IChangeToken ChangeToken { get; } // 配置变更通知 } ``` ### 配置更新机制 1. **ChangeToken**: 当配置发生变化时,`ChangeToken` 会触发通知 2. **RevisionId**: 每次配置更新都会生成新的版本 ID 3. **YARP 内部**: 监听 `ChangeToken`,触发时重新加载配置 ### 实现动态更新的方式 ```csharp public class CustomConfigProvider : IProxyConfigProvider { private volatile CustomProxyConfig _config; public IProxyConfig GetConfig() => _config; public void UpdateConfig(List routes, List clusters) { var oldConfig = _config; _config = new CustomProxyConfig(routes, clusters); oldConfig.SignalChange(); // 触发 ChangeToken } } ``` --- ## 7. 与现有实体的映射关系 ### GwTenantRoute → RouteConfig | GwTenantRoute 字段 | RouteConfig 字段 | 映射说明 | |-------------------|------------------|----------| | `Id` | `RouteId` | 直接映射 | | `PathPattern` | `Match.Path` | 路径匹配模式 | | `ClusterId` | `ClusterId` | 目标集群 | | `Priority` | `Order` | 路由优先级 | | `TenantCode` | `Metadata["TenantCode"]` | 租户标识 (元数据) | | `ServiceName` | `Metadata["ServiceName"]` | 服务名称 (元数据) | | `IsGlobal` | `Metadata["IsGlobal"]` | 全局路由标记 | ### GwServiceInstance → DestinationConfig | GwServiceInstance 字段 | DestinationConfig 字段 | 映射说明 | |-----------------------|------------------------|----------| | `Address` | `Address` | 后端地址 | | `Health` | `Health` | 健康检查端点 | | `Weight` | `Metadata["Weight"]` | 权重 (加权负载均衡) | | `DestinationId` | Dictionary Key | 目标字典的 Key | ### 多租户路由生成逻辑 ``` for each GwTenantRoute: routeId = $"{TenantCode}_{ServiceName}" or Id routeConfig = new RouteConfig { RouteId = routeId, Match = new RouteMatch { Path = PathPattern }, ClusterId = ClusterId, Order = Priority, Metadata = { TenantCode, ServiceName, IsGlobal } } ``` --- ## 8. 实体结构对比与建议 ### 当前实体 vs YARP 需求 | 方面 | 当前实体 | YARP 需求 | 差异 | |------|----------|-----------|------| | 路由匹配 | 只有 `PathPattern` | `Methods`, `Hosts`, `Headers`, `QueryParameters` | 缺少高级匹配 | | 负载均衡 | 无配置 | `LoadBalancingPolicy` | 缺少策略配置 | | 会话亲和 | 无配置 | `SessionAffinityConfig` | 缺少会话保持 | | 转换规则 | 无配置 | `Transforms` | 缺少请求/响应转换 | | 授权策略 | 无配置 | `AuthorizationPolicy` | 缺少授权配置 | | 限流 | 无配置 | `RateLimiterPolicy` | 缺少限流配置 | ### 建议新增字段 **GwTenantRoute 新增:** ```csharp // 匹配规则扩展 public string? Methods { get; set; } // GET,POST,PUT public string? Hosts { get; set; } // api.example.com // 策略配置 public string? LoadBalancingPolicy { get; set; } // RoundRobin, WeightedRoundRobin public string? AuthorizationPolicy { get; set; } // 授权策略 public string? RateLimiterPolicy { get; set; } // 限流策略 public string? CorsPolicy { get; set; } // CORS 策略 // 转换规则 (JSON) public string? Transforms { get; set; } // 请求/响应转换 // 会话亲和 public bool SessionAffinityEnabled { get; set; } public string? SessionAffinityPolicy { get; set; } // Cookie, Header public string? SessionAffinityKeyName { get; set; } ``` **GwServiceInstance 新增:** ```csharp // 健康检查 public string? HealthCheckPath { get; set; } // /health public int? HealthCheckInterval { get; set; } // 秒 // 主动健康检查端点 public string? HealthEndpoint { get; set; } // http://host:port/health ``` --- ## 9. 参考资源 - [YARP 官方文档](https://microsoft.github.io/reverse-proxy/) - [YARP GitHub 仓库](https://github.com/microsoft/reverse-proxy) - [配置提供程序示例](https://github.com/microsoft/reverse-proxy/tree/main/samples) - [Yarp.EfCore.Configuration](https://github.com/microsoft/reverse-proxy/tree/main/samples/Yarp.EfCore.Configuration) - EF Core 数据库配置示例