Files
cs-note/hzh/Gen2D/12-三级降级策略.md
T

5.9 KiB
Raw Blame History

tags, create time
tags create time
fallback-pattern
resilience
degradation
error-handling
go
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 = 最简串行队列(跳过所有高级特性)

这种设计确保降级过程是渐进的——功能逐步减少但服务始终可用。类比现实中的「应急灯」:市电断了 → 应急灯亮 → 最差情况还有手电筒。永远保留一条最低限度的通路。


设计哲学

宁可降级,也不能拒绝服务。

三级降级的核心思想是渐进式降级:

  1. 功能完整 — TaskQueue 提供持久化、重试、死信等高级特性
  2. 性能可控 — WorkerPool 提供有界并发和用户隔离
  3. 始终可用 — Legacy FIFO 确保在任何配置下都能接收任务

每一级降级都意味着功能的减少,但服务的可用性始终得到保障。前端收到 200 OK 后,通过 SSE 或轮询获取任务进度,对用户而言体验一致。

关联文档