Airflow 气流:带ExternalTaskSensor的Master Dag永远卡住
要求一个接一个地运行DAG,并在每个DAG成功后运行 我有一个主DAG,我在其中调用所有DAG,以便按顺序一个接一个地执行 此外,在每个dag_A、dag_B、dag_C中,我必须给定schedule_interval=None并在GUI中手动打开 我正在使用ExternalTaskSensor,因为在第一个dag_A中的所有任务完成之前,它就启动了第二个dag_B,为了避免此类问题,我正在使用ExternalTaskSensor。如果有更好的实现,请告诉我 不知道我错过了什么 代码:master_dag.pyAirflow 气流:带ExternalTaskSensor的Master Dag永远卡住,airflow,Airflow,要求一个接一个地运行DAG,并在每个DAG成功后运行 我有一个主DAG,我在其中调用所有DAG,以便按顺序一个接一个地执行 此外,在每个dag_A、dag_B、dag_C中,我必须给定schedule_interval=None并在GUI中手动打开 我正在使用ExternalTaskSensor,因为在第一个dag_A中的所有任务完成之前,它就启动了第二个dag_B,为了避免此类问题,我正在使用ExternalTaskSensor。如果有更好的实现,请告诉我 不知道我错过了什么 代码:maste
import datetime
import os
from datetime import timedelta
from airflow.models import DAG, Variable
from airflow.operators.dagrun_operator import TriggerDagRunOperator
from airflow.operators.sensors import ExternalTaskSensor
default_args = {
'owner': 'airflow',
'start_date': datetime.datetime(2020, 1, 7),
'provide_context': True,
'execution_timeout': None,
'retries': 0,
'retry_delay': timedelta(minutes=3),
'retry_exponential_backoff': True,
'email_on_retry': False,
}
dag = DAG(
dag_id='master_dag',
schedule_interval='7 3 * * *',
default_args=default_args,
max_active_runs=1,
catchup=False,
)
trigger_dag_A = TriggerDagRunOperator(
task_id='trigger_dag_A',
trigger_dag_id='dag_A',
dag=dag,
)
wait_for_dag_A = ExternalTaskSensor(
task_id='wait_for_dag_A',
external_dag_id='dag_A',
external_task_id='proc_success',
poke_interval=60,
allowed_states=['success'],
dag=dag,
)
trigger_dag_B = TriggerDagRunOperator(
task_id='trigger_dag_B',
trigger_dag_id='dag_B',
dag=dag,
)
wait_for_dag_B = ExternalTaskSensor(
task_id='wait_for_dag_B',
external_dag_id='dag_B',
external_task_id='proc_success',
poke_interval=60,
allowed_states=['success'],
dag=dag)
trigger_dag_C = TriggerDagRunOperator(
task_id='trigger_dag_C',
trigger_dag_id='dag_C',
dag=dag,
)
trigger_dag_A >> wait_dag_A >> trigger_dag_B >> wait_dag_B >> trigger_dag_C
每个DAG都有多个正在运行的任务,最后一个任务已成功运行后台
- 分别轮询外部
或DAG
任务的
/DagRun
的状态(基于是否传递了任务实例
)外部任务id
- 现在,由于单个
可以有多个活动DAG
s,因此必须告知传感器应该感测哪些运行/实例DagRun
- 为此,它使用执行日期作为区分标准。这可以(仅)用以下两种方式之一表示
您的实现中的问题
- 在
s中,您没有传递ExternalTaskSensor
或execution\u date\u fn
参数execution\u delta
- 因此,要轮询子级
s的DAG
s的传感器会被卡住(显然,父级/协调器DAG的DagRun
执行日期与子级DAG不同)
进一步提示
- 您可以跳过传递
;执行此操作时,外部任务\u id
实际上将成为ExternalTaskSensor
。当您的子DAG(A、B和C)有多个结束任务时,这尤其有用(因此,完成其中任何一个结束任务都不能保证完成整个DAG)ExternalDagSensor
- 还可以查看此讨论:
编辑-1 事后一想,我最初的判断似乎是错误的;尤其是下面的陈述不成立 显然,您的家长/编曲人DAG的执行日期是 与儿童DAG不同 查看,很明显,
TriggerDagRunOperator
将自己的执行日期
传递给子DagRun
,这意味着ExternalTaskSensor
应该能够感测到该DAG或其任务
trigger_dag(
dag_id=self.trigger_dag_id,
run_id=run_id,
conf=self.conf,
# own execution date passed to child DAG
execution_date=self.execution_date,
replace_microseconds=False,
)
因此,这种解释并不成立
我建议你去
- 在UI中或通过查询meta db,检查您所触发的子DAG/您正在传递的
的任务的外部任务id
执行日期
- 并将其与编排器DAG的执行日期进行比较
这将澄清某些细节感谢您的详细解释,感谢您的支持response@Kar如果您能够解决这个问题,请考虑将解决方案添加到这里作为对其他人的回答。
:param execution_date_fn: function that receives the current execution date
and returns the desired execution dates to query. Either execution_delta
or execution_date_fn can be passed to ExternalTaskSensor, but not both.
:type execution_date_fn: callable
@provide_session
def poke(self, context, session=None):
if self.execution_delta:
dttm = context['execution_date'] - self.execution_delta
elif self.execution_date_fn:
dttm = self.execution_date_fn(context['execution_date'])
else:
# if neither of above is passed, use current DAG's execution date
dttm = context['execution_date']
trigger_dag(
dag_id=self.trigger_dag_id,
run_id=run_id,
conf=self.conf,
# own execution date passed to child DAG
execution_date=self.execution_date,
replace_microseconds=False,
)