3. 异步任务编排基础:任务依赖、DAG、工作流引擎与异步执行模型
在分布式系统中,单个业务请求往往需要拆解为多个子任务,这些子任务之间存在明确的执行顺序与数据依赖。异步任务编排正是解决“谁先执行、谁后执行、失败后怎么办”的核心技术。本章从任务依赖关系出发,逐步深入到有向无环图(DAG)、工作流引擎及异步执行模型,为后续基于 OpenTelemetry 的故障排查奠定理论基础。
3.1 任务依赖关系
任务依赖定义了子任务之间的执行约束。常见的依赖类型包括:
| 依赖类型 | 说明 | 示例 |
|---|---|---|
| 顺序依赖 | 任务 B 必须在任务 A 完成后才能启动 | 先下载文件,再解压 |
| 并行依赖 | 任务 C 等待任务 A 和任务 B 都完成后才能启动 | 等待两个数据源都就绪后合并 |
| 条件依赖 | 根据上游任务的输出结果决定下游任务是否执行 | 若校验失败则跳过后续处理 |
| 数据依赖 | 下游任务需要上游任务的输出数据作为输入 | 将特征工程的结果传给模型训练 |
实践要点:在定义依赖关系时,应避免循环依赖。循环依赖会导致任务永远无法完成,是编排系统中最常见的配置错误之一。
3.2 有向无环图(DAG)
DAG 是任务编排的数学基础。它将每个子任务建模为节点,将依赖关系建模为有向边,并保证图中不存在环路。DAG 的核心特性包括:
- 拓扑排序:总能找到一种线性顺序,使得所有依赖关系得到满足。
- 并行度:同一层级的无依赖节点可以并发执行。
- 容错边界:单个节点失败不会影响无依赖的其他分支。
下图展示了一个典型的异步任务 DAG 结构,包含数据采集、预处理、特征工程、模型训练与结果聚合五个阶段:
DAG 与可观测性:在 OpenTelemetry 中,每个 DAG 节点对应一个 Span,节点间的有向边对应 Span 的 Parent-Child 关系。通过 Trace 可以完整还原 DAG 的执行路径与耗时分布。
3.3 工作流引擎
工作流引擎是 DAG 的运行时载体,负责解析 DAG 定义、调度任务执行、处理失败重试与超时。主流的工作流引擎对比:
| 引擎 | 语言 | 状态持久化 | 重试策略 | 可观测性集成 |
|---|---|---|---|---|
| Temporal | Go / Java / Python | 内置 Event History | 指数退避 + 最大重试次数 | 原生 OpenTelemetry |
| Airflow | Python | 数据库(PostgreSQL/MySQL) | 固定间隔 + 重试次数 | 需额外配置 exporter |
| Argo Workflows | YAML / Go | Kubernetes CRD | Pod 级别重启 | 通过 OpenTelemetry Operator |
| Celery | Python | Redis / RabbitMQ | 任务级别重试 | 需手动注入 Trace |
选型建议:如果团队已经采用 Kubernetes 生态,Argo Workflows 的 DAG 原生支持与 Operator 模式能降低运维成本;若需要强一致性保证和长时间运行的工作流,Temporal 的 Event Sourcing 架构更为可靠。
3.4 异步执行模型
异步执行模型决定了任务在 DAG 中的具体运行方式。常见的模型包括:
- 事件驱动模型:任务通过事件总线触发,上游完成后发布事件,下游订阅后执行。适合高吞吐、低耦合场景。
- 回调模型:每个任务注册回调函数,上游完成后直接调用下游回调。适合任务数量固定、依赖关系明确的场景。
- Future/Promise 模型:每个任务返回一个 Future,下游通过
.then()或await等待结果。适合编程语言原生支持的异步框架。 - 状态机模型:工作流引擎维护全局状态,任务执行后更新状态,引擎根据状态转移决定下一步。适合需要持久化与恢复的复杂工作流。
下图对比了事件驱动模型与回调模型在 DAG 执行中的差异:
异步模型与 Trace 传播:在事件驱动模型中,Trace 上下文需要通过消息头传递(如 Kafka Headers 或 RabbitMQ 的 Headers Exchange);在回调模型中,上下文通常通过线程局部变量或协程上下文隐式传递。OpenTelemetry 的 Propagator 组件负责处理这两种场景的上下文注入与提取。
3.5 异步任务编排的故障模式
理解编排基础后,需要提前识别常见的故障模式:
- 死锁:两个任务互相等待对方释放资源,导致 DAG 永远无法推进。
- 级联失败:一个任务失败后,其下游所有任务被阻塞或连锁失败。
- 超时未处理:任务执行时间超过预期,但工作流引擎未设置超时机制,导致资源泄漏。
- 数据倾斜:并行分支中某个任务处理的数据量远大于其他分支,拖慢整体进度。
排查思路:在后续章节中,我们将利用 OpenTelemetry 的 Span 链路与 Metrics 指标,精准定位上述故障的根因。例如,通过 Span 的 Duration 分布可以快速发现数据倾斜,通过 Span 的 Status Code 可以识别级联失败的传播路径。