En las lecciones anteriores conocimos Event-Driven Architecture (EDA) — su principios y componentes. Vimos cómo los eventos crean un acoplamiento débil entre los microservices, reducen dependencias y mejoran la escalabilidad. Aprendiste cómo funcionan las comunicaciones asíncronas, estudiaste los conceptos de publicadores (producers) y suscriptores (subscribers), y también entendiste cómo los message brokers como Kafka, RabbitMQ y ActiveMQ gestionan la transmisión de datos. Además discutimos errores típicos al implementar EDA y las mejores prácticas de diseño.
Es hora de aplicar la teoría en la práctica y diseñar una arquitectura orientada a eventos para un caso concreto.
Diseño práctico de una arquitectura orientada a eventos
Planteamiento: caso "Tienda de comercio electrónico"
Imagina que tienes que diseñar la arquitectura de eventos para una tienda online. Como arquitecto principal del sistema te enfrentas a tareas como:
- Procesar pedidos, incluyendo notificaciones sobre el estado de los pedidos, pagos y entregas.
- Actualizar automáticamente la información de disponibilidad de productos en el inventario.
- Enviar notificaciones a los usuarios sobre descuentos en sus productos favoritos.
- Loguear todos los eventos para analítica (por ejemplo, para generar reports).
Nuestro objetivo es usar un enfoque orientado a eventos para reducir el acoplamiento entre servicios y mejorar la resiliencia.
Paso 1: Definición de eventos
El primer paso es entender qué eventos ocurren en el sistema. Un evento es una "noticia" de que algo pasó. Por ejemplo:
| Evento | Descripción |
|---|---|
OrderPlaced |
El pedido fue creado por el usuario |
OrderPaid |
El usuario pagó el pedido |
OrderShipped |
El pedido fue enviado por el servicio de envío |
InventoryUpdated |
Cambió la cantidad de producto en el inventario |
DiscountCreated |
Se creó un nuevo descuento que puede interesar a los usuarios |
UserNotificationSent |
Se envió una notificación al usuario |
Cada evento tiene su payload y metadatos, como la hora de creación, identificador de usuario, etc.
Paso 2: Identificación de publicadores y suscriptores
Ahora que hemos definido los eventos, hay que entender quién los produce (publicadores) y quién reacciona a ellos (suscriptores).
| Evento | Publicador | Suscriptores |
|---|---|---|
OrderPlaced |
Order Service | Inventory Service, Payment Service |
OrderPaid |
Payment Service | Shipping Service, Notification Service |
OrderShipped |
Shipping Service | Notification Service |
InventoryUpdated |
Inventory Service | Analytics Service, Notification Service |
DiscountCreated |
Admin Service | Notification Service |
UserNotificationSent |
Notification Service | Analytics Service |
Ejemplo:
- Cuando el usuario crea un pedido,
Order Servicepublica el eventoOrderPlaced. Ese evento lo procesanInventory Servicepara reducir el stock yPayment Servicepara iniciar el proceso de pago.
Paso 3: Creación del esquema de interacción
Visualicemos cómo los servicios intercambian eventos. Aquí tienes un esquema que muestra la interacción a través de un message broker (por ejemplo, Apache Kafka):
User
↓
Order Service ──> OrderPlaced ─┬──> Inventory Service (reducir stock)
└──> Payment Service (iniciar el pago)
↓
Payment Service ──> OrderPaid ─┬──> Shipping Service (enviar pedido)
└──> Notification Service (notificar al usuario)
↓
Shipping Service ──> OrderShipped → Notification Service
Paso 4: Definición de la estructura de los eventos
Los eventos deben contener información útil para los suscriptores.
Ejemplo de estructura del evento OrderPlaced:
{
"eventId": "12345",
"eventType": "OrderPlaced",
"timestamp": "2023-10-01T12:34:56Z",
"payload": {
"orderId": "7890",
"userId": "456",
"orderItems": [
{
"productId": "101",
"quantity": 2
},
{
"productId": "202",
"quantity": 1
}
],
"totalPrice": 159.99
}
}
Estructuras así ayudan a unificar el procesamiento de eventos, ya que los suscriptores siempre saben qué esperar.
Paso 5: Modelado del broker de mensajes
Para implementar la arquitectura usaremos Apache Kafka. Cada evento se publicará en su propio topic.
| Topic | Tipo de evento | Ejemplos de mensajes |
|---|---|---|
orders |
OrderPlaced |
Datos sobre pedidos creados |
payments |
OrderPaid |
Datos de pagos exitosos |
shipping |
OrderShipped |
Datos de pedidos enviados |
inventory |
InventoryUpdated |
Datos sobre cambios en el inventario |
notifications |
UserNotificationSent |
Datos de notificaciones enviadas |
Ejercicio: implementación del producer y del consumer para el evento OrderPlaced
Implementación del producer:
// Producer para enviar el evento OrderPlaced a Kafka
@Component
public class OrderEventProducer {
private final KafkaTemplate<String, String> kafkaTemplate;
public OrderEventProducer(KafkaTemplate<String, String> kafkaTemplate) {
this.kafkaTemplate = kafkaTemplate;
}
public void sendOrderPlacedEvent(String orderId, String eventPayload) {
kafkaTemplate.send("orders", orderId, eventPayload);
System.out.println("Evento OrderPlaced enviado: " + eventPayload);
}
}
Implementación del consumer:
// Consumer para procesar el evento OrderPlaced
@Component
@KafkaListener(topics = "orders", groupId = "inventory-service")
public class OrderEventConsumer {
@Autowired
private InventoryService inventoryService;
@KafkaHandler
public void handleOrderPlacedEvent(String message) {
System.out.println("Evento OrderPlaced recibido: " + message);
inventoryService.updateInventory(message);
}
}
Consejos para diseñar una arquitectura orientada a eventos
- Minimiza las dependencias. Cada servicio debe estar lo más aislado posible. Por ejemplo,
Notification Serviceno debería conocer la lógica interna deOrder Service. - Registra los eventos. Esto te ayudará a seguir lo que ocurre en el sistema, sobre todo en el procesamiento asíncrono.
- Define esquemas para los eventos. Usa JSON Schema para que todos los eventos sigan un formato claro.
- Asegura la consistencia. Si un evento no se procesa, puedes volver a intentarlo gracias a Kafka's "At least once".
Ejercicio final
Para afianzar conocimientos, diseña una arquitectura orientada a eventos para un sistema de reserva de billetes de avión. Define los eventos clave (FlightBooked, PaymentProcessed, TicketIssued), sus publicadores y suscriptores. Describe la interacción entre servicios y crea el esquema de eventos.
¡Eso es todo! Ahora, de forma práctica, has aprendido los fundamentos del diseño de arquitecturas orientadas a eventos. Por delante — más EDA y magia asíncrona.
GO TO FULL VERSION