vault backup: 2026-06-03 10:30:42
This commit is contained in:
+61
-38
@@ -1,8 +1,19 @@
|
||||
# 01 - 系统总览
|
||||
---
|
||||
tags: [architecture, system-design, go, gin, dependency-injection, viper, config]
|
||||
create time: 2026-06-03 10:00
|
||||
---
|
||||
|
||||
> **一句话概括**:Gen2D 采用经典分层架构,Gin HTTP Server -> Handler -> Service -> 基础设施 -> 外部依赖,各层职责清晰、可独立替换。
|
||||
# 01. 系统总览
|
||||
|
||||
## 架构全景
|
||||
## 概述
|
||||
|
||||
Gen2D 采用经典分层架构,数据流自上而下贯穿 Gin HTTP Server → Handler → Service → 基础设施 → 外部依赖,各层职责清晰、可独立替换。
|
||||
|
||||
> **一句话概括**:分层架构,职责分离,轻量 DI,零配置可启动。
|
||||
|
||||
## 正文
|
||||
|
||||
### 架构全景
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
@@ -57,7 +68,7 @@ graph TB
|
||||
Pipeline -->|"Progress"| EB
|
||||
```
|
||||
|
||||
## 分层详解
|
||||
### 分层详解
|
||||
|
||||
| 层级 | 目录 | 核心职责 | 代表组件 |
|
||||
|------|------|----------|----------|
|
||||
@@ -70,9 +81,9 @@ graph TB
|
||||
| **精灵处理** | `pkg/splitsprite/`, `pkg/gifmaker/` | 精灵表切割、GIF 预览生成 | `splitsprite.Process`, `gifmaker.Encode` |
|
||||
| **配置** | `internal/config/` | YAML 加载、环境变量绑定、默认值 | `config.Load()` |
|
||||
|
||||
## 依赖注入模式
|
||||
### 依赖注入模式
|
||||
|
||||
Gen2D 采用轻量级的 **Set\*/Init\* 函数注入** 模式,避免引入 DI 框架。
|
||||
Gen2D 采用轻量级的 **Set*/Init* 函数注入** 模式,避免引入 DI 框架。
|
||||
|
||||
```
|
||||
main.go 中的注入链路:
|
||||
@@ -93,9 +104,11 @@ eventbus.Init() → 初始化事件总线
|
||||
- `service.InitImageGenConfig()` 将配置缓存为包级变量,避免在函数签名中传递大量参数
|
||||
- 每个 `Set*` 函数对应一个包级全局变量,简单但足够清晰
|
||||
|
||||
> :bulb: **为什么不用 Wire / Fx?** 项目规模可控,`cmd/main.go` 约 220 行即可完成全部注入,框架级 DI 的复杂度收益比不高。
|
||||
> [!tip] 为什么不用 Wire / Fx?
|
||||
>
|
||||
> 项目规模可控,`cmd/main.go` 约 220 行即可完成全部注入,框架级 DI 的复杂度收益比不高。
|
||||
|
||||
## 配置级联
|
||||
### 配置级联
|
||||
|
||||
Gen2D 使用 Viper 实现三层配置覆盖,优先级从高到低:
|
||||
|
||||
@@ -130,40 +143,50 @@ graph LR
|
||||
| `workerpool` | `GEN2D_WORKERPOOL_*` | workers, queue_size, max_per_user |
|
||||
| `taskqueue` | `GEN2D_TASKQUEUE_*` | driver, memory.buffer_size, rabbitmq.* |
|
||||
|
||||
## 请求全链路
|
||||
### 请求全链路
|
||||
|
||||
一个素材生成请求的完整生命周期:
|
||||
|
||||
```
|
||||
1. 浏览器 → POST /api/v1/generate
|
||||
2. Gin 中间件链 → Logger → Recovery → Metrics → Auth → RateLimit
|
||||
3. Handler.Generate()
|
||||
├── 参数绑定 & 校验
|
||||
├── 保存任务到 MySQL(status=pending)
|
||||
├── 构建 TaskMessage
|
||||
└── 提交到 TaskQueue(优先)或 WorkerPool(fallback)
|
||||
4. 返回 { taskId } 给浏览器
|
||||
5. Consumer 从 TaskQueue 消费消息
|
||||
6. Consumer → WorkerPool.Submit()
|
||||
7. WorkerPool 的 Worker 执行任务:
|
||||
├── 注入 ProgressReporter 到 context
|
||||
├── RunPipeline() — Eino Graph 执行
|
||||
│ ├── PromptOptimizer(合并风格 + 技术参数)
|
||||
│ ├── AssetGenerator(调用 AI 出图 API)
|
||||
│ ├── QualitySupervisor(质检,最多重试 3 次)
|
||||
│ └── FormatAdapter(精灵表切割 + GIF 预览)
|
||||
├── 上传素材到七牛云
|
||||
└── 更新 MySQL 任务状态
|
||||
8. EventBus.Publish() → SSE 推送给浏览器
|
||||
9. 浏览器通过 EventSource 实时接收进度
|
||||
```mermaid
|
||||
graph LR
|
||||
BROWSER["浏览器<br/>POST /api/v1/generate"] --> GIN["Gin中间件链"]
|
||||
GIN --> HANDLER["Handler.Generate"]
|
||||
HANDLER --> VALIDATE["参数绑定校验"]
|
||||
HANDLER --> MYSQL["保存任务MySQL<br/>status=pending"]
|
||||
HANDLER --> MSG["构建TaskMessage"]
|
||||
MSG --> TQ{"提交目标"}
|
||||
TQ -->|"优先"| TASKQUEUE["TaskQueue队列排队"]
|
||||
TQ -->|"Fallback"| WORKERPOOL["WorkerPool直连"]
|
||||
VALIDATE --> TQ
|
||||
MYSQL --> TQ
|
||||
TASKQUEUE --> CONSUMER["Consumer消费"]
|
||||
WORKERPOOL --> SUBMIT["WorkerPool.Submit"]
|
||||
CONSUMER --> SUBMIT
|
||||
SUBMIT --> WORKER["Worker执行"]
|
||||
WORKER --> PROGRESS["注入ProgressReporter"]
|
||||
WORKER --> PIPELINE["Eino Pipeline执行"]
|
||||
PIPELINE --> PROMPT["PromptOptimizer"]
|
||||
PIPELINE --> ASSET["AssetGenerator"]
|
||||
PIPELINE --> QUALITY["QualitySupervisor<br/>质检最多重试3次"]
|
||||
PIPELINE --> FORMAT["FormatAdapter<br/>精灵表切割GIF预览"]
|
||||
PROGRESS --> UPLOAD["上传素材七牛云"]
|
||||
QUALITY --> UPLOAD
|
||||
UPLOAD --> STATUS["更新MySQL状态"]
|
||||
STATUS --> EVENTBUS["EventBus.Publish"]
|
||||
EVENTBUS --> SSE["SSE推送"]
|
||||
SSE --> BROWSER_SSE["浏览器EventSource<br/>实时接收进度"]
|
||||
```
|
||||
|
||||
## 关键设计决策
|
||||
### 关键设计决策
|
||||
|
||||
> [!question] 思考:为什么 Gen2D 选择了异步任务 + SSE 推送的组合?
|
||||
>
|
||||
> 如果直接同步调用 Eino Pipeline,一个生成请求可能要等待 10~120 秒。在 HTTP 模型下,长时间占用的连接会耗尽服务器的并发能力。**异步提交 + SSE 推送**把「等待时间」从连接持有中解放出来——客户端收到 taskId 后可以自由离开,后续通过 SSE 长连接接收进度更新。这也是 Web 应用在 AI 场景下的标准模式。
|
||||
|
||||
| 决策 | 选择 | 理由 |
|
||||
|------|------|------|
|
||||
| 分层架构 | Handler-Service-Infra 三层 | 解耦各层职责,便于独立测试和替换 |
|
||||
| 依赖注入 | Set\*/Init\* 函数 | 轻量、零依赖,项目规模可控 |
|
||||
| 依赖注入 | Set*/Init* 函数 | 轻量、零依赖,项目规模可控 |
|
||||
| 配置管理 | Viper 三层级联 | 容器化友好,零配置可启动 |
|
||||
| 异步任务 | 提交-队列-消费-执行 | API 快速返回,长任务不阻塞请求 |
|
||||
| 事件推送 | EventBus + SSE | 比 WebSocket 轻量,HTTP 原生支持 |
|
||||
@@ -171,8 +194,8 @@ graph LR
|
||||
|
||||
## 关联文档
|
||||
|
||||
- [索引](00-index.md) — 文档导航与架构总览图
|
||||
- [协程池](02-worker-pool.md) — 有界并发与 per-user 限流
|
||||
- [任务队列](03-task-queue.md) — 可插拔队列接口与双实现
|
||||
- [RabbitMQ 集成](04-rabbitmq.md) — 持久化消息与重试机制
|
||||
- [生成管线](05-generation-pipeline.md) — Eino 4 阶段管线与质量回退
|
||||
- [[00-索引]] — 文档导航与架构总览图
|
||||
- [[02-协程池]] — 有界并发与 per-user 限流
|
||||
- [[03-任务队列]] — 可插拔队列接口与双实现
|
||||
- [[04-RabbitMQ集成]] — 持久化消息与重试机制
|
||||
- [[05-生成管线]] — Eino 4 阶段管线与质量回退
|
||||
|
||||
Reference in New Issue
Block a user