2. Airflow核心概念

在金融ETL场景中,Airflow之所以能承担日终清算、行情补数、风控指标回算等关键任务,根本原因在于它把“调度”拆解为一组职责清晰、可独立观测的核心构件。理解这些构件之间的协作关系,比记住API更重要。本节围绕DAG、Task、Operator、Sensor、Hook、Executor、Scheduler、Metadata Database与Web UI九个概念,建立一张可落地的认知地图。

一、核心原理:声明式编排与集中式状态

Airflow采用“声明式编排 + 集中式状态”的设计。开发者用Python代码声明DAG(有向无环图),描述任务之间的依赖关系;Airflow自身不执行业务逻辑,而是把DAG解析为Task实例,交由Operator决定“做什么”,由Executor决定“在哪跑”,由Scheduler决定“何时跑”,最终把每一次运行的状态写入Metadata Database,并通过Web UI呈现。

其中,DAG是编排单元,定义调度周期、起止时间、重试策略与任务依赖;Task是DAG中的节点,是调度的最小单位;Operator是Task的模板类,如PythonOperator、BashOperator、SparkSubmitOperator;Sensor是特殊的Operator,用于等待外部条件(如文件到达、分区就绪);Hook封装外部系统连接,如HiveHook、S3Hook、HttpHook,供Operator复用;Executor负责实际执行,常见有LocalExecutor、CeleryExecutor、KubernetesExecutor;Scheduler是心脏,持续解析DAG文件、判断依赖、触发任务;Metadata Database存储DAG、Task、Run、XCom等元数据;Web UI则是观测与干预入口。

Airflow 核心构件协作关系 DAG 调度周期 / 依赖 / 重试 声明式编排单元 Task DAG中的节点 调度最小单位 Operator Python / Bash / Spark 决定“做什么” Sensor 等待外部条件 文件/分区就绪 Hook 封装外部连接 Hive / S3 / HTTP Executor Local / Celery / K8s 决定“在哪跑” Scheduler 解析DAG / 判断依赖 决定“何时跑” Metadata Database 状态 / XCom Web UI 观测运行状态 / 手动触发 / 清除重跑 / 查看日志

二、方法流程:一次调度到底发生了什么

以“日终行情文件到达后触发清算DAG”为例,完整链路如下:

  1. Scheduler周期性扫描DAG目录,解析Python文件,生成DagRun与TaskInstance,写入Metadata Database。
  2. Sensor(如S3KeySensor)轮询对象存储,确认行情文件已到达,返回成功。
  3. 依赖满足后,Scheduler将下游Task置为queued,交给Executor。
  4. Executor在Worker上启动进程,Operator通过Hook连接Hive/Spark执行清算逻辑。
  5. 任务状态、日志、XCom结果回写Metadata Database,Web UI实时刷新。
  6. 若失败,按DAG中retries与retry_delay自动重试;超过上限则标记failed并触发告警。
# 金融ETL典型DAG片段
with DAG(
    dag_id="fin_eod_clearing",
    schedule_interval="0 2 * * *",
    start_date=datetime(2024, 1, 1),
    catchup=False,
    default_args={
        "retries": 3,
        "retry_delay": timedelta(minutes=5),
        "on_failure_callback": alert_dingtalk,
    },
) as dag:
    wait_file = S3KeySensor(
        task_id="wait_market_file",
        bucket_name="fin-market",
        bucket_key="dt={{ ds }}/quotes.csv",
        poke_interval=60,
        timeout=3600,
    )
    clear = SparkSubmitOperator(
        task_id="run_clearing",
        application="s3://fin-jobs/clearing.jar",
        conn_id="spark_prod",
    )
    wait_file >> clear

三、案例场景:构件如何各司其职

假设某券商需要在每日凌晨2点完成“行情落地→清算→风控指标→报表推送”四步链路。DAG负责声明四步依赖与重试策略;Sensor等待上游文件;PythonOperator与SparkSubmitOperator分别承担轻量校验与重计算;HiveHook、S3Hook复用连接配置;CeleryExecutor把Spark任务分发到计算集群;Scheduler按cron触发;Metadata Database记录每次Run的耗时与失败原因;Web UI供运维在早盘前快速定位卡点并手动重跑。

构件核心职责金融ETL中的典型用法
DAG声明依赖与调度策略日终清算、行情补数、指标回算
Task调度最小单位单个校验、单个分区写入
Operator定义任务类型SparkSubmit、Python、Bash
Sensor等待外部条件等待行情文件、分区就绪
Hook封装外部连接Hive、S3、HTTP、数据库
Executor决定执行位置Celery分发、K8s弹性扩缩
Scheduler解析与触发cron触发、依赖判断
Metadata DB集中存储状态Run历史、XCom、日志索引
Web UI观测与干预查看Gantt、清除重跑、看日志

四、误区与复盘

误区一:把DAG当脚本写。在DAG文件顶层执行数据库查询或大文件读取,会导致Scheduler解析变慢甚至阻塞。正确做法是把重逻辑放进Operator的可调用对象中。

误区二:Sensor滥用。大量长时间poke的Sensor会占用Worker槽位。金融场景建议使用mode="reschedule"或改用Triggerer。

误区三:忽视Metadata Database性能。高频短任务会产生海量TaskInstance记录,需定期清理并配置合适的数据库连接池。

复盘要点:排查调度问题时,先看Web UI的Task状态与日志,再查Metadata Database中的task_instance与dag_run表,最后确认Scheduler与Executor的日志。Hook连接失败优先检查Connection配置,而非修改DAG代码。