简体   繁体   English

Django Celery-使用RabbitMQ在视图之间以及任务之间传递对象

[英]Django Celery - Passing an object to the views and between tasks using RabbitMQ

This is the first time I'm using Celery, and honestly, I'm not sure I'm doing it right. 这是我第一次使用Celery,说实话,我不确定我做对了。 My system has to run on Windows, so I'm using RabbitMQ as the broker. 我的系统必须在Windows上运行,因此我使用RabbitMQ作为代理。

As a proof of concept, I'm trying to create a single object where one task sets the value, another task reads the value, and I also want to show the current value of the object when I go to a certain url. 作为概念证明,我试图创建一个对象,其中一个任务设置该值,另一个任务读取该值,并且我还想在转到某个URL时显示该对象的当前值。 However I'm having problems sharing the object between everything. 但是我在所有对象之间共享对象时遇到问题。

This is my celery.py 这是我的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))

The object I'm trying to share is: 我要分享的对象是:

class SchedulerQ():

    item = 0

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

    def getItem(self):
        return self.item

This is my tasks.py 这是我的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

I'm starting my tasks in my apps.py...I'm not sure if this is the right place as the tasks/workers don't seem to work until I start the workers in a separate console where I run the celery -A cesGroundStation -l info . 我正在我的apps.py中启动任务...我不确定这是否是正确的地方,因为任务/工人似乎无法工作,直到我在运行celery -A cesGroundStation -l info的单独控制台中启动工人为止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()

In my views.py I have this: 在我的views.py中,我有:

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

The django app runs without errors, however my output from "celery -A cesGroundStation -l info" is this: Celery command output django应用程序运行没有错误,但是我的“ celery -A cesGroundStation -l info” 输出是这样的: Celery命令输出

First it seems to start multiple "SchedulerThread" tasks, secondly the "SchedulerQ" object isn't being passed to the Rotators, as it's not reading the updated value. 首先,它似乎启动了多个“ SchedulerThread”任务,其次,“ SchedulerQ”对象没有传递给Rotators,因为它没有读取更新的值。

And if I go to the url for which shows the views.schedulerQ view I get this error: Django views error 如果我转到显示views.schedulerQ视图的URL,则会收到此错误: Django views error

I have very, very little experience with Python, Django and Web Development in general, so I have no idea where to start with that last error. 一般而言,我对Python,Django和Web开发的经验很少,所以我不知道从上一个错误开始。 Solutions suggest using Redis to pass the object to the views, but I don't know how I'd do that using RabbitMQ. 解决方案建议使用Redis将对象传递给视图,但是我不知道如何使用RabbitMQ做到这一点。 Later on the schedulerQ object will implement a queue and the scheduler and rotators will act as more of a producer/consumer dynamic with the view showing the contents of the queue, so I believe using the database might be too resource intensive. 稍后在schedulerQ对象上将实现队列,并且调度程序和旋转器将充当生产者/消费者动态的角色,并显示队列内容,因此我认为使用数据库可能会占用大量资源。 How can I share this object across all tasks, and is this even the right approach? 如何在所有任务中共享该对象,这是否是正确的方法?

The right approach would be to use some persistence layer, such as a database or results back end to store the information you want to share between tasks if you need to share information between tasks (in this example, what you are currently putting in your class). 正确的方法是使用一些持久层,例如数据库或结果后端 ,以便在需要在任务之间共享信息时存储要在任务之间共享的信息(在此示例中,您当前在班级中放置的内容) )。

Celery operates on a distributed message passing paradigm - a good way to distill that idea for this example, is that your module will be executed independently every time a task is dispatched. Celery使用分布式消息传递范例进行操作-在本示例中,提炼该想法的一种好方法是,每次分派任务时,模块将独立执行。 Whenever a task is dispatched to Celery, you must assume it is running in a seperate interpreter and loaded independently of other tasks. 每当将任务分派给Celery时,您都必须假定它在单独的解释器中运行并且独立于其他任务加载。 That SchedulerQ class is instantiated anew each time. 每次都重新实例化SchedulerQ类。

You can share information between tasks in ways described in the docs linked previously and some best practice tips discuss data persistence concerns. 您可以按照前面链接的文档中所述的方式在任务之间共享信息,并且一些最佳实践技巧讨论了数据持久性问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM