Как запустить приложение для сельдерея с приложением Django, масштабируемым с помощью AWS Elastic Beanstalk?
Как использовать django с Elastic Benastalk, который также запускал бы задачи с помощью сельдерея только на главном узле?
5 ответов
Вот так я и настроил сельдерей с django на эластичном бобовом стебле, и его масштабируемость работала нормально.
Пожалуйста, имейте в виду, что опция leader_only для container_commands работает только при перестройке среды или развертывании приложения. Если служба работает достаточно долго, узел-лидер может быть удален с помощью Elastic Beanstalk. Чтобы справиться с этим, вам, возможно, придется применить защиту экземпляра для вашего узла-лидера. Проверьте: http://docs.aws.amazon.com/autoscaling/latest/userguide/as-instance-termination.html
Добавьте скрипт bash для сельдерея и настройте бит.
Добавьте файл root_folder /.ebextensions / files / celery_configuration.txt:
#!/usr/bin/env bash
# Get django environment variables
celeryenv=`cat /opt/python/current/env | tr '\n' ',' | sed 's/export //g' | sed 's/$PATH/%(ENV_PATH)s/g' | sed 's/$PYTHONPATH//g' | sed 's/$LD_LIBRARY_PATH//g' | sed 's/%/%%/g'`
celeryenv=${celeryenv%?}
# Create celery configuraiton script
celeryconf="[program:celeryd-worker]
; Set full path to celery program if using virtualenv
command=/opt/python/run/venv/bin/celery worker -A django_app --loglevel=INFO
directory=/opt/python/current/app
user=nobody
numprocs=1
stdout_logfile=/var/log/celery-worker.log
stderr_logfile=/var/log/celery-worker.log
autostart=true
autorestart=true
startsecs=10
; Need to wait for currently executing tasks to finish at shutdown.
; Increase this if you have very long running tasks.
stopwaitsecs = 600
; When resorting to send SIGKILL to the program to terminate it
; send SIGKILL to its whole process group instead,
; taking care of its children as well.
killasgroup=true
; if rabbitmq is supervised, set its priority higher
; so it starts first
priority=998
environment=$celeryenv
[program:celeryd-beat]
; Set full path to celery program if using virtualenv
command=/opt/python/run/venv/bin/celery beat -A django_app --loglevel=INFO --workdir=/tmp -S django --pidfile /tmp/celerybeat.pid
directory=/opt/python/current/app
user=nobody
numprocs=1
stdout_logfile=/var/log/celery-beat.log
stderr_logfile=/var/log/celery-beat.log
autostart=true
autorestart=true
startsecs=10
; Need to wait for currently executing tasks to finish at shutdown.
; Increase this if you have very long running tasks.
stopwaitsecs = 600
; When resorting to send SIGKILL to the program to terminate it
; send SIGKILL to its whole process group instead,
; taking care of its children as well.
killasgroup=true
; if rabbitmq is supervised, set its priority higher
; so it starts first
priority=998
environment=$celeryenv"
# Create the celery supervisord conf script
echo "$celeryconf" | tee /opt/python/etc/celery.conf
# Add configuration script to supervisord conf (if not there already)
if ! grep -Fxq "[include]" /opt/python/etc/supervisord.conf
then
echo "[include]" | tee -a /opt/python/etc/supervisord.conf
echo "files: celery.conf" | tee -a /opt/python/etc/supervisord.conf
fi
# Reread the supervisord config
supervisorctl -c /opt/python/etc/supervisord.conf reread
# Update supervisord in cache without restarting all services
supervisorctl -c /opt/python/etc/supervisord.conf update
# Start/Restart celeryd through supervisord
supervisorctl -c /opt/python/etc/supervisord.conf restart celeryd-beat
supervisorctl -c /opt/python/etc/supervisord.conf restart celeryd-worker
Позаботьтесь о выполнении сценария во время развертывания, но только на главном узле (leader_only: true). Добавьте файл root_folder /.ebextensions / 02-python.config:
container_commands:
04_celery_tasks:
command: "cat .ebextensions/files/celery_configuration.txt > /opt/elasticbeanstalk/hooks/appdeploy/post/run_supervised_celeryd.sh && chmod 744 /opt/elasticbeanstalk/hooks/appdeploy/post/run_supervised_celeryd.sh"
leader_only: true
05_celery_tasks_run:
command: "/opt/elasticbeanstalk/hooks/appdeploy/post/run_supervised_celeryd.sh"
leader_only: true
- Beat настраивается без необходимости повторного развертывания с помощью отдельных приложений django: https://pypi.python.org/pypi/django_celery_beat.
- Сохранение результатов задачи - хорошая идея для: https://pypi.python.org/pypi/django_celery_beat
Требования к файлу .txt
celery==4.0.0
django_celery_beat==1.0.1
django_celery_results==1.0.1
pycurl==7.43.0 --global-option="--with-nss"
Настройте сельдерей для брокера Amazon SQS (получите нужную конечную точку из списка: http://docs.aws.amazon.com/general/latest/gr/rande.html) root_folder / django_app / settings.py:
...
CELERY_RESULT_BACKEND = 'django-db'
CELERY_BROKER_URL = 'sqs://%s:%s@' % (aws_access_key_id, aws_secret_access_key)
# Due to error on lib region N Virginia is used temporarily. please set it on Ireland "eu-west-1" after fix.
CELERY_BROKER_TRANSPORT_OPTIONS = {
"region": "eu-west-1",
'queue_name_prefix': 'django_app-%s-' % os.environ.get('APP_ENV', 'dev'),
'visibility_timeout': 360,
'polling_interval': 1
}
...
Конфигурация сельдерея для приложения django django_app
Добавить файл root_folder / django_app / celery.py:
from __future__ import absolute_import, unicode_literals
import os
from celery import Celery
# set the default Django settings module for the 'celery' program.
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'django_app.settings')
app = Celery('django_app')
# Using a string here means the worker don't have to serialize
# the configuration object to child processes.
# - namespace='CELERY' means all celery-related configuration keys
# should have a `CELERY_` prefix.
app.config_from_object('django.conf:settings', namespace='CELERY')
# Load task modules from all registered Django app configs.
app.autodiscover_tasks()
Изменить файл root_folder / django_app / __ init__.py:
from __future__ import absolute_import, unicode_literals
# This will make sure the app is always imported when
# Django starts so that shared_task will use this app.
from django_app.celery import app as celery_app
__all__ = ['celery_app']
Проверьте также:
- Как вы работаете с AWS Elastic Beanstalk? (решение без масштабируемости)
- Pip Requirements.txt --global-option, вызывающий ошибки установки с другими пакетами. "опция не распознана" (решение проблем, возникающих из-за унылой точки на эластичном бобовом стебле, которая не может справиться с глобальными вариантами правильного решения зависимости от пикруля)
Вот как я расширил ответ @smentek, чтобы учесть несколько рабочих экземпляров и один экземпляр ритма - то же самое применимо там, где вы должны защитить своего лидера. (У меня до сих пор нет автоматизированного решения для этого).
Обратите внимание, что обновления envvar для EB через EB cli или веб-интерфейс не отражаются ритмом сельдерея или работниками, пока не произойдет перезапуск сервера приложений. Это застало меня врасплох один раз.
В одном файле celery_configuration.sh выводятся два сценария для супервизора, обратите внимание, что celery-beat имеет autostart=false
иначе вы получите много ударов после перезапуска экземпляра:
# get django environment variables
celeryenv=`cat /opt/python/current/env | tr '\n' ',' | sed 's/export //g' | sed 's/$PATH/%(ENV_PATH)s/g' | sed 's/$PYTHONPATH//g' | sed 's/$LD_LIBRARY_PATH//g' | sed 's/%/%%/g'`
celeryenv=${celeryenv%?}
# create celery beat config script
celerybeatconf="[program:celeryd-beat]
; Set full path to celery program if using virtualenv
command=/opt/python/run/venv/bin/celery beat -A lexvoco --loglevel=INFO --workdir=/tmp -S django --pidfile /tmp/celerybeat.pid
directory=/opt/python/current/app
user=nobody
numprocs=1
stdout_logfile=/var/log/celery-beat.log
stderr_logfile=/var/log/celery-beat.log
autostart=false
autorestart=true
startsecs=10
; Need to wait for currently executing tasks to finish at shutdown.
; Increase this if you have very long running tasks.
stopwaitsecs = 10
; When resorting to send SIGKILL to the program to terminate it
; send SIGKILL to its whole process group instead,
; taking care of its children as well.
killasgroup=true
; if rabbitmq is supervised, set its priority higher
; so it starts first
priority=998
environment=$celeryenv"
# create celery worker config script
celeryworkerconf="[program:celeryd-worker]
; Set full path to celery program if using virtualenv
command=/opt/python/run/venv/bin/celery worker -A lexvoco --loglevel=INFO
directory=/opt/python/current/app
user=nobody
numprocs=1
stdout_logfile=/var/log/celery-worker.log
stderr_logfile=/var/log/celery-worker.log
autostart=true
autorestart=true
startsecs=10
; Need to wait for currently executing tasks to finish at shutdown.
; Increase this if you have very long running tasks.
stopwaitsecs = 600
; When resorting to send SIGKILL to the program to terminate it
; send SIGKILL to its whole process group instead,
; taking care of its children as well.
killasgroup=true
; if rabbitmq is supervised, set its priority higher
; so it starts first
priority=999
environment=$celeryenv"
# create files for the scripts
echo "$celerybeatconf" | tee /opt/python/etc/celerybeat.conf
echo "$celeryworkerconf" | tee /opt/python/etc/celeryworker.conf
# add configuration script to supervisord conf (if not there already)
if ! grep -Fxq "[include]" /opt/python/etc/supervisord.conf
then
echo "[include]" | tee -a /opt/python/etc/supervisord.conf
echo "files: celerybeat.conf celeryworker.conf" | tee -a /opt/python/etc/supervisord.conf
fi
# reread the supervisord config
/usr/local/bin/supervisorctl -c /opt/python/etc/supervisord.conf reread
# update supervisord in cache without restarting all services
/usr/local/bin/supervisorctl -c /opt/python/etc/supervisord.conf update
Тогда в container_commands мы только перезапускаем beat для лидера:
container_commands:
# create the celery configuration file
01_create_celery_beat_configuration_file:
command: "cat .ebextensions/files/celery_configuration.sh > /opt/elasticbeanstalk/hooks/appdeploy/post/run_supervised_celeryd.sh && chmod 744 /opt/elasticbeanstalk/hooks/appdeploy/post/run_supervised_celeryd.sh && sed -i 's/\r$//' /opt/elasticbeanstalk/hooks/appdeploy/post/run_supervised_celeryd.sh"
# restart celery beat if leader
02_start_celery_beat:
command: "/usr/local/bin/supervisorctl -c /opt/python/etc/supervisord.conf restart celeryd-beat"
leader_only: true
# restart celery worker
03_start_celery_worker:
command: "/usr/local/bin/supervisorctl -c /opt/python/etc/supervisord.conf restart celeryd-worker"
Если кто-то следит за ответом smentek и получает ошибку:
05_celery_tasks_run: /usr/bin/env bash does not exist.
Знайте, что если вы используете Windows, ваша проблема может заключаться в том, что файл celery_configuration.txt имеет WINDOWS EOL, когда он должен иметь UNIX EOL. Если вы используете Notepad++, откройте файл и нажмите "Правка> Преобразование EOL> Unix (LF)". Сохранить, повторно развернуть, и ошибки больше нет.
Кроме того, пара предупреждений для действительно любительских людей, таких как я:
Обязательно включите "django_celery_beat" и "django_celery_results" в ваш "INSTALLED_APPS" в файле settings.py.
Чтобы проверить ошибки сельдерея, подключитесь к вашему экземпляру с помощью "eb ssh", а затем "tail -n 40 /var/log/celery-worker.log" и "tail -n 40 /var/log/celery-beat.log" (где "40" относится к числу строк, которые вы хотите прочитать из файла, начиная с конца).
Надеюсь, это кому-нибудь поможет, это спасло бы меня несколько часов!
Потратив три дня на поиски решения, я наконец нашел простой метод. Чтобы настроить его, создайте новый каталог в основной папке вашего проекта с именем .platform/hooks/postdeploy. Внутри этого каталога добавьте файл без расширения с именем « postdeploy » и вставьте в него предоставленный скрипт. Обязательно замените заполнитель фактическим названием проекта.
С помощью этой настройки вы можете легко проверить статус Celery, подключившись к вашему экземпляру через SSH и выполнив команду « systemctl status celery.service ». Такой подход упрощает процесс управления и мониторинга Celery с помощью диспетчера служб systemd.
после развертывания
#!/usr/bin/env bash
echo "[Unit]
Name=Celery
Description=Celery service for My App
After=network.target
StartLimitInterval=0
[Service]
Type=simple
Restart=always
RestartSec=30
User=root
WorkingDirectory=/var/app/current
ExecStart=$PYTHONPATH/celery -A your_project_folder.celery worker --loglevel=INFO
ExecReload=$PYTHONPATH/celery -A your_project_folder.celery worker --loglevel=INFO
EnvironmentFile=/opt/elasticbeanstalk/deployment/env
[Install]
WantedBy=multi-user.target
" | sudo tee /etc/systemd/system/celery.service
# Start celery service
sudo systemctl start celery.service
# Enable celery service to load on system start
sudo systemctl enable celery.service
Также не забудьте настроить файл конфигурации внутри .ebextensions . Контент должен быть таким:
любое_имя.конфигурация
{
"commands": {
"01_install_ctl": {
"command": "sudo yum install -y /usr/bin/systemctl"
}
}
}
Как указано в ответе, принятое решение требует большого количества внешней работы, кроме кодирования. Теперь есть хорошая библиотека, которая с этим справляется.
https://github.com/ybrs/single-beat
Вы устанавливаете библиотеку и создаете сервер Redis с elasticache.
И ваш procfile может быть таким с переменной среды, нацеленной на сервер кэша.
web: gunicorn --bind :8000 --workers 3 --threads 2 appname.wsgi:application
celery_beat: SINGLE_BEAT_REDIS_SERVER=$SINGLE_BEAT_REDIS single-beat celery -A proj beat -l INFO --scheduler django_celery_beat.schedulers:DatabaseScheduler
celery_worker: celery -A proj worker -l INFO -P solo