气流在同一时间在不同时间运行任务?

时间:2019-02-07 18:23:10

标签: python airflow

我在一天内有30个单独的任务,它们彼此之间没有依赖关系。这些任务运行相同的代码。唯一的区别是数据量,有些任务将在几秒钟内完成,有些任务将花费2个小时或更长时间。

问题在于追赶过程中,以秒为单位完成的任务被需要花费数小时才能完成的任务阻塞,然后才能转移到下一个执行日期。

我可以将它们分解为单个任务,但这似乎很愚蠢,将来有30项任务会越来越多。

是否可以在不同的执行时间在同一dag中运行任务?就像任务完成后一样,无论其他任务的执行情况如何,都将在下一个执行日期开始。

添加图片作为插图。基本上,我想在第一行看到另外两个绿色的方框,而第三行仍在后面。

airflow_dag_ideal

编辑:

在y2k-shubham的explanation之后,我尝试实现它。但是它仍然无法正常工作。快速任务从2019-01-30 00开始,在几秒钟内完成,由于慢速任务仍在运行,因此没有开始2019-01-30 01。如果可能的话,最好并行运行2019-01-30 012019-01-30 022019-01-30 03 ...

添加代码示例

import time
from datetime import datetime

from airflow import DAG
from airflow.operators.python_operator import PythonOperator
from airflow.utils.trigger_rule import TriggerRule

default_args = {
    'owner': 'test',
    'depends_on_past': False,
    'start_date': datetime(2019, 1, 30, 0, 0, 0),
    'trigger_rule': TriggerRule.DUMMY
}

dag = DAG(dag_id='test_dag', default_args=default_args, schedule_interval='@hourly')


def fast(**kwargs):
    return 1


def slow(**kwargs):
    time.sleep(600)
    return 1


fast_task = PythonOperator(
    task_id='fast',
    python_callable=fast,
    provide_context=True,
    priority_weight=10000,
    pool='fast_pool',
    # weight_rule='upstream', # using 1.9, this param doesn't exist
    dag=dag
)

slow_task = PythonOperator(
    task_id='slow',
    python_callable=slow,
    provide_context=True,
    priority_weight=500,
    pool='slow_pool',
    # weight_rule='upstream', # using 1.9, this param doesn't exist
    dag=dag
)

fast_task >> slow_task # not working

3 个答案:

答案 0 :(得分:1)

这可能是因为您执行的插槽少于慢的作业。调度程序并不特别在乎运行任务的顺序,因为您说过也不关心。

如果这对您确实很重要,则应将它们分解为不同的中断,或者应声明依赖项,以使较便宜的任务先完成。表达您想要的东西有多种方法,您只需要弄清楚那是什么。

答案 1 :(得分:1)

我可以为您的困境想出3种解决方案(当他们想到时会添加更多选择)

  1. start_date(除task本身的DAG之外的各个start_date 上设置 DAG ),如here所述。但是,我绝不赞成这种方法,因为这就像退回到Airflow尝试的基于时间的克朗替换。

  2. 使用pools运行时/优先级隔离task。这是一个想法(您可能需要根据需要进行重做):将所有微小的task 放在tiny_task_pool中,而所有 big 都放在{ {1}}。让big_task_pool的{​​{1}}数量比tiny_task_pool显着更多。这将使您的微小任务中的starvation的可能性大大降低。您甚至可以在slot级别中发挥创意。

  3. 即使您的big_task_pool之间没有真正的依赖关系故意引入一些依赖关系也不会造成太大的伤害。 (或大多数)大任务由{em>小任务组成pool(因此改变了task的结构)。这将成为一种最短工作优先的方法。您还可以探索priority_weight / priority_rule以获得更细粒度的控制。

以上所有替代方法都假定downstream的长度(执行时间)是事先已知的。在现实世界中,可能并非如此。甚至可能会随着时间的推移逐渐变化。为此,我建议您调整您的 dag定义脚本 ,以将DAG的平均(或中位数)运行时间算入过去'n'决定他们的优先级。

  • 对于task方法,只需向在先前运行中运行时间更长的task提供稍后的start_date(实际上是相同的日期,以后的时间)
  • 对于start_date的方法,请根据其先前的运行持续时间在不同的task周围移动pool
  • 对于任务相关性方法,请延长运行task的{​​{1}}的时间。这听起来可能很困难,但是您可以像这样可视化:创建3个pool并将它们链接起来(一个接一个)。现在,您必须填写前两个task之间的所有小任务,以及接下来的两个{}之间的大任务。

答案 2 :(得分:0)

结果是,可以设置两个变量,这将很容易解决我的问题。

concurrencymax_active_runs

在下面的示例中,您可以运行4个dag,每个dag可以同时运行4个任务。其他组合也是可能的。

dag = DAG(
    dag_id='sample_dag',
    default_args=default_args,
    schedule_interval='@daily',
    # this will allow up to 16 tasks to be run at the same time
    concurrency=16,
    # this will allow up to 4 dags to be run at the same time
    max_active_runs=4,
)