3. 整体架构:引擎分层架构图

异步任务编排核心引擎采用严格的分层架构,将职责从接口接入到底层存储进行垂直切分。每一层只关注自身边界内的逻辑,通过定义清晰的契约与相邻层交互。这种设计使得调度策略、执行逻辑、存储方案可以独立演进,是引擎具备高可用与可扩展性的基础。

架构设计原则: 层间单向依赖、上层依赖下层、下层对上层无感知。API 层与调度层之间通过内存队列解耦,调度层与执行层之间通过任务状态表解耦,执行层与存储层之间通过数据访问接口解耦。

3.1 引擎分层架构总览

引擎整体划分为四个核心层次,自顶向下依次为:API 层、调度层、执行层、存储层。每一层内部包含若干子模块,共同完成异步任务的编排与生命周期管理。

IAM 异步任务编排引擎 — 分层架构总览 API 层(接入与编排入口) REST / gRPC 接口 DAG 定义解析 任务提交与回调 鉴权与限流 调度层(任务编排与状态机) DAG 调度引擎 依赖解析器 状态机管理 重试与超时策略 执行层(任务执行与资源管理) 执行器池 资源隔离 结果回写 异常处理 存储层(持久化与状态记录)

3.2 各层职责详解

下表从核心职责、关键组件、输入输出三个维度,对四个层次进行对比说明。

层次 核心职责 关键组件 输入 → 输出
API 层 对外暴露统一接口,接收任务定义与编排请求 REST 控制器、gRPC 服务端、DAG 解析器、限流器 HTTP/gRPC 请求 → 内部任务 DTO
调度层 解析 DAG 依赖关系,驱动任务状态机流转 DAG 调度引擎、依赖解析器、状态机、重试管理器 任务 DTO → 可执行任务单元
执行层 实际执行任务逻辑,管理资源与异常 执行器线程池、资源隔离模块、结果收集器 可执行任务单元 → 执行结果
存储层 持久化任务定义、状态、日志与结果 MySQL/Redis 客户端、ORM 映射、缓存管理器 数据实体 → 持久化记录

3.3 层间交互流程

一个完整的异步任务编排生命周期,从提交到完成,经历以下标准交互流程:

  1. 客户端提交:用户通过 API 层提交任务 DAG 定义(JSON/YAML),API 层完成鉴权、参数校验与限流后,将 DAG 结构写入存储层,同时将任务 ID 推入调度层的内存队列。
  2. 调度层解析:调度层从队列中消费任务 ID,从存储层加载 DAG 定义,构建依赖图并计算初始可执行节点集合。调度层维护每个节点的状态机(PENDING → READY → RUNNING → SUCCESS/FAILED)。
  3. 任务下发:当节点状态变为 READY 时,调度层将任务上下文封装为执行单元,通过内部通道发送给执行层。
  4. 执行层执行:执行层从线程池中分配工作线程,执行具体业务逻辑。执行完成后,将结果与状态回写到存储层,并通知调度层状态变更。
  5. 调度层推进:调度层收到状态变更事件后,重新计算依赖关系,解锁后续节点,重复步骤 3-4 直至整个 DAG 完成。
  6. 结果聚合:DAG 执行完毕后,调度层触发回调通知,API 层将最终结果返回给客户端。
层间交互时序流程 API 层 调度层 执行层 存储层 ① 提交 DAG 定义 ② 加载 DAG 并解析 ③ 下发可执行单元 ④ 回写结果与状态 ⑤ 状态变更通知 ⑥ 触发回调通知

3.4 关键设计要点

设计要点 1:调度层与执行层的解耦
调度层不直接调用执行层的方法,而是通过“任务状态表”作为中间契约。调度层将任务状态更新为 READY,执行层通过轮询或监听机制获取 READY 任务并执行。这种设计使得调度层可以水平扩展,执行层也可以独立调整线程池大小,互不阻塞。
设计要点 2:存储层作为事实来源
所有层的状态变更最终都要持久化到存储层。即使调度层或执行层发生崩溃,重启后可以从存储层恢复所有未完成的任务状态,保证“至少一次”的语义。存储层使用 MySQL 存储任务定义与状态,Redis 缓存热点数据与分布式锁。
避坑提醒:避免层间循环依赖
执行层在回写结果时,不应直接调用调度层的接口来推进状态。正确的做法是:执行层只负责写结果到存储层,调度层通过监听存储层的变化(如数据库 binlog 或 Redis 发布/订阅)来感知状态变更。这样可以防止层间循环调用导致的死锁或级联故障。

3.5 分层架构的收益

维度 收益说明
可扩展性 每一层可以独立水平扩展。例如,执行层压力大时只需增加执行节点,无需改动调度逻辑。
可维护性 层间职责清晰,新成员可以快速定位问题所在层。单元测试可以针对单层 mock 相邻层接口。
容错性 单层故障不会扩散到其他层。调度层宕机后,执行层继续处理已有任务;存储层保证数据不丢失。
技术异构 各层可以使用不同的技术栈。例如,调度层用 Go 实现高并发状态机,执行层用 Java 对接遗留系统。