- Implemented tenant and user management features including: - Tenant creation and management with associated migrations. - User creation and management with associated migrations. - Tenant membership management with associated migrations. - Platform user roles management with associated migrations. - Quota management with associated migrations. - Article and template management with associated migrations. - Added HTTP handlers for templates and workspaces. - Created tests for protected and public routes. - Introduced a script to check tenant scope in SQL queries. - Documented task plan for backend completion and frontend foundation.
11 KiB
GEO 平台技术架构 V1 二次审查报告
基于更新后的 geo-platform-ops-admin-tech-architecture-v1.md(1257 行),对照
docs/refer中 8 个功能截图、两份 PRD 及 5 万并发用户目标进行审查。
一、前次缺失修复确认
| # | 前次严重缺失 | 修复状态 | 说明 |
|---|---|---|---|
| 1 | 定时调度器完全未设计 | ✅ 已修复 | §13.7.2 新增 cmd/scheduler,数据库到期扫描 + 行级锁防重 |
| 2 | Prompt 规则管理无后端模块 | ✅ 已修复 | §13.5.3 新增 tenant/prompt-rule,§13.11.2 新增 prompt_rules 表 |
| 3 | 模板管理后端模块缺失 | ✅ 已修复 | §13.5.3 新增 tenant/template,§13.11.2 新增 article_templates 表 |
| 4 | 数据库 Schema 缺失 | ✅ 已修复 | §13.11 提供 30+ 表的最小 Schema,含关键字段和索引 |
| 5 | GEO 指标采集方案未定义 | ✅ 已修复 | §13.9 定义完整的问题驱动监控模型 |
| 6 | 文章优化/版本管理缺失 | ✅ 已修复 | 新增 optimization_tasks + article_versions 表 |
| 7 | 浏览器插件通信协议缺失 | ✅ 已修复 | §13.8 定义插件会话模型 + 回调协议 |
| 8 | 绑定回调接口缺失 | ✅ 已修复 | §13.6.3 新增 /api/callback/plugin/bind |
| 9 | 竞品库管理缺失 | ✅ 已修复 | §13.11.3 新增 competitors 表 |
| 10 | 复合维度查询缺失 | ✅ 已修复 | §13.9 + §13.11.6 定义 keyword_model_daily_metrics 多维聚合 |
| 11 | 前端路由粒度不足 | ✅ 已修复 | §13.4 展开了完整路由 |
| 12 | SSE 细节不足 | ✅ 已修复 | §13.10 定义事件类型、负载格式、连接策略 |
Tip
前次审查中指出的 15 项问题已全部修复。 文档从 774 行扩展到 1257 行,新增的 §13 闭环补齐方案质量很高。
二、功能完整性复查(对照 docs/refer 截图)
| 功能页 | 路由 | API | 数据模型 | 异步组件 | 评价 |
|---|---|---|---|---|---|
| 工作台 | ✅ | ✅ 聚合 API | ✅ | ✅ | 完备 |
| 模板创作 | ✅ | ✅ | ✅ article_templates |
✅ worker-generate |
完备 |
| 自定义生成 | ✅ | ✅ | ✅ prompt_rules schedule_tasks |
✅ scheduler + worker-generate |
完备 |
| 文章优化 | ✅ | ✅ | ✅ optimization_tasks article_versions |
✅ worker-generate |
完备 |
| 媒体管理 | ✅ | ✅ + 回调 | ✅ plugin_sessions publish_records |
✅ 插件 + worker-publish-callback |
完备 |
| 品牌词库 | ✅ | ✅ | ✅ 含问题版本 + 竞品 | ✅ worker-analytics |
完备 |
| 知识库 | ✅ | ✅ | ✅ 分组 + 多来源 | ✅ worker-knowledge |
完备 |
| 数据追踪 | ✅ | ✅ | ✅ 5 张聚合表 | ✅ scheduler + worker-analytics |
完备 |
结论:8 个功能页全部达到"页面 → 路由 → API → 对象 → 任务 → 存储 → 状态回传"的完整闭环。
三、面向 5 万并发用户的技术问题
以下是基于"5 万人同时使用 + 足够简单"目标的严格审查:
🔴 必须解决的问题
1. Gateway 单点瓶颈 — 缺少水平扩展方案
文档中 cmd/gateway 是唯一入口,但未说明:
- Gateway 是否无状态可水平扩展(多实例部署)
- 前端连接的负载均衡策略(L4/L7)
- Gateway 与
tenant-api/platform-api之间的通信方式(直连 or 服务发现)
5 万并发用户假设平均每人每 10 秒发一次请求 = 5000 QPS。单个 Go 进程可以处理,但 SSE 长连接会占用大量连接数。
建议:明确 Gateway 无状态 + Kubernetes HPA 策略 + Nginx/Ingress L7 负载均衡。
2. SSE 连接数问题 — 5 万长连接的资源消耗
§13.10 设计了 SSE 推送,但 5 万用户全部保持 SSE 长连接意味着:
- 5 万个 TCP 连接同时保活
- 每个连接 15s heartbeat = 3333 条/秒 仅心跳
- 内存占用:每连接约 10-50KB → 约 500MB - 2.5GB 仅连接缓冲
建议:
- V1 默认使用 轮询(10s 间隔),仅在执行长任务时临时升级为 SSE
- 或者只在活跃操作页面(文章生成中、发布中)才建立 SSE,非活跃页面走轮询
- 明确 SSE 连接上限和优雅关闭策略
3. Scheduler 单实例风险
§13.7.2 描述 Scheduler 使用数据库行级锁防重复派发,但:
- 单 Scheduler 实例是单点故障
- 行级锁在高并发下有锁竞争风险
建议:
- V1 可接受单实例 + 进程级健康检查自动重启
- 但需要明确:如果 Scheduler 宕机 5 分钟,到期任务是否会堆积?重启后是否能自动追回?
- 文档中应补充
Scheduler 故障恢复策略
4. PostgreSQL 单库承压
30+ 张表全部在一个 PostgreSQL 实例中,5 万用户场景下:
articles表增长最快(每用户每天可能生成 5-20 篇)question_monitor_runs按问题数 × 模型数 × 天数增长audit_logs写入量大,查询范围广
建议:
- 审计日志表按月分区(
PARTITION BY RANGE (created_at)) - 监控数据表按日期分区
articles添加tenant_id分区索引或按 tenant 分片策略- 明确 V1 阶段的数据量估算和归档策略
5. 缺少限流与熔断设计
5 万用户中如果某个租户突发大量请求(如批量生成 1000 篇文章),可能打爆队列。文档只在 §7.2 提到 Redis 限流计数,但缺乏系统性设计:
建议:
- 在 Gateway 层增加租户级限流(令牌桶/滑动窗口)
- 在 Worker 层增加模型调用限频(保护下游 LLM API)
- 在 MQ 层设置队列容量上限 + 拒绝策略
- 生成任务提交时校验排队深度,超阈值直接拒绝并提示
🟡 建议优化的问题
6. 对象存储缺少 CDN 加速策略
知识库的原始文档和图片素材通过对象存储管理(§7.5),但 5 万用户同时访问文章预览中的图片时:
- 需要 CDN 分发(阿里云 OSS 天然支持,MinIO 需手动配 Nginx/CDN)
- 建议文档中明确:线上版走 OSS CDN,私有化部署走 Nginx 反代 MinIO
7. Redis 缓存雪崩风险
§13.9.2 提到 Redis 缓存 30 天摘要,但未设计:
- 缓存预热策略
- 缓存过期时间错开(避免集体失效)
- 缓存穿透保护(布隆过滤器或空值缓存)
建议:关键缓存(工作台统计、趋势图)使用 TTL + 异步刷新 模式,避免大量请求击穿到 PostgreSQL。
8. worker-generate 职责过重
§13.5.2 中 worker-generate 同时承载:模板生成、Prompt 生成、批量生成、文章优化。这意味着:
- 一个 Worker 进程要处理 4 种不同的任务类型
- 批量生成可能堵塞优化任务
建议:
- 队列内使用
routing key或priority区分任务类型 - 或拆分为
q.generate.interactive(即时任务,高优先级)和q.generate.batch(批量/定时任务,低优先级) - V1 在代码层面保持一个 Worker 二进制,但消费端可部署多实例分配不同 routing key
9. Sponge 框架兼容性未评估
§2.2 提到使用 sponge 框架,但文档中的分层架构(transport → app → domain → repository)与 sponge 的代码生成模式是否兼容未说明:
- sponge 生成的代码结构是否支持
internal/tenant+internal/platform的双域拆分? - sponge 的 handler/service/dao 分层与文档中的 transport/app/domain/repository 如何映射?
建议:明确 sponge 的使用范围(仅脚手架?还是深度依赖代码生成?),避免框架约束与架构设计冲突。
我的意见:优先架构设计为先,sponge 只是为了快速生成代码,但是一定架构设计为先
10. 缺少全局配置管理方案
文档提到 internal/shared/config,但未说明:
- 配置从哪里加载(文件?环境变量?配置中心?)
- 运行时配置变更是否支持热加载
- 多个服务(gateway / tenant-api / platform-api / scheduler / workers)的配置如何统一管理
建议:V1 使用 YAML 配置文件 + 环境变量覆盖,明确配置层级。
是用动态配置加载技术
🟢 文档层面的小问题
11. §5.5.9 platform/audit 内容空缺
第 406-407 行 platform/audit 只有标题没有内容,而 §13 中才补齐。应删除或填充。
12. §5.6.3 两服务协作原则有"悬挂列表"
第 436-439 行的 4 个日志类型列表与上文语义断裂,像是从 platform/audit 模块复制过来的遗留。
13. viewer 角色在 §6.2.2 被删除
原版有 viewer(只读成员),更新版替换为 kol。但 PRD 中明确定义了"只读成员"角色,建议保留 viewer 并额外增加 kol。
14. Mermaid 图中缺少 scheduler 节点
§8 交互图(第 553-599 行)未包含 scheduler,虽然 §13.5.1 补了修订图,但原图应同步更新或标注以修订图为准。
15. 后端结构图(§9)缺少 scheduler 节点
第 603-691 行的 Mermaid 图中 cmd 子图也缺少 scheduler 二进制。
四、面向"足够简单"目标的评估
| 维度 | 评价 | 风险点 |
|---|---|---|
| 服务数量 | ✅ 合理 — 8 个进程 | 足够收敛,V1 可控 |
| 中间件数量 | ⚠️ 偏多 — PG + Redis + RabbitMQ + Qdrant + OSS | 但都是必需的,无冗余 |
| 数据库表 | ⚠️ 30+ 张 | 但每张表职责单一,不算过度 |
| 框架选型 | ⚠️ Sponge 框架 | 需确认不会引入额外复杂度 |
| 部署复杂度 | ✅ Docker Compose 可覆盖本地开发 | 生产环境需 K8s |
| 前端应用数 | ✅ 2 + 1 插件 | 合理 |
Important
总体评价:架构已从"宏观方案"升级为"可开发闭环方案"。功能覆盖度 100%,数据模型完整。主要残留问题集中在 5 万并发的性能架构层面(SSE 连接管理、数据库分区、限流熔断)和文档一致性上。
五、修改优先级建议
| 优先级 | 修改项 | 工作量 |
|---|---|---|
| P0 | 补充 Gateway 水平扩展和负载均衡方案 | 0.5h |
| P0 | 修订 SSE 策略:默认轮询、长任务页面才开 SSE | 0.5h |
| P0 | 补充租户级限流 + 队列容量保护设计 | 1h |
| P1 | 补充 PostgreSQL 分区策略(审计/监控表) | 0.5h |
| P1 | 恢复 viewer 角色 + 增加 kol |
5min |
| P1 | 评估 sponge 框架与双域分层的兼容性 | 1h |
| P2 | 统一旧图与新图(§8/§9 补 scheduler) | 15min |
| P2 | 修复 §5.5.9 空内容 + §5.6.3 悬挂列表 | 10min |
| P2 | 补充配置管理方案 | 0.5h |
| P2 | 补充对象存储 CDN 方案 | 15min |