如何在运行时创建celery队列,以便发送到该队列的任务被工作人员接收?

时间:2014-02-10 21:10:26

标签: django queue celery amqp worker

我正在使用django 1.4,芹菜3.0,rabbitmq

为了描述这个问题,我在系统中有很多内容网络,我想要一个队列来处理与这些网络相关的任务。

然而,当系统处于活动状态时,内容会立即创建,因此我需要动态创建队列并让现有工作人员开始接收它们。

我尝试按以下方式安排任务(内容是django模型实例):

queue_name = 'content.{}'.format(content.pk)
# E.g. queue_name = content.0c3a92a4-3472-47b8-8258-2d6c8a71e3ba
add_content.apply_async(args=[content], queue=queue_name)

这将创建一个名为content.0c3a92a4-3472-47b8-8258-2d6c8a71e3ba的队列,创建一个名为content.0c3a92a4-3472-47b8-8258-2d6c8a71e3ba的新交换和路由密钥content.0c3a92a4-3472-47b8-8258-2d6c8a71e3ba,并将任务发送到该队列。

但是我从未看到工作人员接受这些任务。我当前设置的工作人员没有收听任何特定的队列(没有使用队列名称初始化)并接收发送给他们的任务。默认队列就好了。我的芹菜设置是:

BROKER_URL = "amqp://test:password@localhost:5672/vhost"
CELERY_TIMEZONE = 'UTC'
CELERY_ALWAYS_EAGER = False

from kombu import Exchange, Queue

CELERY_DEFAULT_QUEUE = 'default'
CELERY_DEFAULT_EXCHANGE = 'default'
CELERY_DEFAULT_EXCHANGE_TYPE = 'direct'
CELERY_DEFAULT_ROUTING_KEY = 'default'

CELERY_QUEUES = (
    Queue(CELERY_DEFAULT_QUEUE, Exchange(CELERY_DEFAULT_EXCHANGE),
        routing_key=CELERY_DEFAULT_ROUTING_KEY),
)

CELERY_CREATE_MISSING_QUEUES = True
CELERYD_PREFETCH_MULTIPLIER = 1

知道如何让工作人员接收发送到这个新创建的队列的任务吗?

2 个答案:

答案 0 :(得分:7)

您需要告诉工作人员开始使用新队列。相关文档为here

从命令行:

$ celery control add_consumer content.0c3a92a4-3472-47b8-8258-2d6c8a71e3ba

或者在python中:

>>> app.control.add_consumer('content.0c3a92a4-3472-47b8-8258-2d6c8a71e3ba', reply=True)

两个表单都接受目标参数,因此如果需要,您只能告诉单个工作人员新的队列。

答案 1 :(得分:0)

我们可以动态添加队列并将工作人员附加到他们身上。

from celery import current_app as app
from task import celeryconfig #your celeryconfig module

动态定义任务并将其路由到队列

from task import process_data
process_data.apply_async(args,kwargs={}, queue='queue-name')
reply = app.control.add_consumer('queue_name', destination = ('your-worker-name',), reply = True)

您必须将队列名称保存在持久数据存储中,例如redis,以便在重新启动时记住它。

redis.sadd('CELERY_QUEUES','queue_name')

celeryconfig.py也使用相同的方法来记住队列名称

CELERY_QUEUES = {
    'celery-1': {
        'binding_key': 'celery-1'
    },
    'gateway-1': {
        'binding_key': 'gateway-1'
    },
    'gateway-2': {
        'binding_key': 'gateway-2'
    }
}
for queue in redis.smembers('CELERY_QUEUES'):
        CELERY_QUEUES[queue] = dict(binding_key=queue)