如何将 broker_url 从 Django settings.py 传递到 Celery 服务
How to pass broker_url from Django settings.py to a Celery service
我将 Celery 运行 作为 Ubuntu 20.04 上的一项服务,并将 RabbitMQ 作为代理。
Celery 反复重启,因为它无法访问 RabbitMQ url (RABBITMQ_BROKER),一个保存在 settings.py outside 的变量Django 根目录.
如果我尝试通过命令行启动 celery,也会发生同样的情况。
我已经确认可以通过 views.py print 语句在 Django 中访问该变量。
如果我将 RABBITMQ_BROKER 变量放在 Django 根芹菜工程中的 settings.py 中。
我的问题是,当 celery 放在 /etc/opt/mydjangoproject/settings.py 中时,如何让 celery 识别变量 RABBITMQ_BROKER?
我的 celery.py 文件:
import os
from celery import Celery
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mydjangoproject.settings')
app = Celery('mydjangoproject')
default_config = 'mydjangoproject.celery_config'
app.config_from_object(default_config)
app.autodiscover_tasks()
我的 celery_config.py 文件:
from django.conf import settings
broker_url = settings.RABBITMQ_BROKER
etc...
/etc/opt/mydjangoproject/中的settings.py(不相关内容已删除):
from mydangoproject.settings import *
RABBITMQ_BROKER = 'amqp://rabbitadmin:somepassword@somepassword@webserver:5672/mydangoproject'
etc...
我的/etc/systemd/system/celery.服务文件:
[Unit]
Description=Celery Service
After=network.target
[Service]
Type=forking
User=DJANGO_USER
Group=DJANGO_USER
EnvironmentFile=/etc/conf.d/celery
WorkingDirectory=/opt/mydjangoproject
ExecStart=/bin/sh -c '${CELERY_BIN} -A $CELERY_APP multi start $CELERYD_NODES \
--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} --loglevel="${CELERYD_LOG_LEVEL}"'
ExecReload=/bin/sh -c '${CELERY_BIN} -A $CELERY_APP multi restart $CELERYD_NODES \
--pidfile=${CELERYD_PID_FILE} --logfile=${CELERYD_LOG_FILE} \
--loglevel="${CELERYD_LOG_LEVEL}" $CELERYD_OPTS'
Restart=always
[Install]
WantedBy=multi-user.target
我的/etc/conf.d/celery 文件:
CELERYD_NODES="worker"
CELERY_BIN="/opt/mydjangoproject/venv/bin/celery"
CELERY_APP="mydjangoproject"
CELERYD_CHDIR="/opt/mydjangoproject/"
CELERYD_MULTI="multi"
CELERYD_OPTS="--time-limit=300 --without-heartbeat --without-gossip --without-mingle"
CELERYD_PID_FILE="/run/celery/%n.pid"
CELERYD_LOG_FILE="/var/log/celery/%n%I.log"
CELERYD_LOG_LEVEL="INFO"
将以下行添加到 /etc/opt/mydjangoproject/settings.py
的末尾,让 celery 选择正确的代理 url(大小写可能因您使用的 celery 版本而异):
BROKER_URL = broker_url = RABBITMQ_BROKER
这会将配置放在调用 celery 的 config_from_object
函数时可以读取的位置。
接下来,您还必须向您的 systemd 单元添加一个环境变量。由于您正在以 mydjangoproject.settings
访问设置,因此您必须使 mydjangoproject
目录的父目录可在 PYTHONPATH 中访问:
Environment=PYTHONPATH=/etc/opt
PYTHONPATH
提供了 python 尝试导入时要尝试的目录列表。但是,因为我们有两个同名的不同目录,我们将它们用作单个包,we also have to add the following lines to /etc/opt/mydjangoproject/__init__.py
and /opt/mydjangoproject/__init__.py
:
import pkgutil
__path__ = pkgutil.extend_path(__path__, __name__)
我通过将以下内容添加到 /etc/systemd/system/celery.service
来解决这个问题
Environment="PYTHONPATH=/etc/opt/mydjangoproject:/opt/mydjangoproject"
Environment="DJANGO_SETTINGS_MODULE=settings"
我将 Celery 运行 作为 Ubuntu 20.04 上的一项服务,并将 RabbitMQ 作为代理。
Celery 反复重启,因为它无法访问 RabbitMQ url (RABBITMQ_BROKER),一个保存在 settings.py outside 的变量Django 根目录.
如果我尝试通过命令行启动 celery,也会发生同样的情况。
我已经确认可以通过 views.py print 语句在 Django 中访问该变量。
如果我将 RABBITMQ_BROKER 变量放在 Django 根芹菜工程中的 settings.py 中。
我的问题是,当 celery 放在 /etc/opt/mydjangoproject/settings.py 中时,如何让 celery 识别变量 RABBITMQ_BROKER?
我的 celery.py 文件:
import os
from celery import Celery
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mydjangoproject.settings')
app = Celery('mydjangoproject')
default_config = 'mydjangoproject.celery_config'
app.config_from_object(default_config)
app.autodiscover_tasks()
我的 celery_config.py 文件:
from django.conf import settings
broker_url = settings.RABBITMQ_BROKER
etc...
/etc/opt/mydjangoproject/中的settings.py(不相关内容已删除):
from mydangoproject.settings import *
RABBITMQ_BROKER = 'amqp://rabbitadmin:somepassword@somepassword@webserver:5672/mydangoproject'
etc...
我的/etc/systemd/system/celery.服务文件:
[Unit]
Description=Celery Service
After=network.target
[Service]
Type=forking
User=DJANGO_USER
Group=DJANGO_USER
EnvironmentFile=/etc/conf.d/celery
WorkingDirectory=/opt/mydjangoproject
ExecStart=/bin/sh -c '${CELERY_BIN} -A $CELERY_APP multi start $CELERYD_NODES \
--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} --loglevel="${CELERYD_LOG_LEVEL}"'
ExecReload=/bin/sh -c '${CELERY_BIN} -A $CELERY_APP multi restart $CELERYD_NODES \
--pidfile=${CELERYD_PID_FILE} --logfile=${CELERYD_LOG_FILE} \
--loglevel="${CELERYD_LOG_LEVEL}" $CELERYD_OPTS'
Restart=always
[Install]
WantedBy=multi-user.target
我的/etc/conf.d/celery 文件:
CELERYD_NODES="worker"
CELERY_BIN="/opt/mydjangoproject/venv/bin/celery"
CELERY_APP="mydjangoproject"
CELERYD_CHDIR="/opt/mydjangoproject/"
CELERYD_MULTI="multi"
CELERYD_OPTS="--time-limit=300 --without-heartbeat --without-gossip --without-mingle"
CELERYD_PID_FILE="/run/celery/%n.pid"
CELERYD_LOG_FILE="/var/log/celery/%n%I.log"
CELERYD_LOG_LEVEL="INFO"
将以下行添加到 /etc/opt/mydjangoproject/settings.py
的末尾,让 celery 选择正确的代理 url(大小写可能因您使用的 celery 版本而异):
BROKER_URL = broker_url = RABBITMQ_BROKER
这会将配置放在调用 celery 的 config_from_object
函数时可以读取的位置。
接下来,您还必须向您的 systemd 单元添加一个环境变量。由于您正在以 mydjangoproject.settings
访问设置,因此您必须使 mydjangoproject
目录的父目录可在 PYTHONPATH 中访问:
Environment=PYTHONPATH=/etc/opt
PYTHONPATH
提供了 python 尝试导入时要尝试的目录列表。但是,因为我们有两个同名的不同目录,我们将它们用作单个包,we also have to add the following lines to /etc/opt/mydjangoproject/__init__.py
and /opt/mydjangoproject/__init__.py
:
import pkgutil
__path__ = pkgutil.extend_path(__path__, __name__)
我通过将以下内容添加到 /etc/systemd/system/celery.service
来解决这个问题Environment="PYTHONPATH=/etc/opt/mydjangoproject:/opt/mydjangoproject"
Environment="DJANGO_SETTINGS_MODULE=settings"