docs(routing): add phase2 closure task board
This commit is contained in:
@@ -145,6 +145,18 @@
|
||||
- 主状态库继续使用 SQLite
|
||||
- 路由运行态使用 Redis 或 memory backend 抽象
|
||||
- 智能路由日志必须最终结构化写回插件 SQLite
|
||||
- 2026-05-29 已新增 Phase 2 可开工任务单 `docs/plans/2026-05-29-phase2-intelligent-routing-closure-plan.md`
|
||||
- 已把 `管理页入口 / 正式数据面入口 / route 健康视图 / 真实验收矩阵` 拆成可执行任务
|
||||
- 已明确当前 Phase 2 不是再证明“路由能跑”,而是把现有能力收敛成产品闭环:
|
||||
- 管理员可维护 `logical_group -> route -> shadow_group`
|
||||
- 插件存在正式数据面入口,而不只是实验 proxy
|
||||
- route 的 sticky / failover / cooldown 状态可被运营查看
|
||||
- `remote43` 真验收敛成固定矩阵,而不是零散命令
|
||||
- 当前 Phase 2 的建议实施顺序是:
|
||||
- `P2-T1 管理页入口`
|
||||
- `P2-T2 正式数据面入口`
|
||||
- `P2-T3 route 健康视图`
|
||||
- `P2-T4 真实验收矩阵`
|
||||
- 2026-05-28 已完成 Phase 1 / `P1-T1 SQLite schema foundation`
|
||||
- 提交:`7f75d8a6 feat(routing): add logical group schema foundation`
|
||||
- 新 migration:`internal/store/migrations/0010_logical_groups_and_routes.sql`
|
||||
|
||||
423
docs/plans/2026-05-29-phase2-intelligent-routing-closure-plan.md
Normal file
423
docs/plans/2026-05-29-phase2-intelligent-routing-closure-plan.md
Normal file
@@ -0,0 +1,423 @@
|
||||
# Phase 2 实施计划:智能路由产品闭环
|
||||
|
||||
日期:2026-05-29
|
||||
|
||||
## 目标
|
||||
|
||||
把已经跑通的路由基础设施收敛成一个可正式承载流量、可被运营使用、可被真实服务器反复验证的 **Phase 2 产品闭环**。
|
||||
|
||||
本阶段只做以下四块:
|
||||
|
||||
1. 管理页入口
|
||||
2. 正式数据面入口
|
||||
3. route 健康视图
|
||||
4. 真实验收矩阵
|
||||
|
||||
本阶段完成后,必须满足:
|
||||
|
||||
- 管理员可以在 UI 上维护 `logical_group -> route -> shadow_group`
|
||||
- 插件存在一个正式、稳定、可审计的数据面入口,而不只是实验性质的最小 proxy API
|
||||
- route 的 sticky / failover / cooldown / 最近错误状态可以被运营查看
|
||||
- 每次核心改动都可以按固定矩阵在 `remote43` 上复验,不再依赖临时手工串命令
|
||||
|
||||
本阶段**不做**:
|
||||
|
||||
- 供应商帐号库存页
|
||||
- 普通用户 Portal 逻辑分组改造
|
||||
- 成本感知 / 延迟感知 / A/B 路由
|
||||
- 多公开模型同名双线路主备产品化
|
||||
|
||||
## 0. 当前基线
|
||||
|
||||
截至本计划编写时,以下基础已经存在并且做过 `remote43` 真验:
|
||||
|
||||
- `logical_group / route / route_model` SQLite 持久化
|
||||
- `logical_group / route` 管理 API
|
||||
- `route_decision_logs / route_failover_events / route_sticky_audit`
|
||||
- `memory / redis` sticky runtime backend
|
||||
- `POST /api/routing/resolve`
|
||||
- `POST /api/routing/proxy/chat/completions`
|
||||
- failover / cooldown / sticky rebinding
|
||||
- canonical shadow provider 方案
|
||||
- `managed subscription key -> real host /v1/chat/completions = 200`
|
||||
|
||||
因此 Phase 2 不是从零开始,而是把“可工作的工程链路”升级成“可持续运营的产品链路”。
|
||||
|
||||
## 1. 总体约束
|
||||
|
||||
### 技术约束
|
||||
|
||||
- 主状态库继续使用 **SQLite**
|
||||
- 路由运行态继续使用 **Redis**
|
||||
- 路由日志必须继续结构化落 SQLite
|
||||
- 不修改宿主源码
|
||||
- 不直写宿主数据库
|
||||
- 所有 route / shadow group 行为都通过插件控制面和宿主 HTTP API 完成
|
||||
|
||||
### 质量门禁
|
||||
|
||||
每个任务完成后必须通过:
|
||||
|
||||
```bash
|
||||
gofmt -l .
|
||||
go vet ./...
|
||||
go test -cover ./internal/...
|
||||
go test ./tests/integration/... -count=1
|
||||
```
|
||||
|
||||
如有前端或脚本改动,还必须通过:
|
||||
|
||||
```bash
|
||||
bash ./scripts/test/test_tksea_portal_assets.sh
|
||||
bash ./scripts/test/test_real_host_scripts.sh
|
||||
```
|
||||
|
||||
### 远端验证门禁
|
||||
|
||||
每个闭环功能完成后,必须执行:
|
||||
|
||||
1. 提交代码
|
||||
2. 推送远端仓库
|
||||
3. 部署到 `remote43`
|
||||
4. 验证 `http://127.0.0.1:18173/healthz`
|
||||
5. 通过公网或 remote43 本机完成真实 API 验证
|
||||
6. 留下可回读证据
|
||||
7. 更新 `docs/EXECUTION_BOARD.md`
|
||||
|
||||
## 2. 实施顺序
|
||||
|
||||
```text
|
||||
P2-T1 管理页入口
|
||||
P2-T2 正式数据面入口
|
||||
P2-T3 route 健康视图
|
||||
P2-T4 真实验收矩阵
|
||||
```
|
||||
|
||||
说明:
|
||||
|
||||
- `P2-T1` 先把控制面能力真正暴露给运营
|
||||
- `P2-T2` 把现有实验 proxy 收敛成正式数据面入口
|
||||
- `P2-T3` 再补 route 运行状态可视化
|
||||
- `P2-T4` 最后把前面三者收敛成固定验收矩阵
|
||||
|
||||
## 2.1 依赖矩阵
|
||||
|
||||
| 任务 | 依赖 | 可并行度 | 完成后解锁 |
|
||||
| --- | --- | --- | --- |
|
||||
| `P2-T1` | `P1-T2` | 可独立 | 运营侧能维护 logical routing |
|
||||
| `P2-T2` | `P1-T3` + `P1-T4` + 已有 canonical shadow 真验 | 建议紧跟 `P2-T1` | 正式数据面接入 |
|
||||
| `P2-T3` | `P1-T3` + `P1-T4` | 可与 `P2-T2` 部分交叉 | 运行状态可视化 |
|
||||
| `P2-T4` | `P2-T1` + `P2-T2` + `P2-T3` | 不建议提前 | 标准化真验与回归 |
|
||||
|
||||
---
|
||||
|
||||
## 3. P2-T1 管理页入口
|
||||
|
||||
## 目标闭环
|
||||
|
||||
让管理员不再只能靠 API 维护 logical routing,而是能在现有 admin portal 中完成:
|
||||
|
||||
- 创建 / 编辑 `logical_group`
|
||||
- 维护 `public_model`
|
||||
- 创建 / 编辑 `route`
|
||||
- 维护 `public_model -> shadow_model`
|
||||
- 关联 `shadow_host_id / shadow_group_id`
|
||||
|
||||
## 建议实现
|
||||
|
||||
优先复用现有 `deploy/tksea-portal/admin/` 结构,新增独立页面,例如:
|
||||
|
||||
- `deploy/tksea-portal/admin/logical-groups.html`
|
||||
|
||||
首版只做最小运营流,不做复杂图表:
|
||||
|
||||
1. 左侧:`logical_group` 列表
|
||||
2. 中间:当前分组详情
|
||||
3. 右侧:
|
||||
- `public_model` 列表
|
||||
- route 列表
|
||||
- route model 映射编辑器
|
||||
|
||||
## 需要对接的 API
|
||||
|
||||
- `GET /api/logical-groups`
|
||||
- `POST /api/logical-groups`
|
||||
- `GET /api/logical-groups/{group_id}`
|
||||
- `PUT /api/logical-groups/{group_id}`
|
||||
- `POST /api/logical-groups/{group_id}/models`
|
||||
- `GET /api/logical-groups/{group_id}/routes`
|
||||
- `POST /api/logical-groups/{group_id}/routes`
|
||||
- `PUT /api/logical-groups/{group_id}/routes/{route_id}`
|
||||
- `GET /api/logical-groups/{group_id}/routes/{route_id}/models`
|
||||
- `POST /api/logical-groups/{group_id}/routes/{route_id}/models`
|
||||
|
||||
## 文件范围
|
||||
|
||||
- Add:
|
||||
- `deploy/tksea-portal/admin/logical-groups.html`
|
||||
- Update:
|
||||
- `deploy/tksea-portal/admin/index.html`
|
||||
- 如有必要补充 portal 静态资源脚本
|
||||
|
||||
## 产出清单
|
||||
|
||||
- 一个可直接访问的逻辑分组管理页
|
||||
- 至少一条从页面发起的 `create group -> create route -> add route model` 成功链路
|
||||
- 页面内保留 `shadow_host_id / shadow_group_id` 的显式展示
|
||||
|
||||
## 远端验收
|
||||
|
||||
至少完成:
|
||||
|
||||
1. 登录 `/portal/admin/`
|
||||
2. 打开 `logical-groups.html`
|
||||
3. 创建临时 `logical_group`
|
||||
4. 创建临时 route
|
||||
5. 绑定一条 `public_model -> shadow_model`
|
||||
6. 通过 `GET /api/logical-groups/{group_id}` 回读一致
|
||||
|
||||
---
|
||||
|
||||
## 4. P2-T2 正式数据面入口
|
||||
|
||||
## 目标闭环
|
||||
|
||||
把当前实验性质的 `POST /api/routing/proxy/chat/completions` 升级成正式、可演进的数据面入口。
|
||||
|
||||
这个入口的职责是:
|
||||
|
||||
1. 接收公开模型请求
|
||||
2. 调用 `resolve`
|
||||
3. 命中 sticky / failover / cooldown
|
||||
4. 自动解析 `shadow_host_id / shadow_group_id / shadow_model`
|
||||
5. 必要时自动供给 `managed subscription key`
|
||||
6. 转发到真实 host `/v1/chat/completions`
|
||||
7. 回写 route logs
|
||||
|
||||
## 建议实现
|
||||
|
||||
首版不要急着做“全 OpenAI 兼容网关”,先只收敛为一个正式插件入口,例如:
|
||||
|
||||
- `POST /api/routing/chat/completions`
|
||||
|
||||
保留现有最小 proxy 作为内部/调试入口,但对外语义切到正式路由入口。
|
||||
|
||||
建议请求字段最少包含:
|
||||
|
||||
- `logical_group_id`
|
||||
- `model`
|
||||
- `subject_id`
|
||||
- `messages`
|
||||
- `subscription_user_id` 或调用方显式 key 来源
|
||||
- `request_id`(允许外部传入,也允许服务端自动生成)
|
||||
|
||||
建议响应至少包含:
|
||||
|
||||
- `request_id`
|
||||
- `selected_route_id`
|
||||
- `shadow_host_id`
|
||||
- `shadow_group_id`
|
||||
- `shadow_model`
|
||||
- `sticky_hit`
|
||||
- `fallback_used`
|
||||
- `forward.upstream_status`
|
||||
|
||||
## 文件范围
|
||||
|
||||
- Update:
|
||||
- `internal/app/http_api.go`
|
||||
- `internal/app/route_proxy_api.go`
|
||||
- 如有必要新增 `internal/app/route_gateway_api.go`
|
||||
- Add tests:
|
||||
- `internal/app/*_test.go`
|
||||
- `tests/integration/...` 补一轮正式入口集成测试
|
||||
|
||||
## 产出清单
|
||||
|
||||
- 正式路由数据面入口
|
||||
- 与实验 proxy 明确分层的 API 语义
|
||||
- 同一 `request_id` 可串起 resolve / forward / decision log
|
||||
|
||||
## 远端验收
|
||||
|
||||
至少完成:
|
||||
|
||||
1. 创建临时 `logical_group / route / route_model`
|
||||
2. 调正式入口发起最小 chat
|
||||
3. 命中真实 canonical shadow route
|
||||
4. 返回 `forward.upstream_status=200`
|
||||
5. 通过 `GET /api/routing/logs/decisions` 回读该次请求
|
||||
|
||||
---
|
||||
|
||||
## 5. P2-T3 Route 健康视图
|
||||
|
||||
## 目标闭环
|
||||
|
||||
让运营能看见 route 当前是否健康,而不是只能翻日志。
|
||||
|
||||
首版关注四类状态:
|
||||
|
||||
- `healthy`
|
||||
- `cooldown`
|
||||
- `failing`
|
||||
- `disabled`
|
||||
|
||||
## 建议实现
|
||||
|
||||
首版不做复杂 dashboard,只做一个列表页 + 轻量聚合 API。
|
||||
|
||||
建议新增:
|
||||
|
||||
- `GET /api/routing/routes/health`
|
||||
- 可选过滤:
|
||||
- `logical_group_id`
|
||||
- `route_id`
|
||||
- `status`
|
||||
|
||||
聚合数据来源:
|
||||
|
||||
- `logical_group_routes.status`
|
||||
- sticky runtime 中的 `routefail:{route_id}`
|
||||
- sticky runtime 中的 `routecool:{route_id}`
|
||||
- 最近一段时间的 `route_decision_logs`
|
||||
- 最近一段时间的 `route_failover_events`
|
||||
|
||||
建议返回字段:
|
||||
|
||||
- `route_id`
|
||||
- `logical_group_id`
|
||||
- `shadow_host_id`
|
||||
- `shadow_group_id`
|
||||
- `priority`
|
||||
- `runtime_status`
|
||||
- `failure_count`
|
||||
- `cooldown_until`
|
||||
- `last_error_class`
|
||||
- `last_selected_at`
|
||||
- `last_upstream_status`
|
||||
- `recent_failover_count`
|
||||
|
||||
前端建议增加:
|
||||
|
||||
- `deploy/tksea-portal/admin/route-health.html`
|
||||
|
||||
## 文件范围
|
||||
|
||||
- Add:
|
||||
- `internal/app/route_health_api.go`
|
||||
- `deploy/tksea-portal/admin/route-health.html`
|
||||
- Update:
|
||||
- `deploy/tksea-portal/admin/index.html`
|
||||
|
||||
## 产出清单
|
||||
|
||||
- 一组 route 健康聚合 API
|
||||
- 一个可查看 route 运行状态的管理页
|
||||
- 至少一条 route 的 `healthy -> cooldown -> failover` 可视化回读
|
||||
|
||||
## 远端验收
|
||||
|
||||
至少完成:
|
||||
|
||||
1. 先写入一条 route failure 或 cooldown
|
||||
2. 打开 `route-health.html`
|
||||
3. 看到该 route 状态变为 `failing` 或 `cooldown`
|
||||
4. 再触发一次 resolve
|
||||
5. 验证健康页和日志页一致
|
||||
|
||||
---
|
||||
|
||||
## 6. P2-T4 真实验收矩阵
|
||||
|
||||
## 目标闭环
|
||||
|
||||
把当前靠零散命令完成的真验,收敛成固定矩阵和固定证据格式。
|
||||
|
||||
## 验收矩阵
|
||||
|
||||
### 控制面
|
||||
|
||||
1. `logical_group` 创建 / 查询 / 更新
|
||||
2. route 创建 / 查询 / 更新
|
||||
3. route model 创建 / 查询
|
||||
|
||||
### 路由运行态
|
||||
|
||||
1. sticky bind
|
||||
2. sticky hit
|
||||
3. failure threshold failover
|
||||
4. cooldown failover
|
||||
5. sticky rebinding
|
||||
|
||||
### 数据面
|
||||
|
||||
1. 正式入口 -> canonical shadow route -> real host chat `200`
|
||||
2. `managed subscription key` 自动供给
|
||||
3. `request_id` 全链路串接
|
||||
4. route decision log 回写
|
||||
|
||||
### 管理页
|
||||
|
||||
1. `logical-groups.html`
|
||||
2. `route-health.html`
|
||||
3. 必要的 admin index 导航可见
|
||||
|
||||
## 建议沉淀形式
|
||||
|
||||
- 优先补充现有 acceptance / verify 脚本
|
||||
- 必要时新增:
|
||||
- `scripts/acceptance/verify_route_control_plane.sh`
|
||||
- `scripts/acceptance/verify_route_data_plane.sh`
|
||||
- `scripts/acceptance/verify_route_health_ui.sh`
|
||||
|
||||
每次真验至少输出:
|
||||
|
||||
- 代码提交号
|
||||
- remote43 当前 `repo HEAD`
|
||||
- request/sample IDs
|
||||
- 关键 API 响应摘要
|
||||
- decision log 回读摘要
|
||||
|
||||
## 产出清单
|
||||
|
||||
- 一份标准化验收矩阵
|
||||
- 至少两条可复用脚本
|
||||
- `EXECUTION_BOARD` 中新增“P2 标准真验矩阵”记录
|
||||
|
||||
## 远端验收
|
||||
|
||||
本任务自身的验收就是:
|
||||
|
||||
- 按矩阵完整跑通一次
|
||||
- 证据可复读
|
||||
- 后续任何 Phase 2 回归都可复用
|
||||
|
||||
---
|
||||
|
||||
## 7. 当前建议实施顺序
|
||||
|
||||
```text
|
||||
P2-T1 管理页入口
|
||||
P2-T2 正式数据面入口
|
||||
P2-T3 Route 健康视图
|
||||
P2-T4 真实验收矩阵
|
||||
```
|
||||
|
||||
原因:
|
||||
|
||||
- 先让人能配置
|
||||
- 再让流量能正式走
|
||||
- 再让状态能看见
|
||||
- 最后让整个 Phase 2 可持续回归
|
||||
|
||||
## 一句话结论
|
||||
|
||||
Phase 2 的重点已经不是“证明路由能跑”,而是把现有能力收敛成:
|
||||
|
||||
- 可操作的控制面
|
||||
- 可正式承载流量的数据面
|
||||
- 可视化的 route 健康面
|
||||
- 可重复执行的真实验收矩阵
|
||||
|
||||
只有这四块完成后,插件的智能路由能力才算从“工程验证成功”进入“产品闭环可运营”。
|
||||
Reference in New Issue
Block a user