Airflow 将顶级DAG布线在一起
我需要几个相同的(仅在参数上不同)顶级Airflow 将顶级DAG布线在一起,airflow,Airflow,我需要几个相同的(仅在参数上不同)顶级DAGs,它们也可以与以下约束/假设一起触发: 单个顶级DAG将具有计划_interval=None,因为它们只需要偶尔手动触发 但是,DAG系列需要每天运行 串联DAG的顺序和数量是固定的(在编写代码之前就知道了),很少有变化(几个月一次) 无论DAG是否失败或成功,触发链都不得中断 目前,它们必须串联在一起运行;将来,它们可能需要并行触发 因此,我在dags目录中为每个DAG创建了一个文件,现在我必须将它们连接起来以便顺序执行。我已经确定了两种方法
DAG
s,它们也可以与以下约束/假设一起触发:
- 单个顶级DAG将具有
,因为它们只需要偶尔手动触发计划_interval=None
- 但是,DAG系列需要每天运行
- 串联DAG的顺序和数量是固定的(在编写代码之前就知道了),很少有变化(几个月一次)
- 无论DAG是否失败或成功,触发链都不得中断
- 目前,它们必须串联在一起运行;将来,它们可能需要并行触发
因此,我在
dags
目录中为每个DAG创建了一个文件,现在我必须将它们连接起来以便顺序执行。我已经确定了两种方法:
子运算符
- 工作时没有任何故障
- 可以,但有;仍然有很多
- 子dag的
由其父dag提供,这将迫使顶级dag上的荒谬id也独立运行dag_id
TriggerDagRunOperator
- 在中工作,但并行运行(而不是顺序运行),因为它不会等待触发的DAG完成后再移动到下一个DAG
可能有助于克服上述限制,但它会使事情变得非常混乱ExternalTaskSensor
我的问题是
- 如何克服
s的SubDag
中dag\u id
前缀的限制parent\u id
- 如何强制触发器DAG操作员等待DAG完成
- 是否有其他/更好的方法将独立(顶级)DAG连接在一起
- 对于我为每个顶级DAG创建单独文件(对于仅在输入上不同的DAG)的方法,是否有解决方法
我在用它
气流1.9.0-4
Python 3.6-slim
withCeleryExecutor
redis:3.2.7
编辑-1 澄清@Viraj Parekh 你能更详细地说明你所说的等待完成是什么意思吗 在被触发之前的DAG 当我触发
import\u parent\u v1
DAG时,它应该使用TriggerDagRunOperator
触发的所有3个外部DAG开始并行运行,即使我按顺序链接它们。实际上,日志表明,当它们一个接一个地被激发时,执行会在上一个DAG完成之前移动到下一个DAG(TriggerDagRunOperator
)。
注意:在本例中,顶级DAG命名为importer\u child\u v1\u db\u X
,其对应的task\u id
s(对于TriggerDagRunOperator
)命名为importer\u v1\u db\u X
有没有可能让TriggerDagRunOperator成为
DAG中的最后一个任务
我必须在一个工作流中将几个类似(只是参数不同)的DAG链接在一起,从而一个接一个地触发它们。因此,我最后可以放的不仅仅是一个触发器,还有很多(这里有3个,但在生产中最多可以放15个)
- 你能更详细地解释一下在触发之前等待DAG完成是什么意思吗?是否可以让TriggerDagRunOperator成为DAG中的最后一个任务
- 要创建类似的DAG,可以从一个Python文件动态生成DAG。你可以这样做:
从气流导入DAG
from airflow.operators.python_operator import PythonOperator
def create_dag(dag_id,
schedule,
dag_number,
default_args):
def hello_world_py(*args):
print('Hello World')
print('This is DAG: {}'.format(str(dag_number)))
dag = DAG(dag_id,
schedule_interval=schedule,
default_args=default_args)
with dag:
t1 = PythonOperator(
task_id='hello_world',
python_callable=hello_world_py,
dag_number=dag_number)
return dag
# build a dag for each number in range(10)
for n in range(1, 10):
dag_id = 'hello_world_{}'.format(str(n))
default_args = {'owner': 'airflow',
'start_date': datetime(2018, 1, 1)
}
schedule = '@daily'
dag_number = n
globals()[dag_id] = create_dag(dag_id,
schedule,
dag_number,
default_args)
你可以在这里阅读更多关于这种方法的信息。如果大多数生产DAG非常相似,您可能需要考虑将配置存储在气流变量中。
您可能无法克服SubDag操作符的前缀限制-我建议从您的工作流中完全删除SubDag,并将它们作为单独的dag运行-如果您发现自己不得不这样做,那么返回并重新运行旧的dag运行会更容易。接受@Viraj的提示Parekh,我能够使TriggerDagRunOperator
以预期的方式工作。我在此发布我的(部分)答案;当事情变得清晰时会更新
如何克服SubDag
s的dag\u id
中parent\u id
前缀的限制
正如@Viraj所说,实现这一点没有捷径。扩展SubDagOperator
以删除可能有用,但我决定避开它
如何强制触发器DAG操作员等待DAG完成
- 从中可以看出,
TriggerDagRunOperator
的工作就是触发外部DAG;就这样。默认情况下,不应等待DAG完成。因此,我观察到的行为是可以理解的
ExternalTaskSensor
是显而易见的出路。然而,在学习气流的基础知识时,我依靠手动触发DAG(schedule\u interval=None
)。在这种情况下,ExternalTaskSensor
很难准确指定外部任务的执行日期
(等待谁完成任务),否则将导致
- 因此,从中得到提示,我通过等待相关任务的所有
task\u实例的完成来了解ExternalTaskSensor
的行为
execution\u date[外部任务]>=execution\u date[触发器运行器]+execution\u delta
这实现了:外部DAG依次运行
trigger_dag = TriggerDagRunOperator(
task_id=f'dag_id-trigger',
trigger_dag_id='dag_id',
python_callable=set_args,
dag=dag,
)
def get_most_recent_dag_run(execution_date, **kwargs):
return DagRun.find(dag_id='dag_id').pop().execution_date
sensor = ExternalTaskSensor(
task_id=f'dag_id-sensor',
external_dag_id='dag_id',
execution_date_fn=get_most_recent_dag_run,
dag=dag,
poke_interval=5,
external_task_id='last_task_id' # This is task need to be in your external dag
)