Una arquitectura dirigida por eventos ( EDA ) es un patrón de arquitectura de software que permite la creación, definición, consumo y respuesta a eventos .
Un evento se puede definir como un "cambio importante en el estado " [1] . Por ejemplo, cuando un cliente compra un automóvil, el estado del automóvil cambia de "en venta" a "vendido". La arquitectura del sistema del concesionario de automóviles puede tratar este cambio de estado como un evento creado, publicado, definido y consumido por las diversas aplicaciones dentro de la arquitectura.
Este patrón arquitectónico se puede aplicar en el diseño y la implementación de aplicaciones y sistemas que comunican eventos entre servicios y componentes de software débilmente acoplados . Un sistema controlado por eventos normalmente contiene orígenes de eventos (o agentes) y consumidores de eventos (o sumideros). Los fregaderos son los encargados de responder una vez ocurrido un evento. La reacción puede o no ser generada completamente por el sumidero. Por ejemplo, un sumidero solo puede ser responsable de filtrar, transformar y entregar un evento a otro componente, o puede crear su propia reacción a este evento. La primera categoría de sumideros puede basarse en componentes tradicionales, como el middleware de mensajería, y la segunda categoría de sumideros (que forman su propia respuesta a medida que se ejecuta) puede requerir una plataforma de ejecución de transacciones más adecuada.
La creación de aplicaciones y sistemas dentro de una arquitectura basada en eventos permite que se diseñen de una manera que promueva una mejor interactividad, ya que los sistemas basados en eventos están más estructurados hacia entornos impredecibles y asincrónicos [2] .
Una arquitectura basada en eventos corresponde a una arquitectura orientada a servicios (SOA) porque los servicios pueden activarse mediante activadores disparados desde eventos entrantes [2] [3] .
Este paradigma es especialmente útil cuando el sumidero no proporciona su propia ejecución de acciones.
La arquitectura orientada a servicios impulsada por eventos evoluciona las arquitecturas SOA y EDA para proporcionar una capa de servicios más profunda y robusta mediante la explotación de relaciones de causa y efecto previamente desconocidas para formar un nuevo modelo de eventos. Este nuevo patrón de inteligencia empresarial conduce a una mayor automatización del procesamiento, agregando a la empresa una productividad previamente inalcanzable mediante la inyección de información valiosa en el patrón de actividad reconocido.
Un evento puede constar de dos partes: un encabezado de evento y un cuerpo de evento. El encabezado del evento puede incluir información como el nombre del evento, la marca de tiempo del evento y el tipo del evento. El cuerpo del evento describe lo que realmente sucedió. El cuerpo de un evento no debe confundirse con la plantilla o la lógica que se puede aplicar en respuesta a los eventos.
La arquitectura basada en eventos consta de cuatro capas lógicas. Comienza con el sonido real, su representación técnica en forma de evento, y termina con un conjunto no vacío de reacciones a este evento. [cuatro]
La primera capa lógica es el generador de eventos, que registra un hecho y lo representa como un evento. Dado que prácticamente todo lo que se puede percibir puede ser un hecho, también lo puede ser un generador de eventos. Como ejemplo, el generador podría ser un cliente de correo electrónico, un sistema de comercio electrónico o algún tipo de sensor. Convertir los diversos datos de los sensores en una sola forma de datos estandarizada que se pueda evaluar es un gran desafío en el diseño y la implementación de esta capa. [4] Sin embargo, dado que el evento es estrictamente declarativo, cualquier operación de transformación se puede aplicar fácilmente, eliminando así la necesidad de un alto nivel de estandarización.
Un canal de eventos es un mecanismo a través del cual se pasa información desde un generador de eventos a un mecanismo de manejo de eventos [4] o sumidero.
Puede ser una conexión TCP/IP o cualquier tipo de archivo de entrada (texto sin formato, formato XML, correo electrónico, etc.). Se pueden abrir varios canales de eventos al mismo tiempo. Por lo general, debido a los requisitos del procesamiento de eventos casi en tiempo real, los canales de eventos se leen de forma asíncrona. Los eventos se almacenan en una cola, a la espera de que el motor de eventos los procese más tarde.
El mecanismo de manejo de eventos es el lugar donde se identifica un evento y se selecciona una reacción adecuada, que luego se ejecuta. Esto también puede resultar en la generación de una serie de aserciones. Por ejemplo, si un evento que ha llegado al motor de procesamiento informa que “Se está acabando el producto N”, este hecho puede generar las reacciones “Pedir producto N” y “Avisar al personal”. [cuatro]
Aquí están las consecuencias del evento. Puede manifestarse de diversas maneras y formas; por ejemplo, un mensaje enviado a alguien, o una aplicación que muestra algún tipo de advertencia en pantalla. [4] . Según el nivel de automatización proporcionado por el sumidero (motor de eventos), es posible que estos pasos no sean necesarios.
Hay tres estilos principales de manejo de eventos: simple, encadenado y complejo. A menudo, estos tres estilos se usan juntos en una gran arquitectura impulsada por eventos [4] .
El manejo simple de eventos se refiere a eventos directamente relacionados con cambios medibles específicos en las condiciones. Con el manejo simple de eventos, ocurren eventos conocidos que desencadenan efectos secundarios. El manejo simple de eventos se usa comúnmente para administrar el flujo de trabajo en tiempo real, lo que reduce la latencia y el costo [4] .
Por ejemplo, los eventos simples son generados por un sensor que detecta un cambio en la presión de los neumáticos o la temperatura ambiente.
Durante el procesamiento del flujo de eventos (ESP), ocurren eventos normales y conocidos. Los eventos regulares (comandos, transmisiones RFID) se verifican en busca de conocimiento y se transmiten a los suscriptores de información. El procesamiento de flujo de eventos se usa comúnmente para administrar el flujo de información en tiempo real y a nivel empresarial, lo que permite la toma de decisiones oportuna [4] .
El procesamiento de eventos complejos le permite considerar secuencias de eventos simples y ordinarios e inferir la ocurrencia de un evento complejo. El procesamiento de eventos complejos evalúa la influencia mutua de los eventos y luego toma medidas. Es posible que los eventos (conocidos o comunes) no sigan la escritura y ocurran durante largos períodos de tiempo. La correlación de eventos puede ser causal, temporal o espacial. El manejo de eventos complejos requiere el uso de intérpretes de eventos complejos, patrones y coincidencias de eventos y métodos de correlación. El procesamiento de eventos complejos se usa comúnmente para identificar y responder a comportamientos anómalos, amenazas y oportunidades [4] .
La arquitectura impulsada por eventos está muy poco acoplada y bien distribuida. La mejor distribución de esta arquitectura se debe a que un evento puede ser cualquier cosa que exista en cualquier lugar. La arquitectura está muy poco acoplada, ya que el evento en sí no sabe las consecuencias de su ocurrencia, es decir, si tenemos un sistema de seguridad que registra información cuando se abre la puerta de entrada, entonces la puerta en sí no sabe que el sistema de seguridad agregará información sobre la apertura de la puerta. [cuatro]
La biblioteca Java Swing se basa en una arquitectura basada en eventos. Esto se relaciona especialmente bien con la motivación de Swing de proporcionar componentes y funcionalidades relacionados con la interfaz de usuario. La interfaz utiliza convenciones de nomenclatura (como "ActionListener" y "ActionEvent") para organizar las relaciones entre eventos. Una clase que necesita ser notificada de algún evento simplemente implementa el oyente apropiado, anula los métodos heredados y se agrega al objeto que genera el evento. A continuación se muestra el ejemplo más simple:
public class FooPanel extiende JPanel implementa ActionListener { public FooPanel () { super (); JButton btn = new JButton ( "¡Haz clic en mí!" ); btn _ addActionListener ( esto ); esto _ añadir ( btn ); } @Override public void actionPerformed ( ActionEvent ae ) { System . fuera _ println ( "¡Se ha hecho clic en el botón!" ); } }Una alternativa es incrustar el oyente en el objeto como una clase anónima . A continuación se muestra un ejemplo.
public class FooPanel extiende JPanel { public FooPanel () { super (); JButton btn = new JButton ( "¡Haz clic en mí!" ); btn _ addActionListener ( new ActionListener () { public void actionPerformed ( ActionEvent ae ) { System . out . println ( "¡Se ha hecho clic en el botón!" ); } }); } }El mismo código de estilo funcional de Java 8, usando una lambda en lugar de una clase anónima:
public class FooPanel extiende JPanel { public FooPanel () { super (); JButton btn = new JButton ( "¡Haz clic en mí!" ); btn _ addActionListener ( ae -> System . out . println ( "¡Se ha hecho clic en el botón!" )); } }La plataforma JavaScript del lado del servidor hace un uso extensivo de los generadores de eventos ( EventEmitter ). Muchos objetos en Node generan eventos: net.Server genera un evento en cada solicitud entrante, fs.readStream genera un evento cuando se abre un archivo. Ejemplo de trabajo con EventEmitter:
barra.js:
var Foo = requiere ( "./foo.js" ). Foo , foo = new Foo (); foo _ addListener ( "escribir" , función () { consola . log ( "Barra" ); });foo.js:
var EventEmitter = require ( "eventos" ). EventEmitter , Foo = función () { var foo = esto ; foo _ escribir = función () { consola . registro ( "foo" ); foo _ emitir ( "escribir" ); }; setTimeout ( this . write , 3000 ); }; foo _ prototipo = nuevo EventEmitter (); exportaciones _ foo = foo ;