← 返回技术文章与笔记

云剪辑系统设计进阶:基于 RocketMQ 的分布式调度与自定义任务队列编排

消息队列 · Pipeline · DAG · Worker 内调度

一、问题背景:从「任务执行」到「系统级编排能力」

在云剪辑场景中,单纯的「视频处理能力」并不是瓶颈,真正的挑战在于:

因此,系统目标不是「执行任务」,而是:

构建一个具备调度能力、编排能力、并发控制能力的云剪辑执行引擎。

二、系统总体架构(进阶版)

客户端请求
   ↓
任务抽象(Pipeline DSL)
   ↓
任务切片(Job → Task Graph)
   ↓
RocketMQ 分发(分布式调度)
   ↓
Worker 进程(多线程 + 自定义任务队列)
   ↓
DAG 调度器(本地)
   ↓
执行单元(解码 / 渲染 / 编码 / AI)
   ↓
结果聚合 & 输出

三、RocketMQ 的角色:分布式「粗粒度调度器」

我们基于 Apache RocketMQ 构建分布式调度层,但需要明确一点:RocketMQ 只负责任务分发(粗粒度),不负责执行侧的细粒度优化。

3.1 默认模型的局限性

以 RocketMQ C++ Consumer 为例,常见形态是:

于是会出现:

线程级并发 ≠ 任务级并发

示例:8 线程 × 每线程 30 个任务,默认执行上等价于只有 8 路并发在跑业务逻辑,而不是 240 路任务级并发。

四、核心优化:自定义任务队列(Custom Task Queue)

为解决上述问题,引入第二层调度机制:

Worker 内部构建「任务级并发调度系统」。

4.1 分层调度模型

RocketMQ(进程级调度)
   ↓
Consumer 线程(线程级调度)
   ↓
自定义任务队列(任务级调度) ← 核心
   ↓
执行线程池(资源调度)

4.2 自定义任务队列设计目标

4.3 核心结构设计

struct TaskWrapper {
    std::string taskId;
    std::function<void()> func;
    int priority;
    std::vector<std::string> dependencies;
};

队列划分示意:

4.4 执行流程

  1. RocketMQ 拉取一批任务
  2. 转换为 TaskWrapper
  3. 加入任务队列
  4. DAG 调度器分析依赖关系
  5. 就绪任务进入线程池执行
  6. 执行完成 → 更新依赖
  7. 触发下游任务

4.5 并发执行模型(关键)

Consumer 线程(例如 8 个)
    ↓
每个线程 → 提交任务到统一队列
    ↓
统一任务队列(全局或分片)
    ↓
线程池(N 核规模)

此时实际并发可以提升到 CPU 核心数级别(例如 32 / 64),由线程池与队列策略共同约束,而不是被消费线程数硬卡在 8。

五、Pipeline 编排:从线性流程到 DAG

系统核心抽象为 Pipeline;下面是一个增强版 JSON 示意(DSL 形态可按业务再封装):

{
  "pipeline": {
    "name": "广告视频生成",
    "tasks": [
      { "id": "decode", "className": "VideoDecodeTask" },
      { "id": "audio", "className": "AudioProcessTask" },
      { "id": "render", "className": "RenderTask" },
      { "id": "encode", "className": "EncodeTask" }
    ],
    "dependencies": [
      { "from": "decode", "to": "render" },
      { "from": "audio", "to": "render" },
      { "from": "render", "to": "encode" }
    ]
  }
}

本质:Pipeline 即 DAG(有向无环图);边表示数据或语义上的先后约束,节点表示可替换的执行单元。

六、组件化任务系统(可插拔执行单元)

通过任务工厂 + 类型注册表(配置里的 className 映射到具体 C++ 类型与构造器),实现与「反射式发现」相近的体验:任务 = 可注册、可发现、可动态创建的组件。C++ 无 JVM 式内置反射,一般用宏注册、静态初始化或插件入口完成绑定。

auto task = TaskFactory::createTask("RenderTask");
task->execute();

从而做到 配置驱动执行:改 JSON / 配置即可改链路,而不必改调度框架代码。

七、DAG 调度器(本地执行核心)

自定义调度器负责:

八、资源隔离与优化(进阶)

8.1 不同任务类型隔离

可拆分为多类线程池,例如 DecodePool / RenderPool / EncodePool,避免互相抢占默认池导致尾延迟放大。

8.2 背压(Backpressure)

当队列堆积过多时,可以:

8.3 批处理优化

例如多帧合并渲染、批量编码等,在吞吐优先场景下与低延迟路径分开建模。

九、完整执行链路(进阶版)

用户请求
   ↓
生成 Pipeline(JSON DSL)
   ↓
投递 RocketMQ
   ↓
Worker 拉取任务
   ↓
进入自定义任务队列
   ↓
DAG 调度器分析依赖
   ↓
线程池并发执行
   ↓
结果汇总
   ↓
编码输出

十、系统核心价值

十一、总结

系统的本质升级在于:从「任务执行框架」升级为「任务调度系统」。核心三层为:

  1. RocketMQ:分布式粗粒度调度与投递
  2. 自定义任务队列:任务级并发与队列治理
  3. DAG 调度器:依赖与状态驱动的执行编排

在云剪辑场景中,真正的挑战并不在于「如何处理视频」,而在于「如何组织处理过程」。通过将任务拆解为原子组件、用 Pipeline 描述依赖,并结合 RocketMQ 与本地任务队列构成分层调度体系,可以得到高并发、可扩展、易演进的云剪辑引擎,使系统从功能实现走向能力平台,支撑多业务与多场景持续迭代。