5.9 KiB
5.9 KiB
tags, create time
| tags | create time | |||||
|---|---|---|---|---|---|---|
|
2026-06-03 10:55 |
12. 三级降级策略
概述
Generate handler 实现三级降级 — TaskQueue -> WorkerPool -> Legacy FIFO,宁可降级也不拒绝服务。
正文
降级链总览
flowchart TD
R["HTTP Request\nPOST /api/v1/generate"] --> A{"TaskQueue 可用?"}
A -->|"Submit 成功"| S1["200 OK\ntaskId 返回"]
A -->|"Submit 失败"| B{"WorkerPool 可用?"}
B -->|"Submit 成功"| S2["200 OK\ntaskId 返回"]
B -->|"ErrPoolFull"| E2["503 Service\nUnavailable"]
B -->|"ErrUserLimit"| E3["429 Too Many Requests"]
B -->|"Pool 不可用"| C{"Legacy FIFO Queue 可用?"}
C -->|"Enqueue 成功"| S3["200 OK\ntaskId 返回"]
C -->|"Queue 不可用"| E4["500 Internal Server Error"]
style A fill:#4caf50,stroke:#333,color:#fff
style B fill:#ff9800,stroke:#333,color:#fff
style C fill:#f44336,stroke:#333,color:#fff
style S1 fill:#8bc34a,stroke:#333,color:#fff
style S2 fill:#8bc34a,stroke:#333,color:#fff
style S3 fill:#8bc34a,stroke:#333,color:#fff
三级详解
第一级:TaskQueue(优先路径)
| 属性 | 说明 |
|---|---|
| 组件 | taskqueue.TaskQueue 接口(Memory / RabbitMQ) |
| 特点 | 支持持久化、分布式、消息确认 |
| 提交 | taskQueue.Submit(ctx, msg) |
| 失败时 | 返回 HTTP 500,标记任务为 failed |
// handler/generate.go — 第一级
if taskQueue != nil {
msg := taskqueue.TaskMessage{...}
if err := taskQueue.Submit(ctx, msg); err != nil {
c.JSON(500, "提交任务失败")
return
}
c.JSON(200, taskId)
return // 成功,不再降级
}
第二级:WorkerPool(有界并发)
| 属性 | 说明 |
|---|---|
| 组件 | workerpool.Pool |
| 特点 | 有界队列 + per-user 并发限制 |
| 提交 | workerPool.Submit(task) |
| 失败类型 | ErrPoolFull -> 503 / ErrUserLimitReached -> 429 |
// handler/generate.go — 第二级
if workerPool != nil {
err := workerPool.Submit(workerpool.Task{...})
switch {
case errors.Is(err, workerpool.ErrPoolFull):
c.JSON(503, "系统繁忙,请稍后重试")
case errors.Is(err, workerpool.ErrUserLimitReached):
c.JSON(429, "您的生成任务已达上限")
default:
c.JSON(500, "提交任务失败")
}
return
}
第三级:Legacy FIFO(最后保底)
| 属性 | 说明 |
|---|---|
| 组件 | service.TaskQueue(串行 FIFO 队列) |
| 特点 | 零配置、串行执行、无并发控制 |
| 用途 | 兜底,确保系统在任何配置下都能运行 |
// handler/generate.go — 第三级
if generateQueue != nil {
generateQueue.Enqueue(&service.TaskJob{...})
}
c.JSON(200, taskId)
HTTP 状态码映射
flowchart LR
subgraph "降级路径"
TQ["TaskQueue"]
WP["WorkerPool"]
LF["Legacy FIFO"]
end
subgraph "HTTP 响应"
E200["200 OK\n任务已接受"]
E429["429 Too Many Requests\n用户限流"]
E500["500 Internal Server Error\n系统错误"]
E503["503 Service Unavailable\n系统繁忙"]
end
TQ -->|"成功"| E200
TQ -->|"失败"| E500
WP -->|"成功"| E200
WP -->|"队列满"| E503
WP -->|"用户限流"| E429
LF -->|"成功"| E200
LF -->|"不可用"| E500
| 状态码 | 含义 | 触发条件 |
|---|---|---|
200 |
任务已接受 | 任意一级提交成功 |
429 |
用户限流 | WorkerPool 用户并发达到上限 |
500 |
系统内部错误 | TaskQueue 提交失败 / 所有级别不可用 |
503 |
服务暂不可用 | WorkerPool 队列已满 |
为什么需要三级?
flowchart TB
subgraph "第一级:分布式能力"
TQ["TaskQueue\n持久化 + 消息确认\n支持 RabbitMQ 横向扩展"]
end
subgraph "第二级:并发控制"
WP["WorkerPool\n有界队列背压\nper-user 限流保护"]
end
subgraph "第三级:可用性兜底"
LF["Legacy FIFO\n零依赖、零配置\n确保始终可运行"]
end
TQ -->|"不可用时降级到"| WP
WP -->|"不可用时降级到"| LF
| 级别 | 核心价值 | 典型场景 |
|---|---|---|
| TaskQueue | 分布式 + 持久化 | 生产环境,多实例部署 |
| WorkerPool | 并发控制 + 背压 | 单机部署,需要限制资源 |
| Legacy FIFO | 可用性兜底 | 开发/测试环境,或队列组件故障 |
[!tip] 分级降级的核心原则
每一级都是前一级功能的超集。也就是说:
- TaskQueue = 持久化排队 + 重试 + Consumer 消费 + WorkerPool 执行
- WorkerPool = 有界并发 + 直接执行(跳过持久化和消费者)
- Legacy FIFO = 最简串行队列(跳过所有高级特性)
这种设计确保降级过程是渐进的——功能逐步减少但服务始终可用。类比现实中的「应急灯」:市电断了 → 应急灯亮 → 最差情况还有手电筒。永远保留一条最低限度的通路。
设计哲学
宁可降级,也不能拒绝服务。
三级降级的核心思想是渐进式降级:
- 功能完整 — TaskQueue 提供持久化、重试、死信等高级特性
- 性能可控 — WorkerPool 提供有界并发和用户隔离
- 始终可用 — Legacy FIFO 确保在任何配置下都能接收任务
每一级降级都意味着功能的减少,但服务的可用性始终得到保障。前端收到 200 OK 后,通过 SSE 或轮询获取任务进度,对用户而言体验一致。
关联文档
- 11-Consumer-Producer桥接 — Consumer 连接 TaskQueue 和 WorkerPool
- 02-协程池 — WorkerPool 的背压和限流机制
- 03-任务队列 — TaskQueue 接口的可插拔设计
- 00-索引 — 返回文档总览