Files
zclaw_openfang/docs/saas-backend-optimization.md
iven 5fdf96c3f5 chore: 提交所有工作进度 — SaaS 后端增强、Admin UI、桌面端集成
包含大量 SaaS 平台改进、Admin 管理后台更新、桌面端集成完善、
文档同步、测试文件重构等内容。为 QA 测试准备干净工作树。
2026-03-29 10:46:41 +08:00

386 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# ZCLAW SaaS 后端优化计划
> 生成时间: 2026-03-28
> 分析范围: crates/zclaw-saas
## 一、架构概览
```
┌─────────────────────────────────────────────────────────────────┐
│ ZCLAW SaaS Backend │
│ (Rust + Axum + PostgreSQL) │
├─────────────────────────────────────────────────────────────────┤
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ auth │ │ account │ │model_cfg │ │ relay │ │
│ │ 认证 │ │ 账号管理 │ │ 模型配置 │ │ 中转服务 │ │
│ └────┬─────┘ └────┬─────┘ └────┬─────┘ └────┬─────┘ │
│ │ │ │ │ │
│ └─────────────┴─────────────┴─────────────┘ │
│ │ │
│ ┌──────┴──────┐ │
│ │ middleware │ │
│ │ - auth │ │
│ │ - rate_limit│ │
│ └──────┬──────┘ │
│ │ │
│ ┌──────┴──────┐ │
│ │ PostgreSQL │ │
│ └─────────────┘ │
└─────────────────────────────────────────────────────────────────┘
```
## 二、API 接口清单 (共 42 个端点)
### 2.1 认证模块 `/api/v1/auth` (5 个)
| 方法 | 路径 | 权限 | 功能 |
|------|------|------|------|
| POST | `/auth/register` | 公开 | 用户注册 |
| POST | `/auth/login` | 公开 | 用户登录 |
| POST | `/auth/refresh` | 认证 | 刷新 Token |
| GET | `/auth/me` | 认证 | 获取当前用户 |
| PUT | `/auth/password` | 认证 | 修改密码 |
### 2.2 账号管理 `/api/v1` (12 个)
| 方法 | 路径 | 权限 | 功能 |
|------|------|------|------|
| GET | `/accounts` | admin | 列出账号 |
| GET | `/accounts/:id` | 自己/admin | 账号详情 |
| PUT | `/accounts/:id` | 自己/admin | 更新账号 |
| PATCH | `/accounts/:id/status` | admin | 更新状态 |
| GET | `/tokens` | 认证 | 列出 Token |
| POST | `/tokens` | 认证 | 创建 Token |
| DELETE | `/tokens/:id` | 认证 | 撤销 Token |
| GET | `/logs/operations` | admin | 操作日志 |
| GET | `/stats/dashboard` | admin | 仪表盘 |
| POST | `/devices/register` | 认证 | 注册设备 |
| POST | `/devices/heartbeat` | 认证 | 设备心跳 |
| GET | `/devices` | 认证 | 设备列表 |
### 2.3 模型配置 `/api/v1` (15 个)
| 方法 | 路径 | 权限 | 功能 |
|------|------|------|------|
| GET | `/providers` | 认证 | 服务商列表 |
| GET | `/providers/:id` | 认证 | 服务商详情 |
| POST | `/providers` | provider:manage | 创建服务商 |
| PUT | `/providers/:id` | provider:manage | 更新服务商 |
| DELETE | `/providers/:id` | provider:manage | 删除服务商 |
| GET | `/models` | 认证 | 模型列表 |
| GET | `/models/:id` | 认证 | 模型详情 |
| POST | `/models` | model:manage | 创建模型 |
| PUT | `/models/:id` | model:manage | 更新模型 |
| DELETE | `/models/:id` | model:manage | 删除模型 |
| GET | `/keys` | 认证 | API Key 列表 |
| POST | `/keys` | 认证 | 创建 Key |
| POST | `/keys/:id/rotate` | 认证 | 轮换 Key |
| DELETE | `/keys/:id` | 认证 | 撤销 Key |
| GET | `/usage` | 认证 | 用量统计 |
### 2.4 中转服务 `/api/v1/relay` (5 个)
| 方法 | 路径 | 权限 | 功能 |
|------|------|------|------|
| POST | `/relay/chat/completions` | relay:use | 聊天补全 |
| GET | `/relay/tasks` | 认证 | 任务列表 |
| GET | `/relay/tasks/:id` | 认证 | 任务详情 |
| GET | `/relay/models` | 认证 | 可用模型 |
| POST | `/relay/tasks/:id/retry` | relay:admin | 重试任务 |
### 2.5 配置迁移 `/api/v1/config` (10 个)
| 方法 | 路径 | 权限 | 功能 |
|------|------|------|------|
| GET | `/config/items` | 认证 | 配置列表 |
| GET | `/config/items/:id` | 认证 | 配置详情 |
| POST | `/config/items` | config:write | 创建配置 |
| PUT | `/config/items/:id` | config:write | 更新配置 |
| DELETE | `/config/items/:id` | config:write | 删除配置 |
| GET | `/config/analysis` | 认证 | 配置分析 |
| POST | `/config/seed` | config:write | 种子配置 |
| POST | `/config/sync` | 认证 | 同步配置 |
| POST | `/config/diff` | 认证 | 配置差异 |
| GET | `/config/sync-logs` | 认证 | 同步日志 |
---
## 三、问题清单
### 🔴 高优先级 (影响功能/性能)
#### P1-001: 登录接口 N+1 查询
**位置:** `auth/handlers.rs:login()`
**现状:**
```rust
// 查询 1: 获取用户信息
let row = sqlx::query_as("SELECT id, username, ... FROM accounts WHERE username = $1")...
// 查询 2: 获取密码哈希
let (password_hash,) = sqlx::query_as("SELECT password_hash FROM accounts WHERE id = $1")...
// 查询 3: 获取权限
let permissions = get_role_permissions(&state.db, &role).await?;
```
**影响:** 每次登录触发 3 次数据库查询
**修复方案:**
```sql
SELECT a.id, a.username, a.email, a.display_name, a.role, a.status,
a.totp_enabled, a.created_at, a.password_hash,
r.permissions
FROM accounts a
LEFT JOIN roles r ON a.role = r.id
WHERE a.username = $1 OR a.email = $1
```
**工作量:** 小 (1-2 小时)
---
#### P1-002: 流式响应 Token 统计缺失
**位置:** `relay/handlers.rs:chat_completions()`
**现状:**
```rust
Ok(service::RelayResponse::Sse(body)) => {
model_service::record_usage(..., 0, 0, ...); // 流式记录 0 tokens
}
```
**影响:** 流式请求的 token 使用量无法统计,影响计费和监控
**修复方案:**
1. 解析 SSE 流中的 `usage` 字段
2. 在流结束后更新统计
**工作量:** 中 (4-6 小时)
---
#### P1-003: 健康检查端点缺失
**位置:** `main.rs`
**现状:**`/health``/ready` 端点
**影响:**
- K8s/Docker 无法进行健康检查
- 负载均衡器无法判断服务状态
**修复方案:**
```rust
.route("/health", get(|| async {
Json(json!({"status": "ok"}))
}))
.route("/ready", get(|State(state): State<AppState>| async move {
// 检查数据库连接
let db_ok = sqlx::query("SELECT 1").fetch_one(&state.db).await.is_ok();
Json(json!({"ready": db_ok, "db": if db_ok { "connected" } else { "disconnected" }}))
}))
```
**工作量:** 小 (1 小时)
---
### 🟡 中优先级 (影响可维护性)
#### P2-001: 权限系统无缓存
**位置:** `auth/handlers.rs:get_role_permissions()`
**现状:** 每次请求都查询数据库获取权限
**影响:**
- 数据库压力增加
- 响应延迟增加
**修复方案:**
1. 方案 A: 在 JWT 中嵌入权限 (无需查询,但权限变更需重新登录)
2. 方案 B: 添加内存缓存 (LRU Cache权限变更即时生效)
**推荐:** 方案 B使用 `moka``dashmap` 缓存
**工作量:** 中 (4-8 小时)
---
#### P2-002: 错误响应格式不统一
**位置:** 所有 handlers
**现状:**
```json
// 格式 1
{"error": "AUTH_ERROR", "message": "认证失败"}
// 格式 2
{"ok": true}
// 格式 3
{"ok": true, "message": "密码修改成功"}
```
**影响:** 前端需要处理多种格式,增加复杂度
**修复方案:** 统一为 RFC 7807 Problem Details 格式:
```json
{
"type": "https://zclaw.ai/errors/auth-error",
"title": "认证失败",
"status": 401,
"detail": "用户名或密码错误",
"code": "AUTH_ERROR"
}
```
**工作量:** 中 (4-6 小时)
---
#### P2-003: 分页响应缺少元数据
**位置:** `account/handlers.rs:list_accounts()`
**现状:**
```rust
pub struct PaginatedResponse<T> {
pub items: Vec<T>,
// 缺少 total, page, total_pages
}
```
**影响:** 前端无法显示总页数和分页导航
**修复方案:**
```rust
pub struct PaginatedResponse<T> {
pub items: Vec<T>,
pub total: i64,
pub page: i64,
pub page_size: i64,
pub total_pages: i64,
}
```
**工作量:** 小 (2-3 小时)
---
### 🟢 低优先级 (技术债务)
#### P3-001: 数据库 Schema 使用 TEXT 类型
**位置:** `db.rs`
**现状:**
```sql
created_at TEXT NOT NULL, -- 应该用 TIMESTAMPTZ
role TEXT NOT NULL DEFAULT 'user' -- 应该用外键
```
**影响:**
- 无法使用 PostgreSQL 时间函数
- 角色无外键约束,可能导致数据不一致
**修复方案:** 编写迁移脚本,逐步更新 Schema
**工作量:** 大 (需要数据迁移)
---
#### P3-002: 缺少请求追踪
**现状:** 操作日志只记录业务操作,不记录 API 请求详情
**影响:**
- 无法追踪请求链路
- 问题排查困难
**修复方案:** 添加请求追踪中间件:
- 生成 `request_id`
- 记录请求耗时
- 关联日志与请求
**工作量:** 中 (4-6 小时)
---
#### P3-003: API 版本控制策略缺失
**现状:** 只有 `v1`,无版本升级策略
**影响:** 未来 API 变更可能导致兼容性问题
**修复方案:**
1. 在响应头添加 `X-API-Version`
2. 支持 `Accept: application/vnd.zclaw.v1+json`
3. 添加版本废弃机制
**工作量:** 小 (2-3 小时)
---
## 四、优化实施计划
### Phase 1: 高优先级修复 (1-2 天)
| 任务 | 工作量 | 负责人 | 状态 |
|------|--------|--------|------|
| P1-001 登录 N+1 查询优化 | 2h | - | 待开始 |
| P1-003 健康检查端点 | 1h | - | 待开始 |
| P1-002 流式 Token 统计 | 6h | - | 待开始 |
### Phase 2: 中优先级优化 (2-3 天)
| 任务 | 工作量 | 负责人 | 状态 |
|------|--------|--------|------|
| P2-001 权限缓存 | 8h | - | 待开始 |
| P2-002 错误格式统一 | 6h | - | 待开始 |
| P2-003 分页元数据 | 3h | - | 待开始 |
### Phase 3: 技术债务清理 (按需)
| 任务 | 工作量 | 负责人 | 状态 |
|------|--------|--------|------|
| P3-001 Schema 迁移 | 2-3 天 | - | 待评估 |
| P3-002 请求追踪 | 6h | - | 待开始 |
| P3-003 API 版本控制 | 3h | - | 待开始 |
---
## 五、NOT in Scope
以下内容在本次优化范围之外:
1. **前端 Admin UI 优化** - 仅关注后端 API
2. **数据库分库分表** - 当前数据量不需要
3. **微服务拆分** - 架构已足够清晰
4. **GraphQL 支持** - REST API 已满足需求
5. **WebSocket 支持** - 当前无实时推送需求
---
## 六、风险评估
| 风险 | 可能性 | 影响 | 缓解措施 |
|------|--------|------|----------|
| Schema 迁移数据丢失 | 低 | 高 | 先备份,分批迁移 |
| 权限缓存不一致 | 中 | 中 | 设置 TTL主动失效 |
| 流式解析兼容性 | 中 | 低 | 多模型测试 |
---
## 七、验收标准
- [ ] 所有 API 端点有健康检查
- [ ] 登录接口响应时间 < 100ms (P99)
- [ ] 流式请求 Token 统计准确率 > 95%
- [ ] 错误响应格式统一
- [ ] 分页接口包含完整元数据