我正在尝试在 2 个 DAG 之间实现 DAG 依赖,例如 A 和 B。DAG A 每小时运行一次,DAG B 每 15 分钟运行一次。
DAG :
from datetime import datetime,timedelta
from airflow import DAG
from airflow.operators.dummy_operator import DummyOperator
default_args = {
'owner': 'dependency',
'depends_on_past': False,
'start_date': datetime(2020, 9, 10, 10, 1),
'email': ['xxxx.com'],
'email_on_failure': True,
'email_on_retry': False,
'retries': 1,
'retry_delay': timedelta(minutes=5)
}
with DAG('DAG_A', schedule_interval='0/60 * * * *',max_active_runs=1, catchup=False,
default_args=default_args) as dag:
task1 = DummyOperator(task_id='task1', retries=1, dag=dag)
task2 = DummyOperator(task_id='task2', retries=1, dag=dag)
task3 = DummyOperator(task_id='task3', retries=1, dag=dag)
task1 >> task2 >> task3
DAG B:
from datetime import datetime,timedelta
from airflow import DAG
from airflow.operators.dummy_operator import DummyOperator
default_args = {
'owner': 'dependency',
'depends_on_past': False,
'start_date': datetime(2020, 9, 10, 10, 1),
'email': ['xxxx.com'],
'email_on_failure': True,
'email_on_retry': False,
'retries': 1,
'retry_delay': timedelta(minutes=5)
}
with DAG('DAG_B', schedule_interval='0/15 * * * *',max_active_runs=1, catchup=False,
default_args=default_args) as dag:
task4 = DummyOperator(task_id='task4', retries=1, dag=dag)
task5 = DummyOperator(task_id='task5', retries=1, dag=dag)
task6 = DummyOperator(task_id='task6', retries=1, dag=dag)
task4 >> task5 >> task6
我尝试过使用 ExternalTaskSensor 操作符。我无法理解传感器是否发现 DAG A 处于成功状态,它会触发下一个任务,否则等待任务完成。
提前致谢。
答案 0 :(得分:1)
我认为以“一般”方式实现这一目标的唯一方法是使用一些外部锁定机制
虽然使用池,您可以获得相当好的近似值:
https://airflow.apache.org/docs/apache-airflow/1.10.3/concepts.html?highlight=pool
如果您将池大小设置为 1 并将 dag A 和 B 都分配给池,则一次只能运行其中之一。您还可以以您认为最合适的方式添加 priority_weight - 以防您需要将 A 优先于 B 或相反。
答案 1 :(得分:1)
您可以使用 ExternalTaskSensor 来实现您的目标。关键是用正确的 execution_date
初始化这个传感器,在你的例子中是 DAG_A 的最后一个 execution_date
的 DagRun
。
检查此示例,其中 DAG_A 每 9 分钟运行一次,持续 200 秒。 DAG_B 每 3 分钟运行一次,持续 30 秒。这些值是任意的,仅用于演示目的,几乎可以是任何值。
DAG A(这里没有什么新东西):
import time
from airflow import DAG
from airflow.models.baseoperator import chain
from airflow.operators.dummy import DummyOperator
from airflow.operators.python import PythonOperator
from airflow.utils.dates import days_ago
def _executing_task(**kwargs):
print("Starting task_a")
time.sleep(200)
print("Completed task_a")
dag = DAG(
dag_id="example_external_task_sensor_a",
default_args={"owner": "airflow"},
start_date=days_ago(1),
schedule_interval="*/9 * * * *",
tags=['example_dags'],
catchup=False
)
with dag:
start = DummyOperator(
task_id='start')
task_a = PythonOperator(
task_id='task_a',
python_callable=_executing_task,
)
chain(start, task_a)
DAG B:
import time
from airflow import DAG
from airflow.utils.db import provide_session
from airflow.models.dag import get_last_dagrun
from airflow.models.baseoperator import chain
from airflow.operators.dummy import DummyOperator
from airflow.operators.python import PythonOperator
from airflow.utils.dates import days_ago
from airflow.sensors.external_task import ExternalTaskSensor
def _executing_task():
time.sleep(30)
print("Completed task_b")
@provide_session
def _get_execution_date_of_dag_a(exec_date, session=None, **kwargs):
dag_a_last_run = get_last_dagrun(
'example_external_task_sensor_a', session)
print(dag_a_last_run)
print(f"EXEC DATE: {dag_a_last_run.execution_date}")
return dag_a_last_run.execution_date
dag = DAG(
dag_id="example_external_task_sensor_b",
default_args={"owner": "airflow"},
start_date=days_ago(1),
schedule_interval="*/3 * * * *",
tags=['example_dags'],
catchup=False
)
with dag:
start = DummyOperator(
task_id='start')
wait_for_dag_a = ExternalTaskSensor(
task_id='wait_for_dag_a',
external_dag_id='example_external_task_sensor_a',
allowed_states=['success', 'failed'],
execution_date_fn=_get_execution_date_of_dag_a,
poke_interval=30
)
task_b = PythonOperator(
task_id='task_b',
python_callable=_executing_task,
)
chain(start, wait_for_dag_a, task_b)
我们正在使用 execution_date_fn
的参数 ExternalTaskSensor
来获取 DAG_A 的最后一个 DagRun 的 execution_date
,如果我们不这样做这样做,它将等待 DAG_A 与 DAG_B 的实际运行相同的 execution_date
,这在许多情况下可能不存在。
函数 _get_execution_date_of_dag_a
使用来自 Airflow 模型的 get_last_dagrun
查询元数据数据库以获取 exec_date。
最后,另一个重要参数是 allowed_states=['success', 'failed']
,我们告诉它等待 DAG_A 处于这些状态之一(即,如果它处于 running
状态将继续执行poke)。
试试看,告诉我它是否适合你!