芹菜一个经纪人多个队列和工人

时间:2017-03-22 23:37:24

标签: python rabbitmq celery

我有一个名为tasks.py的python文件,我在其中定义了4个单一任务。我想配置芹菜以使用4个队列,因为每个队列将分配不同数量的工作人员。我正在阅读我应该使用 route_task 属性,但我尝试了几个选项而不是成功。

我正在关注此文档celery route_tasks docs

我的目标是运行4个工作人员,每个任务一个,不要混合不同队列中不同工作人员的任务。这是可能的?这是一个很好的方法吗?

如果我做错了什么,我很乐意改变我的代码以使其正常工作

到目前为止,这是我的配置

tasks.py

app = Celery('tasks', broker='pyamqp://guest@localhost//')
app.conf.task_default_queue = 'default'
app.conf.task_queues = (
    Queue('queueA',    routing_key='tasks.task_1'),
    Queue('queueB',    routing_key='tasks.task_2'),
    Queue('queueC',    routing_key='tasks.task_3'),
    Queue('queueD',    routing_key='tasks.task_4')
)


@app.task
def task_1():
    print "Task of level 1"


@app.task
def task_2():
    print "Task of level 2"


@app.task
def task_3():
    print "Task of level 3"


@app.task
def task_4():
    print "Task of level 4"

为每个队列运行芹菜一个工作者

celery -A tasks worker --loglevel=debug -Q queueA --logfile=celery-A.log -n W1&
celery -A tasks worker --loglevel=debug -Q queueB --logfile=celery-B.log -n W2&
celery -A tasks worker --loglevel=debug -Q queueC --logfile=celery-C.log -n W3&
celery -A tasks worker --loglevel=debug -Q queueD --logfile=celery-D.log -n W4&

2 个答案:

答案 0 :(得分:5)

无需进入复杂路由以将任务提交到不同的队列。像往常一样定义你的任务。

from celery import celery

app = Celery('tasks', broker='pyamqp://guest@localhost//')

@app.task
def task_1():
    print "Task of level 1"


@app.task
def task_2():
    print "Task of level 2"

现在在排队任务时,将任务放在适当的队列中。这是一个如何做的例子。

In [12]: from tasks import *

In [14]: result = task_1.apply_async(queue='queueA')

In [15]: result = task_2.apply_async(queue='queueB')

这会将task_1放在名为queueAtask_2的队列中queueB

现在你可以让你的工人去消费它们。

celery -A tasks worker --loglevel=debug -Q queueA --logfile=celery-A.log -n W1&
celery -A tasks worker --loglevel=debug -Q queueB --logfile=celery-B.log -n W2&

答案 1 :(得分:0)

注意:答案中taskmessage可以互换使用。它基本上是producer发送到RabbitMQ

的有效载荷

您可以遵循Chillar建议的方法,也可以定义并使用task_routes配置将消息路由到适当的队列。这样,您无需在每次调用apply_async时都指定队列名称。

示例:将 task1 路由到QueueA,将 task2 路由到QueueB

app = Celery('my_app')
app.conf.update(
    task_routes={
        'task1': {'queue': 'QueueA'},
        'task2': {'queue': 'QueueB'}
    }
)

将任务发送到多个队列有点棘手。您将必须声明一个交换,然后使用适当的routing_key路由您的任务。您可以获取有关交换类型here的更多信息。为了说明起见,我们以direct为例。

  1. 创建Exchange

    from kombu import Exchange, Queue, binding
    exchange_for_queueA_and_B = Exchange('exchange_for_queueA_and_B', type='direct')
    
  2. 在队列上为该交换创建绑定

    app.conf.update(
        task_queues=(
            Queue('QueueA', [
                binding(exchange_for_queueA_and_B, routing_key='queue_a_and_b')
            ]),
            Queue('QueueB', [
                binding(exchange_for_queueA_and_B, routing_key='queue_a_and_b')
            ])
        )
    )
    
  3. 定义task_route,将 task1 发送到交换机

    app.conf.update(
        task_routes={
            'task1': {'exchange': 'exchange_for_queueA_and_B', 'routing_key': 'queue_a_and_b'}
        }
    )
    

您还可以按照上述答案中Chillar的建议,在exchange方法中声明routing_keyapply_async的这些选项。

此后,您可以在同一台计算机或不同计算机上定义您的工作程序,以从这些队列中进行消耗。

celery -A my_app worker -n consume_from_QueueA_and_QueueB -Q QueueA,QueueB
celery -A my_app worker -n consume_from_QueueA_only -Q QueueA