创建 celery 任务然后同步运行

Posted

技术标签:

【中文标题】创建 celery 任务然后同步运行【英文标题】:Create celery tasks then run synchronously 【发布时间】:2014-12-02 04:44:11 【问题描述】:

我的应用在一个页面上收集了一堆电话号码。一旦用户点击提交按钮,我就会创建一个 celery 任务来呼叫每个号码并发出提醒消息,然后将他们重定向到一个页面,在那里他们可以看到有关呼叫的实时更新。我正在使用网络套接字实时更新每个呼叫的状态,并且需要同步执行任务,因为我只能从一个号码拨出。

所以一旦第一个调用/任务完成,我希望下一个调用/任务启动。

我查看了CELERY_ALWAYS_EAGER 设置,但它刚刚经历了第一次迭代并停止了。

@task
def reminder(number):
    # CODE THAT CALLS NUMBER HERE....

def make_calls(request):
    for number in phone_numbers:                     
        reminder.delay(number)      

    return redirect('live_call_updates') 

【问题讨论】:

你每个电话号码都有一个celery任务,或者你是用celery异步启动通话的吗? 【参考方案1】:

如果您想一个接一个地触发每个呼叫,为什么不将所有呼叫包装在一个任务中

@task
def make_a_lot_of_calls(numbers):
    for num in numbers:
        # Assuming that reminder blocks till the call finishes
        reminder(number)

def make_calls(request):
    make_a_lot_of_calls.delay(phone_numers)                          
    return redirect('live_call_updates') 

【讨论】:

重写任务以与 celery 一起使用有时可能是合适的,但在这里似乎对任务进行一次调用是一个合适的定义。【参考方案2】:

如果您查看celery DOCS on tasks,您会看到同步调用任务时,您使用的是 apply() 方法而不是 apply_async() 方法。

所以在你的情况下你可以使用:

 reminder.apply(args=[number])

DOCS 还指出:If the CELERY_ALWAYS_EAGER setting is set, it will be replaced by a local apply() call instead.

感谢@JivanAmara,他在 cmets 中重申,当使用 apply() 时,任务将在本地运行(在调用它的服务器/计算机中)。如果您打算跨多个服务器/机器运行任务,这可能会产生影响。

【讨论】:

请记住,使用 apply() 运行任务将同步运行,但也会在本地运行。如果您打算让多台机器进行处理,这是一个问题。【参考方案3】:

可以使用celery chain

from celery import chain
tasks = [reminder.s(number) for number in phone_numbers]
chain(*tasks).apply_async()

【讨论】:

以上是关于创建 celery 任务然后同步运行的主要内容,如果未能解决你的问题,请参考以下文章

在 Celery 中,我如何运行一个任务,然后让该任务运行另一个任务并继续执行?

在没有工人的情况下运行 celery 任务

Celery .delay() 同步工作,不延迟

在 Celery 任务中调用 API 永远不会返回

仅在单击按钮时运行 celery 任务

使用 django 和 celery 运行定期任务