Подтвердить что ты не робот

Как вы управляете работником с AWS Elastic Beanstalk?

Я запускаю приложение django на эластичном бобовом стебле aws. Я хотел бы запустить фоновое задание или работника, чтобы запустить сельдерей.

Я не могу найти, возможно ли это или нет. Если да, то как это можно достичь?

Вот что я делаю прямо сейчас, но каждый раз это создает ошибку типа события.

container_commands:
  01_syncdb:
    command: "django-admin.py syncdb --noinput"
    leader_only: true
  50_sqs_email:
    command: "./manage.py celery worker --loglevel=info"
    leader_only: true
4b9b3361

Ответ 1

Как @chris-wheadon предложил в своем комментарии, вы должны попытаться запустить сельдерей в качестве демона на заднем плане. AWS Elastic Beanstalk уже использует supervisord для запуска некоторых процессов deamon. Таким образом, вы можете использовать это для запуска celeryd и избегать создания собственного AMI для этого. Это хорошо работает для меня.

Что я делаю, так это программно добавляю конфигурационный файл celeryd к экземпляру после того, как приложение развернуто в нем EB. Сложность в том, что в файле должны быть установлены необходимые переменные окружения для демона (например, ключи доступа AWS, если вы используете S3 или другие службы в своем приложении).

Ниже приведена копия скрипта, который я использую, добавьте этот скрипт в вашу папку .ebextensions которая конфигурирует вашу среду EB.

Сценарий установки создает файл в папке /opt/elasticbeanstalk/hooks/appdeploy/post/ (документация), который используется во всех экземплярах EB. Любой сценарий оболочки будет выполнен после развертывания. Размещенный там скрипт оболочки работает следующим образом:

  1. В celeryenv переменного, virutalenv среда хранятся в формате, который следует за supervisord обозначения. Это список переменных env, разделенных запятыми.
  2. Затем скрипт создает переменную celeryconf которая содержит файл конфигурации в виде строки, которая включает ранее проанализированные переменные env.
  3. Затем эта переменная celeryd.conf в файл с именем celeryd.conf, файл конфигурации супервизора для демона celeryd.conf.
  4. Наконец, путь к вновь созданному файлу конфигурации добавляется в основной файл supervisord.conf, если его там еще нет.

Вот копия сценария:

files:
  "/opt/elasticbeanstalk/hooks/appdeploy/post/run_supervised_celeryd.sh":
    mode: "000755"
    owner: root
    group: root
    content: |
      #!/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''
      celeryenv=${celeryenv%?}

      # Create celery configuraiton script
      celeryconf="[program:celeryd]
      ; Set full path to celery program if using virtualenv
      command=/opt/python/run/venv/bin/celery worker -A myappname --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"

      # 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

Ответ 2

Я пытался сделать что-то подобное на PHP, но по какой-то причине я не мог заставить рабочего работать. Я переключился на AMI на сервере EC2 и имел успех с тех пор.

Ответ 3

Мне не удалось настроить сервер Django в рабочей среде AWS, вместо этого я использовал сервер Flask. Первоначально я пытался настроить Celery для планирования периодических задач на работника, но я чувствую, что это работает против модели, которую пытается навязать AWS. Я думаю, что "путь AWS" заключается в создании небольшого приложения Flask в рабочей среде. Оттуда вы можете запустить этого работника, отправив сообщения SQS (используя boto3), чтобы приложение Flask могло запустить долгосрочную задачу и в конечном итоге вернуть ответ HTTP 200, или вы можете добавить файл cron.yaml для планирования периодических задач используя запись crontab.

Используя этот подход, вы удаляете Celery для управления задачами и полагаетесь на второй сервер Flask, которым вы управляете через SQS, или с файлом cron.yaml, как cron.yaml ниже.

Конфигурация WSGI

Я использовал инструмент awsebcli для создания своей рабочей среды с именем "sqs-worker", например, eb create -t worker sqs-worker. Затем мне нужно было настроить WSGIPath для новой среды, поэтому я запустил eb config sqs-worker. Я просто использовал имя моего файла application.py, application.py.

  aws:elasticbeanstalk:container:python:
    NumProcesses: '1'
    NumThreads: '15'
    StaticFiles: /static/=static/
    WSGIPath: application.py

Рабочий план

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

worker/
├── .ebextensions
│   └── 01_logging.config
├── .elasticbeanstalk/...
├── venv/...
├── .gitignore
├── application.py
├── cron.yaml
├── requirements.txt
└── tasks.py

.ebextensions

.ebextensions содержит дополнительную конфигурацию для среды Amazon AWS AMI Linux, которая является отдельной задачей для вашего приложения Python. У меня есть один файл конфигурации для создания файла журнала для отладки 'flask.log . This config file also arranges for . This config file also arranges for включение flashk.log to be included in the log files collected by Amazon so that you'll see it whenever you run eb logs из командной строки.

commands:
  00_create_dir:
    command: mkdir -p /var/log/app-logs
  01_change_permissions:
    command: chmod g+s /var/log/app-logs
  02_change_owner:
    command: chown wsgi:wsgi /var/log/app-logs

files:
  "/opt/elasticbeanstalk/tasks/taillogs.d/flask.conf":
    mode: "000755"
    owner: root
    group: root
    content: |
      /var/log/app-logs/flask.log
  "/opt/python/log/flask.log" :
    mode: "000666"
    owner: ec2-user
    group: ec2-user
    content: |
      # flask log file

Разные предметы в работнике

.elasticbeanstalk был создан инструментом awsebcli, который, я думаю, выходит за рамки этого вопроса.

venv - это виртуальная среда для Python, и он был создан python3 -m venv venv. Виртуальную среду можно запустить, запустив source venv/bin/activate. Затем пакеты можно установить в виртуальную среду, как обычно, с помощью pip, pip install package, а затем pip install package requirements.txt можно сгенерировать как pip freeze > requirements.txt.

Файл .gitignore сообщает программе git, что игнорировать. Так как инструмент awsebcli использует awsebcli с awsebcli git, этот файл, вероятно, будет вам полезен. Последний раздел, касающийся "Elastic Beanstalk Files", был автоматически добавлен awsebcli.

# .gitignore
__pycache__
.pytest_cache
.vscode
db.sqlite3
venv
chromedriver
# Elastic Beanstalk Files
.elasticbeanstalk/*
!.elasticbeanstalk/*.cfg.yml
!.elasticbeanstalk/*.global.yml

Применение колбы

Я обнаружил, что мне нужно дать имя моему файлу application.py Flask application.py, и что мне нужно было дать имя моему приложению объекта application Flask. Здесь tasks.py - это простой скрипт на Python с несколькими определенными функциями очистки. Обратите внимание, что мы /opt/python/log/flask.log в /opt/python/log/flask.log. Я создаю flask.log в конфигурационном файле .ebextension, так что позаботьтесь об этом позже. Я перечислил несколько конечных точек, чтобы проиллюстрировать, что вы можете использовать разные конечные точки в вашем файле cron.yaml.

# application.py
import datetime
from flask import Flask, Response
import logging

import tasks

application = Flask(__name__)

logging.basicConfig(filename='/opt/python/log/flask.log', level=logging.INFO)

def get_timestamp():
    date_fmt = '%Y/%m/%d %H:%M:%S'
    date_now = datetime.datetime.now()
    date_str = datetime.datetime.strftime(date_now, date_fmt)
    return date_str

@application.route('/worker/scrape/', methods = ['POST'])
def scrape():
    application.logger.info(get_timestamp())
    data = tasks.scrape()
    application.logger.info(data)
    return Response(status="200")

@application.route('/worker/archives/', methods = ['POST'])
def scrape_archives():
    application.logger.info(get_timestamp())
    data = tasks.scrape_archives()
    application.logger.info(data)
    return Response(status="200")

@application.route('/worker/posts/', methods = ['POST'])
def scrape_posts():
    application.logger.info(get_timestamp())
    data = tasks.scrape_posts()
    application.logger.info(data)
    return Response(status="200")

Cron

Вот мой файл cron.yaml. Я использую нотацию crontab для запуска всего каждые три минуты, одна задача в минуту.

# cron.yaml
version: 1
cron:
 - name: "scrape"
   url: "/worker/scrape/"
   schedule: "0-59/3 * * * *"
 - name: "scrape-archives"
   url: "/worker/archives/"
   schedule: "1-59/3 * * * *"
 - name: "scrape-posts"
   url: "/worker/posts/"
   schedule: "2-59/3 * * * *"

Полезные ссылки

Платформа Python в AWS: https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/create-deploy-python-container.html

Развертывание Flask на AWS: https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/create-deploy-python-flask.html

Развертывание Django в AWS: https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/create-deploy-python-django.html.

Обзор рабочей среды: https://colintoh.com/blog/configure-worker-for-aws-elastic-beanstalk

Колба AWS Gotchas: http://blog.uptill3.com/2012/08/25/python-on-elastic-beanstalk.html

Видео от AWS: https://medium.com/aws-activate-startup-blog/a-sample-app-for-startups-2f8483c62b68