我可以通过每分钟运行一次的调度程序作业DAG创建一个即席参数化DAG吗?

时间:2020-03-12 14:13:21

标签: airflow airflow-scheduler

我正在研究Airflow,以确定它是否适合我的用例,并且从文档中不清楚是否适合这种情况。我想根据一些非常动态的标准来安排每个客户的工作流程,这些标准不属于每隔X分钟运行一次的标准“ CRON”循环等(因为一起运行会产生一些影响)

客户数据库

Customer_id, "CRON" desired interval (best case)
1 , 30 minutes
2 , 2 hours
...
... <<<<<<< thousands of these potential jobs

我想每分钟查询一次系统中当前工作的状态以及经常变化的现实世界中的“传感器”数据(例如某些DB上的负载,其他资源的配额或临时优先级,提升等)

决定后,我需要为每个客户创建一个“ DAG”(管道)工作,这一次被认为值得运行(因为考虑到一些复杂的分析,也许我们想推迟“ CRON”的工作) )。

例如:

每分钟运行一次此测试:

for customer in DB:
  if (shouldRunDAGForCustomer(customer)):
     Create a DAG with states ..... and run it
"Sleep for a minute"

def shouldRunDagForCustomer(...):
   currentStateOfJobs = ....
   situationalAwarenessOfWorld = .... // check all sort of interesting metrics
   if some criteria is met for this customer: return true // run the dag for this customer
   else : return false

从我读过的材料来看,似乎给了Dags特定的时间表,它们的结构是静态的。似乎DAG也在所有输入上运行,而不是每个输入都生成。 如果给定的DAG尚未完成,但计划时间已到,则还不清楚计划如何进行。对于相同的输入(错误),我是否可能多次运行同一管道。由于我有一些管道,其完成时间取决于客户,系统的动态负载等。因此,我想自己管理调度方面和“ DAG”的生成

1 个答案:

答案 0 :(得分:0)

这可以通过每分钟安排的“控制器” DAG来实现,然后在满足所需条件时触发“目标” DAG的运行。气流就是一个很好的例子,请参见example_trigger_controller_dagexample_trigger_target_dag。控制器使用TriggerDagRunOperator(),该操作员可以启动任何所需DAG的运行。

trigger = TriggerDagRunOperator(
    task_id="test_trigger_dagrun",
    trigger_dag_id="example_trigger_target_dag",  # Ensure this equals the dag_id of the DAG to trigger
    conf={"message": "Hello World"},
    dag=dag,
)

然后,目标DAG不需要做任何特殊的事情,除了应该具有schedule_interval=None。请注意,在触发时,您可以填充conf词典,以供目标以后使用,以防您想要自定义每次触发的运行。

bash_task = BashOperator(
    task_id="bash_task",
    bash_command='echo "Here is the message: \'{{ dag_run.conf["message"] if dag_run else "" }}\'"',
    dag=dag,
)

回到您的案例,您的情况类似,但是与示例不同的是,您不会每次都启动DAG,并且有多个目标DAG可以启动。这就是ShortCircuitOperator发挥作用的地方,它基本上是一个运行您指定的python方法的任务,只需要返回true或false。如果返回true,则照常继续执行下一个下游任务,否则“短路”并停止跳过该下游任务。如果您想看一下演示,值得运行example_short_circuit_operator。通过使用for循环并动态创建任务,我认为您将在控制器DAG中得到以下内容:

dag = DAG(
    dag_id='controller_customer_pipeline',
    default_args=args,
    schedule_interval='* * * * *',
)

def shouldRunDagForCustomer(customer, ...):
   currentStateOfJobs = ....
   situationalAwarenessOfWorld = .... // check all sort of interesting metrics
   if some criteria is met for this customer: return true // run the dag for this customer
   else : return false

for customer in DB:
   check_run_conditions = ShortCircuitOperator(
      task_id='check_run_conditions_' + customer,
      python_callable=shouldRunDagForCustomer,
      op_args=[customer],
      op_kwargs={...}, # extra params if needed
      dag=dag,
   )

   trigger_run = TriggerDagRunOperator(
      task_id='trigger_run_' + customer,
      trigger_dag_id='target_customer_pipeline_' + customer,  # standardize on DAG ids for per customer DAGs
      conf={"foo": "bar"},  # pass on extra info to triggered DAG if needed
      dag=dag,
   )

   check_run_conditions >> trigger_run

然后,您的目标DAG就是每个客户的工作。

这可能不是实现此类功能的唯一方法,但基本上可以,我认为在Airflow中实现是可行的。