芹菜连锁表演

she*_*hei 4 python celery celery-canvas

我想知道为什么芹菜链与临时解决方案相比如此缓慢。

在临时解决方案中,我手动转发任务,缺点是我无法等待链的末尾。

在下面的代码中,canvas 解决方案需要 16 秒,而 ad hoc 需要 3 秒。想知道与简单的解决方案相比,其他画布内容是否也很慢。

import sys
from celery import Celery, chain
from celery.task import task
from datetime import datetime

broker = "amqp://admin:admin@172.16.1.30:5672/tasks"
backend = 'redis://:redis@172.16.1.30:6379/1'

app = Celery(
    "celery-bench",
    broker=broker,
    backend=backend
)

app.conf.accept_content = ['json']
app.conf.task_serializer = 'json'
app.conf.result_serializer = 'json'

@task(name="result", queue="bench-results")
def result(result):
    return result

@task(name="simple-task-auto-chain", queue="bench-tasks")
def simple_task_auto_chain(date, arg):
    if arg >= 0:
        simple_task_auto_chain.delay(date, arg-1)
        return arg
    else:
        return result.delay(
            "AutoChain %s"%(str(datetime.now() - datetime.fromisoformat(date)))
        )

@task(name="simple-task", queue="bench-tasks")
def simple_task(args):
    date, arg = args
    if arg >= 0:
        return (date, arg - 1)
    else:
        return result.s(
            "CanvasChain %s"%(str(datetime.now() - datetime.fromisoformat(date)))
        ).delay()

def bench_auto_chain(n=1000):
    now = datetime.now()
    simple_task_auto_chain.delay(now, n)

def bench_canvas_chain(n=1000):
    now = datetime.now()
    chain(
        simple_task.s((now, n)),
        *[simple_task.s()] * (n + 1),
    ).delay()

# celery -A benchs-chain worker -l info --concurrency 1 --queues bench-results
# celery -A benchs-chain worker -l info --concurrency 1 --queues bench-tasks
# ./benchs-chain.py auto (~3s)
# ./benchs-chain.py canvas (~16s)
if __name__=='__main__':
    if len(sys.argv) > 1:
        if 'canvas' in sys.argv:
            bench_canvas_chain()
        if 'auto' in sys.argv:
            bench_auto_chain()
Run Code Online (Sandbox Code Playgroud)

编辑:我认为我们得到了类似的东西,这就是画布链表现不佳的原因。 在此输入图像描述

wow*_*in2 5

是的你是对的。对于这种情况,你的方法会更快。

引用自 Celery 文档:

同步步骤的成本很高,因此您应该尽可能避免使用和弦。尽管如此,和弦仍然是工具箱中一个强大的原语,因为同步是许多并行算法的必需步骤。

Chain 还具有比 auto-chain 更多的功能,例如:

  • 收集每个任务的结果
  • 甚至允许构建调用图
  • 将子任务管理封装在任务本身之外

正如您所看到的,创建链所需的时间减少了一半(约 18 秒)。
在引擎盖下chain使用chord。它们都消耗更多的内存,并且有许多准备步骤需要运行,正如您所描述的那样。

当您从父任务调用下一个任务时 - 您创建了一个任务,该任务不知道接下来会发生什么,在最后或之前的几个步骤。另一件事是,对于较长的任务,您不会感觉到时间差异。最后你会丢失很多信息,在这个简单的场景中你可能不需要这些信息。

  • @DejanLekic您可以在`celery/canvas.py`文件中`_chain`类的`prepare_steps`方法中找到它:https://github.com/celery/celery/blob/a537c2d290f42e112b16937055dca0e90f8341c3/celery/canvas.py#L739 (2认同)