Airflow 1.10.3即使并发度为8,子DAG也只能并行运行1个任务

Airflow 1.10.3即使并发度为8,子DAG也只能并行运行1个任务,airflow,directed-acyclic-graphs,airflow-scheduler,Airflow,Directed Acyclic Graphs,Airflow Scheduler,最近,我将气流从1.9升级到1.10.3(最新版本) 但是,我确实注意到一个与SubDag并发相关的性能问题。子DAG中只能拾取1个任务,这不是它应该的方式,子DAG的并发设置是8 见下文: get\u monthly\u summary-214和get\u monthly\u summary-215是两个子dag,可以由父dag并发在并行控制器中运行 但是,当放大子页面时,说获取每月摘要-214,然后 您可以肯定地看到,一次只运行一个任务,其他任务都在排队,并且它一直以这种方式运行。当我们检

最近,我将气流从1.9升级到1.10.3(最新版本)

但是,我确实注意到一个与SubDag并发相关的性能问题。子DAG中只能拾取1个任务,这不是它应该的方式,子DAG的并发设置是8

见下文:
get\u monthly\u summary-214
get\u monthly\u summary-215
是两个子dag,可以由父dag并发在并行控制器中运行

但是,当放大子页面时,说
获取每月摘要-214
,然后 您可以肯定地看到,一次只运行一个任务,其他任务都在排队,并且它一直以这种方式运行。当我们检查SubDag并发时,它实际上是8,正如我们在代码中指定的:

我们确实设置了池插槽大小,它是32,我们确实有8个芹菜工人来处理排队的任务,我们与并发相关的气流配置如下所示:

# The amount of parallelism as a setting to the executor. This defines
# the max number of task instances that should run simultaneously
# on this airflow installation
parallelism = 32

# The number of task instances allowed to run concurrently by the scheduler
dag_concurrency = 16

# The app name that will be used by celery
celery_app_name = airflow.executors.celery_executor

# The concurrency that will be used when starting workers with the
# "airflow worker" command. This defines the number of task instances that
# a worker will take, so size up your workers based on the resources on
# your worker box and the nature of your tasks
worker_concurrency = 16
 dag = DAG(
    dag_id=DAG_NAME,
    description=f"{DAG_NAME}-{__version__}",
    ...
)    
with dag:
        ur_operator = sub_dag_operator_with_default_executor(
                task_id=f"your_task_id",
                subdag=load_sub_dag(
                    parent_dag_name=DAG_NAME,
                    child_dag_name=f"your_child_dag_name",
                    args=args,
                    concurrency=dag_config.get("concurrency_in_sub_dag") or DEFAULT_CONCURRENCY,
                ),
                queue="mini",
                dag=dag
            )
此外,所有子DAG都是使用名为
mini
的队列配置的,而其所有内部任务都是名为
default
的默认队列,因为如果在同一队列上同时运行子DAG操作符和子DAG内部任务,我们以前可能会遇到一些问题。我还尝试对所有任务和操作员使用
default
队列,但没有帮助


旧版本1.9似乎很好,每个子DAG可以并行执行多个任务,我们遗漏了什么吗?

这是因为在Airflow 1.9.0中,子DAG操作符使用了默认的执行器

气流1.9.0

但是,从Airflow 1.10及以后,SubDagOperator的默认执行器更改为SequentialExecutor

气流>=1.10

改变它的提交是

更改的详细原因可在中找到

我们应该将subdag_运算符的默认执行器更改为SequentialExecutor。subdagoperator不支持气流池,因此它可能会消耗所有工作人员资源(例如celeryExecutor)。这会导致airflow-74中提到的问题,并限制subdag_操作符的使用。通过使用顺序执行器指定,我们在生产中使用subdag_运算符


根据上面发布的@kaxil的发现,如果您仍然希望在子DAG内并行执行任务,一个变通解决方案是创建一个包装函数,以便在构造
子DAG操作符时显式传递
执行器

from airflow.operators.subdag_operator import SubDagOperator
from airflow.executors import GetDefaultExecutor

def sub_dag_operator_with_default_executor(subdag, *args, **kwargs):
    return SubDagOperator(subdag=subdag, executor=GetDefaultExecutor(), *args, **kwargs)
创建子dag操作符时,使用默认执行器调用子dag操作符。为了缓解子dag操作员的压力

我们应该将subdag_运算符的默认执行器更改为SequentialExecutor。subdagoperator不支持气流池,因此它可能会消耗所有工作人员资源(例如celeryExecutor)。这会导致airflow-74中提到的问题,并限制subdag_操作符的使用。通过使用顺序执行器指定,我们在生产中使用subdag_运算符

我们建议创建一个特殊队列(在我们的例子中,我们指定queue='mini'和芹菜工人来处理subdag_操作符,这样它就不会消耗普通芹菜工人的所有资源。详情如下:

# The amount of parallelism as a setting to the executor. This defines
# the max number of task instances that should run simultaneously
# on this airflow installation
parallelism = 32

# The number of task instances allowed to run concurrently by the scheduler
dag_concurrency = 16

# The app name that will be used by celery
celery_app_name = airflow.executors.celery_executor

# The concurrency that will be used when starting workers with the
# "airflow worker" command. This defines the number of task instances that
# a worker will take, so size up your workers based on the resources on
# your worker box and the nature of your tasks
worker_concurrency = 16
 dag = DAG(
    dag_id=DAG_NAME,
    description=f"{DAG_NAME}-{__version__}",
    ...
)    
with dag:
        ur_operator = sub_dag_operator_with_default_executor(
                task_id=f"your_task_id",
                subdag=load_sub_dag(
                    parent_dag_name=DAG_NAME,
                    child_dag_name=f"your_child_dag_name",
                    args=args,
                    concurrency=dag_config.get("concurrency_in_sub_dag") or DEFAULT_CONCURRENCY,
                ),
                queue="mini",
                dag=dag
            )
然后,当您创建特殊芹菜工作程序(我们使用的是轻量级主机,如2核和3G内存)时,将
气流\uuuuu芹菜\uuuu默认\u队列指定为
mini
,这取决于您希望并行运行的子dag操作符的数量,您应该创建多个特殊芹菜工作程序以负载平衡资源,我们建议,每个特殊芹菜工人一次最多照顾2个副dag操作员,否则将耗尽(例如,2核和3G内存主机上的内存不足)

此外,您还可以通过在airflow UI
Variables
配置页面中创建的ENV VAR
concurrency\u in_sub\u dag
来调整子dag内部的
并发性

更新[22/05/2020]上述仅适用于气流(=1.10.0) 对于beyone 1.10.3,请使用

from airflow.executors import get_default_executor
相反

谢谢!。 我对最新版本(1.10.5)GetDefaultExecutor的代码做了一些修改,使其不再工作:

from airflow.executors.celery_executor import CeleryExecutor

def sub_dag_operator_with_celery_executor(subdag, *args, **kwargs):
return SubDagOperator(subdag=subdag, executor=CeleryExecutor(), *args, 
**kwargs)

谢谢,我想你是对的,我发现这里的差异也限制了subdag操作符的使用,很遗憾。非常有帮助。注意:从1.10.4
GetDefaultExecutor
被重命名为
get\u default\u executor
顺便说一句,所有跳过的错误在1.10.5中得到了修复,这意味着使用
子DAG
的原因之一已被删除,多亏了很多。包括
get_default_executor
import,在函数
sub_default_executor\U中使用executor
executor=get_default_executor()
中使用带有_default_executor的sub_dag_操作符,并使用该函数代替subdag操作符解决了问题。您仍然可以使用默认executor作为“from.executors import get_default_executor”。如果celeryExecutor()不适合