Some checks failed
CI / Lint & TypeCheck (push) Has been cancelled
CI / Unit Tests (push) Has been cancelled
CI / Build Frontend (push) Has been cancelled
CI / Rust Check (push) Has been cancelled
CI / Security Scan (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
- Create docs/brainstorming/ with 5 discussion records (Mar 16 - Apr 7) - Archive ~30 outdated audit reports (V5-V11) to docs/archive/old-audits/ - Archive superseded analysis docs to docs/archive/old-analysis/ - Archive completed session plans to docs/archive/old-plans/ - Archive old test reports/validations to respective archive folders - Remove empty directories left after moves - Keep current docs: TRUTH.md, feature docs, deployment, knowledge-base, superpowers
386 lines
12 KiB
Markdown
386 lines
12 KiB
Markdown
# 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%
|
||
- [ ] 错误响应格式统一
|
||
- [ ] 分页接口包含完整元数据
|