Запуск фоновых задач 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, будут ли мои процессы в очереди в конечном итоге выполняться на моем доступном веб-dyno? Или процессы в очереди никогда не запустятся?
  • Если процессы в очереди никогда не будут запущены, есть ли другой способ сделать это, например, с помощью 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)

4 ответа

$ cat Procfile
web: bin/web

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

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

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

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

Вы можете использовать менеджер процессов, например, 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

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

Чтобы запустить и запустить процесс в фоновом режиме:

Procfile:

run: python my_app.py

А потом выполните:

heroku ps:scale run=1

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

heroku run worker
Другие вопросы по тегам