# YARP Gateway 架构文档 ## 1. 整体架构模式 本项目基于 **YARP (Yet Another Reverse Proxy)** 实现的 API 网关,采用 **反向代理模式**,支持多租户路由、动态配置和分布式负载均衡。 ### 1.1 架构图 ``` ┌─────────────────────────────────────────────────────────────────────────────┐ │ 外部请求 │ └─────────────────────────────────┬───────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────────────────────┐ │ ASP.NET Core Pipeline │ ├─────────────────────────────────────────────────────────────────────────────┤ │ ┌────────────────┐ ┌─────────────────────┐ ┌──────────────────────┐ │ │ │ CORS 中间件 │ -> │ JwtTransformMiddleware │ -> │ TenantRoutingMiddleware │ │ │ └────────────────┘ └─────────────────────┘ └──────────────────────┘ │ └─────────────────────────────────┬───────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────────────────────┐ │ YARP Reverse Proxy │ ├─────────────────────────────────────────────────────────────────────────────┤ │ ┌───────────────────────────┐ ┌──────────────────────────────────────┐ │ │ │ DynamicProxyConfigProvider │ -> │ DistributedWeightedRoundRobinPolicy │ │ │ └───────────┬───────────────┘ └──────────────────────────────────────┘ │ │ │ │ │ ▼ │ │ ┌───────────────────────────────────────────────────────────────────────┐ │ │ │ RouteConfig / ClusterConfig │ │ │ └───────────────────────────────────────────────────────────────────────┘ │ └─────────────────────────────────┬───────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────────────────────┐ │ 后端服务集群 │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │ │ Service A│ │ Service B│ │ Service C│ │ Service D│ │ │ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │ └─────────────────────────────────────────────────────────────────────────────┘ ``` ### 1.2 核心设计模式 | 模式 | 应用场景 | 实现位置 | |------|----------|----------| | 反向代理 | 请求转发 | `Yarp.ReverseProxy` | | 策略模式 | 负载均衡策略 | `DistributedWeightedRoundRobinPolicy` | | 观察者模式 | 配置变更监听 | `PgSqlConfigChangeListener` | | 工厂模式 | DbContext 创建 | `GatewayDbContextFactory` | | 单例模式 | 配置提供者 | `DatabaseRouteConfigProvider`, `DatabaseClusterConfigProvider` | | 生产者-消费者 | 配置变更通知 | `Channel` in `PgSqlConfigChangeListener` | --- ## 2. 核心组件和职责 ### 2.1 中间件层 (Middleware) #### JwtTransformMiddleware **文件路径**: `src/Middleware/JwtTransformMiddleware.cs` **职责**: - 解析 JWT Token - 提取租户信息 (tenant claim) - 将用户信息注入请求头 **处理流程**: ``` Authorization Header -> JWT 解析 -> 提取 Claims -> 注入 X-Tenant-Id, X-User-Id, X-User-Name, X-Roles ``` #### TenantRoutingMiddleware **文件路径**: `src/Middleware/TenantRoutingMiddleware.cs` **职责**: - 从请求头获取租户 ID - 根据 URL 路径提取服务名称 - 查询路由缓存获取目标集群 - 设置动态集群 ID ### 2.2 配置提供层 (Config Providers) #### DynamicProxyConfigProvider **文件路径**: `src/DynamicProxy/DynamicProxyConfigProvider.cs` **职责**: - 实现 YARP 的 `IProxyConfigProvider` 接口 - 整合路由和集群配置 - 提供配置变更通知机制 ```csharp public interface IProxyConfigProvider { IProxyConfig GetConfig(); } ``` #### DatabaseRouteConfigProvider **文件路径**: `src/Config/DatabaseRouteConfigProvider.cs` **职责**: - 从数据库加载路由配置 - 转换为 YARP `RouteConfig` 格式 - 支持热重载 #### DatabaseClusterConfigProvider **文件路径**: `src/Config/DatabaseClusterConfigProvider.cs` **职责**: - 从数据库加载集群配置 - 管理服务实例 (地址、权重) - 配置健康检查策略 ### 2.3 服务层 (Services) #### RouteCache **文件路径**: `src/Services/RouteCache.cs` **职责**: - 内存缓存路由信息 - 支持全局路由和租户专用路由 - 提供快速查询接口 **数据结构**: ``` _globalRoutes: ConcurrentDictionary // 全局路由 _tenantRoutes: ConcurrentDictionary> // 租户路由 ``` **查询优先级**: 租户专用路由 > 全局路由 #### PgSqlConfigChangeListener **文件路径**: `src/Services/PgSqlConfigChangeListener.cs` **职责**: - 监听 PostgreSQL NOTIFY 事件 - 双重保障:事件监听 + 轮询回退 - 触发配置热重载 **监听流程**: ``` PostgreSQL NOTIFY -> OnNotification -> _reloadChannel -> ReloadConfigAsync │ └── FallbackPollingAsync (5分钟轮询) ``` #### KubernetesPendingSyncService **文件路径**: `src/Services/KubernetesPendingSyncService.cs` **职责**: - 同步 Kubernetes 服务发现 - 管理待处理服务列表 - 清理过期服务记录 #### RedisConnectionManager **文件路径**: `src/Services/RedisConnectionManager.cs` **职责**: - 管理 Redis 连接 - 提供分布式锁实现 - 连接池管理 ### 2.4 负载均衡层 #### DistributedWeightedRoundRobinPolicy **文件路径**: `src/LoadBalancing/DistributedWeightedRoundRobinPolicy.cs` **职责**: - 实现加权轮询负载均衡 - 基于 Redis 的分布式状态存储 - 支持实例权重配置 **算法流程**: ``` 1. 获取分布式锁 (Redis) 2. 读取负载均衡状态 3. 计算权重选择目标 4. 更新状态并释放锁 5. 失败时降级到简单选择 ``` --- ## 3. 数据流和请求处理流程 ### 3.1 请求处理流程图 ```mermaid sequenceDiagram participant Client as 客户端 participant CORS as CORS中间件 participant JWT as JwtTransformMiddleware participant Tenant as TenantRoutingMiddleware participant YARP as YARP代理 participant LB as 负载均衡器 participant Service as 后端服务 Client->>CORS: HTTP请求 CORS->>JWT: 跨域检查通过 JWT->>JWT: 解析JWT Token JWT->>Tenant: 注入租户信息头 Tenant->>Tenant: 提取服务名称 Tenant->>Tenant: 查询RouteCache Tenant->>YARP: 设置动态集群ID YARP->>LB: 获取可用目标 LB->>LB: 加权轮询选择 LB->>Service: 转发请求 Service-->>Client: 返回响应 ``` ### 3.2 配置变更流程 ```mermaid flowchart TD A[数据库变更] --> B[SaveChangesAsync] B --> C[DetectConfigChanges] C --> D[NOTIFY gateway_config_changed] D --> E[PgSqlConfigChangeListener] E --> F{收到通知?} F -->|是| G[ReloadConfigAsync] F -->|否| H[轮询检测版本变化] H --> G G --> I[RouteCache.ReloadAsync] G --> J[DatabaseRouteConfigProvider.ReloadAsync] G --> K[DatabaseClusterConfigProvider.ReloadAsync] I --> L[更新内存缓存] J --> L K --> L L --> M[DynamicProxyConfigProvider.UpdateConfig] M --> N[触发 IChangeToken] N --> O[YARP重新加载配置] ``` ### 3.3 Kubernetes 服务发现流程 ``` ┌─────────────────┐ │ Kubernetes API │ └────────┬────────┘ │ 30s 间隔 ▼ ┌─────────────────────────────┐ │ KubernetesPendingSyncService │ ├─────────────────────────────┤ │ 1. 获取 K8s 服务列表 │ │ 2. 对比现有待处理记录 │ │ 3. 新增/更新/清理记录 │ └────────┬────────────────────┘ │ ▼ ┌─────────────────────────────┐ │ GwPendingServiceDiscovery │ │ (待处理服务发现表) │ └────────┬────────────────────┘ │ ▼ ┌─────────────────────────────┐ │ PendingServicesController │ │ - GET: 查看待处理服务 │ │ - POST /assign: 分配集群 │ │ - POST /reject: 拒绝服务 │ └─────────────────────────────┘ ``` --- ## 4. 关键抽象层 ### 4.1 配置模型 ``` ┌───────────────────────────────────────────────────────────────┐ │ 配置层次结构 │ ├───────────────────────────────────────────────────────────────┤ │ │ │ ┌─────────────────┐ ┌─────────────────┐ │ │ │ JwtConfig │ │ RedisConfig │ │ │ │ - Authority │ │ - Connection │ │ │ │ - Audience │ │ - Database │ │ │ │ - Validate* │ │ - InstanceName │ │ │ └─────────────────┘ └─────────────────┘ │ │ │ │ ┌─────────────────────────────────────────────────────────┐ │ │ │ DynamicProxyConfigProvider │ │ │ │ ┌─────────────────┐ ┌─────────────────┐ │ │ │ │ │ RouteConfig[] │ │ ClusterConfig[] │ │ │ │ │ │ - RouteId │ │ - ClusterId │ │ │ │ │ │ - ClusterId │ │ - Destinations │ │ │ │ │ │ - Match.Path │ │ - LoadBalancing │ │ │ │ │ │ - Metadata │ │ - HealthCheck │ │ │ │ │ └─────────────────┘ └─────────────────┘ │ │ │ └─────────────────────────────────────────────────────────┘ │ │ │ └───────────────────────────────────────────────────────────────┘ ``` ### 4.2 数据模型 ``` ┌─────────────────┐ ┌─────────────────┐ │ GwTenant │ │ GwTenantRoute │ ├─────────────────┤ ├─────────────────┤ │ Id │ │ Id │ │ TenantCode ────┼────►│ TenantCode │ │ TenantName │ │ ServiceName │ │ Status │ │ ClusterId │ │ Version │ │ PathPattern │ │ IsDeleted │ │ Priority │ └─────────────────┘ │ IsGlobal │ │ Status │ │ Version │ └────────┬────────┘ │ ▼ ┌─────────────────┐ │ GwServiceInstance│ ├─────────────────┤ │ Id │ │ ClusterId ────┤ │ DestinationId │ │ Address │ │ Health │ │ Weight │ │ Status │ │ Version │ └─────────────────┘ ``` ### 4.3 接口定义 ```csharp // 路由缓存接口 public interface IRouteCache { Task InitializeAsync(); Task ReloadAsync(); RouteInfo? GetRoute(string tenantCode, string serviceName); RouteInfo? GetRouteByPath(string path); } // Redis 连接管理接口 public interface IRedisConnectionManager { IConnectionMultiplexer GetConnection(); Task AcquireLockAsync(string key, TimeSpan? expiry = null); Task ExecuteInLockAsync(string key, Func> func, TimeSpan? expiry = null); } // 负载均衡策略接口 (YARP) public interface ILoadBalancingPolicy { string Name { get; } DestinationState? PickDestination(HttpContext context, ClusterState cluster, IReadOnlyList availableDestinations); } ``` --- ## 5. 入口点分析 ### 5.1 程序入口 (`Program.cs`) **文件路径**: `src/Program.cs` **启动流程**: ``` 1. 创建 WebApplication Builder └── 配置 Serilog 日志 2. 配置选项 ├── JwtConfig (JWT 认证配置) └── RedisConfig (Redis 连接配置) 3. 注册数据库服务 └── GatewayDbContext (PostgreSQL) 4. 注册核心服务 (Singleton) ├── DatabaseRouteConfigProvider ├── DatabaseClusterConfigProvider ├── RouteCache ├── RedisConnectionManager ├── DynamicProxyConfigProvider └── DistributedWeightedRoundRobinPolicy 5. 注册后台服务 (HostedService) ├── PgSqlConfigChangeListener └── KubernetesPendingSyncService 6. 配置中间件管道 ├── CORS ├── JwtTransformMiddleware └── TenantRoutingMiddleware 7. 映射端点 ├── /health (健康检查) ├── /api/gateway/* (管理 API) └── /api/* (代理路由) 8. 初始化并运行 └── RouteCache.InitializeAsync() ``` ### 5.2 依赖注入关系 ``` Program.cs │ ├── Config/ │ ├── JwtConfig (Options) │ ├── RedisConfig (Options + Singleton) │ ├── DatabaseRouteConfigProvider (Singleton) │ └── DatabaseClusterConfigProvider (Singleton) │ ├── DynamicProxy/ │ └── DynamicProxyConfigProvider (Singleton, IProxyConfigProvider) │ ├── Services/ │ ├── RouteCache (Singleton, IRouteCache) │ ├── RedisConnectionManager (Singleton) │ ├── PgSqlConfigChangeListener (HostedService) │ └── KubernetesPendingSyncService (HostedService) │ ├── LoadBalancing/ │ └── DistributedWeightedRoundRobinPolicy (Singleton, ILoadBalancingPolicy) │ └── Data/ └── GatewayDbContext (DbContextFactory) ``` --- ## 6. 技术栈 | 组件 | 技术 | 用途 | |------|------|------| | 反向代理 | YARP 2.x | 核心代理功能 | | 数据库 | PostgreSQL + EF Core | 配置存储 | | 缓存 | Redis | 分布式状态、锁 | | 服务发现 | Fengling.ServiceDiscovery | Kubernetes 集成 | | 日志 | Serilog | 结构化日志 | | 容器化 | Docker | 部署支持 | | 目标框架 | .NET 10.0 | 运行时 | --- ## 7. 扩展点 1. **负载均衡策略**: 实现 `ILoadBalancingPolicy` 接口 2. **配置提供者**: 继承 `IProxyConfigProvider` 3. **中间件**: 添加自定义中间件到管道 4. **服务发现**: 扩展 `IServiceDiscoveryProvider` 5. **健康检查**: 配置 `HealthCheckConfig`