Arquitectura Orientada a Eventos - Diseno de Sistemas Desacoplados

16 min de lectura | 2025.12.12

Que es la Arquitectura Orientada a Eventos

La Arquitectura Orientada a Eventos (EDA: Event-Driven Architecture) es un patron de diseno en el que la comunicacion entre sistemas se realiza a traves de eventos (notificaciones de sucesos). Reduce las dependencias entre componentes y permite construir sistemas escalables y flexibles.

Que es un evento: Es un mensaje que representa un cambio de estado significativo dentro del sistema. Ejemplos de eventos son “Un usuario se ha registrado”, “Un pedido se ha completado”, “El inventario ha disminuido”.

Diferencias con el Enfoque Tradicional Basado en Solicitudes

Orientado a Solicitudes (Sincrono)

flowchart LR
    Order["Servicio de Pedidos"] --> Stock["Servicio de Inventario"] --> Payment["Servicio de Pagos"] --> Notify["Servicio de Notificaciones"]

    Note["Espera la respuesta de cada servicio"]
  • Los servicios estan fuertemente acoplados
  • Una falla en un servicio afecta a todo el sistema
  • El tiempo de procesamiento es la suma de todos los servicios

Orientado a Eventos (Asincrono)

flowchart TB
    Order["Servicio de Pedidos"] --> Event["Evento de Pedido Completado"]
    Event --> Stock["Servicio de Inventario<br/>(procesa independientemente)"]
    Event --> Payment["Servicio de Pagos<br/>(procesa independientemente)"]
    Event --> Notify["Servicio de Notificaciones<br/>(procesa independientemente)"]
  • Los servicios estan desacoplados
  • Las fallas se localizan
  • El procesamiento paralelo es posible

Tipos de Eventos

Eventos de Dominio

Representan sucesos que ocurren en el dominio del negocio.

// Ejemplo de evento de dominio
{
  "eventType": "OrderPlaced",
  "eventId": "evt_123456",
  "timestamp": "2024-01-15T10:30:00Z",
  "payload": {
    "orderId": "ord_789",
    "customerId": "cust_456",
    "items": [...],
    "totalAmount": 5000
  }
}

Eventos de Integracion

Eventos compartidos entre diferentes servicios.

Eventos de Notificacion

Eventos que solo notifican cambios de estado sin incluir datos detallados.

// Evento de notificacion (Fat vs Thin)
// Thin Event - Se requiere obtener detalles por separado
{ "eventType": "UserUpdated", "userId": "123" }

// Fat Event - Incluye toda la informacion necesaria
{ "eventType": "UserUpdated", "userId": "123", "name": "Alice", "email": "..." }

Event Sourcing

Un patron que almacena el estado como un historial de eventos.

CRUD Tradicional

flowchart TB
    subgraph CRUD["CRUD Tradicional - Solo almacena el estado actual"]
        Orders["orders<br/>id: 1, status: 'shipped'"]
    end

Event Sourcing

flowchart TB
    subgraph Events["Almacena todos los eventos"]
        E1["1. OrderCreated (2024-01-01)"]
        E2["2. PaymentReceived (2024-01-02)"]
        E3["3. OrderShipped (2024-01-03)"]
    end

    Events -->|Reproducir| State["Estado actual: status = 'shipped'"]

Ventajas

  • Registro de auditoria completo: Se puede rastrear todo el historial de cambios
  • Viaje en el tiempo: Se puede reconstruir el estado en cualquier punto
  • Reproduccion de eventos: Se puede reconstruir el estado despues de corregir errores

Desventajas

  • Aumenta la complejidad
  • La evolucion del esquema de eventos es un desafio
  • Se necesitan estrategias para el rendimiento de lectura

CQRS (Separacion de Responsabilidades de Comando y Consulta)

Un patron que separa los modelos de lectura (Query) y escritura (Command).

flowchart TB
    Command["Command<br/>(Modelo de escritura)"]
    Command -->|Emitir evento| EventStore["Event Store"]
    EventStore -->|Proyeccion| Query["Query<br/>(Modelo de lectura)"]

Modelo de Escritura

// Manejador de comandos
async function handlePlaceOrder(command) {
  const order = new Order(command.orderId);
  order.addItems(command.items);
  order.place();

  await eventStore.save(order.getUncommittedEvents());
}

Modelo de Lectura

// Vista optimizada para lectura
const orderSummary = {
  orderId: "123",
  customerName: "Alice",  // Informacion del cliente ya unida
  itemCount: 3,
  totalAmount: 5000,
  status: "shipped"
};

Patrones de Implementacion

Patron Saga

Implementa transacciones que abarcan multiples servicios mediante una cadena de eventos.

1. Crear pedido → OrderCreated
2. Reservar inventario → InventoryReserved (o InventoryReservationFailed en caso de fallo)
3. Procesar pago → PaymentProcessed (o PaymentFailed en caso de fallo)
4. Confirmar pedido → OrderConfirmed

En caso de fallo, transaccion de compensacion:
PaymentFailed → Liberar inventario (compensacion) → Cancelar pedido

Patron Outbox

Un patron para garantizar la actualizacion de la base de datos y la emision de eventos.

1. Dentro de la transaccion:
   - Actualizar datos del negocio
   - Insertar evento en la tabla outbox

2. En un proceso separado:
   - Sondear la tabla outbox
   - Emitir eventos a la cola de mensajes
   - Marcar como emitido

Consideraciones a Tener en Cuenta

Consistencia Eventual

Servicio de pedidos: Estado del pedido = "completado"
Servicio de inventario: Evento aun no procesado → Existe periodo de inconsistencia
     ↓ Despues de procesar el evento
Servicio de inventario: Inventario reducido → Consistencia recuperada

Orden de Eventos

Orden correcto:
1. OrderCreated
2. OrderUpdated
3. OrderShipped

Si el orden se altera:
1. OrderShipped (?)
2. OrderCreated
→ El estado puede corromperse

Idempotencia

Disenar para que el resultado no cambie aunque el mismo evento se entregue multiples veces.

async function handleInventoryReserved(event) {
  // Verificar duplicados con clave de idempotencia
  const processed = await db.processedEvents.findById(event.eventId);
  if (processed) return;

  await db.inventory.reserve(event.payload);
  await db.processedEvents.insert({ eventId: event.eventId });
}

Resumen

La arquitectura orientada a eventos es un patron poderoso para disenar sistemas complejos de manera desacoplada y flexible. Al combinarla con Event Sourcing y CQRS, se puede mejorar la auditabilidad y la escalabilidad. Sin embargo, es necesario abordar desafios especificos de sistemas distribuidos como la consistencia eventual y el orden de eventos.

← Volver a la lista