Eventos asíncronos

Cómo funcionan los flujos asíncronos basados en eventos: publicación, consumo y procesamiento entre microservicios a través del Event Bus.

Qué es un flujo asíncrono basado en eventos

En un flujo asíncrono, un servicio publica un evento indicando que algo ocurrió, y otros servicios reaccionan a ese evento sin que el publicador necesite esperar una respuesta. No hay una conexión directa entre quien produce el evento y quien lo consume.

Este modelo es fundamental en arquitecturas distribuidas porque permite desacoplamiento temporal: los servicios no necesitan estar disponibles al mismo tiempo para comunicarse.

Diferencia con la comunicación sincrónica

AspectoSincrónicoAsíncrono (eventos)
AcoplamientoEl emisor conoce al receptorEl emisor no sabe quién consume
DisponibilidadAmbos deben estar activosEl consumidor puede procesar después
RespuestaInmediataNo hay respuesta directa
EscalabilidadLimitada por el receptor más lentoCada consumidor escala independientemente
ComplejidadMenorMayor (orden, duplicados, consistencia)

Anatomía de un evento

Un evento bien definido contiene:

  • Tipo: nombre que identifica qué ocurrió (OrderPlaced, PaymentCompleted)
  • Payload: datos relevantes del hecho (ID de la orden, monto, timestamp)
  • Metadata: información de trazabilidad (correlationId, timestamp, source)
  • Versión: para manejar evolución del esquema
{
  "type": "OrderPlaced",
  "version": "1.0",
  "timestamp": "2024-01-15T10:30:00Z",
  "correlationId": "abc-123-def",
  "source": "ms-orders",
  "payload": {
    "orderId": "order-456",
    "customerId": "cust-789",
    "totalAmount": 150.00,
    "items": [
      { "productId": "prod-001", "quantity": 2 }
    ]
  }
}

El flujo completo de un evento

sequenceDiagram
    participant MS1 as Microservicio Origen
    participant EB as Event Bus
    participant MS2 as Consumidor A
    participant MS3 as Consumidor B
    participant MS4 as Consumidor C

    MS1->>EB: Publicar evento (OrderPlaced)
    Note over MS1: El publicador continúa su trabajo

    EB->>MS2: Entregar evento
    EB->>MS3: Entregar evento
    EB->>MS4: Entregar evento

    MS2->>MS2: Actualizar inventario
    MS3->>MS3: Enviar notificación
    MS4->>MS4: Registrar analytics

Paso 1: Publicación

El microservicio origen completa su operación principal (por ejemplo, crear una orden) y publica un evento al Event Bus. Una vez publicado, el servicio no espera a que nadie lo procese.

Paso 2: Distribución

El Event Bus recibe el evento y lo distribuye a todos los consumidores suscritos. Dependiendo de la tecnología (Kafka, RabbitMQ, SNS/SQS), la distribución puede ser:

  • Fan-out: todos los suscriptores reciben una copia
  • Competencia: solo un consumidor del grupo procesa cada mensaje
  • Combinación: fan-out entre grupos, competencia dentro de cada grupo

Paso 3: Consumo

Cada consumidor recibe el evento y ejecuta su lógica de forma independiente. Un consumidor lento no afecta a los demás.

Paso 4: Confirmación

El consumidor confirma (acknowledge) que procesó el evento correctamente. Si falla, el Event Bus puede reintentar la entrega.

Patrones de publicación

Publicar después de persistir

El servicio primero guarda en su base de datos y luego publica el evento. Es simple pero tiene un riesgo: si la publicación falla después de persistir, el evento se pierde.

Outbox Pattern

El servicio guarda el evento en una tabla outbox dentro de la misma transacción que la operación de negocio. Un proceso separado lee la tabla outbox y publica los eventos al bus. Esto garantiza consistencia entre la operación y la publicación.

Event Sourcing

En lugar de guardar el estado actual, se guardan todos los eventos que produjeron ese estado. La publicación es inherente al modelo.

Desafíos de los flujos asíncronos

Orden de eventos

Los eventos pueden llegar en orden diferente al que fueron publicados. Los consumidores deben ser capaces de manejar esto, ya sea reordenando o siendo tolerantes al desorden.

Eventos duplicados

El Event Bus puede entregar el mismo evento más de una vez (at-least-once delivery). Los consumidores deben ser idempotentes: procesar el mismo evento dos veces debe producir el mismo resultado que procesarlo una vez.

Consistencia eventual

Los datos entre servicios no están sincronizados instantáneamente. Después de publicar un evento, puede pasar un tiempo antes de que todos los consumidores reflejen el cambio. El sistema debe diseñarse para tolerar esta ventana de inconsistencia.

Observabilidad

Rastrear un flujo asíncrono es más difícil que uno sincrónico. El correlationId es esencial para poder seguir la cadena de eventos a través de múltiples servicios.

Cuándo usar eventos asíncronos

Son adecuados cuando:

  • Múltiples servicios necesitan reaccionar al mismo hecho
  • No se necesita una respuesta inmediata
  • Se quiere desacoplar servicios para escalar independientemente
  • El proceso puede tolerar consistencia eventual

No son adecuados cuando:

  • Se necesita una respuesta inmediata para el usuario
  • La operación requiere consistencia fuerte entre servicios
  • La complejidad añadida no se justifica por el volumen o los requisitos

Resumen

Los flujos asíncronos basados en eventos permiten que los servicios se comuniquen sin acoplamiento directo. El publicador no conoce a los consumidores, y cada consumidor procesa a su ritmo. Esto aporta escalabilidad y resiliencia, pero introduce desafíos de orden, duplicados y consistencia que deben abordarse con patrones como idempotencia, outbox y trazabilidad distribuida.