如何配置 Celery 作为 systemd 服务与 Gunicorn 提供的 Django 应用程序一起运行?

don*_*ior 5 django rabbitmq celery python-3.x systemd

我遵循了有关如何配置 Celery 以与 Django (python 3) 和 RabbitMQ 一起使用的Celery 官方文档。我已经有一个 systemd 服务来使用 Gunicorn 启动我的 Django 应用程序,NGINX 用作反向代理。

现在我需要根据官方文档对 Celery 本身进行守护进程,但我当前的设置似乎无法正常工作,因为我的应用程序无法识别,我在 Celery systemd 服务启动时收到以下错误:

# systemctl start celery-my_project
# journalctl -xe

Error: 
Unable to load celery application
The module celery-my_project.celery was not found
Failed to start Celery daemon
Run Code Online (Sandbox Code Playgroud)

作为测试,我摆脱了所有的 systemd/Gunicorn/NGINX 并基本上手动启动了我的 virtualenv/Django 应用程序和 Celery 工作程序: Celery 任务被 Celery 工作程序正确检测到:

celery -A my_project worker -l debug 
Run Code Online (Sandbox Code Playgroud)

如何正确配置 systemd 单元以便我可以守护 Celery?

应用程序服务(systemd 单元)

[Unit]
Description=My Django Application
After=network.target

[Service]
User=myuser
Group=mygroup
WorkingDirectory=/opt/my_project/
ExecStart=opt/my_project/venv/bin/gunicorn --workers 3 --log-level debug --bind unix:/opt/my_project/my_project/my_project.sock my_project.wsgi:application

[Install]
WantedBy=multi-user.target
Run Code Online (Sandbox Code Playgroud)

Celery 服务(systemd 单元)

[Unit]
Description=Celery daemon
After=network.target

[Service]
Type=forking
User=celery
Group=mygroup
EnvironmentFile=/etc/celery/celery-my_project.conf
WorkingDirectory=/opt/my_project
ExecStart=/bin/sh -c '${CELERY_BIN} multi start ${CELERYD_NODES} -A ${CELERY_APP} --pidfile=${CELERYD_PID_FILE} --logfile=${CELERYD_LOG_FILE} --loglevel=${CELERYD_LOG_LEVEL} ${CELERYD_OPTS}'
ExecStop=/bin/sh -c '${CELERY_BIN} multi stopwait ${CELERYD_NODES} --pidfile=${CELERYD_PID_FILE}'
ExecReload=/bin/sh -c '${CELERY_BIN} multi restart ${CELERYD_NODES} -A ${CELERY_APP} --pidfile=${CELERYD_PID_FILE} --logfile=${CELERYD_LOG_FILE} --loglevel=${CELERYD_LOG_LEVEL} ${CELERYD_OPTS}'

[Install]
WantedBy=multi-user.target
Run Code Online (Sandbox Code Playgroud)

Celery服务配置文件(systemd环境文件)

# Name of nodes to start
# here we have a single node
CELERYD_NODES="w1"

# Absolute or relative path to the 'celery' command:
CELERY_BIN="/opt/my_project/venv/bin/celery"

# App instance to use
CELERY_APP="my_project"

# How to call manage.py
CELERYD_MULTI="multi"

# Extra command-line arguments to the worker
CELERYD_OPTS="--time-limit=300 --concurrency=8"

# - %n will be replaced with the first part of the nodename.
# - %I will be replaced with the current child process index
#   and is important when using the prefork pool to avoid race conditions.
CELERYD_PID_FILE="/var/run/celery/%n.pid"
CELERYD_LOG_FILE="/var/log/celery/%n%I.log"
CELERYD_LOG_LEVEL="DEBUG"
Run Code Online (Sandbox Code Playgroud)

Django 项目布局

# Project root: /opt/my_project

my_project
    manage.py
    my_project
        __init__.py
        settings.py
        celery.py
    my_app
        tasks.py
        forms.py
        models.py
        urls.py
        views.py    
    venv
Run Code Online (Sandbox Code Playgroud)

__init__.py

from .celery import app as celery_app

__all__ = ('celery_app',)
Run Code Online (Sandbox Code Playgroud)

芹菜.py

import os
from celery import Celery

os.environ.setdefault('DJANGO_SETTINGS_MODULE','my_project.settings')

app = Celery('my_project')
app.config_from_object('django.conf:settings', namespace='CELERY')
app.autodiscover_tasks()
Run Code Online (Sandbox Code Playgroud)