371 lines
7.1 KiB
Markdown
371 lines
7.1 KiB
Markdown
# YARP Gateway - 租户路由网关
|
||
|
||
基于YARP的租户感知API网关,支持JWT解析、动态租户路由、加权负载均衡。
|
||
|
||
## 功能特性
|
||
|
||
- ✅ JWT解析与Header传递
|
||
- ✅ 基于租户的动态路由
|
||
- ✅ 加权轮询负载均衡
|
||
- ✅ PostgreSQL配置持久化
|
||
- ✅ RESTful API管理接口
|
||
- ✅ Docker Compose部署
|
||
- ✅ Serilog结构化日志
|
||
- ✅ Prometheus指标导出
|
||
|
||
## 架构设计
|
||
|
||
```
|
||
客户端请求 → JWT解析中间件 → 租户路由中间件 → YARP网关 → 后端微服务
|
||
```
|
||
|
||
### 路由流程
|
||
|
||
1. 客户端携带JWT访问 `/api/product/list`
|
||
2. JWT解析中间件提取租户ID(如 `customerA`)
|
||
3. 添加Header: `X-Tenant-Id: customerA`
|
||
4. 租户路由中间件根据路径提取服务名(`product`)
|
||
5. 动态构造Cluster ID: `customerA-product`
|
||
6. YARP将请求转发到该Cluster下的服务实例
|
||
7. 加权轮询策略选择实例
|
||
|
||
## 快速开始
|
||
|
||
### 前置要求
|
||
|
||
- .NET 10 SDK
|
||
- PostgreSQL 16+
|
||
- Docker & Docker Compose(可选)
|
||
|
||
### 本地开发
|
||
|
||
1. **创建数据库**
|
||
|
||
```bash
|
||
psql -h 192.168.100.10 -U postgres -c "CREATE DATABASE fengling_gateway;"
|
||
```
|
||
|
||
2. **执行迁移**
|
||
|
||
```bash
|
||
psql -h 192.168.100.10 -U postgres -d fengling_gateway -f sql/init.sql
|
||
```
|
||
|
||
3. **运行网关**
|
||
|
||
```bash
|
||
cd src/YarpGateway
|
||
dotnet run
|
||
```
|
||
|
||
4. **测试请求**
|
||
|
||
```bash
|
||
# 生成测试JWT(需要配置Auth服务)
|
||
# 然后测试请求
|
||
curl -H "Authorization: Bearer <JWT_TOKEN>" \
|
||
http://localhost:8080/api/product/list
|
||
```
|
||
|
||
### Docker部署
|
||
|
||
1. **启动所有服务**
|
||
|
||
```bash
|
||
cd docker
|
||
docker-compose up -d
|
||
```
|
||
|
||
2. **查看日志**
|
||
|
||
```bash
|
||
docker-compose logs -f gateway
|
||
```
|
||
|
||
3. **停止服务**
|
||
|
||
```bash
|
||
docker-compose down
|
||
```
|
||
|
||
## API接口
|
||
|
||
### 租户管理
|
||
|
||
**获取所有租户**
|
||
```http
|
||
GET /api/gateway/tenants
|
||
```
|
||
|
||
**创建租户**
|
||
```http
|
||
POST /api/gateway/tenants
|
||
Content-Type: application/json
|
||
|
||
{
|
||
"tenantCode": "customerC",
|
||
"tenantName": "客户C"
|
||
}
|
||
```
|
||
|
||
**删除租户**
|
||
```http
|
||
DELETE /api/gateway/tenants/{id}
|
||
```
|
||
|
||
### 路由管理
|
||
|
||
**获取租户路由**
|
||
```http
|
||
GET /api/gateway/tenants/{tenantCode}/routes
|
||
```
|
||
|
||
**创建路由**
|
||
```http
|
||
POST /api/gateway/tenants/{tenantCode}/routes
|
||
Content-Type: application/json
|
||
|
||
{
|
||
"serviceName": "product",
|
||
"pathPattern": "/api/product/{**catch-all}"
|
||
}
|
||
```
|
||
|
||
**删除路由**
|
||
```http
|
||
DELETE /api/gateway/routes/{id}
|
||
```
|
||
|
||
### 服务实例管理
|
||
|
||
**获取实例列表**
|
||
```http
|
||
GET /api/gateway/clusters/{clusterId}/instances
|
||
```
|
||
|
||
**添加实例**
|
||
```http
|
||
POST /api/gateway/clusters/{clusterId}/instances
|
||
Content-Type: application/json
|
||
|
||
{
|
||
"destinationId": "product-3",
|
||
"address": "http://customerA-product-3:8001",
|
||
"weight": 2
|
||
}
|
||
```
|
||
|
||
**删除实例**
|
||
```http
|
||
DELETE /api/gateway/instances/{id}
|
||
```
|
||
|
||
### 配置热更新
|
||
|
||
```http
|
||
POST /api/gateway/reload
|
||
```
|
||
|
||
## JWT格式要求
|
||
|
||
### 必需Claims
|
||
|
||
```json
|
||
{
|
||
"tenant": "customerA",
|
||
"sub": "123456",
|
||
"unique_name": "张三",
|
||
"role": ["admin", "user"]
|
||
}
|
||
```
|
||
|
||
### Header转换
|
||
|
||
JWT解析后,以下Header会自动添加到请求中:
|
||
|
||
- `X-Tenant-Id`: 租户ID
|
||
- `X-User-Id`: 用户ID
|
||
- `X-User-Name`: 用户名
|
||
- `X-Roles`: 角色列表(逗号分隔)
|
||
|
||
## 负载均衡策略
|
||
|
||
### 加权轮询 (WeightedRoundRobin)
|
||
|
||
权重高的实例获得更多流量分配。
|
||
|
||
**配置权重**:
|
||
```bash
|
||
POST /api/gateway/clusters/customerA-product/instances
|
||
{
|
||
"destinationId": "product-1",
|
||
"address": "http://customerA-product-1:8001",
|
||
"weight": 10 # 权重10
|
||
}
|
||
```
|
||
|
||
**默认权重**: 1
|
||
|
||
## 数据库表结构
|
||
|
||
### gw_tenant
|
||
租户基础信息表
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| Id | BIGINT | 主键 |
|
||
| TenantCode | VARCHAR(50) | 租户编码(唯一) |
|
||
| TenantName | VARCHAR(100) | 租户名称 |
|
||
| Status | INTEGER | 状态:1=启用 0=禁用 |
|
||
|
||
### gw_tenant_route
|
||
租户服务路由配置表
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| Id | BIGINT | 主键 |
|
||
| TenantCode | VARCHAR(50) | 租户编码 |
|
||
| ServiceName | VARCHAR(100) | 服务名称 |
|
||
| ClusterId | VARCHAR(100) | YARP Cluster ID |
|
||
| PathPattern | VARCHAR(200) | 路径匹配模式 |
|
||
|
||
### gw_service_instance
|
||
服务实例配置表
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| Id | BIGINT | 主键 |
|
||
| ClusterId | VARCHAR(100) | Cluster ID |
|
||
| DestinationId | VARCHAR(100) | Destination ID |
|
||
| Address | VARCHAR(200) | 服务地址 |
|
||
| Weight | INTEGER | 权重 |
|
||
| Health | INTEGER | 健康状态:1=健康 0=不健康 |
|
||
|
||
## 监控和日志
|
||
|
||
### 日志位置
|
||
|
||
- **控制台**: 实时输出
|
||
- **文件**: `logs/gateway-{Date}.log`
|
||
|
||
### Prometheus指标
|
||
|
||
默认导出到 `/metrics` 端点(需添加 Prometheus 包)
|
||
|
||
**可用指标**:
|
||
- `gateway_requests_total`: 请求总数(按租户、服务、状态码分组)
|
||
- `gateway_request_duration_seconds`: 请求耗时(按租户、服务分组)
|
||
|
||
## 配置说明
|
||
|
||
### appsettings.json
|
||
|
||
```json
|
||
{
|
||
"ConnectionStrings": {
|
||
"DefaultConnection": "Host=postgres;Port=5432;Database=fengling_gateway;..."
|
||
},
|
||
"Jwt": {
|
||
"Authority": "https://your-auth-server.com",
|
||
"Audience": "fengling-gateway"
|
||
},
|
||
"ReverseProxy": {
|
||
"Routes": { "catch-all-route": { ... } },
|
||
"Clusters": { "dynamic-cluster": { ... } }
|
||
},
|
||
"Serilog": { ... }
|
||
}
|
||
```
|
||
|
||
### 环境变量
|
||
|
||
- `ConnectionStrings__DefaultConnection`: 数据库连接字符串
|
||
- `Jwt__Authority`: JWT认证服务器地址
|
||
- `Jwt__Audience`: JWT受众
|
||
|
||
## 性能调优
|
||
|
||
### 连接池配置
|
||
|
||
```csharp
|
||
services.AddDbContext<GatewayDbContext>(options =>
|
||
options.UseNpgsql(connectionString, o =>
|
||
{
|
||
o.CommandTimeout(30);
|
||
o.MaxBatchSize(100);
|
||
}));
|
||
```
|
||
|
||
### 日志级别优化
|
||
|
||
生产环境建议:
|
||
```json
|
||
{
|
||
"Logging": {
|
||
"LogLevel": {
|
||
"Default": "Warning",
|
||
"Microsoft.AspNetCore": "Warning",
|
||
"Yarp.ReverseProxy": "Information"
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
## 故障排查
|
||
|
||
### 常见问题
|
||
|
||
**1. 路由404**
|
||
- 检查 `gw_tenant_route` 表是否有对应路由配置
|
||
- 检查JWT中的tenant claim是否正确
|
||
|
||
**2. 数据库连接失败**
|
||
- 验证连接字符串是否正确
|
||
- 检查PostgreSQL是否启动
|
||
- 检查防火墙设置
|
||
|
||
**3. 负载均衡不均**
|
||
- 检查实例权重配置
|
||
- 检查实例健康状态
|
||
|
||
## 项目结构
|
||
|
||
```
|
||
src/YarpGateway/
|
||
├── Config/ # 配置提供者
|
||
│ ├── JwtConfig.cs
|
||
│ ├── DatabaseRouteConfigProvider.cs
|
||
│ └── DatabaseClusterConfigProvider.cs
|
||
├── Controllers/ # API控制器
|
||
│ └── GatewayConfigController.cs
|
||
├── Data/ # 数据库上下文
|
||
│ └── GatewayDbContext.cs
|
||
├── LoadBalancing/ # 负载均衡策略
|
||
│ └── WeightedRoundRobinPolicy.cs
|
||
├── Middleware/ # 中间件
|
||
│ ├── JwtTransformMiddleware.cs
|
||
│ └── TenantRoutingMiddleware.cs
|
||
├── Metrics/ # 监控指标
|
||
│ └── GatewayMetrics.cs
|
||
├── Models/ # 数据模型
|
||
│ ├── GwTenant.cs
|
||
│ ├── GwTenantRoute.cs
|
||
│ └── GwServiceInstance.cs
|
||
├── appsettings.json
|
||
├── Dockerfile
|
||
└── Program.cs
|
||
```
|
||
|
||
## 开发计划
|
||
|
||
- [ ] 添加Prometheus指标导出
|
||
- [ ] 实现Vue3管理界面
|
||
- [ ] 添加限流策略
|
||
- [ ] 添加熔断机制
|
||
- [ ] 实现配置中心集成
|
||
- [ ] 添加服务发现集成
|
||
|
||
## 许可证
|
||
|
||
MIT License
|