Celery 在远程任务上使用 Django Result Backend

Posted

技术标签:

【中文标题】Celery 在远程任务上使用 Django Result Backend【英文标题】:Celery use Django Result Backend on Remote tasks 【发布时间】:2019-06-15 01:12:21 【问题描述】:

我有一个使用 Celery 创建异步任务的 Django 应用程序。其中一些任务存在于 Django 项目中,而另一些则存在于具有自己的代码库的远程工作人员中。

我目前使用django-celery-results 包将任务调用的结果存储在 Django 数据库中,以便我可以使用 Django ORM 轻松查询调用的状态。这在我调用“本地”任务时效果很好,但在我调用远程任务时似乎效果不佳。

例如:

app.send_task("django.foo")  # Return status SUCCESS and store result in DB
app.send_task("remote.bar")  # Stuck in PENDING and never create result in DB

通过阅读Celery Docs,我发现如果客户端和工作人员不使用相同的CELERY_RESULT_BACKEND 设置,任务可能会卡在PENDING 中。在这种情况下,我不能在远程工作人员上使用 django-db 后端,因为它不是 Django 应用程序。

那么在这种情况下......当以这种方式进行远程调用时,我如何存储我的结果?

注意,在remote.bar的情况下,我确认远程工作人员收到消息并执行方法。只是我的客户端(Django App)没有收到响应。

【问题讨论】:

使用 Django 后台任务而不是 Celery,因为它很容易在这里查看我的答案:***.com/questions/54225303/… 所以你不想使用数据库作为结果后端。你还有很多其他的选择,你可以使用 redis:docs.celeryproject.org/en/latest/userguide/… 【参考方案1】:

正如其他答案已经说明的那样,您可以设置result_backend。我必须用Celery(result_backends=....) 指定它,因为我在 Django 设置中设置的 SQL 地址 URL 被忽略了。但是,这种方法的问题是您需要提供 直接访问数据库,这使事情变得简单,但如果您的 celery 工人需要在不同的网络中,则不安全。

如果担心安全问题,您将不得不创建 API 来更新来自客户端的结果。这里有更多关于这种方法的解释。

REST API or "direct" database access for remote Celery/Django workers?

【讨论】:

【参考方案2】:

n.b.,如果不同的 celery worker 使用不同的结果后端,您可以即时配置 app 实例。

from celery.app import Celery
app = Celery(broker_url='my_broker_url', result_backend='non-django-orm backend')
result = app.send_task('remote.bar')
# you can check status here just fine.

如果您想支持这样的配置,您将需要多个工作人员,因为每个工作人员只能连接并将结果存储到单个后端。

【讨论】:

我过去使用 Pika 库完成了 amqp 工作人员的自定义实现。在这些情况下,我已经发送消息,等待客户端的响应,然后将其存储在客户端的某个结果后端中。这不是 Celery 结果后端的工作方式吗?我不应该能够检索 amqp 响应,然后将其存储在 Django DB 中,以便我可以使用信号和其他工具为任务完成或失败创建回调吗? 这不是芹菜的工作原理。 celery 的工作方式是 celery worker 消费通过 broker 发送的任务,然后将任务执行的结果存储到结果后端。关心任何特定任务的结果或结果的客户端会轮询结果后端以查看他们的任务是否已准备好。这样做的原因是 celery 是为分布式多处理而设计的,所以 celery 假设在任务完成时客户端不可用并且需要存储结果。

以上是关于Celery 在远程任务上使用 Django Result Backend的主要内容,如果未能解决你的问题,请参考以下文章

Django中使用Celery实现定时任务(用djcelery)

不同服务器上的 Django 和 celery,一旦任务完成,celery 能够向 django 发送回调

多个工作节点上的 Django + Celery 任务

在使用 django_celery_beat 设置的 Django 视图中使用 Celery 定期任务输出,并使用 Redis 设置缓存

Django 中使用 Celery

Django-celery 和 RabbitMQ 不执行任务