Celery worker自省获得hostname/nodename

Celery worker introspection to obtain hostname/nodename

我想 运行 py.test 对我的 Django 1.8 应用程序进行集成测试 完整的 Celery 3.1 设置,即具有真实队列(不是 CELERY_ALWAYS_EAGER)。

为此,我需要说服工作人员使用我的基于服务器的测试数据库 (PostgreSQL) 而不是标准配置的数据库(SQlite3,它不能与第二个进程通信)。

为此,我想在首次使用数据库之前简单地修改工作进程中的 DATABASES setting。 (我想为其他 py.test 测试保留 SQlite 以及用于交互式测试的正常非测试数据库。)

为此,worker 需要识别它 运行ning 处于测试模式而不是 'normal' 模式。 为了指示测试模式,我使用不同的节点名称启动工作程序:

celery worker -A myapp --concurrency=1 -n myworker --loglevel=info

普通模式对比

celery worker -A myapp --concurrency=1 -n mytestworker --loglevel=info

测试模式。

问题: 我的Django应用程序中的celery.py模块如何读取 输出 worker 的节点名(主机名,由 -n 选项设置)?

似乎涉及三个过程(我没有进一步的 超出上述 =1):

的并发配置
  1. celery.exe(我在Windows),
  2. 工人本身,以及
  3. 单个 工作进程(这对我来说是相关的)。

这是正确的吗?

芹菜发送到每个进程的 signals 似乎不同:

  1. celeryd_init 发送到 celery.exe,
  2. worker_init 被发送到 worker,
  3. worker_process_init发送到工作进程

这也是正确的吗?

我在我的 Django 应用程序中向 celery.py 添加了以下内容:

import celery.signals

def init_here(signal, sender):
    print("call %s(sender=%s)" % (signal, sender))

@celery.signals.celeryd_init.connect
def celeryd_init(sender, instance, **kwargs):
    init_here("celeryd_init", sender)

@celery.signals.worker_init.connect
def worker_init(sender, **kwargs):
    init_here("worker_init", sender)

@celery.signals.worker_process_init.connect
def worker_process_init(sender, **kwargs):
    init_here("worker_process_init", sender)

当我如上所述以测试模式启动 worker 时,我得到以下输出(除其他外):

call celeryd_init(sender=celery@mytestworker)
call worker_init(sender=celery@mytestworker)
[2015-09-30 15:53:23,767: WARNING/MainProcess] celery@mytestworker ready.
[2015-09-30 15:53:24,282: WARNING/Worker-1] call worker_process_init(sender=None)

太糟糕了!相关进程Worker-1没有收到相关信息celery@mytestworker。 它如何获取主机名?

即使你可以让它工作,我也不建议使用工作人员名称来检测你是否处于测试模式。这将是一个黑客。

我解决知道我的代码是否处于测试模式 运行 的问题的方法是有一个名为 proj/test_settings.py 的不同设置文件(而 "regular"一个在 proj/settings.py),其中 proj 是我的项目名称(与下面的 PROJ 相同)。我让它创建一个设置来确定我们是否处于测试模式:

from .settings import *

PROJ_TESTING = True

此变量仅由 test_settings 文件设置为 true。请注意,也可以在此 test_settings.py 文件中包含一些覆盖 settings.py 中设置的默认值的行。例如,我确实有更改数据库配置和日志记录的代码。

我安排启动测试的代码来设置环境变量DJANGO_SETTINGS_MODULE=proj.test_settings。由于我在测试中使用的 celery worker 是由运行我的测试的代码启动的,因此他们正在加载测试设置并且 运行 PROJ_TESTING 为真。所以如果我需要检查测试模式,我可以这样做:

from django.conf import settings

if settings.PROJ_TESTING:
  # Do what we need when we are testing.
else:
  # Do something else.

这种处理方法反映了我们如何通过将 DEBUG 设置设置为 True 来设置调试模式。