我需要有几个相同的(仅在参数上有所不同)顶级DAG
,这些也可以与以下约束/假设一起触发:
schedule_interval=None
,因为它们仅偶尔需要手动触发 因此,我在dags
目录中为每个DAG创建了一个文件,现在我必须连接它们以顺序执行。我确定了两种方法可以做到:
SubDagOperator
dag_id
must be prefixed是其父母的,这将在顶级 DAG上强制使用荒谬的 ID,这些ID也应该独立运行 TriggerDagRunOperator
ExternalTaskSensor
可能有助于克服上述限制,但会使事情变得混乱我的问题是
parent_id
的{{1}}中dag_id
前缀的限制?SubDag
强制等待DAG完成?TriggerDagRunOperator
Airflow 1.9.0-4
Python 3.6-slim
与CeleryExecutor
EDIT-1
澄清 @Viraj Parekh 的queries
您能否详细说明等待完成的含义 触发之前DAG的功能?
当我触发redis:3.2.7
DAG时,应该依次使用import_parent_v1
触发的所有3个外部DAG都开始并行运行。实际上, logs 表示,虽然它们被一个接一个地触发,但执行在下一个DAG(TriggerDagRunOperator
)之前完成。
注意:在此示例中,顶级DAG被命名为TriggerDagRunOperator
,而它们对应的importer_child_v1_db_X
(对于task_id
)被命名为TriggerDagRunOperator
是否可以仅将TriggerDagRunOperator用作 DAG中的最后一项任务?
我必须在工作流中将几个相似的(仅在参数上有所不同)DAG链接在一起,以一个一个的触发它们。因此,我最后不能只给出一个 importer_v1_db_X
,有很多(这里是3个,但在生产中最多可以有15个)
答案 0 :(得分:3)
在 @Viraj Parekh 的answer的提示下,我能够按预期的方式使TriggerDagRunOperator
工作。我特此发布我的(部分)答案;会在情况变得清晰时更新。
如何克服
parent_id
的{{1}}中dag_id
前缀的限制?
正如@Viraj所说,没有直接的方法可以实现这一目标。扩展SubDag
以删除this check可能有效,但我决定避免使用它
如何强制
SubDagOperator
强制等待DAG完成?
看看implementation,很明显TriggerDagRunOperator
的工作只是触发触发外部DAG;就是这样。默认情况下,它不是应该等待DAG完成。因此,我观察到的行为是可以理解的。
TriggerDagRunOperator
是显而易见的出路。但是,在学习ExternalTaskSensor
的基础知识时,我依靠的是DAG(Airflow
)的手动触发。在这种情况下,schedule_interval=None
很难为外部任务(正在等待其完成的任务)准确地指定ExternalTaskSensor
,从而使sensor gets stuck失败。
因此,从implementation那里获得提示,我等待{em}的所有execution_date
的完成,从而使ExternalTaskSensor
的行为minor adjustment有关任务
task_instance
这达到了desired result:外部DAG依次运行。
我创建单独文件的方法是否有解决方法? (对于仅在输入上有所不同的DAG)每个顶级DAG?
再次通过@Viraj,可以通过assigning DAGs to global scope使用execution_date[external_task] >= execution_date[TriggerDagRunOperator] + execution_delta
来完成
EDIT-1
也许我是指错误的资源(上面的link已经失效),但是ExternalTaskSensor
已经包含参数globals()[dag_id] = DAG(..)
和execution_delta
来轻松限制{{1 }}(s)感测到的任务。
答案 1 :(得分:1)
您能否通过触发DAG等待完成DAG来进一步说明您的意思?是否可以仅将TriggerDagRunOperator成为DAG中的最后一项任务?
要创建与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,它们很相似,那么您可能要考虑将配置存储在气流变量enter link description here
中您可能无法克服SubDag Operator的前缀限制-我建议您从工作流程中完全删除SubDag,而仅将它们作为独立的DAG运行-这样可以更轻松地返回和如果您发现自己必须这样做,请重新运行较旧的DagRun。
答案 2 :(得分:1)
当我使用 schedule none 时,这对我有用。
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
)
答案 3 :(得分:1)
如果您正在寻找一种等待触发 DAG 完成的方法,那么在 Airflow 2.0 中它变得比以前容易多了。
有一个新版本的 TriggerDagRunOperator 允许您这样做。不再需要使用 ExternalTaskSensor。
我制作了一个 10 分钟的教程https://youtu.be/8uKW0mPWmCk
享受