[Airflow]start_date, schedule_interval,execution_date

2,334 阅读2分钟

Airflow(2.0)采坑很多, 给出最经典的场景代码,然后给出解释

场景

时区是北京时间,今天是2021-01-14,我希望从今天开始(含今天),每周一到周五,下午3点,执行当天任务

包括的场景要素如下:

  • 时区(timezone)设置
  • 任务开始时间(start_date)的设置
  • 任务周期(scedule_interval)设置
  • 任务真正执行时间的设置(execution_date)
  • 执行当天任务(任务中execution_date的使用)
# airflow config
[core]
default_timezone = Asia/Shanghai
[webserver]
default_ui_timezone = Asia/Shanghai

# DAG arguments
dag = DAG(
	dag_id = 'demo_dag'
	start_date = datetime(2021113)
	schedule_interval = '0 15 * * 1-5')

# Task
def demo_func(*args, **context):
    execution_date = context['next_ds'] # !!!!!非常关键
    print('Do current day job: %s' % execution_date)

demo_task = PythonOperator(
    task_id='demo_task',
    python_callable=demo_func,
    op_args=['foo'],
    dag=demo_dag,
)

背后逻辑

时区设置

配置文件设置之后,Dag会取用,所以不需要在dag的start_date里面另外设置tzinfo

任务开始时间的设置

期待2021-01-14开始跑,那么dag的start_date需要设置前一天2021-01-13

因为真实的第一次运行时间是start_date + schedule_interval

所以如果start_date设置的是2021-01-14,那么真实的第一次运行时间是2021-01-15 15:00:00

周期的设置

可以放心使用crontab语法,例如场景中的0 15 * * 1-5

关于execution_date,尤其是执行当日任务

对于通常的ETL任务来说,都是后一天跑前一天的数据,所以Airflow的逻辑就是这样:

  1. 计算一个下一次的excution_date,存入dag的next_dagrun字段
  2. 计算一个下一次dagrun的触发时间,存入dag的next_dagrun_create_after字段
  3. scheduler不停检查当前时间和next_dagrun_create_after字段,当前时间超过next_dagrun_create_after视为需要执行
  4. 如果发现有需要创建的dagrun,则以next_dagrunexecution_date创建一个Dagrun实例去执行

所以,恶心的事情就来了2021-01-14 15:00:00执行的dagrun, execution_date2021-01-13!

当在我的场景之中,我其实是想收盘后下载当天的数据,所以期待的就是

execution_date = DagRun的真实执行日期

翻看源码之后,发现Airflow贯彻的是ETL的逻辑

execution_date = DagRun的真实执行时间 - 一个schedule_interval周期

所以,要想满足场景,只能是日期依赖的代码不使用macroexection_date | ds,而是使用next_exection_date | next_ds