Hacer Deploy de FastAPI y Celery (con RabbitMQ y PostgreSQL) en Heroku

rooyca

rooyca

Posted on July 9, 2022

Hacer Deploy de FastAPI y Celery (con RabbitMQ y PostgreSQL) en Heroku

Como ya es conocido por todos, plataformas como Heroku y Netlify nos permiten desplegar nuestros proyectos y páginas web sin costo alguno. El día de hoy haremos uso de Heroku para desplegar un proyecto de Scraping hecho con FastAPI.

DOCS

Heroku

Heroku es una Plataforma como Servicio (PaaS) que le permite a los desarrollados construir, ejecutar y operar aplicaciones enteramente en la Nube.

Heroku cuenta (a la fecha) con cuatro planes:

  • Gratis
    • Aplicaciones no comerciales, pruebas de concepto y proyectos personales.
  • Producción ($25 o más)
    • Aplicaciones de negocios, tales como Aplicaciones y Apis internas de empresas.
  • Avanzado ($250 o más)
    • Aplicaciones con funcionalidades complejas que requieren alta disponibilidad, muy poca latencia y manejo de altos volúmenes de peticiones.
  • Empresa (Precio por definir)
    • Aplicaciones de organizaciones a gran escala.

Más información

Scraping con FastAPI

Uno de los problemas que encontré a lo largo del desarrollo de este proyecto fue el de los tiempos de respuesta. Cuando se hace una petición a la API para que obtenga la información de una lista de Letterboxd, dicho proceso puede tomar algunos segundos, incluso minutos. El problema radica en que el servidor se queda "pegado" tratando de responder a la solicitud por lo que no es posible realizar una nueva petición. Como podrán imaginar, esperar hasta UN minuto por solicitud no es nada practico ni agradable, por lo que aquí es donde entra Celery y RabbitMQ.

SynYAsync

En la pagina oficial de Celery encontramos lo siguiente:

Celery is a simple, flexible, and reliable distributed system to process vast amounts of messages, while providing operations with the tools required to maintain such a system. It’s a task queue with focus on real-time processing, while also supporting task scheduling.

Y en la página de RabbitMQ:

RabbitMQ is a messaging broker - an intermediary for messaging. It gives your applications a common platform to send and receive messages, and your messages a safe place to live until received.

En pocas palabras, y con posibilidades de caer en equivocaciones, podríamos decir que Celery se encarga del manejo de las solicitudes para que estas puedan procesarse en "segundo plano" y así liberar el End Point para continuar recibiendo peticiones. Esto se logra -a muy grandes rasgos- asignándole una ID a la tarea, esta ID es la respuesta de esa primera petición. Con dicha ID podemos, en otro End Point, estar pendientes de nuestra tarea, cuando ya esté lista recibiremos el JSON de la lista de películas.

Response

Ahora bien, entonces ¿cuál es la función de RabbitMQ en todo esto?

"Sencillo", RabbitMQ lo que hace es almacenar la solicitud y la respuesta que genera Celery.

De las dos definiciones anteriores ruego se tome en serio muy poco de lo expuesto y en lugar aconsejo que se haga una investigación por cuenta propia.

¿Dónde correr RabbitMQ?

Rabbit

Para esto encontré dos opciones:

  1. Google Cloud o cualquier plataforma similar (AWZ, Azure, etc.)
  2. CloudAMQP

En este caso vamos a utilizar la primer opción, pero si deseas probar la segunda puedes dar click en el enlace de arriba y encontrarás una guía completa.

La pregunta es, ¿cómo hice para correr RabbitMQ con Google CLoud? Fácil, hice uso de Contenedores. Primero busqué la imagen de RabbitMQ para posteriormente correrla... todo muy sencillo hasta ahí.

El problema vino a la hora de tratar de obtener una IP externa. Lo que hice fue lo siguiente. En la consola de Google Cloud corrí:

(Remplazando todo lo que está completamente en Mayúsculas)

gcloud container clusters get-credentials [NOMBRE_CLUSTER] --zone [ZONA_CLUSTER]

Después, para exponer el servicio:

kubectl patch service/SERVICO_NOMBRE-rabbitmq-svc \
  --namespace default \
  --patch '{"spec": {"type": "LoadBalancer"}}'

Enter fullscreen mode Exit fullscreen mode

Por último, para obtener la IP externa y los puertos:

kubectl get service SERVICO_NOMBRE-rabbitmq-svc

¿Cómo correr Celery en Heroku?

Celery
Como sabrán, a la hora de correr un APP en Heroku necesitamos un archivo llamado Procfile en el que le especificamos a Heroku los comando que se ejecutarán a la hora de iniciar la aplicación.

Entonces, para poder ejecutar FastAPI y Celery a la vez necesitamos que nuestro archivo Procfile luzca algo así:

web: gunicorn -w 3 -k uvicorn.workers.UvicornWorker main:app
worker: celery -A main.celery worker -Q letterboxList

Enter fullscreen mode Exit fullscreen mode
  • Donde main hace referencia al nombre del archivo principal.
  • app y celery hacen referencia al nombre de las variables dentro del main archivo que se encargan de iniciar FastAPI y Celery, respectivamente.
  • Por último, letterboxList hace referencia al nombre de la tarea.

Ya para finalizar, en mi caso tuve que realizar un paso más.

Tuve que dirigirme a la página de Heroku, seleccionar el APP que había creado, darle en Resources y revisar que los dos Dynos estuvieran activados. En mi caso el de worker no lo estaba así que tuve que darle al icono del Lápiz (la opción de editar Dyno) y activarlo.

OneMore

Y eso sería todo, así de sencillo es correr FastAPI y Celery en Heroku. Por último, si desean ver el resultado final de este proyecto pueden dar click aquí.

Recuerden que si tienen alguna duda pueden escribirme por:

  • Discord: rooyca#6075
  • Telegram: @seiseiseis

Hasta la próxima. Que tengan un excelente día.

💖 💪 🙅 🚩
rooyca
rooyca

Posted on July 9, 2022

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related