如何理解airflow的schedule_interval
airflow的schdule_interval刚接触的时候还是有点烧脑的,为什么我希望它开始的时候,它就是不开始。
先来看一下官方的解释:airflow scheduler
Note that if you run a DAG on a schedule_interval of one day, the run stamped 2016-01-01 will be trigger soon after 2016-01-01T23:59. In other words, the job instance is started once the period it covers has ended.
Let’s Repeat That The scheduler runs your job one schedule_interval AFTER the start date, at the END of the period.
来仔细品品这段话。
如果你设置schedule_interval=@daily,在2016-01-01标记的(也就是满足定时触发条件的时间)任务,在2016-01-01T23:59以后会立即触发。换句话说,任务实例在自身覆盖的周期结束时立刻触发。
再重复强调一下,调度器运行一个任务的时间是:从开始时间算起,一个调度周期后开始执行,也就是在一个调度周期结束的时候。
结合两句话,也就是满足某个调度运行的时间在这个时间周期结束的时候才开始运行。1号的任务,在2号0点开始运行,0点的任务,在1点0分的时候运行。
写个例子来验证一下
from airflow import DAG
from airflow.operators.bash_operator import BashOperator
from datetime import datetime, timedelta
start_time=datetime(2020,6,6,11,40,0)
default_args = {
'owner': 'defy',
'depends_on_past': False,
'email': ['a@b.com'],
'email_on_failure': False,
'email_on_retry': False,
'retries': 0,
'retry_delay': timedelta(minutes=2),
'start_date': start_time,
}
dag = DAG(
'schedule2',
default_args=default_args,
schedule_interval="* * * * *"
)
task = BashOperator(
task_id='schedule2-task',
bash_command='echo {}'.format('{{ execution_date }}'),
dag=dag)
task
为了快速验证,以分钟为间隔。
从图上可以看到,当前时间是11:50,运行的是11:49的任务。
这样好像比较清楚了。
这时候,突然临座小哥问到:如果我想每天早上6点运行一个任务处理昨天一整天的数据,这个DAG在今天下午5点创建,明天早上6点会运行吗?我就是想让这个任务在明天早上6点开始运行,怎么设置?我:
先来分析一下。
每天6点运行,cron表达式:"0 6 * * *",那任务周期就是24小时。今天下午5点创建DAG,到明天6点还不到24小时的一个周期,应该还不会开始运行,要到后天早上6点才会。
测试代码如下:
from airflow import DAG
from airflow.operators.bash_operator import BashOperator
from datetime import datetime, timedelta
start_time=datetime(2020,6,1,17,0,0)
day='{{ (execution_date - macros.timedelta(hours=24)).strftime("%Y%m%d") }}'
default_args = {
'owner': 'defy',
'depends_on_past': False,
'email': ['a@b.com'],
'email_on_failure': False,
'email_on_retry': False,
'retries': 0,
'retry_delay': timedelta(minutes=2),
'start_date': start_time,
}
dag = DAG(
'schedule2',
default_args=default_args,
schedule_interval="0 6 * * *"
)
task = BashOperator(
task_id='schedule2-task',
bash_command='echo {}'.format(day),
dag=dag)
task
其实这里并没有说明今天下午5点创建DAG,明天6点会不会运行的问题,因为这个时间要等太久了。按照理论来说,要到后天早上6点才会开始运行。
那明天早上6点必须运行怎么办呢?可以使用手动触发任务,传入时间参数来完成,这样整个任务就可以非常灵活的执行了。具体方法可以参见另一篇文章:airflow的安装和使用 - 完全版
其实要弄清楚任务在什么时候触发,最清晰明了的办法是在界面上查看所有任务的触发时间列表:
[Tree View] -> [点击任务小方块] -> [Task Instances]
如图:
最关键的信息就是[Execution Date]这一列,看这个就可以更加清楚知道schedule_interval的运行机制