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_id
      由其父dag提供,这将迫使顶级dag上的荒谬id也独立运行
  • TriggerDagRunOperator

    • 在中工作,但并行运行(而不是顺序运行),因为它不会等待触发的DAG完成后再移动到下一个DAG
    • ExternalTaskSensor
      可能有助于克服上述限制,但它会使事情变得非常混乱

  • 我的问题是

    • 如何克服
      SubDag
      s的
      dag\u id
      parent\u id
      前缀的限制
    • 如何强制触发器DAG操作员等待DAG完成
    • 是否有其他/更好的方法将独立(顶级)DAG连接在一起
    • 对于我为每个顶级DAG创建单独文件(对于仅在输入上不同的DAG)的方法,是否有解决方法

    我在用它

    • 气流1.9.0-4
    • Python 3.6-slim
    • CeleryExecutor
      with
      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 )