You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
11 KiB
11 KiB
AI 服务流程图 (Mermaid)
日期: 2026-01-30
版本: 1.0
目录
整体架构
graph TB
subgraph "客户端层"
Client[Web/Mobile Client]
end
subgraph "API 层"
FastAPI[FastAPI Server<br/>端口: 6170]
end
subgraph "任务队列"
RabbitMQ[RabbitMQ<br/>消息队列]
CeleryWorker[Celery Worker<br/>AI 任务处理]
end
subgraph "AI 服务"
AIProvider[AI Provider<br/>OpenAI/DALL-E]
end
subgraph "存储层"
PostgreSQL[(PostgreSQL 17<br/>任务状态/积分)]
MinIO[MinIO<br/>文件存储]
end
Client -->|HTTP Request| FastAPI
FastAPI -->|提交任务| RabbitMQ
RabbitMQ -->|分发任务| CeleryWorker
CeleryWorker -->|调用 AI| AIProvider
CeleryWorker -->|上传文件| MinIO
FastAPI -->|读写数据| PostgreSQL
CeleryWorker -->|更新状态| PostgreSQL
style Client fill:#e1f5ff
style FastAPI fill:#fff3e0
style CeleryWorker fill:#f3e5f5
style AIProvider fill:#e8f5e9
style PostgreSQL fill:#fce4ec
style MinIO fill:#fff9c4
图片生成完整流程
sequenceDiagram
participant C as 客户端
participant A as FastAPI API
participant CS as Credit Service
participant DB as PostgreSQL
participant Q as RabbitMQ
participant W as Celery Worker
participant AI as AI Provider<br/>(DALL-E 3)
participant M as MinIO
Note over C,M: 1. 创建任务阶段
C->>A: POST /ai/generate-image<br/>{prompt, width, height}
A->>A: 验证请求 & 认证
A->>CS: 预扣积分
CS->>DB: 检查余额
CS->>DB: 创建 consumption_log<br/>(status=PENDING)
CS-->>A: 返回 consumption_log_id
A->>DB: 创建 ai_jobs<br/>(status=PENDING)
A->>Q: 提交 Celery 任务
A-->>C: 返回 Job ID & Task ID
Note over C,M: 2. 异步执行阶段
Q->>W: 分发任务
W->>W: 创建独立 Event Loop
W->>DB: 更新状态<br/>(PROCESSING, 10%)
W->>DB: 获取 Job 信息<br/>(consumption_log_id)
W->>W: 创建 OpenAI Provider
W->>DB: 更新状态<br/>(PROCESSING, 30%)
W->>AI: 调用 DALL-E 3<br/>generate_image()
AI-->>W: 返回图片 URL
W->>DB: 更新状态<br/>(PROCESSING, 70%)
W->>AI: 下载图片 (3MB+)
AI-->>W: 图片数据
W->>M: 上传到 MinIO
M-->>W: 返回文件元数据<br/>(url, checksum, size)
W->>DB: 更新状态<br/>(COMPLETED, 100%)<br/>+ output_data
W->>CS: 确认积分消耗
CS->>DB: 更新 consumption_log<br/>(status=CONFIRMED)
Note over C,M: 3. 查询结果阶段
C->>A: GET /ai/jobs/{job_id}
A->>DB: 查询任务状态
DB-->>A: 返回完整结果
A-->>C: 返回 output_data<br/>(file_url, metadata)
任务状态流转
stateDiagram-v2
[*] --> PENDING: 任务创建
PENDING --> PROCESSING: Worker 接收任务
PROCESSING --> COMPLETED: 执行成功
PROCESSING --> FAILED: 执行失败
PROCESSING --> TIMEOUT: 执行超时
PROCESSING --> CANCELLED: 用户取消
COMPLETED --> [*]: 确认积分
FAILED --> [*]: 退还积分
TIMEOUT --> [*]: 退还积分
CANCELLED --> [*]: 退还积分
note right of PENDING
状态码: 1
进度: 0%
end note
note right of PROCESSING
状态码: 2
进度: 0% → 100%
步骤:
- 10%: 开始处理
- 30%: AI 调用中
- 70%: 文件处理中
- 100%: 完成
end note
note right of COMPLETED
状态码: 3
进度: 100%
包含 output_data
end note
note right of FAILED
状态码: 4
包含 error_message
end note
积分系统集成
sequenceDiagram
participant U as 用户
participant A as AI Service
participant CS as Credit Service
participant DB as Database
Note over U,DB: 任务创建时
U->>A: 请求生成图片
A->>CS: 预扣积分<br/>deduct_credits()
CS->>DB: 检查用户余额
alt 余额充足
CS->>DB: 创建消费记录<br/>(status=PENDING)
CS->>DB: 扣减用户积分
CS-->>A: 返回 consumption_log_id
A->>DB: 创建任务<br/>(关联 consumption_log_id)
else 余额不足
CS-->>A: 抛出异常
A-->>U: 返回错误: 积分不足
end
Note over U,DB: 任务完成时
A->>CS: 确认积分消耗<br/>confirm_consumption()
CS->>DB: 更新消费记录<br/>(status=CONFIRMED)
CS->>DB: 关联资源 ID
Note over U,DB: 任务失败时
A->>CS: 退还积分<br/>refund_credits()
CS->>DB: 更新消费记录<br/>(status=REFUNDED)
CS->>DB: 返还用户积分
积分状态流转
stateDiagram-v2
[*] --> PENDING: 预扣积分
PENDING --> CONFIRMED: 任务成功
PENDING --> REFUNDED: 任务失败/取消/超时
CONFIRMED --> [*]
REFUNDED --> [*]
note right of PENDING
积分已扣除
等待任务完成
end note
note right of CONFIRMED
积分消耗确认
关联资源 ID
end note
note right of REFUNDED
积分已退还
记录失败原因
end note
Event Loop 隔离机制
graph TB
subgraph "Celery ForkPoolWorker"
subgraph "任务 1"
T1[generate_image_task]
L1[Event Loop 1]
E1[Engine 1]
S1[Session 1]
T1 -->|创建| L1
L1 -->|创建| E1
E1 -->|创建| S1
S1 -.->|dispose| E1
E1 -.->|close| L1
end
subgraph "任务 2"
T2[generate_video_task]
L2[Event Loop 2]
E2[Engine 2]
S2[Session 2]
T2 -->|创建| L2
L2 -->|创建| E2
E2 -->|创建| S2
S2 -.->|dispose| E2
E2 -.->|close| L2
end
end
DB[(PostgreSQL)]
S1 -->|独立连接| DB
S2 -->|独立连接| DB
style T1 fill:#e3f2fd
style T2 fill:#f3e5f5
style L1 fill:#fff3e0
style L2 fill:#fff3e0
style E1 fill:#e8f5e9
style E2 fill:#e8f5e9
style S1 fill:#fce4ec
style S2 fill:#fce4ec
Event Loop 创建流程
sequenceDiagram
participant CT as Celery Task
participant RA as run_async_task()
participant EL as Event Loop
participant GA as get_async_session()
participant E as Engine
participant S as Session
participant DB as Database
CT->>RA: 调用异步任务
RA->>EL: 创建新 Event Loop<br/>asyncio.new_event_loop()
RA->>EL: 设置为当前 Loop<br/>set_event_loop()
loop 每次数据库操作
EL->>GA: 获取独立连接
GA->>E: 创建 Engine<br/>(poolclass=None)
GA->>S: 创建 Session
S->>DB: 执行数据库操作
S->>E: dispose()
end
RA->>EL: 关闭 Loop<br/>loop.close()
RA-->>CT: 返回结果
错误处理流程
graph TB
Start[任务开始] --> Try{执行任务}
Try -->|成功| UpdateSuccess[更新状态: COMPLETED<br/>progress: 100%]
Try -->|失败| CatchError[捕获异常]
UpdateSuccess --> ConfirmCredit[确认积分消耗]
ConfirmCredit --> End[任务结束]
CatchError --> UpdateFailed[更新状态: FAILED<br/>记录错误信息]
UpdateFailed --> RefundCredit[退还积分]
RefundCredit --> CheckRetry{检查重试次数}
CheckRetry -->|< 3 次| Retry[延迟重试<br/>countdown = 60 * retries]
CheckRetry -->|>= 3 次| RaiseError[抛出异常]
Retry --> Start
RaiseError --> End
style Start fill:#e3f2fd
style End fill:#e3f2fd
style UpdateSuccess fill:#c8e6c9
style UpdateFailed fill:#ffcdd2
style ConfirmCredit fill:#fff9c4
style RefundCredit fill:#ffe0b2
错误类型处理
graph LR
subgraph "错误类型"
E1[AI Provider 错误]
E2[网络错误]
E3[文件存储错误]
E4[数据库错误]
E5[积分不足]
E6[超时错误]
end
subgraph "处理策略"
H1[重试 3 次]
H2[立即失败]
H3[退还积分]
end
E1 --> H1
E2 --> H1
E3 --> H1
E4 --> H1
E5 --> H2
E6 --> H2
H1 --> H3
H2 --> H3
style E1 fill:#ffcdd2
style E2 fill:#ffcdd2
style E3 fill:#ffcdd2
style E4 fill:#ffcdd2
style E5 fill:#ffcdd2
style E6 fill:#ffcdd2
style H1 fill:#fff9c4
style H2 fill:#ffe0b2
style H3 fill:#c8e6c9
文件存储流程
sequenceDiagram
participant W as Celery Worker
participant AI as AI Provider
participant FS as FileStorageService
participant M as MinIO
participant DB as Database
W->>AI: 生成内容
AI-->>W: 返回临时 URL
W->>W: 下载文件<br/>httpx.AsyncClient.get()
W->>FS: upload_file()<br/>(content, filename, type)
FS->>FS: 计算 checksum<br/>(SHA-256)
FS->>FS: 生成存储路径<br/>(category/user_id/checksum.ext)
FS->>M: 上传文件<br/>put_object()
M-->>FS: 上传成功
FS->>DB: 创建 file_metadata 记录
DB-->>FS: 记录创建成功
FS-->>W: 返回文件元数据<br/>(url, size, checksum)
W->>W: 更新 output_data<br/>包含文件信息
关键技术点
1. Event Loop 隔离
def run_async_task(coro):
"""为每个任务创建独立的 Event Loop"""
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
try:
return loop.run_until_complete(coro)
finally:
loop.close()
2. 独立数据库连接
def get_async_session():
"""为每个操作创建独立的数据库连接"""
engine = create_async_engine(
settings.DATABASE_URL,
poolclass=None # 禁用连接池
)
async_session_maker = sessionmaker(
engine, class_=AsyncSession
)
return async_session_maker, engine
3. 资源清理模式
async_session_maker, engine = get_async_session()
try:
async with async_session_maker() as session:
# 数据库操作
pass
finally:
await engine.dispose() # 确保资源释放
性能指标
pie title 任务执行时间分布 (总计 ~60秒)
"AI 生成" : 10
"文件下载" : 1
"文件上传" : 0.1
"数据库操作" : 0.05
"网络延迟" : 48.85