Airflow 系列1:基本概念与架构介绍


本文基于 Apache Airflow 2.3.4 进行整理,主要介绍 Airflow 的基本概念、核心组件以及整体架构。

本篇文章不展开具体安装部署,也不编写完整 DAG 示例,重点是先把 Airflow 的整体运行逻辑讲清楚,为后续部署、数据库配置、执行器配置、DAG 编写和运维排查做铺垫。

一、背景介绍

在大数据平台中,经常会有大量离线任务需要定时执行,例如:

  • 数据采集任务
  • 数据清洗任务
  • Hive SQL 任务
  • Spark 作业
  • 数据同步任务
  • 报表生成任务

这些任务通常不是孤立存在的,而是存在明显的上下游依赖关系。

例如,在数仓分层中,通常需要先完成 ODS 层数据采集,再执行 DWD 层清洗,然后才能继续构建 DWS 层汇总数据,最后再生成 ADS 层指标结果。

如果只使用 crontab 来调度这些任务,会遇到几个比较明显的问题:

  • 很难描述复杂的任务依赖关系
  • 任务失败后不方便自动重试
  • 不方便统一查看任务运行状态
  • 不方便查看任务日志
  • 不方便手动补跑历史任务
  • 不方便做失败告警和运行监控

Airflow 就是为了解决这类工作流编排问题而出现的。

它并不是一个计算框架,也不直接替代 Spark、Hive、Flink 等组件。Airflow 更准确的定位是:

用来编写、调度、监控和管理工作流的平台。

大数据离线任务依赖示意图

二、Airflow 是什么

Airflow 是一个以编程方式编写、安排和监视工作流的平台。

在 Airflow 中,工作流通常使用 Python 代码进行定义。一个完整的工作流会被组织成一个 DAG,也就是有向无环图。

官方文档中对 Airflow 的描述是:Airflow 是一个用于构建和运行工作流的平台,一个工作流通过 DAG 表示,DAG 中包含多个 Task,这些 Task 会按照依赖关系和数据流进行组织。

简单来说,Airflow 主要做几件事情:

  • 使用 Python 编写工作流
  • 使用 DAG 描述任务依赖关系
  • 使用 Scheduler 按照调度规则触发任务
  • 使用 Executor 执行或分发任务
  • 使用 Web UI 查看任务状态、日志和运行情况
  • 使用 Metadata Database 保存任务运行状态

需要注意的是,Airflow 并不关心任务内部到底执行什么逻辑。

一个 Task 可以是:

  • 执行一段 Shell 命令
  • 执行一个 Python 函数
  • 提交一个 Spark 作业
  • 执行一段 Hive SQL
  • 调用一个接口
  • 发送一封邮件

Airflow 关注的是这些任务应该什么时候执行、按照什么顺序执行、失败后是否重试、运行状态如何记录、运行日志如何查看。

Airflow 工作流抽象图

三、Airflow 的核心特点

Airflow 有几个比较重要的特点,Word 文档中总结为 Dynamic、Extensible、Elegant、Scalable。

特点 含义 说明
Dynamic 动态 Airflow 使用 Python 定义工作流,可以通过代码动态生成 DAG 和 Task
Extensible 可扩展 可以自定义 Operator、Executor、Hook 和插件,适配不同业务场景
Elegant 简洁 Airflow 支持 Jinja 模板,可以方便地对任务参数进行模板化
Scalable 可扩展 Airflow 可以通过不同 Executor 扩展任务执行能力,适配单机或分布式执行场景

从使用角度看,Airflow 最大的特点是:

工作流即代码。

也就是说,任务调度逻辑不是配置在页面上,而是写在 Python 文件中。

这样做的好处是:

  • 可以使用 Git 管理 DAG 代码
  • 可以对 DAG 做代码审查
  • 可以复用 Python 代码能力
  • 可以动态生成任务
  • 可以更方便地和已有工程代码集成

四、Airflow 中的核心概念

想要理解 Airflow,首先需要理解几个核心概念。

4.1 DAG

DAG 的全称是 Directed Acyclic Graph,中文通常翻译为有向无环图。

在 Airflow 中,一个 DAG 表示一个完整的工作流。

这里有两个关键词:

  • 有向:任务之间的依赖关系是有方向的
  • 无环:任务依赖不能形成闭环

例如下面这种依赖关系是合理的:

dwd -> dws -> ads

但是下面这种依赖关系就是不合理的:

dwd -> dws -> ads -> dwd

因为它形成了环,Airflow 无法判断这个工作流应该从哪里开始,也无法判断什么时候结束。

需要注意的是,DAG 本身并不关心每个任务内部具体做什么。

DAG 主要描述的是:

  • 工作流中有哪些任务
  • 任务之间是什么依赖关系
  • 工作流按照什么时间规则调度
  • 失败后是否重试
  • 是否允许并发运行

DAG 有向无环图示意图

4.2 Task

Task 是 Airflow 中最小的执行单元。

一个 DAG 通常由多个 Task 组成,每个 Task 负责完成一个具体动作。

例如:

  • 一个 Task 负责同步数据
  • 一个 Task 负责执行清洗 SQL
  • 一个 Task 负责提交 Spark 作业
  • 一个 Task 负责发送邮件

Task 之间可以通过依赖关系描述执行顺序。

例如:

t1 >> t2 >> t3

这表示:

  • t1 执行成功后才能执行 t2
  • t2 执行成功后才能执行 t3

在 Airflow 中,通常会使用 upstream 和 downstream 描述任务之间的上下游关系。

  • upstream:上游任务
  • downstream:下游任务

4.3 Operator

Operator 可以理解为任务模板。

在 DAG 文件中,我们通常不是直接创建一个 Task,而是通过某种 Operator 来定义一个 Task。

常见的 Operator 包括:

Operator 作用
BashOperator 执行 Shell 命令
PythonOperator 执行 Python 函数
EmailOperator 发送邮件
EmptyOperator 空任务,通常用于占位或组织依赖

在一些旧版本文档中,也会看到 DummyOperator 这个名字。Airflow 2.x 中更推荐使用 EmptyOperator

例如,使用 BashOperator 可以定义一个执行 Shell 命令的任务:

from airflow.operators.bash import BashOperator

t1 = BashOperator(
    task_id='print_date',
    bash_command='date'
)

这里的 BashOperator 是任务模板,t1 才是 DAG 中的一个具体任务。

4.4 Scheduler

Scheduler 是 Airflow 中非常核心的组件,可以理解为调度器。

它主要负责:

  • 周期性扫描 DAG 文件
  • 解析 DAG 中定义的任务和依赖关系
  • 判断 DAG 是否需要生成新的 DAG Run
  • 判断 Task 的依赖是否已经满足
  • 将可以运行的 Task 提交给 Executor

官方文档中提到,Scheduler 会监控所有 Task 和 DAG,当任务依赖满足后,会触发对应的 Task Instance。

在生产环境中,Scheduler 通常会作为一个长期运行的服务存在。

启动命令如下:

airflow scheduler

只有 Scheduler 正常运行,DAG 才能按照调度周期自动执行。

4.5 Executor

Executor 负责决定任务如何执行。

Scheduler 判断某个 Task 可以运行之后,并不会自己直接执行所有任务,而是把任务交给 Executor。

不同 Executor 对应不同的执行方式。

常见 Executor 包括:

Executor 说明
SequentialExecutor 顺序执行器,默认简单安装时常见,只能顺序执行任务
LocalExecutor 本地执行器,可以在本机并行执行多个任务
CeleryExecutor 基于 Celery 分布式执行任务
KubernetesExecutor 基于 Kubernetes Pod 执行任务

在后续部署文章中,会将默认执行器修改为 LocalExecutor

这里先记住一点:

Scheduler 负责判断任务什么时候可以运行,Executor 负责决定任务以什么方式运行。

4.6 Webserver

Webserver 提供 Airflow 的 Web UI。

通过 Web UI 可以完成很多日常操作:

  • 查看 DAG 列表
  • 查看 DAG 运行状态
  • 查看任务依赖图
  • 手动触发 DAG
  • 查看任务日志
  • 查看任务执行时间
  • 排查失败任务

启动 Webserver 的命令如下:

airflow webserver -p 8080

Webserver 本身不负责任务调度,也不直接执行任务。

它主要从 Metadata Database 中读取 DAG 和 Task 的状态,并展示给用户。

4.7 Metadata Database

Metadata Database 是 Airflow 的元数据库。

Airflow 运行过程中会产生大量状态信息,这些信息都需要保存到元数据库中。

例如:

  • DAG 信息
  • DAG Run 信息
  • Task Instance 状态
  • 任务日志元信息
  • 用户信息
  • 变量信息
  • 连接信息
  • 调度状态

Scheduler、Executor、Webserver 都会依赖 Metadata Database。

默认情况下,Airflow 可以使用 SQLite 作为元数据库,但 SQLite 更适合测试环境。

在实际使用中,通常会将元数据库修改为 MySQL 或 PostgreSQL。

后续文章会介绍如何将 Airflow 的元数据库修改为 MySQL。

Airflow 核心组件架构图

五、Airflow 的任务执行流程

理解了核心组件后,再来看一个 DAG 是如何被 Airflow 调度执行的。

整体流程如下:

  1. 用户编写 Python DAG 文件
  2. DAG 文件放入 Airflow 的 dags 目录
  3. Scheduler 周期性扫描并解析 DAG 文件
  4. Scheduler 根据调度周期判断是否需要创建 DAG Run
  5. Scheduler 判断 DAG 中各个 Task 的依赖是否满足
  6. 满足条件的 Task 被提交给 Executor
  7. Executor 安排任务在本地或 Worker 上执行
  8. Task 执行状态写入 Metadata Database
  9. Webserver 从 Metadata Database 读取状态并展示到页面

可以看到,Airflow 的运行过程不是简单地执行一个 Python 文件。

Python 文件只是用来定义 DAG,真正的调度和执行是由 Scheduler、Executor、Metadata Database、Webserver 等组件协同完成的。

Airflow 调度执行流程图

六、Task Instance 的生命周期

在 Airflow 中,Task 是任务定义,而 Task Instance 是某一次具体运行中的任务实例。

例如,一个 DAG 每天执行一次,那么同一个 Task 每天都会产生一个新的 Task Instance。

Task Instance 会有自己的运行状态。

常见状态如下:

状态 含义
none 任务还没有进入调度
scheduled Scheduler 已经判断任务依赖满足,准备调度
queued 任务已经进入 Executor 队列
running 任务正在运行
success 任务执行成功
failed 任务执行失败
skipped 任务被跳过
up_for_retry 任务失败后等待重试
upstream_failed 上游任务失败,导致当前任务无法执行

理想情况下,一个任务会按照下面的状态流转:

none -> scheduled -> queued -> running -> success

如果任务执行失败,并且配置了重试次数,则可能进入:

running -> failed -> up_for_retry -> scheduled

理解 Task Instance 的状态非常重要。

后续在排查任务为什么没有执行、为什么一直 queued、为什么没有触发下游任务时,基本都会围绕这些状态进行分析。

Task Instance 状态流转图

七、Airflow 适合解决什么问题

结合大数据场景,Airflow 比较适合解决以下问题:

  • 定时调度 Hive SQL
  • 调度 Spark 作业
  • 调度 Shell 脚本
  • 调度 Python 程序
  • 编排数据同步任务
  • 编排离线数仓分层任务
  • 处理任务失败重试
  • 统一查看任务运行状态和日志
  • 结合邮件进行失败告警

例如,在离线数仓中,可以使用 Airflow 编排下面的任务链路:

ods_user_log -> dwd_user_action -> dws_user_summary -> ads_user_report

每一层任务都可以由不同的 Operator 实现。

如果某一层任务失败,Airflow 可以记录失败状态,并根据配置进行重试或告警。

所以,在大数据平台中,Airflow 更适合承担“调度中枢”的角色。

它不负责具体计算,但负责任务什么时候执行、按照什么依赖执行、失败后如何处理、状态如何查看。

八、本篇总结

本文主要介绍了 Airflow 的基本概念和整体架构。

需要重点理解以下几点:

  1. Airflow 是一个使用 Python 编写工作流的调度和编排平台。
  2. DAG 是 Airflow 的核心,用来描述任务之间的依赖关系。
  3. Task 是最小执行单元,Operator 是创建 Task 的任务模板。
  4. Scheduler 负责任务调度,Executor 负责任务执行方式。
  5. Webserver 用于页面展示,Metadata Database 用于保存运行状态。
  6. 理解 Task Instance 状态,对后续排查任务调度问题非常重要。

后续文章将继续介绍 Airflow 的环境准备与单机部署。

参考资料


文章作者: hnbian
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 hnbian !
评论
  目录