我试图让Django和Celery在制作中发挥作用。我的Django项目的布局如下:
- project_root
- manage.py
- app1
- settings.py
- celery_config.py
- __init__.py, models.py, etc...
- app2
- tasks.py
- __init__.py, models.py, etc...
- app3
- tasks.py
- __init__.py, models.py, etc...
依旧......
现在,在开发期间,我可以在project_root中运行celery -A app1 worker -l info
。这可以自动检测其他应用程序中的任务,并且运行正常。
对于生产,我显然需要运行celery
作为守护进程。我已按照the celery website的celeryd
说明操作。
当我运行任务时(来自python manage.py shell
或来自正在运行的Django应用程序),我得到:
>>> from app2.tasks import add
>>> result = add.delay(1,1)
>>> result.ready()
False
>>> result.get(timeout=1)
TimeoutError
... traceback
add()
只是一个用于测试目的的简单函数:
@shared_task
def add(x, y):
return x + y
在芹菜日志中,我得到:
[2014-11-08 12:43:59,191: INFO/MainProcess] Connected to amqp://guest:**@127.0.0.1:5672//
[2014-11-08 12:43:59,196: INFO/MainProcess] mingle: searching for neighbors
[2014-11-08 12:44:00,205: INFO/MainProcess] mingle: all alone
[2014-11-08 12:44:00,228: WARNING/MainProcess] w1@ubuntu ready.
[2014-11-08 12:44:09,216: ERROR/MainProcess] Received unregistered task of type 'app2.tasks.add'.
The message has been ignored and discarded.
Did you remember to import the module containing this task?
Or maybe you are using relative imports?
Please see http://bit.ly/gLye1c for more information.
{'utc': True, 'chord': None, 'args': (1, 2), 'retries': 0, 'expires': None, 'task': 'app2.tasks.add', 'callbacks': None, 'errbacks': None, 'timelimit': (None, None), 'taskset': None, 'kwargs': {}, 'eta': None, 'id': '82e59cbf-88be-4542-82a7-452f2fbafe95'} (213b)
Traceback (most recent call last):
File "/usr/local/lib/python2.7/dist-packages/celery/worker/consumer.py", line 455, in on_task_received
strategies[name](message, body,
KeyError: 'app2.tasks.add'
以下是我的/etc/default/celeryd
供参考:
CELERYD_NODES="w1"
CELERYD_CHDIR="/var/django/project_root"
CELERYD_OPTS="--concurrency=1"
CELERY_CONFIG_MODULE="app1.celery_config"
CELERYD_LOG_FILE="/var/log/celery/%n.log"
CELERYD_PID_FILE="/var/run/celery/%n.pid"
CELERYD_USER="celery"
CELERYD_GROUP="celery"
CELERY_RESULT_BACKEND="amqp"
CELERY_CREATE_DIRS=1
我的project_root/app1/celery_config.py
:
from __future__ import absolute_import
import os
from celery import Celery
from django.conf import settings
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'app1.settings')
app = Celery('app1', backend='amqp', broker='amqp://')
app.config_from_object('django.conf:settings')
app.autodiscover_tasks(lambda: settings.INSTALLED_APPS)
@app.task(bind=True)
def debug_task(self):
print('Request: {0!r}'.format(self.request))
如何让Celery作为守护进程正常工作?
答案 0 :(得分:3)
你的芹菜实例/ app有命名问题。
自
celery -A app1 worker -l info
如果添加,正在运行
CELERY_APP_ARG="app1"
到你的celeryd
文件,一切都应该正常。
注意:强>
使用芹菜很痛苦。它现在也被弃用了。所以你可以使用
<强> 1。芹菜多:
您可以在项目根目录中启动相同的工作程序,而不需要像这样的任何bash脚本
celery multi start my_awesome_worker -A app1 \
--pidfile="somewhere/celery/%n.pid" \
--logfile="somewhere/celery/%n.log"
此方法的另一个优点是,您可以在没有sudo权限的情况下启动守护程序。
<强> 2。监:强>
如果您已经在使用主管,那么您可以再为芹菜启动一个流程,这样可以轻松管理多个工作人员。
使用
从终端运行工作人员时celery -A app1 worker -l info
在你的日志中,它会显示一个将要处理的任务列表,如下所示
[tasks]
. app1.tasks.add
现在,如果你这样做
In [1]: from app1.tasks import add
In [2]: add.name
Out[2]: 'app1.tasks.name' #attention please
In [3]: result = add.delay(1,1)
In [4]: result.ready()
Out[4]: True
In [5]: result.get(timeout=1)
Out[5]: 2
一切正常,因为注册的任务名称和您运行的任务名称是相同的。另一方面,如果你这样做
In [1]: from app1 import tasks
In [2]: tasks.add.name
Out[2]: 'tasks.name' #attention please
In [3]: result = add.delay(1,1)
In [4]: result.ready()
Out[4]: False
In [5]: result.get(timeout=1)
Out[5]: TimeoutError Traceback (most recent call last)
<ipython-input-10-ade09ca12a13> in <module>()
----> 1 r.get(timeout=1)
它会抛出错误,因为已注册的任务名称为app1.tasks.add
,您排队的任务为tasks.add
。所以你的工作人员不知道你添加的任务。有关此here的更多信息。
<强> Warining:强>
此外,如果您正在为另一个应用运行芹菜,请说foo
celery worker -l info -A foo
已注册任务bar
[tasks]
. foo.tasks.bar
现在,如果您对旧app1.tasks.add
进行排队,此工作人员将抛出关键错误。所以你必须导入&amp;正确地路由任务。
File "/usr/local/lib/python2.7/dist-packages/celery/worker/consumer.py", line 455, in on_task_received
KeyError: 'app1.tasks.add'
因为它不知道您排队的任务。你必须导入&amp; route tasks正确无误。
答案 1 :(得分:0)
解决方案原来是添加
CELERY_APP="app1"
CELERY_NODES="app1"
到/etc/default/celeryd