fedorthinks

Curso exprés · No. 18

Cuando una parte de un sistema necesita que otra haga algo, la forma sencilla es llamarla y esperar una respuesta. La forma poderosa es dejar un mensaje en una queue y seguir adelante, dejando que el otro lado lo recoja cuando esté listo. Ese único cambio — de llamar y esperar a enviar un mensaje y continuar — es como los sistemas se mantienen rápidos, sobreviven a los fallos y escalan.

21 conceptos · un diagrama para cada uno · resumen al final

§ 01

Para entender por qué existen las queues, primero hay que sentir el dolor de la alternativa sencilla: un servicio que llama a otro y lo espera. Funciona hasta el momento en que de verdad importa.

El mapa: 21 conceptos en seis grupos

Un mapa de metro: primero ves las líneas enteras, luego recorres estación por estación.

Primero el problema — por qué una llamada directa te falla. Después un capítulo por grupo: la queue (la idea en sí), los roles (quién escribe, quién lee, quién guarda), comandos y eventos (dos tipos de mensaje), los beneficios (por qué pagas) y las partes difíciles (qué se rompe). El último capítulo trata de cuándo usar una queue y cuándo no, e incluye un mapa de relaciones y un resumen.

The direct-call problemSynchronous callFailure propagationBackground workThe queueMessage + queueTemporal decouplingAsynchronousRolesProducer / consumerBrokerCompeting consumersCommands & eventsCommandEventPub/Sub · fan-outEvent-drivenPayoffsResilienceLoad levelingIndependent scalingHard partsIdempotencyOrderingEventual consistencyDead-letter queue
Seis grupos de conceptos — los capítulos 1–6 los siguen. El capítulo 7 trata de elegir, más el resumen.

Cómo leer cada concepto

Un pasaporte: los mismos campos para todos, así es fácil compararlos.

Cada concepto a partir de aquí tiene la misma forma: su nombre en inglés (apréndelo — es la palabra que verás en la documentación de los brokers y en las entrevistas), una imagen de la vida cotidiana, un diagrama y una ficha: problema, idea, ejemplo, coste y cómo se relaciona con otros conceptos. Al final: un mapa de relaciones y un resumen.

Synchronous Call — una llamada directa ata dos servicios entre sí

Telefonear a alguien y quedarte en la línea hasta que termine la tarea — no puedes colgar, no puedes hacer nada más, y si no contesta, te quedas atascado.

La forma obvia de que el servicio A consiga que el servicio B haga algo es una synchronous call: A pregunta y luego espera, conteniéndolo todo hasta que B responde. Esto los acopla estrechamente — la velocidad de A queda ahora secuestrada por la velocidad de B, y A no puede continuar hasta que B termine. Para una respuesta rápida eso está bien. Para un trabajo lento o pesado, A pasa el tiempo congelado, esperando a otro.

Service AService Bworkblocked · waiting on BworkB does the slow workcallanswerthe caller is frozen until the callee answers
A llamó a B y se quedó quieto: todo el trabajo lento de B es tiempo que A pasa bloqueado.
ConceptSynchronous Call· request–response (petición–respuesta)
Problema
El que llama queda congelado hasta que el llamado responde.
Idea
Preguntar, esperar la respuesta y seguir. La forma más simple de hablar.
Ejemplo

El servicio de pedidos llama por HTTP al servicio de precios y espera el precio antes de mostrar el carrito.

Coste

Acoplamiento estrecho: la velocidad y la disponibilidad de A dependen de B.

Relaciones

Su dolor lo cura una Message Queue; para respuestas instantáneas sigue siendo la mejor opción.

Failure Propagation — si el llamado está caído, el que llama se rompe

Llamar al almacén para confirmar un pedido y, como nadie contesta, negarte a aceptar cualquier pedido nuevo — una puerta cerrada bloquea toda la tienda.

El problema más profundo es el fallo. Si B está caído o sobrecargado cuando A llama, la petición de A también falla — el fallo se propaga directamente hacia arriba en la cadena. Un solo servicio lento o roto puede paralizar todo lo que depende de él, y un pico de tráfico hacia B arrastra a A consigo. El acoplamiento estrecho significa que la debilidad se extiende, y el sistema solo está tan disponible como su parte más frágil.

CheckoutcallerOrderscaller + calleeWarehousedown / overloadedcallscalls✗ fails✗ failsone broken service stalls everything above it
El almacén está caído — y el error sube: fallan los pedidos, falla el pago.
ConceptFailure Propagation· cascading failure (fallo en cascada)
Problema

El fallo de un servicio se convierte en el fallo de todos los que lo llaman.

Idea
Una cadena síncrona solo es tan disponible como su eslabón más débil.
Ejemplo

El almacén no responde → los pedidos dan error → el pago deja de funcionar.

Coste
Un pico de tráfico hacia un servicio arrastra todo lo que tiene encima.
Relaciones

Se cura con un búfer: una Message Queue da Resilience — un fallo se convierte en un retraso.

Background Work — cierto trabajo no debería bloquear al usuario

En una caja, pagas y te vas con tu recibo — no te quedas en la caja mientras empaquetan, envían y te mandan un correo. Las partes lentas ocurren después de que te marchas.

Mucho trabajo no necesita terminar antes de que el usuario reciba una respuesta — enviar el correo de confirmación, generar la factura, redimensionar la foto. Esto es background work (trabajo en segundo plano). Hacer que el usuario espere todo eso es lento e inútil. Quieres aceptar la petición, responder rápido y dejar que las partes lentas ocurran después. Una llamada directa no puede hacer eso; obliga a todos a esperar por todo.

UserAPIaccept + replyfast replyQueueafter the replySend emailMake invoiceResize photothe user never waits for the slow parts
La API responde de inmediato; el correo, la factura y la foto se hacen después — desde una queue.
ConceptBackground Work· background jobs (tareas en segundo plano)
Problema
El usuario espera trabajo del que su respuesta no depende.
Idea
Aceptar la petición, responder rápido y hacer las partes lentas después.
Ejemplo

El pago pasó — recibo ya; el correo, la factura y el redimensionado de la foto, en segundo plano.

Coste
El resultado del trabajo en segundo plano no aparece al instante.
Relaciones
Se hace con una Message Queue y Asynchronous Processing.

Una llamada directa acopla dos servicios en el tiempo: el que llama espera y hereda la lentitud y los fallos del llamado. Para trabajo lento o no urgente, eso es una trampa.

§ 02

La solución es dejar de llamar y empezar a enviar mensajes. Una queue es el búfer del medio que permite a un lado dejar trabajo y al otro recogerlo — desacoplándolos en el tiempo.

Message Queue — deja el mensaje y sigue adelante

Dejar un mensaje de voz en lugar de esperar al teléfono: dices lo que necesitas, cuelgas y sigues con tu día — lo atenderán cuando puedan.

En lugar de llamar a B y esperar, A escribe un mensaje que describe el trabajo y lo deja en una queue — una fila donde los mensajes esperan a ser procesados. A queda libre para continuar de inmediato; no le importa cuándo llegue B a ello. El mensaje es un pequeño paquete de «esto es lo que hay que hacer», entregado en lugar de ejecutado en el acto. Ese traspaso es toda la idea.

Service AsendermsgmsgmsgmsgService Breceiverqueuedrops & moves onmessages wait in linepicks up when ready{ "type": "SendEmail", "orderId": 42 }
A deja un mensaje y sigue; los mensajes esperan en la queue; B recoge uno cuando está listo. Abajo — cómo podría verse un mensaje en sí.
PatternMessage Queue· queue (cola)
Problema
Una llamada directa mantiene al emisor en la línea.
Idea

Describir el trabajo como un mensaje y ponerlo en una queue; el receptor lo recoge por su cuenta.

Ejemplo

En lugar de llamar al servicio de correo — un mensaje SendEmail con el número de pedido, en una queue.

Coste
Una pieza móvil nueva que hay que ejecutar y entender.
Relaciones

Da Temporal Decoupling; la guarda un Broker; la leen los Consumers.

Temporal Decoupling — la queue es un búfer en el tiempo

Una bandeja de entrada en un escritorio: el trabajo se acumula en ella y se atiende con calma, así que una avalancha repentina de papeles no abruma a la persona — solo hace la bandeja más alta por un rato.

La queue se sitúa entre los dos lados como un búfer, guardando los mensajes hasta que se procesan. Esto los desacopla en el tiempo (temporal decoupling): el emisor y el receptor ya no tienen que ser rápidos, estar disponibles ni siquiera estar en marcha en el mismo momento. El trabajo producido en ráfagas puede consumirse de forma constante. La queue absorbe la diferencia entre la velocidad a la que llega el trabajo y la velocidad a la que se puede hacer.

arrivals: burstyQueuebufferprocessing: steadysender and receiver no longer need to run at the same time
A la izquierda el trabajo llega a ráfagas, a la derecha se procesa de forma constante. La queue del medio absorbe la diferencia.
ConceptTemporal Decoupling· buffer in time (búfer en el tiempo)
Problema
Ambos lados deben estar vivos y ser rápidos en el mismo momento.
Idea

Un búfer entre ellos: emisor y receptor trabajan cada uno a su propio tiempo.

Ejemplo

Una ráfaga de pedidos se acumula en la queue y se procesa a un ritmo constante.

Coste
El trabajo puede esperar en la queue — el resultado no es instantáneo.
Relaciones
La base de Resilience y Load Leveling.

Asynchronous Processing — no esperar el resultado

Enviar una carta en lugar de mantener una conversación — la mandas y sigues con lo tuyo, confiando en que la leerán y actuarán después, sin que tú estés allí.

Esto es trabajo asíncrono: el emisor no espera el resultado. Lanza el mensaje y continúa, y el resultado ocurre después, por otra vía. Renuncias a la respuesta instantánea de una llamada directa, y a cambio dejas de estar bloqueado. Para todo lo que no necesita una respuesta inmediata, ese trato es la base de los sistemas rápidos y resilientes.

syncAblocked · waiting for resultA continuesasyncAA keeps working — never blockedworkerdoes the work latermessageasync: give up the instant answer, stop being blocked
Arriba, síncrono: A se queda esperando. Abajo, asíncrono: A envía un mensaje y sigue trabajando, y un worker hace la tarea después.
ConceptAsynchronous Processing· async (asíncrono)
Problema
Esperar un resultado que no necesitas ahora mismo.
Idea
Enviar el mensaje y seguir; el resultado ocurre después, por otra vía.
Ejemplo

Un informe se genera en segundo plano; el usuario lo recibe cuando está listo.

Coste

Sin respuesta instantánea; es más difícil seguir la pista de lo que pasó.

Relaciones
Lo opuesto a Synchronous Call; trae Eventual Consistency.

Una queue es un búfer entre emisor y receptor. Deja un mensaje y sigue adelante — el trabajo queda desacoplado en el tiempo, hecho de forma asíncrona cuando el otro lado está listo.

§ 03

Tres roles hacen funcionar una queue, y ponerles nombre aclara la mayor parte de la jerga. Un lado crea mensajes, otro los atiende, y algo en el medio los guarda con seguridad.

Producer / Consumer — un lado crea trabajo, el otro lo hace

Una cocina: los camareros cuelgan comandas y los cocineros las van descolgando una a una para prepararlas. Los dos lados nunca hablan directamente — el riel de comandas es toda la interfaz.

El lado que crea mensajes es el producer (o publisher); el lado que los procesa es el consumer (o worker). El producer deja una comanda; el consumer recoge una, hace el trabajo y pasa a la siguiente. No se conocen ni se esperan — solo conocen la queue. Esta separación limpia permite construir, escalar y cambiar cada lado por su cuenta.

Web appproducerMobile APIproducerQueuethe ticket railWorker 1consumerWorker 2consumerproducers and consumers never talk directly — they only know the queue
Los producers escriben en la queue, los consumers leen de ella. Nunca se encuentran directamente.
TermProducer / Consumer· publisher / worker
Qué es

El producer crea mensajes; el consumer los toma y hace el trabajo.

Idea
Los lados conocen solo la queue, no se conocen entre sí.
Ejemplo

La app web deja «redimensiona esta foto»; un worker toma el mensaje y la redimensiona.

Trampa
El producer no sabe cuándo, ni quién, hará el trabajo.
Relaciones

Un Broker se sitúa entre ellos; muchos consumers en una queue son Competing Consumers.

Message Broker — el broker guarda los mensajes con seguridad

Una oficina de correos entre remitente y destinatario: toma tu carta, la guarda y la conserva hasta que el destinatario la recoge — así no se pierde nada si no está.

En el medio está el message broker — software como RabbitMQ o Apache Kafka que recibe mensajes, los almacena de forma fiable y los entrega a los consumers. Es la oficina de correos del sistema. Su fiabilidad es el punto clave: aunque todos los consumers estén caídos, el broker guarda los mensajes hasta que alguien esté listo para procesarlos, así que el trabajo queda aparcado, no perdido.

ProducerBrokerRabbitMQ · Kafkamsgmsgmsgmsgstored durablyConsumerdownevery consumer down? the messages stay parked, not lost
El broker recibe y almacena los mensajes de forma fiable. El consumer está caído — los mensajes esperan en lugar de desaparecer.
ToolMessage Broker· broker
Problema

Los mensajes necesitan un lugar seguro donde vivir hasta que alguien los tome.

Idea

Un software dedicado recibe, almacena y entrega mensajes — la oficina de correos del sistema.

Ejemplo
RabbitMQ, Apache Kafka.
Coste
Un sistema más que ejecutar y mantener.
Relaciones

Guarda la Message Queue; Resilience se apoya en su fiabilidad.

Competing Consumers — añade consumers para ir más rápido

Cuando las comandas se acumulan, pones más cocineros en la línea — cada uno toma la siguiente comanda y el atraso se despeja más rápido sin cambiar cómo entran los pedidos.

Como los consumers simplemente toman el siguiente mensaje, puedes ejecutar muchos en paralelo sobre una sola queue — este es el patrón Competing Consumers. ¿Crece el atraso? Añade más workers y se reparten la carga automáticamente — cada uno agarra un mensaje distinto. Esta es una de las grandes fortalezas de una queue: escalas la parte lenta de forma independiente añadiendo consumers, sin tocar a los producers ni la queue.

Queuem1 · m2 · m3 · m4 …Worker 1takes m1Worker 2takes m2Worker 3just added · takes m3backlog growing? add workers — they share the queue automatically
Tres workers en una queue: cada uno toma su propio mensaje. Añade un tercero — el atraso se derrite más rápido.
PatternCompeting Consumers· worker pool (grupo de workers)
Problema
Un solo worker no da abasto; el atraso crece.
Idea
Varios consumers leen una queue; cada mensaje va a uno de ellos.
Ejemplo

Antes de una rebaja — de dos workers de redimensionado de fotos a diez.

Coste
El procesamiento en paralelo rompe el orden — ver Message Ordering.
Relaciones

La base de Independent Scaling; funciona con mensajes Command.

Los producers crean mensajes, los consumers los procesan y un broker los guarda con seguridad en el medio. ¿Necesitas más rendimiento? Añade consumers — se reparten la queue automáticamente.

§ 04

Un mensaje puede ser dos cosas muy distintas: una orden de hacer algo, o un anuncio de que algo ocurrió. La segunda cambia en silencio cómo diseñas sistemas enteros.

Command — un comando le dice a un worker que haga una tarea

Una orden de trabajo entregada a un departamento concreto: «redimensiona esta imagen». Nombra la tarea, espera que exactamente un equipo la haga, y ahí termina todo.

Un mensaje command es una instrucción directa dirigida a un consumer: «envía este correo», «procesa este pago». Es la queue usada como lista de tareas — el producer sabe qué debe ocurrir y entrega la tarea para que se haga una vez, por quien la tome. Este es el uso más simple de una queue: delegar trabajo concreto para hacerlo más tarde, exactamente una vez.

CheckoutproducerSendEmailEmail workerthe one consumercommand = “do this”a to-do item: done once, by whoever pulls it
El comando SendEmail: «haz esto». Exactamente un consumer lo toma.
TermCommand· command message (mensaje de comando)
Qué es
Un mensaje-orden: «haz esto». Se nombra con un verbo.
Cómo funciona
El producer sabe qué debe ocurrir; un consumer hace la tarea.
Ejemplo
SendEmail, ProcessPayment, ResizeImage.
Trampa

El producer sigue sabiendo qué trabajo hace falta — queda algo de acoplamiento.

Relaciones

Lo opuesto a Event; a menudo lo despachan Competing Consumers.

Event — un evento anuncia que algo ocurrió

Un anuncio para toda la empresa en un tablón: «acaba de registrarse un nuevo cliente». No le dice a nadie qué hacer — quien le interese reacciona a su manera.

Un event es distinto: enuncia un hecho del pasado — «pedido realizado», «usuario registrado» — sin decir quién debe hacer qué. El producer solo lo anuncia y no sabe ni le importa quién escucha. Quizá nadie reaccione; quizá cinco servicios lo hagan. Esto invierte la relación: en lugar de ordenar a un worker concreto, difundes que algo es cierto y dejas que los interesados decidan.

OrdersproducerOrderPlacedevent = “this happened”listener?listener?listener?the producer doesn't know who listens —maybe nobody, maybe five services
El evento OrderPlaced: «esto ocurrió». El producer no sabe quién escucha.
TermEvent· event message (mensaje de evento)
Qué es
Un hecho del pasado: «esto ocurrió». Se nombra en pasado.
Cómo funciona

El producer lo anuncia y no sabe quién escucha: cero, uno o cinco servicios.

Ejemplo
OrderPlaced, UserRegistered.
Trampa

Es más difícil ver qué pasará al final — las reacciones están repartidas entre servicios.

Relaciones

Lo opuesto a Command; se entrega vía Pub/Sub; la base de Event-driven.

Publish/Subscribe — un evento, muchas reacciones

Un periódico impreso una vez y entregado a cada suscriptor, y cada uno lo lee por sus propias razones — aficionado al deporte, inversor, fan de los crucigramas — del mismo ejemplar.

Este modelo de difusión es publish/subscribe (pub/sub): un producer publica un evento en un topic, y cada consumer interesado se suscribe y recibe su propia copia. Un solo evento «pedido realizado» puede activar a la vez el servicio de correo, el de analítica y el de envíos — esto es fan-out. El publicador ni siquiera sabe que existen. Se pueden añadir nuevas reacciones más tarde sin tocar al publicador.

OrderspublisherTopicorder.placedEmail serviceown copyAnalyticsown copyShippingown copyfan-outone event, many reactions — the publisher doesn't know they exist
Un evento en un topic — y cada suscriptor recibe su propia copia: eso es fan-out.
PatternPublish/Subscribe· pub/sub, topic, fan-out
Problema

Un evento le importa a muchos servicios, y la lista no deja de crecer.

Idea

Publicar en un topic; cada suscriptor recibe su propia copia (fan-out).

Ejemplo
«Pedido realizado» → correo, analítica y envíos reaccionan a la vez.
Coste

Cada copia se procesa por separado; la cadena completa de reacciones es difícil de ver.

Relaciones

Entrega Events; Event-driven Architecture se construye sobre él.

Event-driven Architecture — los eventos desacoplan quién conoce a quién

Añadir un suscriptor nuevo al periódico no cambia nada en cómo se escribe el periódico — el publicador nunca necesita saber quién lee.

Este es el poder profundo del diseño event-driven: el producer de un evento queda totalmente desacoplado de todos los que reaccionan a él. Para añadir una función nueva que responda a «pedido realizado», solo suscribes un consumer nuevo — sin cambiar el servicio de pedidos. Los sistemas construidos así crecen añadiendo oyentes, no editando lo que se escucha. Así evolucionan los sistemas grandes sin que todo dependa de todo.

Order servicenever changesorder.placedEmailAnalyticsShippingLoyalty pointsnew featureadd a feature by adding a listener — not by editing the publisher
Una función nueva es un suscriptor nuevo. El servicio de pedidos no cambia.
PatternEvent-driven Architecture· EDA
Problema
Cada función nueva obliga a editar el servicio donde «ocurre todo».
Idea

Los servicios anuncian eventos; las funciones se añaden como oyentes nuevos.

Ejemplo

Dar puntos de fidelidad por pedido — suscribir un servicio nuevo a «pedido realizado».

Coste

Eventual Consistency, y una petición que salta entre mensajes es más difícil de depurar.

Relaciones

Construida sobre Event y Pub/Sub; da Independent Scaling.

Un command le dice a un consumer que haga una tarea. Un event anuncia un hecho y deja que cualquiera reaccione — y pub/sub reparte un evento a muchos, desacoplando quién conoce a quién.

§ 05

Las queues añaden piezas móviles, así que tienen que ganárselo. Lo hacen comprando tres cosas difíciles de conseguir de otra forma: resiliencia, manejo suave de picos y escalado independiente.

Resilience — un consumer caído solo retrasa el trabajo

Si la cocina cierra una hora, las comandas simplemente esperan en el riel — cuando reabre, los cocineros despachan el atraso. No se pierde ningún pedido.

Como el broker guarda los mensajes, que un consumer se caiga no pierde trabajo — los mensajes esperan hasta que vuelva y entonces se procesan. Compáralo con una llamada directa, donde un servicio caído significa un fallo rotundo. La queue convierte «el servicio está caído» de un error duro en un retraso temporal. Esta resilience — el trabajo sobrevive a un fallo y se reanuda — suele ser la razón más importante por la que los equipos recurren a una queue.

direct callService AService Bdown✗ hard errorrequest failswith a queueService AQueuework parkedService Bdown → backa crash becomes a delay, not a lost order
Arriba: B está caído — la petición falla. Abajo: B está caído — el trabajo espera en la queue y se reanuda cuando B vuelve.
ConceptResilience· fault tolerance (tolerancia a fallos)
Problema

Con una llamada directa, un servicio caído significa un error para todos.

Idea
El broker guarda los mensajes; un fallo se convierte en un retraso.
Ejemplo

El worker de correo se cae una hora — los correos esperan en la queue y salen tras el reinicio.

Coste
Mientras el consumer está caído, el trabajo se acumula y se hace tarde.
Relaciones

Cura Failure Propagation; se apoya en la fiabilidad del Broker.

Load Leveling — absorbe los picos

Un embalse entre una crecida repentina y un pueblo: la oleada entra en el embalse, que suelta el agua a un ritmo constante y seguro río abajo.

Cuando llega de golpe una avalancha de peticiones — una rebaja, un momento viral — una queue te permite nivelar la carga: el pico llena la queue y los consumers la vacían a su propio ritmo constante. El sistema lento de más abajo nunca ve el pico, solo un flujo manejable y parejo. A la presión que genera el atraso se la llama backpressure. Sin una queue, el mismo pico golpearía directamente al sistema y probablemente lo derribaría.

requests in: a spikeQueuebacklogbackpressureconsumers drain: steadythe downstream system never sees the spike
Un pico de peticiones llena la queue, y los consumers la vacían de forma constante. El sistema de más abajo nunca ve el pico.
PatternQueue-Based Load Leveling· load leveling, backpressure
Problema

Un pico de tráfico golpea directamente a un sistema lento y lo derriba.

Idea
El pico llena la queue; los consumers la despachan a su propio ritmo.
Ejemplo

Una rebaja: miles de pedidos por minuto se procesan como un flujo constante.

Coste

El atraso crece y el trabajo se hace tarde (backpressure) — vigila la longitud de la queue.

Relaciones

Se apoya en Temporal Decoupling; los Competing Consumers despejan el atraso.

Independent Scaling — escala y evoluciona cada lado por su cuenta

Puedes contratar más cocineros, cambiar el equipo de la cocina o añadir una estación nueva — todo sin cambiar cómo toman los pedidos los camareros, porque solo tocan el riel de comandas.

El desacoplamiento significa que cada lado puede cambiar de forma independiente (independent scaling). Sube o baja los consumers según la demanda; reescribe un consumer en otro lenguaje; añade un consumer nuevo que reaccione a eventos existentes — todo sin tocar a los producers. La queue es una costura estable entre las partes del sistema, y las costuras estables son lo que permite que un sistema grande crezca y cambie por piezas en lugar de todo a la vez.

ProducersuntouchedQueuestable seamScale workers 2 → 20Rewrite a worker in GoAdd a new consumer
La queue es una costura estable. A la derecha puedes escalar, reescribir y añadir — nada a la izquierda cambia.
ConceptIndependent Scaling· independent scaling and evolution (escalado y evolución independientes)
Problema
Cambiar una parte obliga a tocarlas todas.
Idea
La queue es una costura estable; cada lado cambia por su cuenta.
Ejemplo

Un worker se reescribe en otro lenguaje — los producers ni se enteran.

Coste
El formato del mensaje se vuelve un contrato — cámbialo con cuidado.
Relaciones

Lo entregan Competing Consumers y Event-driven Architecture.

Las queues compran resiliencia (el trabajo sobrevive a una caída), load leveling (los picos se absorben) y escalado independiente — beneficios que una llamada directa simplemente no puede darte.

§ 06

La mensajería asíncrona resuelve problemas reales y crea otros nuevos. Ninguno es un obstáculo insalvable, pero fingir que no existen es como los sistemas con queues acaban con errores sutiles y desesperantes.

At-least-once e Idempotency — los mensajes pueden llegar dos veces

Para estar seguro, el correo a veces entrega una copia de una carta de la que no está seguro que llegó — mejor dos veces que ninguna, pero ahora podrías actuar dos veces sobre la misma instrucción.

La mayoría de los brokers garantizan entrega at-least-once (al menos una vez): prefieren enviar un mensaje dos veces antes que arriesgarse a perderlo, así que un consumer puede recibir ocasionalmente el mismo mensaje más de una vez. Si «cobrar al cliente» se ejecuta dos veces, es un problema real. La solución es la idempotency: diseñar el trabajo para que hacerlo dos veces tenga el mismo efecto que hacerlo una (comprobar primero «¿ya está cobrado?»). Asume duplicados; hazlos inofensivos.

Brokerat-least-oncecharge order 42same msg againConsumeralready charged?charge ✓skipnoyesidempotent consumer: a duplicate does no harm
El broker envió «cobrar pedido 42» dos veces. El consumer comprueba primero «¿ya está cobrado?» — y simplemente se salta el segundo.
PracticeIdempotency· at-least-once delivery (entrega al menos una vez)
Problema

Entrega at-least-once: el mismo mensaje puede llegar más de una vez.

Idea

Hacer el trabajo de modo que ejecutarlo dos veces tenga el mismo efecto que una.

Ejemplo

Antes de cobrar, comprobar «¿el pedido 42 ya está cobrado?» — si sí, saltar.

Coste
Necesitas recordar en algún sitio qué ya se ha hecho.
Relaciones

Imprescindible para todo Consumer; junto con la Dead-Letter Queue hace seguros los reintentos.

Message Ordering — el orden no está garantizado

Dos cartas enviadas en secuencia pueden llegar en cualquier orden — así que si el paso dos aparece antes que el paso uno, el destinatario se confunde.

Con muchos mensajes y muchos consumers en paralelo, los mensajes no se procesan necesariamente en el orden en que se enviaron. Si «actualizar dirección» y «eliminar cuenta» llegan desordenados, sale un disparate. Algunos sistemas conservan el orden dentro de una categoría a cierto coste; a menudo es más barato diseñar un trabajo que no dependa de un orden estricto. Sea como sea, nunca asumas orden a menos que lo hayas dispuesto expresamente.

sentprocessedupdate address1stdelete account2nddelete account1stupdate address2nd · nonsense✗ updating an account that no longer existsnever assume order unless you arranged it
Se envió «actualizar dirección» y luego «eliminar cuenta». Se procesaron al revés — y ahora actualizas una cuenta que ya no existe.
ConceptMessage Ordering· ordering guarantees (garantías de orden)
Problema

Los consumers en paralelo no procesan los mensajes en el orden en que se enviaron.

Idea

No confiar en el orden — o disponerlo explícitamente dentro de una categoría.

Ejemplo

«Eliminar cuenta» se procesó antes que «actualizar dirección» — el resultado es un disparate.

Coste
El orden estricto exige esfuerzo y estorba al paralelismo.
Relaciones

El precio de Competing Consumers; vecino de Eventual Consistency.

Eventual Consistency — el resultado es consistente con el tiempo

Un anuncio que se difunde por una oficina: durante unos momentos unos lo saben y otros no, hasta que la noticia llega a todos y vuelven a coincidir.

Como las reacciones ocurren de forma asíncrona, el sistema es eventualmente consistente: justo después de un evento, distintas partes pueden discrepar brevemente — el pedido existe pero la analítica aún no lo ha contado. Se pone al día en instantes, pero la «consistencia instantánea en todas partes» desaparece. Diseñas alrededor de esta brecha, mostrando a los usuarios estados intermedios razonables, en lugar de asumir que todas las partes se actualizan en el mismo instante.

OrdersAnalyticsorder existsnot counted yetorder countedgap: they briefly disagreetimeeventcaught up
El pedido ya existe, pero la analítica todavía no lo ha contado. Una brecha corta — y luego todos vuelven a coincidir.
ConceptEventual Consistency· consistent in the end (consistente al final)
Problema

Justo después de un evento, partes del sistema ven brevemente cosas distintas.

Idea

Aceptar la brecha: cada parte se pone al día y coincide — un poco después.

Ejemplo

El pedido se crea pero aún no está en el informe; un momento después, sí.

Coste
Hay que diseñar estados intermedios para el usuario («procesando…»).
Relaciones

Consecuencia de Asynchronous Processing y Event-driven Architecture.

Dead-Letter Queue — un mensaje envenenado necesita adónde ir

Una carta con la que nadie puede hacer nada — borrosa, imposible — no puede reintentarse para siempre atascando la fila. Se aparta en una bandeja especial para que alguien la revise.

Algunos mensajes nunca pueden procesarse con éxito — están mal formados o se refieren a datos que ya no existen. Si se dejan, un poison message (mensaje envenenado) así se reintenta para siempre y bloquea la queue. La respuesta estándar es una dead-letter queue: tras unos cuantos intentos fallidos, el mensaje se aparta a una queue separada para inspeccionarlo, de modo que deja de envenenar el flujo. Planifica los mensajes que fallan, o un solo mensaje malo detiene todo lo que hay detrás.

QueueConsumerDoneok messagesDead-letter queuefor a humanretry ×3still failsthe poison message moves aside; the main queue keeps flowing
Los mensajes normales pasan. El envenenado, tras tres intentos, pasa a la dead-letter queue — para que una persona lo inspeccione.
PatternDead-Letter Queue· DLQ
Problema

Un poison message falla siempre, se reintenta sin fin y bloquea la queue.

Idea

Tras unos cuantos fallos, apartar el mensaje a una queue separada para revisarlo.

Ejemplo
Un mensaje sobre un usuario eliminado va a la DLQ tras tres intentos.
Coste

Alguien tiene que vigilar la DLQ, o se vuelve un cementerio de trabajo perdido.

Relaciones

Los reintentos solo son seguros con Idempotency; mantiene el flujo en marcha para Resilience.

La mensajería asíncrona trae duplicados (se manejan con idempotency), orden no garantizado, eventual consistency y mensajes que fallan (usa una dead-letter queue). Planifica los cuatro.

§ 07

Una queue es una herramienta potente, no una opción por defecto. La habilidad está en recurrir a ella cuando desacoplar de verdad compensa, y mantener la llamada directa cuando la simplicidad vale más.

Queue vs Direct Call — usa una queue cuando esperar es el problema

Tomas un número y te vas por un servicio lento que recogerás después — pero para un sí o un no rápido simplemente preguntas en el mostrador, porque sacar un ticket sería más absurdo que esperar.

Recurre a una queue cuando el trabajo es lento, con picos o no urgente, cuando quieres que el que llama siga siendo rápido, o cuando varios servicios deben reaccionar a una misma cosa. Mantén una llamada directa cuando necesitas una respuesta inmediata para continuar — una consulta de precio, una comprobación de permisos — porque ahí la simplicidad y el resultado instantáneo valen más que el desacoplamiento. Ajusta la herramienta a si esperar es de verdad el problema.

Need the answer to continue?Direct callprice lookup · permission checkQueueslow · spiky · non-urgent · fan-outyesnomatch the tool to whether waiting is the real problem
Una pregunta: ¿necesitas la respuesta para continuar? Sí — una llamada directa. No — una queue.
PracticeQueue vs Direct Call· how to choose (cómo elegir)
Pregunta
¿El que llama necesita la respuesta para continuar?
Queue

El trabajo es lento, con picos, no urgente o lo necesitan muchos (fan-out).

Llamada directa

Necesitas una respuesta instantánea: una consulta de precio, una comprobación de permisos.

Coste de la queue

Un broker, duplicados, orden, eventual consistency, trazado más difícil.

Relaciones
La elección entre Synchronous Call y Message Queue.

No recurras a ella por reflejo

Instalar una sala de correo completa con sistema de clasificación para pasarle una nota a la persona del escritorio de al lado — la maquinaria cuesta ya más que el problema que resuelve.

Las queues añaden complejidad real: un broker que ejecutar, duplicados y orden que manejar, eventual consistency alrededor de la cual diseñar, y más dificultad para trazar una petición que ahora salta entre mensajes. Para un sistema simple con una llamada rápida entre dos partes, esa carga no compensa. Añade una queue cuando un beneficio concreto — resiliencia, escala, desacoplamiento — justifique el coste, no porque lo event-driven suene avanzado.

Los conceptos están conectados

Una cinta transportadora: de un dolor a una cura — y la cura tiene sus propios beneficios y sus propios efectos secundarios.

Esta es la imagen completa. El dolor de la synchronous call lo cura una message queue, guardada por un broker. Por la queue viajan commands (a un consumer) y events (a muchos, vía pub/sub). Eso compra los beneficios — resiliencia, load leveling, escalado — y trae las partes difíciles: duplicados, orden, eventual consistency y la DLQ.

Synchronous callMessage queueBrokerCommandEventPub/Sub · fan-outPayoffsresilience · load leveling · scalingHard partsduplicates · order · consistency · DLQreplaced byruns itbuyscosts
Los vínculos principales entre los conceptos del curso: de la llamada directa a la queue, sus beneficios y su precio.
Antes de añadir una queue
  • ¿Es esperar el problema — el trabajo es lo bastante lento, con picos o no urgente como para desacoplarlo?
  • Command o event — ¿un worker haciendo una tarea, o muchos servicios reaccionando a un hecho?
  • ¿Es idempotente el trabajo — seguro de ejecutar dos veces, ya que los mensajes pueden llegar dos veces?
  • ¿Asume orden, y lo he dispuesto o lo he eliminado del diseño?
  • ¿Puede el sistema tolerar una breve inconsistencia eventual?
  • Adónde van los mensajes fallidos — ¿hay una dead-letter queue?
Señales de que usas bien las queues
  • Pones en queue el trabajo lento, con picos y no urgente y mantienes las llamadas directas para respuestas instantáneas.
  • Tus consumers son idempotentes, así que un mensaje duplicado no hace daño.
  • No asumes orden a menos que lo hayas dispuesto explícitamente.
  • Diseñas para eventual consistency en lugar de esperar un acuerdo instantáneo.
  • Los mensajes fallidos acaban en una dead-letter queue en lugar de atascar la fila.

Resumen: los 21 conceptos

El problema de la llamada directa

Synchronous Callrequest–response

Llamar y esperar. Simple, pero acopla los servicios en el tiempo.

Failure Propagationcascading failure

Un servicio caído arrastra a todos los que lo llaman.

Background Workbackground jobs

Trabajo que el usuario no debería esperar: correos, facturas, fotos.

La queue

Message Queuequeue

Deja un mensaje y sigue; el receptor lo recoge por su cuenta.

Temporal Decouplingbuffer in time

Un búfer: los lados no tienen que funcionar en el mismo momento.

Asynchronous Processingasync

No esperar el resultado; el desenlace ocurre después.

Roles

Producer / Consumerpublisher / worker

Uno escribe mensajes, el otro los procesa; solo conocen la queue.

Message Brokerbroker

Software que almacena y entrega mensajes de forma fiable: RabbitMQ, Kafka.

Competing Consumersworker pool

Muchos workers en una queue se reparten la carga.

Comandos y eventos

Commandhaz esto

«Haz esto» — exactamente un consumer lo hace.

Eventesto ocurrió

«Esto ocurrió» — cualquiera reacciona, o nadie.

Publish/Subscribepub/sub, topic, fan-out

Un evento en un topic — cada suscriptor recibe su propia copia.

Event-driven ArchitectureEDA

Las funciones se añaden como oyentes nuevos, no editando al publicador.

Beneficios

Resiliencefault tolerance

La caída de un consumer es un retraso, no trabajo perdido.

Queue-Based Load Levelingload leveling, backpressure

Un pico llena la queue; los consumers la vacían de forma constante.

Independent Scalingindependent evolution

Cada lado escala y cambia por su cuenta.

Partes difíciles

Idempotencyat-least-once

Los duplicados ocurren — hazlos inofensivos.

Message Orderingordering guarantees

El orden no está garantizado a menos que lo dispongas.

Eventual Consistencyconsistent in the end

Partes del sistema discrepan brevemente y luego se ponen al día.

Dead-Letter QueueDLQ

Una queue aparte para los mensajes que fallan una y otra vez.

Elegir

Queue vs Direct Callcómo elegir

Necesitas la respuesta para continuar — llamada directa; si no — una queue.

Las queues son deliberadas: recurre a una cuando desacoplar en el tiempo compra resiliencia, escala o fan-out — y mantén la llamada directa cuando una respuesta instantánea importa más que todo eso.

Fin del curso exprés · 7 capítulos · 21 conceptos

Ahora viene la práctica: toma una cosa lenta que tu app hace en línea — enviar un correo, generar un informe — y muévela detrás de una queue, para que el usuario reciba una respuesta instantánea y un worker haga la parte lenta después. Luego haz que ese worker sea seguro de ejecutar dos veces. El patrón encaja en el momento en que ves que la respuesta se vuelve rápida y el trabajo se sigue haciendo. Pero quédate con una idea por encima de las demás: el cambio es de llamar y esperar a dejar un mensaje y continuar. Desacopla el trabajo en el tiempo y tu sistema se vuelve más rápido, más resistente y más fácil de hacer crecer — al precio de pensar en eventos en lugar de comandos.