CodeGym /Cursos /Módulo 5. Spring /Lección 206: Práctica: diseño de arquitectura orientada a...

Lección 206: Práctica: diseño de arquitectura orientada a eventos

Módulo 5. Spring
Nivel 13 , Lección 5
Disponible

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 Service publica el evento OrderPlaced. Ese evento lo procesan Inventory Service para reducir el stock y Payment Service para 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 Service no debería conocer la lógica interna de Order 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.

Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION