web-dev-qa-db-ja.com

Django AWS Elastic Beanstalkでスケーラブルなアプリを使用してセロリワーカーを実行する方法は?

DjangoをAWS Elastic Beanstalkで使用して、メインノードでのみセロリによってタスクを実行する方法は?

17
smentek

これは、スケーラビリティが正常に機能するエラスティックbeantalkでDjangoを使用してセロリを設定する方法です。

'leader_only'オプションがcontainer_commandsは、アプリの環境の再構築またはdeploymentでのみ機能します。サービスが長く機能する場合、Elastic Beanstalkによってリーダーノードが削除される可能性があります。これに対処するには、リーダーノードにインスタンス保護を適用する必要がある場合があります。チェック: http://docs.aws.Amazon.com/autoscaling/latest/userguide/as-instance-termination.html#instance-protection-instance

セロリワーカー用の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

ファイルrequirements.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.htmlroot_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
}
...

DjangoDjango_appアプリのCelery設定

ファイルを追加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']

次も確認してください:

29
smentek

これは、@ smentekによる回答を拡張して、複数のワーカーインスタンスと単一のビートインスタンスを許可する方法です。リーダーを保護する必要がある場合にも同じことが当てはまります。 (まだそのための自動化されたソリューションはまだありません)。

EB cliまたはWebインターフェイスを介したEBへのenvvarの更新は、アプリサーバーの再起動が行われるまで、セロリビートまたはワーカーによって反映されないことに注意してください。これは一度私を油断しました。

1つのcelery_configuration.shファイルが監視対象の2つのスクリプトを出力します。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でリーダーのビートのみを再開します。

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"
5
Chris Berry

誰かがsmentekの回答をフォローしていてエラーが発生した場合:

05_celery_tasks_run: /usr/bin/env bash does not exist.

windowsを使用している場合、UNIXのEOLが必要なときに「celery_configuration.txt」ファイルにWINDOWSのEOLが含まれていることが問題である可能性があることに注意してください。 Notepad ++を使用している場合は、ファイルを開いて、[編集]> [EOL変換]> [Unix(LF)]をクリックします。保存、再デプロイ、エラーはなくなりました。

また、私のような本当にアマチュアの人々のためのいくつかの警告:

  • 必ずsettings.pyファイルの「INSTALLED_APPS」に「Django_celery_beat」と「Django_celery_results」を含めてください。

  • セロリのエラーを確認するには、「eb ssh」、次に「tail -n 40 /var/log/celery-worker.log」および「tail -n 40 /var/log/celery-beat.log」を使用してインスタンスに接続します(ここで、 "40"は、ファイルから読み取る行の数を示します(末尾から開始)。

これが誰かを助けることを願っています、それは私を数時間節約したでしょう!

2
jaume