Introduction and Orientatiation
Published October 20, 2021
This video features Josue Balandrano Coronel at DjangoCon US 2021 in Online.
All 2021 talks have English and Spanish captions.
Las filas de tareas se encuentran en un sinnúmero de aplicaciones que usamos día a día. Estas nos ayudan a correr tareas tardas o pesadas sin que el usuario tenga que esperar.
En esta presentación explicaré los conceptos básicos de las filas de tareas y como aprovecharlas mejor.
This talk was presented at: https://2021.djangocon.us/talks/usando-filas-de-tareas-task-queues-en/
LINKS:
Follow Josue Balandrano Coronel 👇
On Twitter: https://twitter.com/rmcomplexity
Website: https://rmcomplexity.com
Follow DjangCon US 👇
https://twitter.com/djangocon
Follow DEFNA 👇
https://twitter.com/defnado
https://www.defna.org/
Video production by the speaker and DjangoCon US 2021 Volunteers.
Las filas de tareas permiten sacar del ciclo de solicitud y respuesta HTTP las operaciones lentas o recurrentes, como generar reportes, auditar datos y enviar correos. Su arquitectura básica tiene un productor, que crea mensajes; un mediador o broker, que los almacena y distribuye; y consumidores o workers, que ejecutan las tareas de forma independiente y, en algunos casos, en paralelo. Explica las diferencias generales entre AMQP, RabbitMQ, ZeroMQ, SQS, Redis, PostgreSQL y Kafka, y compara Celery, RQ, Huey y Dramatiq, destacando sus abstracciones, mediadores compatibles, complejidad y capacidades de paralelismo. También muestra que estas colas sirven para dividir procesos en pasos reintentables, desacoplar componentes con distintos requisitos de seguridad y facilitar la migración de un monolito hacia un sistema distribuido o basado en eventos.
Summarised automatically from the transcript.
Automatically transcribed, so expect mistakes in names and technical terms.
Hola, mi nombre es Josué y hoy voy a estar hablando acerca de usando filas de trabajo en aplicaciones web. Las filas de trabajo o task, perdón, filas de tareas, bueno, también trabajo o task son utilizadas en aplicaciones web. En muchas aplicaciones web que están ahorita en producción y son utilizadas para procesar tareas asincrónicamente. Asincrónicamente significa que no son procesados o las cosas no suceden. De una manera lineal en el tiempo. Entonces pueden suceder en diferentes momentos o en diferentes órdenes En aplicaciones web usualmente vemos las cosas desde el punto de vista del ciclo
de respuesta y solicitud HTTP. Entonces, cuando decimos que alguna tarea es procesada sincrónicamente, usualmente nos referimos a que no es procesada en el ciclo de solicitud y respuesta HTTP. Y esto es porque la mayoría de las cosas , la mayoría de las cosas que toman mucho tiempo en procesar. Pues no queremos que el usuario se quede ahí nada más esperando, viendo alguna pantalla que iba cargando. Y lo que queremos es decir al usuario, ok, ya estamos procesando este. Esto y lo procesamos en alguna otra parte y no en este ciclo de solicitud y respuesta HTTP. Y una vez que terminemos
Entonces ya le mandamos algún mensaje o alguna notificación al usuario y le decimos ya está, ya sea por ejemplo algún reporte o alguna otra cosa que podamos que tome mucho tiempo en procesar Puse de ejemplo un reporte porque, por ejemplo, en un reporte se necesitan muchos cálculos, se necesitan hacer muchos cálculos, entonces usualmente se tarda un poquito más de tiempo. Entonces podemos hacer todos esos cálculos en algún otro lado y no dejar al usuario esperando Una vez que terminemos le decimos ya está todo listo. Otra cosa que podríamos también utilizar en una fila de tareas es como por ejemplo a lo mejor auditar datos que están en alguna base de datos o en algún otro lado archivos, cosas por el estilo.
Y son tareas que son más recurrentes, ¿verdad? Entonces, no necesariamente , inclusive cuando estamos hablando de aplicaciones web, y usualmente vemos las cosas desde La aplicación que está corriendo y la aplicación que a la cual el usuario tiene acceso. Este también las filas de tarea pueden ser utilizadas afuera de este contexto, en cualquier otra cosa que podamos estar corriendo. ya en alguna otra parte de nuestra arquitectura en todo el sistema que tenemos entonces vamos a empezar viendo básicamente o la arquitectura básica de una fila de tareas y el concepto y la arquitectura básica es bastante sencillo y
Y es es prácticamente, son solamente estas tres entidades de las cuales vamos a ver ahorita. Este, pero esta es la idea básica. Ya una vez. que empezamos a ver diferentes tipos de implementaciones, las cuales también los vamos a ver un poquito por encimita, pero si vamos a indagar en cuáles son las diferencias. Vamos a ver cómo se pueden complicar estas cosas y depende de los requerimientos del proyecto, la aplicación o el sistema en el cual estemos trabajando. Entonces todo empieza desde el punto de vista, como estábamos diciendo, de la aplicación web, ¿verdad? Del ciclo de solicitud y respuesta HTTP. Entonces a este usualmente a esta parte usualmente se le llama el productor
porque es el que produce las tareas Produce que las tareas en realidad son traducidas a unos mensajes con ciertas sintaxis, las cuales llegan eventualmente otros procesos que las procesan. Entonces, por eso es que esto a esta parte se le llama el productor: es el que produce las tareas y el que dice qué es lo que se va a correr. No dice cuándo ni en dónde, solamente dice qué es lo que se va a correr. Y es el que manda los datos todos los datos necesarios para que para poder correr algún tipo de tarea. Nuevamente esto es. Usualmente lo vemos como la aplicación web, la aplicación que el usuario está interactuando con ella, ¿verdad? Entonces hay muchas tareas, o la mayoría de las tareas son iniciadas cuando el usuario da clic en algún botón, o a lo mejor
este. Va a alguna dirección en específico o tiene algún tipo de interacción con nuestra aplicación. De ahí en adelante, eventualmente, como también dijimos. Hay otras cosas que se pueden producir afuera de este contexto, pero ese es así como que el principal punto de entrada. Después de esto, después del productor o producer, que también se le llama en inglés, tenemos lo que es la fila o un Q. Pero esta fila o este Q no es nada más algo. así tan sencillo es un poquito más más robusto y entonces en realidad aunque aunque detrás otras bambalinas sea solamente una fila O solamente una fila entre comillas
, porque son más cosas involucradas. También a esto se le llama más que nada un mediador o un broker en inglés. Y se le llama así porque siempre está en medio del productor y el consumidor, que el consumidor es lo que eventualmente va a procesar las tareas. Entonces nos pasamos al último paso que son los trabajadores o los workers , que son los procesos que están procesando tareas. Y a toda esa idea, esa entidad se le llaman los consumidores. Entonces depende de quién está consumiendo las tareas del mediador. Y esto es básicamente lo que es el concepto de una fila de tareas. Este concepto
Se utilizan en diferentes partes, no nada más en filas de teletrans, así como lo estamos viendo así, pero también puede ser, por ejemplo, si todo esto está en memoria y estamos hablando que el productor y el consumidor son nada más dos diferentes funciones. También se puede utilizar para desacoplar dos partes de un programa. Entonces, la idea básica viene desde hace mucho y existe existe en el ámbito de software desde hace mucho y es aplicada de esta manera para hacerlo un poquito más robusta y para hacerla de pues más flexible también y que se pueda se pueda hacer o se pueda agrandar o se pueda asignar diferentes
Diferentes recursos para cada una de estas entidades. Entonces, vamos a empezar a indagar en cada una de estas partes de la arquitectura para entenderlas un poquito más. Los productores tienen este nombre, como habíamos dicho, debido a que producen los mensajes que se envían una fila. Y la única cosa es que, como habíamos dicho, pues usualmente el productor es la aplicación web. Pero no necesariamente en todos los casos, ¿verdad? También podríamos producir mensajes directamente desde la interfaz de usuario. Y nada más mandarla directamente hacia el mediador
sin ese servidor web que tenemos detrás en las aplicaciones usualmente. Pero si hacemos algo por el estilo, algo así como estamos diciendo, que nada más específicamente desde el cliente, desde la interfaz de usuario o la interfaz gráfica, entonces tenemos que ser un poquito más conscientes acerca de seguridad y cosas por el estilo. Este en. Y existen otro tipo de variaciones de esto, ¿verdad? Este, dependiendo del proyecto. O sea, también puede ser que la aplicación web Hable con otra aplicación que está detrás de nosotros y esa es la que en realidad sea el productor, no en no la aplicación, nada más. Entonces, el productor puede ser muchas diferentes cosas. Es cualquier Cualquier proceso
que crea mensajes, los cuales son enviados al mediador. Si lo queremos ver, así como que, o definir de una manera un poquito más concreta. Usualmente las bibliotecas que vamos a empezar a ver, que implementan filas de tareas , vamos a ver que tienen interfaces o. O capas de abstracción alrededor de lo que es un productor y lo que es un consumidor, y hace más sencillo nuestro trabajo de crear estos mensajes que van hacia el mediador. No tenemos nosotros que indagar y ver exactamente cómo crear estos mensajes. Y lo único que tenemos que preocuparnos is to define what are the things that we can process, what is
the code , Eso es algo siempre bueno y así vamos a ver cuáles son en realidad, hay diferentes maneras de implementar este tipo de cosas. Entonces vamos a hablar un poquito acerca de cuáles son las diferencias de algunas bibliotecas que son usadas en producción. La siguiente entidad aquí son los mediadores, y como habíamos dicho, esta idea de cómo se implementa una fila de trabajos. Este par de tareas, pues es usada en diferentes contextos en software, no nada más en aplicaciones web. Claro que hay diferentes tipos de implementaciones.
Hay algunas, más complicadas o más complejas que otras y otras más sencillas entonces por ejemplo tenemos lo que se llama AMQ AMQP o AMQP. Las siglas significan Advanced Messaging Queuing Protocol. Y ese protocolo define cómo se pueden implementar diferentes tipos de mediadores. Por ejemplo, RabbitMQ y ZeroMQ son dos aplicaciones o dos implementaciones de AMQP. que son utilizadas en producción desde hace mucho tiempo y son bastante estables y muy robustas. Entonces ellos lo único que tienen que hacer es implementar este protocolo. Y diferentes aplicaciones pueden utilizarlo, por ejemplo, las bibliotecas que vamos a ver,
nuestra aplicación web, cosas por el estilo. También existen otras soluciones más ligeras, como por ejemplo el SQS de Amazon. Que es muy parecido a una implementación de AMQP, pero no implementa todo el protocolo. Implementa solo las partes más necesarias. Y es enfocado más en rapidez, no tanto en ser robusto o súper estable, sino que nada más en que rápidamente procesa mensajes. También varias bases de datos ya vienen con la habilidad de ser usados como mediadores, por ejemplo, Redis y Postgres ya tienen implementaciones de lo que se llama un PopSub. Protocolo, verdad, que es un publicación y suscriptor, entonces de esta manera lo
si lo queremos traducir, lo podemos traducir en el productor. Y el consumidor es el suscriptor, se suscribe a diferentes partes de la implementación y es lo que agarra los mensajes que están ahí. Este, últimamente, o últimamente al procesar muchos de estos mensajes en un sistema distribuido ha sido una necesidad. Debido a la alta cantidad de datos que manejamos hoy en día. Para estos casos, hay varias soluciones para procesar grandes cantidades de mensaje de una manera robusta y han sido creados cosas como Kafka por ejemplo que son un poquito más diferentes no estamos hablando de una base de datos
nada más de Popsop o este o un una implementación de MQP, pero este estos estos proyectos como Kafka son un poquito más especializados en arquitecturas que se que utilizan eventos para hacer todo un un ecosistema verdad entonces si si lo vemos De esta manera, como en las filas de trabajo, pues es básicamente el mismo concepto, pero es llevado a una aplicación en general y no nada más en tareas que se tarden mucho tiempo o en cosas que queremos Que queremos correr en otro ciclo y no en nuestro ciclo principal de la aplicación. Afortunadamente, los proyectos que vamos a ver en esta plática
ofrecen una abstracción encima de los mediadores también. Y eso nos facilita utilizarlos. Como quieras, si debemos de tener un poco de conocimiento de cuál es el mediador que vamos a utilizar. y este y depende de nuestras necesidades va a ser el mediador que vamos a definir o que vamos a escoger para usar en nuestra aplicación porque tienen diferentes cosas que podemos utilizar uno Y también siempre está la necesidad de administrarlos y ver si es seguro y ver cualquier otro problema que podamos tener alrededor de esto. Entonces, como quiera Aunque existan estas abstracciones con las bibliotecas que vamos a ver o que podamos utilizar, como quieran necesitamos ver saber cuáles son
las diferentes partes que están detrás y cómo trabajan una con otra. Lo recomendable usualmente es empezar con algo con lo más básico y ver si se necesitan cosas más avanzadas, a menos que ya se sepa exactamente. cuáles sean los requisitos y es para estos requisitos estoy hablando más que nada si sabemos exactamente O bueno, más o menos como cuántas tareas se van a procesar o cuánto, cuántos diferentes recursos necesitamos, ya sea de memoria. o a lo mejor este de disco duro o a lo mejor nada más este de comunicaciones de red cosas por el estilo Entonces, si todavía no tenemos bien definidos esos requisitos, lo podemos empezar con algo muy básico
y luego cambiar los mediadores depende de cómo nuestros requisitos empiecen a cambiar. Usualmente por eso es bueno ver estas bibliotecas que ya tienen esta capa de abstracción y así es más fácil cambiar los mediadores entre una, o depende de cómo cambien nuestros requerimientos. Ahora, el último paso que tenemos aquí en esta arquitectura básica son los consumidores. Los consumidores son también parte de la aplicación. Y usualmente la implementación de filas de tareas que se utiliza ofrece una capa de abstracción que se encarga de conectar también al mediador y recibir estos mensajes. Entonces los consumidores deben de estar conectados al mediador
de la misma manera, así como lo podemos ver aquí. para estar viendo cuáles son los nuevos mensajes y ver si los va a procesar o no estos diferentes este procesos que están que están corriendo De esta manera, al utilizar estas capas de abstracción, de esta manera nos podemos enfocarnos nada más en el código que va a hacer el procesamiento en sí y no en todo el protocolo que está alrededor de esto. Esto significa que los consumidores son procesos que se encuentran corriendo y escuchando los mediadores para ver cuándo se debe de ejecutar alguna tarea. Y es importante reconocer este detalle, puesto que es muy fácil confundirnos cuando estamos viendo si alguna tarea se está corriendo o no, o si todo el número de tareas que necesitamos correr se están corriendo.
Este cuando tenemos que debuguear todo esto, tenemos que mantener esto en mente y así podemos saber que, ok, entonces los consumidores están. Se tiene que conectar al mediador, agarrar estas tareas y procesarlas, y esto es aparte del ciclo de trabajo, digo, perdón, del ciclo de nuestra aplicación principal. Entonces esa división es usualmente un poquito difícil de ver al principio, o las primeras vezes que uno está teniendo diferentes problemas en producción. Pero ya que esto se entiende y dejó así como que hace clic, es más fácil debuguear este tipo de aplicaciones.
Los consumidores pueden ser muy complicados o bastante sencillos. En algunas instancias vemos que los consumidores son procesos que crean otros subprocesos. para procesar tareas o pueden ser que los consumida que los consumidores solo se encargan de procesar tareas sin crear su proceso y al es Me enfoqué aquí un poquito o en esta explicación en el concepto de subprocesos, debido a que eso también nos va a dar paralelismo en los consumidores. Esto ya es un poquito más avanzado, pero ahorita lo vamos a ver un ejemplo de cómo se puede implementar esto y para qué pueden ser utilizados.
Pero es algo bastante importante también, porque hay diferentes implementaciones allá afuera de filas de tarea, y hay algunos que si te permiten crear estos consumidores. Que pueden procesar cosas en paralelo, pero hay otros que no. Entonces, eso también depende de cuáles son tus necesidades, puesto que el usar consumidores que pueden procesar cosas en paralelo puede ser algo algo benigno pero puede tan o también usualmente va a atraer más más complejidad en la en el uso de la de la biblioteca que estemos de que estemos usando este algunos proyectos tienen la habilidad de manejar cuántos consumidores también están corriendo de manera dinámica.
Entonces podemos decir que primero nada más queremos correr cuatro consumidores, y de manera dinámica eso puede cambiar a seis, diez o bajar a dos, por ejemplo. La única cosa ahí es que usualmente las variables que son importantes para nosotros, para ver cuántos consumidores tenemos que estar corriendo. no las sabemos desde un principio primero que nada y aparte son muy espe muchas veces son muy específicas a la aplicación Entonces, no siempre podemos solucionar o podemos llegar a nuestros requerimientos, nada más con lo que ofrecen. las las diferentes los diferentes proyectos de los cuales vamos a hablar ahorita
este o las diferentes bibliotecas verdad no no nada más el usarlas Se van a resolver todos nuestros problemas, sino que también muchas veces tenemos que ver qué es lo que está alrededor y cuáles son nuestras necesidades, y a lo mejor implementar unas cosas encima de esto. Ya al tener estas abstracciones alrededor de cada una de estas entidades, es más fácil enfocarnos en nuestros requerimientos y no En lo que es básicamente la comunicación entre todos y cada una de estas de estas entidades, este, entonces vamos a empezar a ver cuáles son las diferentes implementaciones que hay afuera. Vamos a ver cuatro que son de las más populares. Existen mucho más y cada una
son un poquito más diferentes. La más común en hasta cierto punto es Celery. Y esta es de las más comunes, puesto que es de las primeras, de hecho, que empezaron a existir. Y eso es algo bueno, pero también a la vez es algo malo, puesto que Cuando Celery empezó había muchas cosas que no existían ya, no había librerías para que, o bueno, no, por ejemplo, no había Implementaciones ya de un del protocolo AMQP, entonces él tuvo que implementar eso. Entonces, había diferentes detalles que se necesitan para implementar una fila de tareas más robusta. Que no existían de allá afuera, creadas por
en algún otro proyecto. Así que se les los tuvo que implementar. Y el problema de eso es que se convierte en un proyecto un poquito más complicado. Complicado de debugar si hay algún problema, pero si todo corre bien, es bastante estable y no siempre es difícil debuguear si el problema está en las tareas que nosotros estemos corriendo. Pero si el problema está en la intercomunicación de cada una de estas entidades, no siempre es tan sencillo de debuguear. Ese es lo malo, pero lo bueno es que si es bastante robusto y flexible en todo lo que se puede hacer. Entonces, si. Mantenemos en mente la arquitectura básica de la cual estábamos hablando ahorita, estas tres entidades de productor, el mediador y el consumidor.
Entonces vamos a tratar de traducir eso en lo que es código, utilizando cada una de estas bibliotecas de las cuales vamos a hablar o de las cuales estamos hablando. En Celery, por ejemplo, para crear un productor es bastante sencillo. Y usualmente en realidad en todas estas bibliotecas de las cuales estamos viendo. este es bastante sencillo crear un productor pero celery fue creado para Django entonces todo esto Y es definido en la misma aplicación que está corriendo, que es en la aplicación de Django. Entonces, en tu aplicación que tú estás creando ahí
utilizas este este código que tenemos aquí en la en la presentación lo cual hace algo bastante sencillo que es importar un objeto de Celery e inicializarlo Al inicializarlo le dices tú específicamente a qué mediador se va a conectar. En este caso está utilizando una implementación de AMQP, pero. Celery es bastante flexible, entonces puedes usar Redis, también puedes usar Elasticsearch. Creo también, puedes usar diferentes productores, a mí digo, perdón, diferentes mediadores Y después lo que tenemos que hacer es definir una tarea. Entonces, en este ejemplo es una tarea bastante sencilla, nada más suma dos números.
Pero la manera en la cual la definimos es utilizando este decorador que utiliza el objeto que inicializamos primero y luego un atributo que se llama task. Entonces al hacer esto, Celeri crea otro objeto encima de la función que estamos creando y ese es lo que se convierte en el mensaje que vamos a producir. Entonces, como vemos, este es el tipo de abstracciones que las implementaciones de filas de tarea que son que están allá afuera nos dan. y así con estas que son una, dos, tres, cuatro, cinco líneas de código, pues ya creamos un productor que está produciendo Este mensajes para este tipo de tareas en específico que es sumar dos números nada
más. Entonces, algo bastante sencillo, esto es lo que se traduce a un productor. Entonces, es el primer paso. Y aquí ya vimos que no nos tenemos que preocupar de cómo es que el mensaje es creado, cuáles son los diferentes atributos de los mensajes. Y vamos a ver esta tendencia en cada una de estas bibliotecas, en cada una de estas implementaciones, este tipo de abstracciones y de hecho la manera en la cual los productores son definidos es también muy parecido. Ya sea para algo bueno o para algo malo, pero en realidad hay un cierto tipo de constancia en las implementaciones que vamos a ver. entonces una vez que que corremos que esto
que corremos nuestra nuestro nuestra aplicación Django principal esto es lo que lo que se va a correr verdad entonces estamos ya creando la la tarea y definiéndola y y el productor lo único que el que le importa en realidad Es nada más el nombre de la tarea y los argumentos que vamos a mandar, entonces, por ejemplo, una vez que ya creamos esto, de esta manera es como mandamos el mensaje. Agarramos la definición de la tarea y en Celery utilizamos . delay y luego mandamos los atributos. de la tarea en este caso son dos números entonces va a sumar 4 más 4 básicamente aquí
pero lo va a sumar en el productor Entonces cuando hacemos esto, en realidad no corren las cosas en nuestra aplicación Django, sino que lo que hace la biblioteca de celería es que agarra esta información, crea un mensaje y la manda al mediador. hasta ahí eso es todo lo que estamos haciendo con este código y nuevamente esta es la primera biblioteca que estamos viendo pero estos mismas mismos conceptos Son los que vamos a ver este de diferente nada más de maneras un poquito diferente. Entonces, primero estamos nada más en el productor, verdad? Y la un la la bueno, una cosa que tiene, como habíamos dicho, que tiene buenos L es que puedes definir que los
los los consumidores, aquí los vemos del lado derecho. Puede ser nada más uno solo o pueden ser consumidores que nada más procesen una tarea a la vez. O pueden ser. consumidores que procesen múltiples trajes a la vez y al hacer esto este lo pone lo pongo de esta manera puesto que It creates a process that is padding of all the subprocesses, and this process administrates the demands and says to you, entonces existe este es una implementación un poquito un poquito diferente a lo que habíamos dicho pero también es común para para para poder procesar cosas en paralelo. Pero es algo también, es un detalle que
es muy bueno saber cuando estamos trabajando con este tipo de implementaciones. Porque así es más fácil debuguear las cosas, es más fácil saber qué es lo que está sucediendo. Entonces, de esta manera, las cosas que estábamos definiendo en el productor también es definido. Para el consumidor en el mismo lugar, entonces, si regresamos aquí a este código, estamos viendo que estamos definiendo todo esto. En nuestra aplicación Django, este y estamos definiendo a cuál es el mediador en cómo nos vamos a conectar al mediador, cómo vamos a mandar los mensajes, puesto que estamos definiendo nuestra tarea aquí, nuestra función. Y de la misma manera estamos
poniendo el código que está dentro de la función, y eso es lo que va a correr el consumidor. Entonces, todo esto, en realidad, de estas dos partes, el productor y el consumidor Están definidas en el mismo lugar, entonces, eso puede ser un poquito confuso, pero nuevamente es algo que es muy común en las implementaciones que vemos allá afuera. También puede ser bueno, puede ser malo, pero en general es bueno, puesto que así estás seguro que todo lo que necesitas para correr, todas las cosas que importas, todos los Los diferentes paquetes y dependencias van a estar ahí. Entonces, así cuando estás tú escribiendo las cosas, las puedes procesar cuando estás escribiendo el juego, los puedes procesar en tu mente
como si fuera algo sincrónico. cuando en realidad en producción se corren de una manera asincrónica. Entonces eso es lo bueno. Lo malo es que Hay veces que nos puede confundir esto y podemos estar esperando que las cosas se corran en el mismo lugar, pero en realidad tenemos que recordar que aunque las definimos en el mismo lugar, no corren en diferentes lugares. Entonces, esto también es muy muy bueno para tener en mente para cuando estamos escribiendo pruebas para nuestro código. Puesto que en las pruebas también podemos probar las cosas de una manera asincrónica, no tiene que ser asincrónico, puesto que todo lo que hace esto asincrónico En realidad son detalles de la implementación que tienen que ver con un paquete externo, con una dependencia externa.
Entonces, no tenemos que probar nosotros si el mediador está funcionando bien o no. Bueno, entonces estos conceptos me tardé un poquito más en definir cómo Celery trabaja, porque estos conceptos van a ser parecidos con las otras implementaciones que vamos a ver ahorita. Entonces, por ejemplo, tenemos también RQ. RQ es muchísimo más sencillo que Celery. Es más nuevo también, entonces el proyecto en sí es menos complicado. Este, pero es bastante robusto y está implementado específicamente con Redis. Redis implementa un protocolo de publicación y suscripción, PopSap. Entonces Arq utiliza utiliza esto en Redis
como mediador, y así es como implementa toda la fila de trabajos. Y Arq utiliza la misma idea de definir las cosas en el mismo lugar, ¿verdad? Entonces, por ejemplo, nada más que si es un poquito diferente. Entonces, por ejemplo, aquí estamos definiendo una función que va a contar palabras de una de un un este de un string Y el siguiente paso es definir el productor cómo se va a conectar con el mediador. Lo hacemos de esta manera Importamos la biblioteca de Redis y después inicializamos este objeto Q que viene siendo la fila
Entonces aquí la diferencia es que con RQ es un poquito más explícito lo que estamos haciendo, porque aquí ya podemos, ya decimos Q. nq y luego nuestra el nombre de nuestra tarea este y los los los argumentos que vamos a pasar a nuestra tarea Entonces aquí es un poquito más explícito el hecho que estamos usando una fila y el hecho que estamos mandando las cosas a la fila. Con Celery, como quiera, si utilizamos. algo diferente no para mandar el mensaje que algo que se que fue este delay o también podemos utilizar apply a sync es una Es un método que se le agrega a nuestra tarea , pero el hecho que estamos usando una fila o qué tipo de fila es abstraído para nosotros, entonces
de esta manera. Arq lo hace un poquito más explícito. Al final del día estamos haciendo lo mismo, estamos definiendo una tarea aquí en código que es una función de Python. Estamos definiendo qué es lo que se va a hacer en esa tarea, creando un mensaje y mandándola al mediador. Pero se ve un poquito diferente. Entonces tenemos el productor en RQ , lo definimos que se conecta con el mediador y perdón y. Y mandamos las cosas al consumidor. Nuevamente estamos definiendo las dos cosas: qué es lo que va a hacer el consumidor y qué es lo que va a hacer el productor en el mismo lugar, y esto facilita un poquito las cosas. Otra implementación que podemos ver que también es
muy popular es Huey. Es también la manera de usarlo, es también bastante sencilla, pero es un poquito más robusta que RQ, porque Hue también trabaja con RuEDIS, pero también trabaja con otras bases de datos como SQLite. Este o inclusive puedes crear filas en memoria, entonces la manera en la cual es más flexible con su implementación o con qué tipos de mediadores puede hablar. Eso lo bueno de ser flexible en esa manera es que puedes empezar con filas en memoria, lo puedes hacer con Hivo y con Celery también. Y si necesitas ya un poquito más de poder, te puedes pasar a Redis. Y si necesitas un poquito más, te puedes pasar a otro.
Y es más sencillo hacer este tipo de cosas. La implementación nuevamente es bastante parecida, entonces por ejemplo aquí creamos un objeto que empieza con RedisHue y es específico para Redis. Este y estas son nuestras diferentes tareas. Ahora Hue nuevamente utiliza un decorador. RQ no utiliza un decorador, pero Hue EC. En el decorador podemos definir diferentes cosas que necesitamos en la tarea, como cuántas veces se va a volver a intentar la tarea o si tiene algún delay, algún retraso o algo por el estilo, lo cual también se puede hacer con Seller y con Arq. Entonces aquí estamos definiendo nuevamente en el mismo lugar
qué es lo que el productor va a hacer y qué es lo que el consumidor va a hacer. Y la diferencia es cómo mandamos este mensaje. Al mandar este mensaje en Huey, lo único que hacemos es importar la función que ya habíamos definido. Y ejecutarla como si fuera una función normal, y esto crea el mensaje que es mandado al mediador y procesado por el consumidor eventualmente. como podemos ver aquí lo cual al al correr esta función no tenemos este un un valor Regular de no, no nos regresa un valor regular, sino que nos regresa este objeto que es un resultado, y este, y eso es lo que pasa después de mandar un mensaje Entonces , la otra cosa también que tiene
Huey en diferencia con RQ es que también los consumidores pueden procesar tareas en paralelo, si eso es lo que necesitamos. Otra implementación muy común también es Dramatic. Y Dramatic es un poquito más parecida a Celery, aunque en realidad es basada en otros proyectos. Este, pero es igual de robusto que A Celery. Y su su API es un poquito. diferente es si trata de ser más sencillo que celery porque en celery hay muchas cosas que al que mientras lo empiezas a usar puede ser un poquito Más complicado la manera en la cual mandas mensajes y la manera en la cual mandas estas tareas
al mediador en Dramatic Todo esta abstracción suele ser un poquito más sencillo, y pero más que nada es porque Dramatic utiliza varios valores por default que al que Son buenos para la mayoría de los casos, entonces nuevamente también Dramatic es bastante flexible y si necesitas configurar las cosas de una manera más granular, también lo puedes hacer con Dromatic. Y es cuando las cosas se tornan un poquito más complicadas, pero eso es verdad para cualquiera de los proyectos que hemos visto. En realidad, no hay ninguna manera de De salirse de esas y necesitas que tu mediador haga cosas muy específicas, por eso también es bueno
cuando tenemos ciertos tipos de requerimientos, tratar de hacerlo Afuera de estas implementaciones y tratar de hacerlo lo más sencillo que se pueda. Este Romaric también opta por un decorador. La diferencia es que Dromaric le llama actores a cada uno de estos de estas tareas que se van a correr. Este y la manera en la cual mandamos el mensaje también es un poquito más explícito, es utilizando el método de send. Entonces como podemos ver aquí utilizamos . send y mandamos los argumentos que son que van a ser para nuestra tarea Y lo que lo que regrese es en realidad el mensaje que se crea. Este mensaje ya fue mandado al mediador y ya eventualmente
un consumidor lo va a agarrar y va a procesar y va a hacer lo que está definido en la función. entonces como vemos la estos son los cuatro proyectos que más he visto yo que se utilizan en producción este Yo principalmente he usado Celery y Dramatic, esos dos. No tengo tanta experiencia con RQ y con Huey. Pero los proyectos que he visto que los utilizan también parece ser bastante robusto y también son utilizados casi de las mismas maneras. Este entonces, como podemos ver, los conceptos de la implementación son muy parecidos. Entonces, una vez que ya Eso es la otra cosa buena también que tenemos en el ecosistema de Python, es que una vez que ya hacemos clic con
estos conceptos, Es fácil también cambiarnos de implementación si alguna API nos gusta más que alguna otra o algo por el estilo. Entonces vamos a ver ahora, nos vamos a pasar a lo que son algunas de las integraciones comunes de filas de trabajo en aplicaciones. Ya vimos cuál es el concepto y cuáles son las diferentes partes de una fila de trabajo. Ahora rápidamente vamos a ver más o menos Cuáles son las diferentes maneras en las cuales la podemos integrar. Una ya habíamos dicho que se integran principalmente para tareas que se tardan mucho tiempo y no queremos procesarlas. En el mismo ciclo
HTTP de nuestra aplicación principal, entonces en eso usualmente recae mandar correos, es eso lo más lo más típico que vemos in ya sea artículos en internet o cosas por el estilo siempre son cosas como podemos mandar artículos usando una fila de tareas Pero otro tipo de aplicaciones que es más que nada de lo que quiero hablar aquí, algunas otras ideas que podemos utilizar por las que podemos utilizar esto. Es por ejemplo el implementar procesos que contienen muchos pasos, pero donde cada uno de los pasos se puede correr de nuevo, se puede intentar de nuevo. O, ya sea que podamos recuperar el proceso desde un paso muy específico.
Entonces, por ejemplo, tenemos lo que viene siendo nuestro productor, nuestra aplicación principal. Y si estamos hablando, por ejemplo, de alguna tienda en línea donde deja que el usuario cree varios artículos al mismo tiempo. Entonces la aplicación va a tomar todos los datos de cada uno de los artículos que el usuario quiere crear y crear diferentes tareas para cada uno de los artículos que se van a crear. Entonces las manda y las crea y la y las procesa en paralelo. Este al último, al terminar de procesarlas , Se encuentra a lo mejor alguna alguna otra aplicación, algún otro proceso del otro lado que le manda una notificación al usuario donde dice
tus artículos ya han sido creados y a lo mejor les dice este este estos artículos no puedo no pudimos crear o algún o hubieron estos errores o no entonces esta es una manera en la cual al usar una fila de trabajos podemos básicamente digo fácilmente recuperar este nuestro lugar en en la En el proceso de esta tarea, que en realidad es una tarea compuesta por muchas otras más pequeñas. Otra aplicación es para desacoplar procesos. Por ejemplo, ya sea porque a lo mejor tenemos que procesar cosas de una manera más segura. Entonces, por ejemplo, cuando estamos procesando pagos. Hay muchas veces que queremos que el código que esté procesando pagos
o los recursos que necesitamos para procesar pagos. tengan un acceso más restringido o que corran de alguna manera muy específica pero no queremos que eso sea tan evidente o que no sea este tan fácil acceder a todas esas cosas entonces podemos crear nuestra capa de seguridad ahí este pero al mismo tiempo utilizar una fila de trabajos digo de tareas para este para manejar esta comunicación y así aunque tengamos esta seguridad alrededor de eso no estamos exponiendo nada entonces por ejemplo del lado izquierdo aquí podemos comenzar Con diferentes aplicaciones a lo mejor que tenemos y pensamos en un sistema un poquito más complicado, podríamos tener diferentes aplicaciones aquí corriendo al mismo tiempo.
Los cuales se tienen que comunicar con otra aplicación, la cual está asegurada de una de una manera diferente, tiene un firewall más restringido o cosas por el estilo. Entonces, la manera en la cual comunicamos estas dos partes lo podemos hacer por medio de la fila de trabajos de un mediador. Entonces, básicamente es una implementación de un mediador, pero de una manera un poquito diferente. Y así sabemos que reducimos de cuántas maneras se puede acceder nuestra aplicación del lado derecho que tiene que ser un poquito más segura. Entonces podemos restringir el acceso a ella. Sin ningún problema, y así estamos desacoplando estos procesos de una manera más eficiente, y así
si tenemos algún problema, podemos ya auditar. Todos los datos que están pasando, puesto que ya sabemos exactamente por dónde entran. Por último, otro uso interesante de las filas es el de el de crear un paso intermedio. Para la migración entre un monolito y un sistema distribuido o basado en eventos o algo por este. Entonces, como habíamos dicho, de mediadores también se pueden utilizar cosas como Kafka. Los cuales son utilizadas en sistemas más distribuidos, entonces aquí por ejemplo podemos tener un monolito que del lado izquierdo, en vez de pensar esto como diferentes aplicaciones podemos pensarlo como diferentes clases o diferentes módulos en Django por ejemplo podría ser diferentes apps de Django que
tenemos ahí definidos los cuales se comunican entonces en vez de comunicarse nada más este entre ellos al importar Alguna clase o alguna interfaz, lo que podemos hacer es comunicarnos por medio de mensajes y por medio de un mediador. Entonces ponemos los mensajes en el mediador y estos mensajes van a ser procesados por el mismo código pero de algún otro alguna otra aplicación que tenemos en nuestro en nuestro mismo proceso de Django entonces De esta manera, como lo habíamos visto, tenemos también definidos el productor y el consumidor en el mismo lugar. Pero podemos empezar a cambiar el código para definir
los límites de cada uno de estos un poquito más y así que sea más sencillo el movernos o migrarnos a una aplicación más distribuida. Este, entonces, estas son tres ideas de las cuales quería hablar. Que no he visto tantos artículos en línea o no he visto tanta información en línea. que expliquen cómo cómo este cómo son más o menos la idea. Sin embargo, sí he visto que esto se utiliza en producción bastante Entonces las filas de tarea no son nada más para hacer procesos que tarden mucho tiempo para procesarlos en algún otro lado, sino que también podemos ser un poquito más creativos en la manera en la cual lo hacemos. utilizamos estas filas de tareas
puesto que lo que estamos haciendo es básicamente desacoplando la manera en la cual se procesan cosas Esto es más que nada de lo que quería hablar : de las diferentes maneras en las cuales se pueden utilizar las filas de tarea y el concepto básico. De las filas de tarea para que sea más sencillo utilizarlas, porque es muy difícil utilizar algo cuando no se tiene el concepto y empiezan a surgir problemas y luego es más difícil debuguearlas y hacer todo esto. Entonces Espero que esta aplicación les haya dado algunas ideas de cómo pueden utilizar las filas de tarea y espero que haya sido bastante claro. Muchas gracias y buenas noches.
Una fila de tareas permite procesar trabajo de forma asíncrona, fuera del ciclo de solicitud y respuesta HTTP. Así, tareas lentas como generar reportes, enviar notificaciones o auditar datos no obligan al usuario a esperar.
Discussed at 0:31La arquitectura tiene un productor, que crea y envía mensajes; un mediador o broker, que los recibe y distribuye; y consumidores o workers, que escuchan el broker y ejecutan las tareas.
Discussed at 4:18Entre las opciones se mencionan RabbitMQ y ZeroMQ mediante AMQP, Amazon SQS, Redis, PostgreSQL y Kafka, cada una con distintos niveles de robustez, rapidez y especialización. La recomendación es comenzar con una solución básica y cambiar de mediador cuando los requisitos de volumen, memoria, disco o red estén claros.
Discussed at 13:21Los consumidores son procesos separados que permanecen conectados al mediador, toman las tareas y las procesan fuera del ciclo principal de la aplicación. Es importante recordar esta separación al depurar, porque definir productor y consumidor en el mismo código no significa que se ejecuten en el mismo proceso o lugar.
Discussed at 15:09Celery es muy robusto y flexible, pero también más complejo; RQ es más sencillo y está basado en Redis; Huey es flexible y puede usar Redis, SQLite o memoria; y Dramatiq ofrece una API sencilla con buenos valores predeterminados, aunque también permite configuraciones avanzadas.
Discussed at 20:35Se define una función como tarea mediante el decorador de Celery y luego se invoca, por ejemplo, con `.delay()` y sus argumentos. Celery crea el mensaje y lo envía al mediador; la aplicación Django no ejecuta el trabajo directamente en ese momento.
Discussed at 25:17También sirven para dividir procesos de varios pasos y reintentarlos, desacoplar componentes que requieren distintos niveles de seguridad y crear una capa intermedia durante la migración de un monolito hacia un sistema distribuido o basado en eventos.
Discussed at 39:07Note: We understand that names change, people change, and bodies change. We respect each individual's journey and privacy. If you have any concerns about a video or need us to remove content, please don't hesitate to contact us. We will handle your request with care and promptly address any issues.
Published July 15, 2026
Published July 15, 2026
Published July 15, 2026
Published July 15, 2026
Published July 15, 2026
Published July 14, 2026