Celery-Django作为守护进程:未找到设置

8 投票
5 回答
4981 浏览
提问于 2025-04-18 12:54

通过跟着这个教程,我现在有了一个正常工作的Celery-Django应用。当我用这个命令启动工作进程时: celery -A myapp worker -n worker1.%h

在我的Django的settings.py文件中,我设置了Celery的所有参数(比如消息代理的IP地址等等)。一切运行得很好。

接下来的步骤是把这个应用作为守护进程运行。所以我又跟着这个第二个教程,一切都很简单,除了现在我在settings.py中设置的Celery参数没有加载。例如,消息代理的IP设置为127.0.0.1,但在我的settings.py中,我设置的是另一个IP地址。

在教程中,他们提到:

确保定义你Celery应用实例的模块也为DJANGO_SETTINGS_MODULE设置了默认值,具体可以参考Django入门中的示例项目。

所以我确保做了这一点。我在/etc/default/celeryd中添加了这行:

export DJANGO_SETTINGS_MODULE="myapp.settings"

但还是不行……我在/etc/init.d/celeryd中也加了这一行,结果还是不行。我不知道该怎么办了。有没有人能给点建议?

编辑: 这是我的celery.py:

from __future__ import absolute_import

import os
from django.conf import settings
from celery import Celery

# set the default Django settings module for the 'celery' program.
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myapp.settings')

app = Celery('myapp')

# Using a string here means the worker will not have to
# pickle the object when using Windows.
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))

编辑 #2: 这是我的/etc/default/celeryd:

# Names of nodes to start
#   most will only start one node:
CELERYD_NODES="worker1.%h"

# Absolute or relative path to the 'celery' command:
CELERY_BIN="/usr/local/bin/celery"

# App instance to use
# comment out this line if you don't use an app
CELERY_APP="myapp"

# Where to chdir at start.
CELERYD_CHDIR="/home/ubuntu/myapp-folder/"

# Extra command-line arguments to the worker
CELERYD_OPTS=""

# %N will be replaced with the first part of the nodename.
CELERYD_LOG_FILE="/var/log/celery/%N.log"
CELERYD_PID_FILE="/var/run/celery/%N.pid"

# Workers should run as an unprivileged user.
#   You need to create this user manually (or you can choose
#   a user/group combination that already exists, e.g. nobody).
CELERYD_USER="ubuntu"
CELERYD_GROUP="ubuntu"

# If enabled pid and log directories will be created if missing,
# and owned by the userid/group configured.
CELERY_CREATE_DIRS=1

# Name of the projects settings module.
export DJANGO_SETTINGS_MODULE=myapp.settings
export PYTHONPATH=$PYTHONPATH:/home/ubuntu/myapp-folder

5 个回答

0

我想给最近遇到这个问题的人提供一个答案。

我按照Celery 4.4.7的入门指南和守护进程教程一步一步来,但没有成功。

我最开始遇到的问题是:

  • celery -A app_name worker -l info可以正常运行(我的celery配置是没问题的)。
  • 我可以把celeryd作为守护进程启动,状态命令显示正常,但无法接收任务。查看日志时,我看到以下内容: [2020-11-01 09:33:15,620: ERROR/MainProcess] consumer: 无法连接到 amqp://guest:**@127.0.0.1:5672//: [Errno 111] 连接被拒绝。
  • 这说明celeryd没有连接到我的消息代理(redis)。因为我在配置中已经设置了CELERY_BROKER_URL,这意味着我的celery应用设置没有被守护进程读取到。
  • 我尝试运行 sudo C_FAKEFORK=1 sh -x -l -E /etc/init.d/celeryd start 来看看我的celery设置是否被读取,结果发现app被设置为默认的default(而不是我在/etc/default/celeryd中指定的CELERY_APP的应用名)。

因为celery -A app_name worker -l info可以正常工作,所以我通过在/etc/default/celeryd/中导出CELERY_APP来解决了这个问题,而不是仅仅按照文档设置变量。

总结一下: 如果celery -A app_name worker -l info可以正常运行(把app_name替换成你在Celery入门指南中定义的名称),而sudo C_FAKEFORK=1 sh -x -l -E /etc/init.d/celeryd start没有显示你的celery应用设置被读取到,那么在/etc/default/celeryd的末尾添加以下内容:

export CELERY_APP="app_name"

1

在你的第二个教程中,他们把django_settings变量设置成了:

export DJANGO_SETTINGS_MODULE="settings"

这可能是你找不到设置文件的原因,因为它可能变成了目录 "/home/ubuntu/myapp-folder/"。

然后你把你的应用定义为"myapp",接着你说设置文件在"myapp.settings"里。

这样可能导致它在以下位置寻找设置文件:

"/home/ubuntu/myapp-folder/myapp/myapp/settings"

所以我的建议是把DJANGO_SETTINGS_MODULE变量中的"myapp."去掉,别忘了引号哦。

1

下面这个方法并不能用来启动celeryd,而是用来把celery工作进程作为一个服务来运行,这样它会在开机时自动启动。

像这样的命令 sudo service celery status 也可以使用。

celery.conf

# This file sits in /etc/init
description "Celery for example"
start on runlevel [2345]
stop on runlevel [!2345]
#Send KILL after 10 seconds
kill timeout 10

script

#project(working_ecm) and Vitrualenv(working_ecm/env) settings
chdir /home/hemanth/working_ecm
exec /home/hemanth/working_ecm/env/bin/python manage.py celery worker -B -c 2 -f /var/log/celery-ecm.log --loglevel=info >> /tmp/upstart-celery-job.log 2>&1
end script

respawn
4

这个问题很可能是因为 celeryd 找不到你的 Django 设置文件,因为 myapp.settings 没有在 $PYTHONPATH 中,所以应用程序运行时找不到。

根据我的记忆,Python 在导入文件时会查看 $PYTHONPATH 和本地文件夹。当 celeryd 运行时,它可能会先检查路径中是否有一个叫 app 的模块,如果找不到,就会在当前文件夹中查找一个名为 app 的文件夹,并且这个文件夹里需要有一个 __init__.py 文件(也就是一个 Python 模块)。

我觉得你只需要在你的 /etc/default/celeryd 文件中添加以下内容:

export $PYTHONPATH:path/to/your/app
5

这里的所有回答都可能是解决问题的一部分,但最后还是没能成功。不过我最终还是找到了让它工作的办法。

首先,在 /etc/init.d/celeryd 文件中,我把这一行改成了:

CELERYD_MULTI=${CELERYD_MULTI:-"celeryd-multi"}

改成:

CELERYD_MULTI=${CELERYD_MULTI:-"celery multi"}

原来的那一行被标记为不推荐使用,这可能是问题所在。

此外,我还把这个作为选项加上了:

CELERYD_OPTS="--app=myapp"

别忘了还要设置一些环境变量:

# Name of the projects settings module.
export DJANGO_SETTINGS_MODULE="myapp.settings"
export PYTHONPATH="$PYTHONPATH:/home/ubuntu/myapp-folder"

经过这些调整,现在在我这边已经可以正常工作了。

撰写回答