前言背景
笔者使用的是最新的airflow作为测试!版本为1.10.12,公司用的生产是比这个版本低了3个小版本,所以引入ExternalTaskMarker报错,如果有相似的小伙伴,可以自行搭建一个airflow,进行测试或者升级你的airflow。
有个调度需求,查询以前历史DAG发现,有一个DAG可以作为我新调度的前置,所以想看看DAG之间task如何关联,所以有了下面的Demo。
如果会科学上网,英语听力还不错的,可以移驾这里,这个大佬讲的会更到位!(点击我!!)
原理
DAG A和DAG B是两个不同py文件写的,我A中一个task是我B中一个task的依赖,只有当A执行完了,我的B才能执行,那么该如何做呢,那么就应该安排一个监工的,看着A中指定task是否执行成功,执行成功那就监工就可以撤了,让B中的那个任务开始执行。
Master.py
vim master.py
from datetime import datetime, timedelta
from airflow import DAG
from airflow.operators.bash_operator import BashOperator
from airflow.utils.dates import days_ago
from airflow.sensors.external_task_sensor import ExternalTaskMarker, ExternalTaskSensor
default_args={
"owner": "airflow",
"start_date": datetime(2020,11, 22),
}
with DAG(
dag_id="master_dag",
default_args=default_args,
schedule_interval="20 15 * * *",
#concurrency=1,
#max_active_runs=1,
tags=['example1'],
) as child_dag:
# [START howto_operator_external_task_sensor]
child_task1 = ExternalTaskSensor(
task_id="master_task1",
external_dag_id="slave_dag",
external_task_id="slave_task1",
# timeout=600,
# allowed_states=['success'],
# failed_states=['failed', 'skipped'],
execution_delta=timedelta(minutes=5),
# mode= "reschedule",
)
# [END howto_operator_external_task_sensor]
child_task2 = BashOperator(task_id="master_task2",bash_command="echo i am master!",dag=child_dag)
child_task1 >> child_task2
Slave.py
vim slave.py
from datetime import datetime, timedelta
from airflow import DAG
from airflow.operators.bash_operator import BashOperator
from airflow.utils.dates import days_ago
from airflow.sensors.external_task_sensor import ExternalTaskMarker, ExternalTaskSensor
default_args={
"owner": "airflow",
"start_date": datetime(2020,11, 22),
}
with DAG(
dag_id="slave_dag",
default_args=default_args,
schedule_interval="15 15 * * *",
#concurrency=1,
#max_active_runs=1,
tags=['example2'],
) as slave_dag:
# [START howto_operator_external_task_marker]
'''
parent_task = ExternalTaskMarker(
task_id="slave_task2",
external_dag_id="master_dag",
external_task_id="master_task1",
execution_delta=timedelta(minutes=3)
)
parent_task
'''
slave_task = BashOperator(
task_id ="slave_task1",
bash_command ="echo i am slave!",
)
slave_task
关系详解
这里master中的任务需要等待slave中的任务完成,所以需要有个监工来看着,那么这个监工有个官方提供组件ExternalTaskSensor
来完成,所以需要引入依赖,
from airflow.sensors.external_task_sensor import ExternalTaskSensor
,因为我的starttime不一直,所以在调度的时候,执行时间则需要用到timedelta,在sensor组建中,提供一个param 就是execution_delta,然后把timedelta传入即可,而传入值特别有讲究!!!我是试出来,毕竟英语太渣,听视频不是很明白。这传入的参数是2个DAG start_time差值的绝对值。我示例是master后5分钟启动,所以我这里填的是5。
原因是这样的,理想情况是,你master询问slave任务,slave任务还在running,所以sensor可以等待他完成,那么如果已经完成很久了,那么sensor问slave是不会给与回应的。
所以总结就是 execution_delta=timedelta(minutes=5)
这个参数是填写到sensor中,他的值取决于两个DAG启动时间差!相应的参数可以传小时,分,秒。需要找到对应的API确认。
external_dag_id="slave_dag",
external_task_id="slave_task1",
sensor依靠这2个参数将slave的指定task进行监控的!
总结
官方也提供了一个特殊场景
如果希望每当parent_task上parent_dag被清除,child_task1
在child_dag特定execution_date还应该被清除,ExternalTaskMarker
应该使用。请注意,child_task1只有当用户清除时选择“递归”时,才会清除parent_task。
这个场景我没用到,所以不想去试了,有兴趣的,可以尝试下。
DAG中的Task关联,官方给予了对应sensor来监控,而且airflow还提供对于HTTP请求的状态的监控,总的来说是一款非常强大的调度工具,本人最近也在从AZKB转到AF,体验还不错,就是需要有一定的函数式编程经验或者有PY开发经验最佳,很多dag脚本是需要用py来进行编写,不过难度不是很大。等国内大佬有更好的总结,我也会加强学习,最近有个新调度框架海豚可实现拖拉拽进行调度。有空我会去尝试的。