Как передать broker_url из Django settings.py в сервис Celery
У меня Celery работает как служба на Ubuntu 20.04 с RabbitMQ в качестве брокера.
Celery неоднократно перезапускается, потому что не может получить доступ к RabbitMQ url (RABBITMQ_BROKER), переменной, хранящейся в settings.py вне корневого каталога Django.
То же самое происходит, если я пытаюсь запустить celery через командную строку.
Я подтвердил, что переменная доступна из Django из оператора печати views.py.
Если я помещаю переменную RABBITMQ_BROKER в settings.py в корне Django, сельдерей работает.
Мой вопрос в том, как мне заставить celery распознать переменную RABBITMQ_BROKER, когда она помещена в /etc/opt/mydjangoproject/settings.py?
Мой файл celery.py:
import os
from celery import Celery
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'backoffice.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...
Настройки.py в /etc/opt/mydjangoproject/ (не относящийся к делу материал удален):
from mydangoproject.settings import *
RABBITMQ_BROKER = 'amqp://rabbitadmin:somepassword@somepassword@webserver:5672/mydangoproject'
etc...
Мой файл /etc/systemd/system/celery.service:
[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 список каталогов, которые нужно попробовать при попытке импорта. Однако, поскольку у нас есть два разных каталога с одинаковым именем, которые мы используем как один пакет, нам также необходимо добавить следующие строки в /etc/opt/mydjangoproject/__init__.py
и /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"