Как избежать ошибки SECRET_KEY при запуске Celery с помощью Supervisor?

У меня есть приложение Django 1.62, работающее на Debian 7.8 с Nginx 1.2.1 в качестве прокси-сервера и Gunicorn 19.1.1 в качестве сервера приложений. Я установил Celery 3.1.7 и RabbitMQ 2.8.4 для обработки асинхронных задач. Я пытаюсь управлять своими различными приложениями, в частности Celery, с помощью Supervisor 3.0a8. Проблема в том, что когда я пытаюсь запустить Celery через Supervisor, я получаю эту ошибку:

ImproperlyConfigured: The SECRET_KEY setting must not be empty.

(Я показываю всю трассировку стека внизу.)

Все мои файлы конфигурации хранятся в каталоге «conf», который находится чуть ниже моего каталога проекта «myproj», например:

conf
├── celeryconfig.py
├── celeryconfig.pyc
├── celery.py
├── __init__.py
├── middleware.py
├── settings
│   ├── base.py
│   ├── dev.py
│   ├── __init__.py
│   ├── prod.py
├── urls.py
├── wsgi.py

Мои производственные настройки Django хранятся в файле настроек prod.py, который наследует мои базовые настройки base.py. Я храню секретный ключ в файле постактивации моей виртуальной среды и считываю его в свои производственные настройки, как показано ниже. С помощью интерпретатора Python я проверил, что секретный ключ присутствует в моих производственных настройках.

# conf/settings/prod.py
from conf.settings.base import *
...
# get_env_variable is defined in base.py
SECRET_KEY = get_env_variable("SECRET_KEY")

Это функция get_env_variable, которая считывает секретный ключ в:

# conf/settings/base.py
def get_env_variable(var_name):
    try:
        return os.environ[var_name]
    except KeyError:
        error_msg = "Set the %s environment variable" % var_name
        raise ImproperlyConfigured(error_msg)

Это мой файл конфигурации Supervisor. Он основан на примере файла из документации по Celery:

# /etc/supervisor/conf.d/myproj.conf
[program:myproj]
command = /www/myproj/bin/start-gunicorn
user = root
stdout_logfile = /var/log/gunicorn/supervisor.log
redirect_stderr = true

[program:celery]
directory=/www/myproj
command=/home/myproj/venv/myproj/bin/celery worker --app=conf -l debug
user=nobody
numprocs=1
stdout_logfile=/var/log/celery/celery.log
stderr_logfile=/var/log/celery/celery.log
autostart=true
autorestart=true
startsecs=10
stopwaitsecs=600
killasgroup=true
priority=998

Вот как я загрузил новую конфигурацию Celery с помощью Supervisor:

sudo service supervisor stop
sudo service supervisor start

Это мой файл приложения Celery:

# conf/celery.py
from __future__ import absolute_import
import os
from celery import Celery
from django.conf import settings
from conf import celeryconfig

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'conf.settings')
app = Celery('conf')
app.config_from_object(celeryconfig)
app.autodiscover_tasks(lambda: settings.INSTALLED_APPS)

Это мой файл конфигурации Celery:

# conf/celeryconfig.py
BROKER_URL = 'amqp://guest@localhost:5672//'
CELERY_RESULT_BACKEND = 'amqp'
CELERY_ACCEPT_CONTENT = ['json', ]
CELERY_TASK_SERIALIZER = 'json'
CELERY_RESULT_SERIALIZER = 'json'
CELERY_TASK_RESULT_EXPIRES = 3600
CELERY_SEND_TASK_ERROR_EMAILS = True

В документации Celery я изменил __init__.py:

# conf/__init__.py
from __future__ import absolute_import
from .celery import app as celery_app

Я могу запустить Celery вручную, используя следующую команду, и он запускается нормально:

workon myproj  # Activate project's virtual environment
celery worker -A conf -l info

Однако, когда я пытаюсь запустить его через Supervisor, я получаю ошибку, которую я описал. Подумав, что, возможно, Supervisor не может получить доступ к секретному ключу Django, потому что это переменная среды, я попытался жестко закодировать ключ в моем файле настроек prod.py (вместо того, чтобы считывать его с помощью функции get_env_variable), но это не исправило проблему. проблема.

Я попытался объединить все свои настройки в файл настроек prod.py, который содержал фактический секретный ключ, но это не помогло.

Я также попытался добавить этот параметр среды в файл конфигурации Supervisor, как показано ниже, но это не решило проблему:

# /etc/supervisor/conf.d/myproj.conf
...
[program:celery]
environment=SECRET_KEY="(my secret key)"
directory=/www/myproj
command=/home/myproj/venv/myproj/bin/celery worker --app=conf -l debug
user=nobody
...

Я попытался установить «пользователя» на имя пользователя, под которым я запускаю веб-сайт, но это тоже не помогло.

# /etc/supervisor/conf.d/myproj.conf
...
[program:celery]
environment=SECRET_KEY="(my secret key)"
directory=/www/myproj
command=/home/myproj/venv/myproj/bin/celery worker --app=conf -l debug
user=myproj
...

Я читал о библиотеке под названием django-supervisor, которая должна упростить интеграцию между Django и Supervisor. но я получаю ту же ошибку, если использую эту библиотеку.

Наконец, я прочитал здесь, на SO что если ваш секретный ключ содержит знак "%", Супервизору это не понравится. Я заметил, что мой ключ содержит один знак «%», поэтому я экранировал его, как этот «%%», но это также не решило проблему.

Может ли кто-нибудь увидеть, что я делаю неправильно? Я видел здесь другие вопросы от пользователей, которые сталкивались с этой же ошибкой при разных обстоятельствах, но я пытался реализовать различные решения, которые обсуждались, и ни одно из них не устранило проблему.

Большое спасибо за ваши идеи. И извините за длинный вопрос, но в этой проблеме много движущихся частей.

Вот вся трассировка стека:

Traceback (most recent call last):
  File "/home/myproj/venv/myproj/bin/celery", line 11, in <module>
    sys.exit(main())
  File "/home/myproj/venv/myproj/local/lib/python2.7/site-packages/celery/__main__.py", line 30, in main
    main()
  File "/home/myproj/venv/myproj/local/lib/python2.7/site-packages/celery/bin/celery.py", line 81, in main
    cmd.execute_from_commandline(argv)
  File "/home/myproj/venv/myproj/local/lib/python2.7/site-packages/celery/bin/celery.py", line 769, in execute_from_commandline
    super(CeleryCommand, self).execute_from_commandline(argv)))
  File "/home/myproj/venv/myproj/local/lib/python2.7/site-packages/celery/bin/base.py", line 307, in execute_from_commandline
    return self.handle_argv(self.prog_name, argv[1:])
  File "/home/myproj/venv/myproj/local/lib/python2.7/site-packages/celery/bin/celery.py", line 761, in handle_argv
    return self.execute(command, argv)
  File "/home/myproj/venv/myproj/local/lib/python2.7/site-packages/celery/bin/celery.py", line 693, in execute
    ).run_from_argv(self.prog_name, argv[1:], command=argv[0])
  File "/home/myproj/venv/myproj/local/lib/python2.7/site-packages/celery/bin/worker.py", line 179, in run_from_argv
    return self(*args, **options)
  File "/home/myproj/venv/myproj/local/lib/python2.7/site-packages/celery/bin/base.py", line 270, in __call__
    ret = self.run(*args, **kwargs)
  File "/home/myproj/venv/myproj/local/lib/python2.7/site-packages/celery/bin/worker.py", line 212, in run
    state_db=self.node_format(state_db, hostname), **kwargs
  File "/home/myproj/venv/myproj/local/lib/python2.7/site-packages/celery/worker/__init__.py", line 95, in __init__
    self.app.loader.init_worker()
  File "/home/myproj/venv/myproj/local/lib/python2.7/site-packages/celery/loaders/base.py", line 128, in init_worker
    self.import_default_modules()
  File "/home/myproj/venv/myproj/local/lib/python2.7/site-packages/celery/loaders/base.py", line 116, in import_default_modules
    signals.import_modules.send(sender=self.app)
  File "/home/myproj/venv/myproj/local/lib/python2.7/site-packages/celery/utils/dispatch/signal.py", line 166, in send
    response = receiver(signal=self, sender=sender, **named)
  File "/home/myproj/venv/myproj/local/lib/python2.7/site-packages/celery/fixups/django.py", line 69, in on_import_modules
    self.worker_fixup.validate_models()
  File "/home/myproj/venv/myproj/local/lib/python2.7/site-packages/kombu/utils/__init__.py", line 322, in __get__
    value = obj.__dict__[self.__name__] = self.__get(obj)
  File "/home/myproj/venv/myproj/local/lib/python2.7/site-packages/celery/fixups/django.py", line 64, in worker_fixup
    self._worker_fixup = DjangoWorkerFixup(self.app)
  File "/home/myproj/venv/myproj/local/lib/python2.7/site-packages/celery/fixups/django.py", line 99, in __init__
    self._cache = import_module('django.core.cache')
  File "/usr/lib/python2.7/importlib/__init__.py", line 37, in import_module
    __import__(name)
  File "/home/myproj/venv/myproj/local/lib/python2.7/site-packages/django/core/cache/__init__.py", line 69, in <module>
    if DEFAULT_CACHE_ALIAS not in settings.CACHES:
  File "/home/myproj/venv/myproj/local/lib/python2.7/site-packages/django/conf/__init__.py", line 54, in __getattr__
    self._setup(name)
  File "/home/myproj/venv/myproj/local/lib/python2.7/site-packages/django/conf/__init__.py", line 49, in _setup
    self._wrapped = Settings(settings_module)
  File "/home/myproj/venv/myproj/local/lib/python2.7/site-packages/django/conf/__init__.py", line 151, in __init__
    raise ImproperlyConfigured("The SECRET_KEY setting must not be empty.")
django.core.exceptions.ImproperlyConfigured: The SECRET_KEY setting must not be empty.

person Jim    schedule 08.04.2015    source источник
comment
в конфигурации супервизора попробуйте установить секретный ключ на 'aa' или любую простую строку и попробуйте   -  person ChillarAnand    schedule 09.04.2015
comment
Спасибо за предложение, но это не решило проблему. Я изменил значение ключа, перезапустил свою виртуальную среду, сделал env | grep SECRET для подтверждения нового секретного ключа, а затем перезапустил Celery через Supervisor, и я все еще получаю сообщение об ошибке.   -  person Jim    schedule 09.04.2015
comment
У меня были точно такие же симптомы. Обновление супервизора до 3.1.3 решило проблему. Я удалил версию из репозиториев apt и установил через pip.   -  person abhaga    schedule 21.04.2015
comment
Вы когда-нибудь думали, как это решить? у меня такая же проблема и это сводит меня с ума   -  person LBJ33    schedule 09.05.2021


Ответы (1)


В конфигурации сельдерея вам нужно указать, какие настройки вы используете. в настоящее время у вас есть prod.py, который вы используете для своего производственного кода, поэтому ваш celery.py должен быть

# conf/celery.py
from __future__ import absolute_import
import os
from celery import Celery
from django.conf import settings
from conf import celeryconfig

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'conf.settings.prod')
app = Celery('conf')
app.config_from_object(celeryconfig)
app.autodiscover_tasks(lambda: settings.INSTALLED_APPS)

Поэтому сельдерей будет знать, какой файл настроек вы хотите использовать (если у вас есть несколько настроек в папке настроек).

person Chitrank Dixit    schedule 12.08.2016