Celery:如何用不同的工人区分不同的环境?

Posted

技术标签:

【中文标题】Celery:如何用不同的工人区分不同的环境?【英文标题】:Celery: how to separate different environments with different workers? 【发布时间】:2015-04-11 22:49:18 【问题描述】:

我需要将某个 django 站点实例的所有任务路由到某个队列。我的设置如下:

运行 Django 项目 (1.7) 的多个网络服务器 一台运行 celery worker 的服务器 (3.1.7) 三种环境:生产、登台、开发。每个环境都使用不同的DJANGO_SETTINGS_MODULE 运行,具有不同的CELERY_DEFAULT_QUEUE 设置。 一个 redis 实例作为代理(所有内容都在同一个数据库中)

在“芹菜服务器”上,我通过主管(简化配置)运行多个工作实例:

[program:production_queue]
environment=PYTHONPATH=/pth/to/src/:/pth/to/site-packages/,DJANGO_SETTINGS_MODULE=website.settings.production
command=/pth/to/python celery -A website.celery worker --events --queues myserver --loglevel WARNING --concurrency 4 -n production@celery.myserver.nl

[program:staging_queue]
environment=PYTHONPATH=/pth/to/src/:/pth/to/site-packages/,DJANGO_SETTINGS_MODULE=website.settings.staging
command=/pth/to/python celery -A website.celery worker --events --queues myserver_staging --loglevel WARNING --concurrency 1 -n staging@celery.myserver.nl

[program:development_queue]
environment=PYTHONPATH=/pth/to/src/:/pth/to/site-packages/,DJANGO_SETTINGS_MODULE=website.settings.development
command=/pth/to/python celery -A website.celery worker --events --queues myserver_development --loglevel INFO --concurrency 1 -n development@celery.myserver.nl

这可行,需要检查:

$ celery -A website.celery inspect activeues
-> production@celery.myserver.nl: OK
    * u'exclusive': False, u'name': u'myserver', u'exchange': u'name': u'celery', u'durable': True, u'delivery_mode': 2, u'passive': False, u'arguments': None, u'type': u'direct', u'auto_delete': False, u'durable': True, u'routing_key': u'celery', u'no_ack': False, u'alias': None, u'queue_arguments': None, u'binding_arguments': None, u'bindings': [], u'auto_delete': False
-> staging@celery.myserver.nl: OK
    * u'exclusive': False, u'name': u'myserver_staging', u'exchange': u'name': u'celery', u'durable': True, u'delivery_mode': 2, u'passive': False, u'arguments': None, u'type': u'direct', u'auto_delete': False, u'durable': True, u'routing_key': u'celery', u'no_ack': False, u'alias': None, u'queue_arguments': None, u'binding_arguments': None, u'bindings': [], u'auto_delete': False
-> development@celery.myserver.nl: OK
    * u'exclusive': False, u'name': u'myserver_development', u'exchange': u'name': u'celery', u'durable': True, u'delivery_mode': 2, u'passive': False, u'arguments': None, u'type': u'direct', u'auto_delete': False, u'durable': True, u'routing_key': u'celery', u'no_ack': False, u'alias': None, u'queue_arguments': None, u'binding_arguments': None, u'bindings': [], u'auto_delete': False

(名称符合 CELERY_DEFAULT_QUEUE 设置)

website/celery.py 包含基础知识(跳过导入):

app = Celery('proj')
app.config_from_object('django.conf:settings')
app.autodiscover_tasks(lambda: settings.INSTALLED_APPS)

因此,我希望使用开发设置运行的网络服务器生成的任务仅在 development_queue 中结束,依此类推。但是,我看到任务正在由不同的队列或所有三个队列处理,这是有问题的。

我的期望是否错误,因为这将是分离这些任务的好方法?所有documentation on routing 都是关于将不同的任务路由到不同的队列,我不需要。我需要将某个站点(环境)的所有任务路由到某个队列。 我可以做些什么来分离这些环境?

【问题讨论】:

是的,我认为您是正确的。您可以根据环境将默认队列设置为不同的队列。因此您可以使用 -Q queue_name 为每个队列运行消费者 嗯,这就是我正在尝试的(参见--queues myserver,与-Q myserver 相同),但正如我所说,它不起作用。 您在使用 Redis 作为代理时查看过 fanout_prefix 和 fanout_patterns 选项吗? docs.celeryproject.org/en/latest/getting-started/brokers/… @Carl 我还没有看到那个选项。看来我只能将其设置为True。你知道它是如何工作的吗?它设置了什么“前缀”?文档说:“您必须设置一个传输选项来为消息添加前缀,以便它们只会被活动虚拟主机接收”,但是 active 虚拟主机是什么? (什么是虚拟主机?)在文档中找不到。 【参考方案1】:

我在这里得到了 Celery 开发者的回复:https://github.com/celery/celery/issues/2508,即:

您必须设置所有CELERY_DEFAULT_QUEUECELERY_DEFAULT_EXCHANGECELERY_DEFAULT_ROUTING_KEY。否则,您最终会得到三个队列,它们都绑定到相同的交换和路由键。

或者使用这里的方法来显式设置它: http://docs.celeryproject.org/en/latest/userguide/routing.html#changing-the-name-of-the-default-queue

这行得通!

【讨论】:

【参考方案2】:

我的设置与您类似,但我的解决方案是使用不同的 RabbitMQ 代理进行开发、登台和生产。

例如,在我的个人开发设置文件中,我有:

CELERY_BROKER = "librabbitmq://user:user@my_machine.domain.com/"

在我的生产设置文件中:

CELERY_BROKER = "librabbitmq://prop:prod@main_cluster.domain.com/"

在我的 celery 应用模块中,我有:

app = Celery('App', broker=settings.CELERY_BROKER)

我不知道这是否有帮助,但我在 celery-users 板上看到了您的帖子,并且由于您没有任何其他回复...

【讨论】:

是的,这就是我最终要做的:为代理使用不同的 redis 数据库。它可以工作,但它只是觉得它应该与 DEFAULT_QUEUE 设置一起工作;-)

以上是关于Celery:如何用不同的工人区分不同的环境?的主要内容,如果未能解决你的问题,请参考以下文章

如何在不同的机器上设置芹菜工人?

使用 Environment Indicator 模块区分不同的 Drupal 环境

如何用JavaScript判断前端应用运行环境(移动平台还是桌面环境)

celery+django+redis使用介绍

Spring读取不同环境的配置文件

如何使用 celery 配置不同的工作池?