python - logs - Ejecución de tareas en segundo plano de Heroku con solo 1 web dyno y 0 trabajadores.
heroku restart app (4)
Tengo una aplicación de Python Flask en Heroku que sirve páginas web, pero también permite que se inicien ciertas tareas que creo que sería mejor estructuradas como tareas de fondo. Como tal, he seguido el tutorial de Heroku rq
para configurar tareas en segundo plano. Mi Procfile se ve así:
web: python app.py
worker: python worker.py
Sin embargo, mis procesos están actualmente escalados web=1 worker=0
. Dado que este proceso en segundo plano no se ejecutará muy a menudo, no me parece sensato proporcionarle un dinamo completo y luego pagar los $ 34 / mes por algo tan pequeño.
Pregunta:
- Si dejo el proceso de
worker
declarado en mi Procfile pero mantengo la escala enweb=1 worker=0
, ¿mis procesos en cola se ejecutarán en mi sitio web disponible? ¿O nunca se ejecutarán los procesos en cola? - Si los procesos en cola nunca se ejecutarán, ¿hay alguna otra forma de hacerlo, por ejemplo, utilizando
twisted
en mi aplicación web para ejecutar las tareas de forma asíncrona?
Información Adicional
worker.py
ve así:
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()
La lógica en la aplicación principal que pone en cola un proceso se ve así:
from rq import Queue
from worker import conn
q = Queue(connection=conn)
q.enqueue(myfunction, myargument)
Actualmente estoy ejecutando mi web y mi programador backend en Heroku usando solo 1 dinamo.
La idea es proporcionar un script de Python principal para que Heroku comience en 1 dinamómetro. Esta secuencia de comandos se utiliza para iniciar tanto los procesos del servidor web como los procesos del programador del cliente. A continuación, puede definir sus trabajos y agregarlos al programador personalizado.
APScheduler se utiliza en mi caso.
Esto es lo que hice:
en Procfile:
web: python run_app.py #the main startup script
en el 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()
También estoy usando 4 procesos de trabajo para servir la web desde Gunicorn, que funciona perfectamente bien.
En gunicorn.conf.py:
loglevel = ''info''
errorlog = ''-''
accesslog = ''-''
workers = 4
Es posible que desee revisar este proyecto como ejemplo: Zjobs@Github
Debería echar un vistazo a Heroku Scheduler, que le permitirá ejecutar una tarea específica en un intervalo programado, como cada 10 minutos. Si ya tiene la configuración de trabajador, podría agregar:
heroku run worker
Podrías usar un gestor de procesos como god o monit .
Con dios, puedes configurar tu configuración como tal
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
Entonces pones esto en tu Procfile
god -c path/to/config.god -D
De forma predeterminada, se reinicia automáticamente el proceso si se bloquea, y puede configurarlo para reiniciar la aplicación si el uso de la memoria es demasiado alto. Echa un vistazo a la documentación.
$ cat Procfile
web: bin/web
$ cat bin/web
python app.py &
python worker.py