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

Запуск фоновых задач Heroku с помощью всего лишь 1 веб-дино и 0 рабочих динамиков

У меня есть приложение Python Flask на Heroku, которое обслуживает веб-страницы, но также позволяет запускать определенные задачи, которые, я считаю, лучше всего структурированы в качестве фоновых задач. Таким образом, я выполнил учебник Heroku rq, чтобы настроить фоновые задачи. Мой Procfile выглядит так:

web: python app.py
worker: python worker.py

Однако мои процессы в настоящее время масштабируются web=1 worker=0. Учитывая, что этот фоновый процесс не будет выполняться очень часто, мне не кажется разумным предоставить ему целый динамофон, а затем заплатить $34 за месяц за что-то маленькое.

Вопрос:

  • Если я оставлю процесс worker, объявленный в моем файле Procfile, но сохранив масштабирование в web=1 worker=0, мои процессы в очереди будут запущены на моем доступном веб-дино? Или очереди не будут выполняться?
  • Если очереди не будут выполняться, есть ли другой способ сделать это, например, используя twisted в моем веб-приложении для выполнения задач асинхронно?

Дополнительная информация

worker.py выглядит следующим образом:

import os
import redis
from rq import Worker, Queue, Connection

listen = ['high', 'default', 'low']

redis_url = os.getenv('REDISTOGO_URL', 'redis://localhost:6379')

conn = redis.from_url(redis_url)

if __name__ == '__main__':
    with Connection(conn):
        worker = Worker(map(Queue, listen))
        worker.work()

Логика в главном приложении, который запускает процесс, выглядит следующим образом:

from rq import Queue
from worker import conn
q = Queue(connection=conn)

q.enqueue(myfunction, myargument)
4b9b3361

Ответ 1

$ cat Procfile
web: bin/web

$ cat bin/web
python app.py &
python worker.py

Ответ 2

Вы можете использовать диспетчер процессов, например god или monit.

С богом вы можете настроить свою конфигурацию так:

God.watch do |w|
  w.name = "app"
  w.start = "python app.py"
  w.keepalive
end

God.watch do |w|
  w.name = "worker"
  w.start = "python worker.py"
  w.keepalive
end

Затем вы помещаете это в свой файл Procfile

god -c path/to/config.god -D

По умолчанию он автоматически перезапускает процесс, если он сбой, и вы можете настроить его для перезапуска приложения, если использование памяти становится слишком высоким. Проверьте документацию.

Ответ 3

В настоящее время я запускаю как мой веб-сервер, так и бэкэнд-планшет в Heroku, используя только 1 дино.

Идея заключается в предоставлении одного основного питона script для Heroku для запуска в 1 dyno. Этот script используется для запуска процессов (ов) веб-сервера и процессов (-ов) планировщика клиента. Затем вы можете определить свои задания и добавить их в настраиваемый планировщик.

APScheduler используется в моем случае.

Это то, что я сделал:

в Procfile:

 web: python run_app.py    #the main startup script

в run_app.py:

# All the required imports
from apscheduler.executors.pool import ThreadPoolExecutor, ProcessPoolExecutor
from apscheduler.triggers.cron import CronTrigger
from run_housekeeping import run_housekeeping
from apscheduler.schedulers.background import BackgroundScheduler
import os

def run_web_script():
    # start the gunicorn server with custom configuration
    # You can also using app.run() if you want to use the flask built-in server -- be careful about the port
    os.system('gunicorn -c gunicorn.conf.py web.jobboard:app --debug')  

def start_scheduler():

     # define a background schedule 
     # Attention: you cannot use a blocking scheduler here as that will block the script from proceeding.
     scheduler = BackgroundScheduler()

     # define your job trigger
     hourse_keeping_trigger = CronTrigger(hour='12', minute='30')

     # add your job
     scheduler.add_job(func=run_housekeeping, trigger=hourse_keeping_trigger)

     # start the scheduler
     scheduler.start()


def run():
    start_scheduler()
    run_web_script()

if __name__ == '__main__':
    run()

Я также использую 4 рабочих процесса для обслуживания сети от Gunicorn, которая работает отлично.

В gunicorn.conf.py:

loglevel = 'info'
errorlog = '-'
accesslog = '-'
workers = 4

Вы можете проверить этот проект в качестве примера: Zjobs @Github

Ответ 4

Вы должны взглянуть на Heroku Scheduler, это позволит вам запускать определенную задачу по расписанию, например каждые 10 минут. Если у вас уже есть рабочая станция, вы можете добавить:

heroku run worker