La arquitectura dirigida por eventos o simplemente EDA (por sus siglas en inglés) es una arquitectura asíncrona y distribuida, pensada para crear aplicaciones altamente escalables.
En una arquitectura EDA los componentes no se comunican de forma tradicional, en la cual se establece comunicación de forma síncrona, se obtiene una respuesta y se procede con el siguiente paso. En esta arquitectura, se espera que las aplicaciones lancen diversos “eventos” para que otros componentes puedan reaccionar a ellos, procesarlos y posiblemente generar nuevos eventos para que otros componentes continúen con el trabajo.
Nuevo concepto: Evento
Un evento lo podemos definir como un cambio significativo en el estado de la aplicación, ya sea por un dato que cambio o alguna acción concreta en el sistema que merece la pena ser observada para tomar acciones en consecuencia.
Como podemos ver en la imagen anterior, todo inicia con la llegada de un nuevo evento a algo que llamaremos por ahora Event Bus, el cual es un componente que se encarga de administrar todos los eventos de la arquitectura. El Event Bus se encargará de recibir el evento y colocarlo en los Event Channels, las cuales son básicamente una serie de Colas (Queues) o Temas (Topics) sobre los cuales habrá ciertos componentes a la escucha de nuevos mensajes.
Por otra parte, los Event Processing son componentes de negocio que está a la escucha de nuevos eventos depositados en los Event Channels. Los Event Processing son los encargados de procesar los eventos, es decir, realizar acciones concretas sobre el sistema, como crear, actualizar o borrar algún registro, finalmente, el proceso puedo terminar de forma silenciosa, o puede generar un nuevo evento para que otro componente lo tome y continúe con el procesamiento.
Un punto importante a tomar en cuenta es que todos los Event Processing son componentes distribuidos, lo que quiere decir que están totalmente desacoplados del resto y que el funcionamiento de uno no afecta al resto. De esta forma, cada Event Processing administra sus propias transacciones, lo que hace difícil mantener la atomicidad de la transacción en una serie de eventos, por lo que es un punto importante a tomar en cuenta al momento de trabajar con esta arquitectura.
En esta arquitectura, cada Event Processing solo tiene conocimiento de la tarea que el realiza y no tiene conocimiento de la existencia de otros Event Processing, lo cual permite que trabajen de forma autónoma.
Tip
De forma general, podemos comprar la arquitectura EDA con el patrón de diseño Observable, ya que EDA está a la escucha de ciertos eventos sobre un determinado Event Channel en lugar de escuchar los eventos directamente del objeto observado.
Ya que EDA es una arquitectura asíncrona, no podemos darnos el lujo de ejecutar una operación y esperar una respuesta, por lo que debemos dejar la solicitud y esperar hasta que alguien la atienda, durante este proceso, podemos llamar directamente a la operación asíncrona del otro componente, sin embargo, esto es una mala idea:
En la imagen anterior podemos ver claramente un fuerte acoplamiento entre los dos componentes, lo cual va en contra de la arquitectura EDA, la cual busca un bajo acoplamiento entre los componentes, además, de que la operatividad de un componente no debe depender de la operatividad del otro. En este escenario, el componente A depende de que B esté funcionando al momento de realizar la llamada, ya que, si no, podrían suceder dos cosas, que el proceso completo falle porque no pudo realizar la llamada a B o la segunda, que el proceso continúe ante la falla, pero perdamos el mensaje enviado a B. Sea cual sea el caso, no es el esperado, porque al final tenemos un fallo total o parcial, lo que nos deja en un estado inconsistente.
Para solucionar este tipo de problemas, debemos hacer uso de un Intermediario que tomará las solicitudes, las almacenará y las entregará al consumidor adecuando cuando este esté disponible, de esta forma, el productor del mensaje podrá dejar el mensaje en el Intermediario y continuar con el proceso, pues el Mediador garantizará que el mensaje será entregado al consumidor. Por otra parte, el consumidor (Componente B) estará a la escucha de nuevos mensajes en el Intermediario para procesarlos. Si el consumidor está fuera de servicio cuando el productor (Componente A) deja el mensaje, este no se perderá, pues el Intermediario lo guardará y lo entregará cuando el Consumidor esté nuevamente operativo.
En EDA, el Intermediario son conocidos como Message-Oriented-Middleware (MOM) o Middleware Orientado a Mensajes por su traducción al español. Los MOM son aplicaciones especializadas en el transporte confiable de mensajes. Entre los más conocidos están WebSphere MQ, Microsoft Message Queuing, Oracle Texudo, Apache Kafka, etc. Más adelante analizaremos como los MOM juegan un papel fundamental en la implementación de una arquitectura EDA.
Ventajas
Escalabilidad: La escalabilidad es uno de los puntos más fuertes de esta arquitectura, pues permite que cada consumidor (Event Consummer) puede escalar de forma independiente y reduce al máximo el acoplamiento entre los componentes.
Despliegue: Debido al bajo acoplamiento entre los componentes, es posible el despliegue sin preocuparse por dependencias o precondiciones, al final, los componentes solamente se suscriben para recibir eventos y reaccionar ante ellos.
Performance: Esta es que ventaja cuestionable, ya que al igual que en REST o SOA, EDA necesita pasar por una serie de pasos para completar una tarea, agregando retrasos en cada paso, desde colocar el Evento por parte del productor, esperar a que el consumidor lo tome, y generar nuevos Eventos, sin embargo, la naturaleza Asíncrona de EDA hace que esta desventaja se supere mediante el procesamiento en paralelo.
Flexibilidad: EDA permite responder rápidamente a un entorno cambiante, debido a que cada componente procesador de eventos tiene una sola responsabilidad y está completamente desacoplado de los demás, de esta forma, si ocurre un cambio, se puede aislar en un solo componente sin afectar al resto, además, si un nuevo requerimiento es requerido, solo es necesario regresar un nuevo tipo de procesador de eventos que escuche un determinado tipo de evento.
Desventajas
Testabilidad: Una arquitectura distribuida y asíncrona agrega cierta complejidad a las pruebas, pues no es posible generar un evento y esperar un resultado para validar el resultado, en su lugar, es necesario crear pruebas más sofisticadas que creen los eventos y esperen la finalización del procesamiento del evento inicial más toda la serie de eventos que se podrían generar como consecuencia del evento inicial para validar el resultado final.
Desarrollo: Codificar soluciones asíncronas es complicado, pero aún más, es la necesidad de crear manejadores de errores más avanzados que permitan recuperarse en una arquitectura asíncrona, donde la falla en un procesador no significa la falla en el resto, lo que puede ocasionar la inconsistencia entre los sistemas.
Conclusiones
EDA es sin lugar a duda una de los estilos arquitectónicos más escalables que existe y que permite que empresa globales puedan atender a millones de solicitudes sin colgar sus sistemas, ya que permite dividir el trabajo en diversos procesadores de mensajes que trabajan de forma totalmente asiladas y desacopladas del resto, sin embargo, implementar EDA no es fácil, pues requiere un esfuerzo mucho mayor que una arquitectura síncrona, y requiere una mejor preparación de los ingenieros que hay detrás de la solución.
Otra de las cosas a considerar al implementar EDA es que, debemos tener un conocimiento más profundo de la solución de negocio que vamos a desarrollar, pues necesitamos ese conocimiento para saber cómo dividir la aplicación en los diversos consumidores, ya que de lo contrario podemos crear módulos de software que no sean lo suficientemente desacoplados del resto.
Finalmente, debemos de entender que en una arquitectura EDA no existe el concepto de transacciones, pues cada consumidor manejará de forma independiente sus propias transacciones, por lo que si un paso de la cadena de procesamiento falla, no implicará el rollback en todos los consumidores, es por ello que debemos de tener manejadores de errores muy avanzados que permiten a un proceso recuperarse en caso de fallo o de plano que levante una serie de nuevos eventos para hacer el rollback en los otros consumidores. Y toma en cuenta que en EDA no hay garantía que un evento sea procesado, ya sea porque no hay consumidores para un determinado evento o por un error en el diseño.
Acerca de este libro
Todo lo que acabas de ver en este artículo es solo una pequeña parte del libro Introducción a la arquitectura de software, el libro más completo en español sobre arquitectura de software, donde cubrimos los temas más importantes para convertirte en un arquitecto de software profesional.
¿Quieres convertirte en arquitecto de software pero no sabes cuál es el camino adecuando? o simplemente no sabes que guía estudiar para convertirte en arquitecto de software, te invito a que veas mi libro: