如何使用Celery和Django将任务路由到不同的队列

时间:2018-08-01 10:51:56

标签: django python-3.x celery python-3.6 django-celery

我正在使用以下堆栈:

  • Python 3.6
  • Celery v4.2.1 (经纪人: RabbitMQ v3.6.0
  • Django v2.0.4

根据Celery's documentation,在不同的队列上运行计划的任务应该与在 CELERY_ROUTES 上为任务定义相应的队列一样容易,尽管如此,所有任务似乎都在Celery的默认队列上执行。

这是 my_app / settings.py 上的配置:

CELERY_BROKER_URL = "amqp://guest:guest@localhost:5672//"
CELERY_ROUTES = {
 'app1.tasks.*': {'queue': 'queue1'},
 'app2.tasks.*': {'queue': 'queue2'},
}
CELERY_BEAT_SCHEDULE = {
    'app1_test': {
        'task': 'app1.tasks.app1_test',
        'schedule': 15,
    },
    'app2_test': {
        'task': 'app2.tasks.app2_test',
        'schedule': 15,
    },

}

这些任务只是用于测试路由的简单脚本:

文件 app1 / tasks.py

from my_app.celery import app
import time


@app.task()
def app1_test():
    print('I am app1_test task!')
    time.sleep(10)

文件 app2 / tasks.py

from my_app.celery import app
import time


@app.task()
def app2_test():
    print('I am app2_test task!')
    time.sleep(10)

当我使用所有必需的队列运行Celery时:

celery -A my_app worker -B -l info -Q celery,queue1,queue2

RabbitMQ将显示只有默认队列“ 芹菜”正在运行任务:

sudo rabbitmqctl list_queues
# Tasks executed by each queue:
#  - celery 2
#  - queue1 0
#  - queue2 0

有人知道如何解决这种意外行为吗?

此致

3 个答案:

答案 0 :(得分:5)

我已经开始工作了,这里没有什么要注意的:

根据Celery's 4.2.0 documentation CELERY_ROUTES 应该是定义队列路由的变量,但它仅对我有用,而使用 CELERY_TASK_ROUTES 。任务路由似乎独立于Celery Beat,因此仅适用于手动安排的任务:

app1_test.delay()
app2_test.delay()

app1_test.apply_async()
app2_test.apply_async()

要使其与Celery Beat一起使用,我们只需要显式定义队列即可。文件 my_app / settings.py 的最终设置如下:

CELERY_BROKER_URL = "amqp://guest:guest@localhost:5672//"
CELERY_TASK_ROUTES = {
 'app1.tasks.*': {'queue': 'queue1'},
 'app2.tasks.*': {'queue': 'queue2'},
}
CELERY_BEAT_SCHEDULE = {
    'app1_test': {
        'task': 'app1.tasks.app1_test',
        'schedule': 15,
        'options': {'queue': 'queue1'}
    },
    'app2_test': {
        'task': 'app2.tasks.app2_test',
        'schedule': 15,
        'options': {'queue': 'queue2'}
    },

}

我希望这可以节省一些其他开发人员的时间。

答案 1 :(得分:4)

向装饰器添加queue参数可能会帮助您,

@app.task(queue='queue1')
def app1_test():
    print('I am app1_test task!')
    time.sleep(10)

答案 2 :(得分:0)

好吧,因为我尝试过使用与运行工作程序相同的命令,所以我发现您只需删除-Q参数后的芹菜,就可以了。

原来的命令是

celery -A my_app worker -B -l info -Q celery,queue1,queue2

新命令是

celery -A my_app worker -B -l info -Q queue1,queue2