有条件地一个接一个地执行多个分支

时间:2020-04-19 12:35:30

标签: airflow

注意


我们的工作流程中有一个multiplexer类似的用例

                                +-----------------------+
                                |                       |
                  +------------>+  branch-1.begin-task  |
                  |             |                       |
                  |             +-----------------------+
                  |
                  |
                  |             +-----------------------+
                  |             |                       |
                  +------------>+  branch-2.begin-task  |
                  |             |                       |
+------------+    |             +-----------------------+
|            |    |
|  MUX-task  +----+                         +
|            |    |                         |
+------------+    |
                  |                         |
                  +- -- -- -- ->
                  |                         |
                  |
                  |                         |
                  |                         +
                  |
                  |             +-----------------------+
                  |             |                       |
                  +------------>+  branch-n.begin-task  |
                                |                       |
                                +-----------------------+

该流程将按以下方式工作

  • MUX-task监听外部队列上的事件(单个队列)
  • 队列中的每个事件触发一个分支(分支n.begin-task)
  • 的执行
  • 一对一,事件到达时,MUX任务必须触发各个分支的执行
  • 一旦所有分支都被触发,MUX任务完成

假设

  • 恰好有n个事件到达队列,一个事件触发每个分支
  • n是动态已知的 :其值是在Variable
  • 中定义的

限制

  • 事件到达的外部队列只有一个
  • 我们没有n队列(每个分支一个),因为分支随着时间增长(n是动态定义的)

我们无法在Airflow的operators and sensors(或Airflow内可用的任何此类东西)中提出解决方案来构建此

  1. Sensor可用于侦听外部队列上的事件;但我们必须听多个事件,而不是一个
  2. BranchPythonOperator可用于触发多个分支中的单个分支的执行,但立即marks remaining branches as skipped

主要瓶颈

由于上述第二个限制,即使将SensorBranchPythonOperator的功能结合在一起的自定义运算符也不起作用。

我们试图围绕SensorsDummyOperatortrigger_rules的幻想组合来实现这一目标,但到目前为止没有成功。

这在气流中可行吗?


UPDATE-1

这里有一些背景信息,以了解工作流程的背景

  • 我们有一个ETL管道将MySQL表(跨越多个Aurora数据库)同步到我们的数据仓库
  • 为了克服我们的同步管道对生产数据库的影响,我们决定这样做
    • 为每个数据库创建一个快照(上次备份的restore AuroraDB cluster
    • 使用该快照
    • 运行MySQL同步管道
    • 然后在同步结束时,终止快照AuroraDB集群)
  • Aurora快照中的snapshot lifecycle events 恢复过程被发布到SQS队列
    • 所有数据库的单个队列
    • 此设置由我们的DevOps团队完成(不同的AWS帐户,我们无权访问基础的Lambda s / SQS /下文)

1 个答案:

答案 0 :(得分:0)

XCOM来救援!


我们决定按以下方式对任务进行建模(这两个任务都是 custom operator s)

  • MUX-task更像是迭代式sensor :它不断监听队列中的事件,并对到达队列中的每个事件采取一些措施
  • 所有branch-x.begin-task都是简单传感器:它们监听XCOM(其名称采用预定义的特定格式的发布) )

工作流程如下

  • MUX-task侦听队列中的事件(侦听部分包含在 for循环中,迭代次数与分支数相同)
  • 事件到达时,MUX-task将其捡起;它标识应触发的“分支”,并为各个分支发布XCOM
  • 各个分支机构的sensor在下一个戳中捡起XCOM ,分支开始执行。实际上,分支的sensor只是充当网关 ,它会通过外部事件(XCOM)打开并允许执行分支

由于传感器太多(每个分支一个),我们很可能employing mode='reschedule'才能克服deadlocks


  • 由于所描述的方法在很大程度上依赖于轮询,因此我们不认为它是超高效的。
  • 基于反应性触发的方法会更可取,但我们仍无法解决

UPDATE-1

  • 如果我们可以将每个分支的建模为单独的DAG ,而不是为每个分支发布XCOM,则触发分支的{ {1}}就像 DAG 一样
  • 但是由于我们的整体式TriggerDagRunOperator 是通过复杂的逻辑通过程序编程生成的 ,因此这种更改将非常困难(大量代码重写)。因此,我们决定继续使用基于民意调查的方法,并在已经花费了几个小时才能完成的管道中忍受了几分钟的额外延迟

UPDATE-2

[参考问题的 UPDATE-1 部分]

由于我们的实际实现要求我们仅等待数据库的创建,因此我们决定简化工作流程,如下所示

  • 数据库端点通过DAG进行了修复(每次恢复DNS快照时它们都没有更改
  • 我们取消了Aurora(以及 Aurora恢复生命周期事件MUX-task队列)
  • 每个分支的开始任务SQS被建模为尝试触发 dummy SQL查询(branch-x.begin-task简单sensor )检查数据库端点是否已激活