Django Celery - 使用RabbitMQ将对象传递给视图和任务之间

时间:2017-03-26 20:18:57

标签: python django rabbitmq celery django-celery

这是我第一次使用Celery,老实说,我不确定我做得对。我的系统必须在Windows上运行,所以我使用RabbitMQ作为代理。

作为一个概念证明,我正在尝试创建一个对象,其中一个任务设置值,另一个任务读取值,我还想显示当我转到某个URL时对象的当前值。但是我在一切之间分享对象时遇到了问题。

这是我的celery.py

from __future__ import absolute_import, unicode_literals
import os
from celery import Celery
from django.conf import settings

os.environ.setdefault('DJANGO_SETTINGS_MODULE','cesGroundStation.settings')

app = Celery('cesGroundStation')

app.config_from_object('django.conf:settings')

app.autodiscover_tasks(lambda: settings.INSTALLED_APPS)

@app.task(bind = True)
def debug_task(self):
    print('Request: {0!r}'.format(self.request))

我想分享的对象是:

class SchedulerQ():

    item = 0

    def setItem(self, item):
        self.item = item

    def getItem(self):
        return self.item

这是我的tasks.py

from celery import shared_task
from time import sleep
from scheduler.schedulerQueue import SchedulerQ

schedulerQ = SchedulerQ()

@shared_task()
def SchedulerThread():
    print ("Starting Scheduler") 
    counter = 0
    while(1):
        counter += 1
        if(counter > 100):
            counter = 0
        schedulerQ.setItem(counter)
        print("In Scheduler thread - " + str(counter))
        sleep(2)
    print("Exiting Scheduler")

@shared_task()
def RotatorsThread():
    print ("Starting Rotators") 
    while(1):
        item = schedulerQ.getItem()
        print("In Rotators thread - " + str(item))
        sleep(2)
    print("Exiting Rotators")

@shared_task()
def setSchedulerQ(schedulerQueue):
    schedulerQ = schedulerQueue

@shared_task()
def getSchedulerQ():
    return schedulerQ

我正在apps.py中开始我的任务...我不确定这是不是正确的地方,因为任务/工作人员似乎没有工作,直到我在一个单独的控制台中启动工作人员运行celery -A cesGroundStation -l info

from django.apps import AppConfig
from scheduler.schedulerQueue import SchedulerQ
from scheduler.tasks import SchedulerThread, RotatorsThread, setSchedulerQ, getSchedulerQ

class SchedulerConfig(AppConfig):
    name = 'scheduler'

    def ready(self):
        schedulerQ = SchedulerQ()
        setSchedulerQ.delay(schedulerQ)
        SchedulerThread.delay()
        RotatorsThread.delay()

在我的views.py中,我有这个:

def schedulerQ():
    queue = getSchedulerQ.delay()
    return HttpResponse("Your list: " + queue)

django应用程序运行没有错误,但是“celery -A cesGroundStation -l info”的输出是这样的:Celery command output

首先它似乎启动了多个“SchedulerThread”任务,其次“SchedulerQ”对象没有被传递给Rotators,因为它没有读取更新的值。

如果我转到显示views.schedulerQ视图的url,我会收到此错误: Django views error

我对Python,Django和Web开发的总体经验非常非常少,所以我不知道从哪里开始最后一个错误。解决方案建议使用Redis将对象传递给视图,但我不知道如何使用RabbitMQ做到这一点。稍后,schedulerQ对象将实现一个队列,并且调度程序和旋转器将充当生产者/消费者动态,并且视图显示队列的内容,因此我认为使用数据库可能过于耗费资源。如何在所有任务中共享此对象,这是否是正确的方法?

1 个答案:

答案 0 :(得分:0)

正确的方法是使用一些持久层,例如数据库或results back end来存储您想要在任务之间共享的信息,如果您需要在任务之间共享信息(在此示例中,您是什么目前正在上课。)

Celery在分布式消息传递范例上运行 - 这个例子提炼出这个想法的好方法是,每次调度任务时,您的模块都将独立执行。每当将任务分派给Celery时,您必须假设它在单独的解释器中运行并且独立于其他任务加载。每次都会重新实例化SchedulerQ类。

您可以按照之前链接的文档中描述的方式在某些任务之间共享信息,并且可以讨论一些best practice tips讨论数据持久性问题。