Cómo la arquitectura impulsada por eventos resuelve los desafíos de las aplicaciones web modernas

¡Hola, Habr!







Mientras nuestra venta continúa para los gustos más exigentes, centraremos su atención en otro tema de nuestra búsqueda creativa: Arquitectura impulsada por eventos (EDA). Debajo del corte, encontrará hermosos diagramas de flujo y una historia sobre cómo este paradigma innovador ayuda en el desarrollo de aplicaciones web.



Este artículo explorará algunos de los desafíos que impulsan la innovación en el desarrollo web moderno. A continuación, nos sumergiremos en la Arquitectura basada en eventos (EDA) para abordar estos desafíos redefiniendo la arquitectura del servidor.



Las aplicaciones web han recorrido un largo camino desde los días en que el contenido HTML estático se ofrecía desde un servidor. Hoy en día, las aplicaciones web se han vuelto mucho más complejas, utilizan una variedad de marcos, centros de datos y tecnologías. En los últimos años, se pueden observar dos tendencias que determinan el desarrollo del mercado de TI:



  • Transferencia de aplicaciones a la nube ;
  • Implementación de arquitectura de microservicios .


Estas ideas determinan en gran medida cómo se diseña y construye el software en la actualidad. Podemos decir que hoy ya no estamos construyendo aplicaciones, sino plataformas. Las aplicaciones ya no ocupan espacio informático compartido. En su lugar, tienen que intercambiar información entre sí mediante protocolos de comunicación ligeros, como API REST o llamadas a procedimiento remoto (RPC). Este modelo ha dado lugar a excelentes productos como Facebook, Netflix, Uber y más.

Este artículo explorará algunos de los desafíos que impulsan la innovación en el desarrollo web moderno. A continuación, nos sumergiremos en la Arquitectura basada en eventos (EDA) para abordar estos desafíos redefiniendo la arquitectura del servidor.



Problemas actuales de la web moderna



Cualquier tecnología web debe hacer frente a los desafíos que deben afrontar las aplicaciones asincrónicas multiusuario modernas, diseñadas para funcionar sin problemas:



Disponibilidad



Ahora no trabajamos con una aplicación, sino con muchas, docenas o incluso cientos, de servicios relacionados, y cada uno de ellos debe resolver sus problemas las 24 horas del día, los siete días de la semana. ¿Cómo se puede lograr esto? La mayoría de las veces, el servicio se escala horizontalmente a varias instancias que se pueden distribuir en varios centros de datos para garantizar una alta disponibilidad. Todas las solicitudes de este servicio en particular se enrutan y distribuyen uniformemente en todas las instancias. Algunas herramientas de implementación proporcionan capacidades de recuperación automática, por lo que si una instancia falla, se crea otra para reemplazarla.



Escalabilidad



La escalabilidad es en muchos aspectos similar a la disponibilidad. La esencia de la accesibilidad es garantizar que al menos una instancia del servicio esté en funcionamiento, lista para atender las solicitudes entrantes. La escalabilidad, a su vez, está relacionada principalmente con el rendimiento. Si una aplicación está sobrecargada, se crean nuevas instancias de esa aplicación para adaptarse al mayor número de solicitudes. Pero escalar aplicaciones verticalmente no es una tarea trivial, especialmente cuando se trata de aplicaciones con estado .



Una fuente de verdad



Antes de la llegada de los microservicios, esta era una tarea bastante sencilla. Todos los datos se ubicaron en una ubicación, por regla general, era una u otra base de datos relacional. Sin embargo, cuando varios servicios comparten una base de datos, se pueden crear problemas como dependencias entre diferentes equipos con respecto a cambios de esquema o problemas de rendimiento. Por lo general, este problema se resolvió asignando su propia base de datos para cada servicio. Una fuente distribuida de la verdad es muy útil para mantener una arquitectura limpia, pero en tal situación debe lidiar con transacciones distribuidas y la complejidad de soportar múltiples bases de datos.



Sincronicidad



En un escenario típico de solicitud-respuesta, el cliente espera que el servidor responda; bloquea todas las acciones hasta que recibe una respuesta o hasta que expira el retraso especificado. Si toma este comportamiento y lo implementa en una arquitectura de microservicio con cadenas de llamadas que se ejecutan en todo el sistema, puede terminar fácilmente en el llamado "infierno de microservicios". Todo comienza con una llamada a un solo servicio, llamémoslo "servicio A". Pero luego el servicio A tiene que llamar al servicio B y comienza la diversión. El problema con este comportamiento es el siguiente: si el servicio en sí está asociado con recursos bloqueados (por ejemplo, un hilo está colgado), los retrasos crecen exponencialmente. Si permitimos un retraso de 500 ms por servicio, y hay cinco llamadas de servicio en la cadena, entonces el primer servicio necesitará un retraso de 2500 ms (2,5 segundos) y el último, 500 ms.







Los desafíos de la web moderna



Introducción a la arquitectura impulsada por eventos



Event-Driven Architecture (EDA) es un paradigma de arquitectura de software que facilita la generación, descubrimiento, consumo de eventos y la respuesta a los mismos.




En las aplicaciones clásicas de tres niveles, el núcleo del sistema es la base de datos. En EDA, el enfoque cambia a los eventos y cómo se filtran a través del sistema. Este cambio de enfoque nos permite cambiar completamente la forma en que diseñamos aplicaciones y resolvemos los problemas antes mencionados.



Antes de ver exactamente cómo se hace esto en EDA, veamos qué es un "evento". Un evento es una acción que inicia alguna notificación o un cambio en el estado de la aplicación. La luz se encendió (notificación), el termostato apagó el sistema de calefacción (notificación), el usuario cambió su dirección (cambio de estado), uno de tus amigos cambió su número de teléfono (cambio de estado). Todos estos son eventos, pero aún no es un hecho que debamos agregarlos a una solución impulsada por eventos. Se supone que solo se agregan a la arquitectura eventos relevantes para la empresa. El evento "el usuario hace un pedido" es importante desde el punto de vista comercial, pero "el usuario come una pizza o un almuerzo" no lo es.



Si piensa en algunos eventos, luego en algunos, queda inmediatamente claro que son importantes para el negocio, y en otros, no. Especialmente sobre aquellos que ocurren en respuesta a otros eventos. Se utiliza una técnica llamada " asalto de eventos " para identificar eventos que pasan por el sistema . Los participantes en el desarrollo de aplicaciones (desde programadores hasta desarrolladores de lógica de negocios y expertos en la materia) son convocados y mapean conjuntamente todos los procesos de negocios, presentándolos en forma de eventos específicos. Cuando dicho mapa está listo, el resultado del trabajo se formula en forma de requisitos que deben cumplirse al desarrollar aplicaciones.







Un ejemplo de una aplicación de reserva descrita por el método de asalto de eventos



Habiendo identificado los eventos que nos interesan y habiendo decidido cómo identificarlos, veamos cómo este paradigma puede resolver los problemas típicos mencionados anteriormente.



El flujo de eventos es unidireccional: del productor al consumidor. Compare esta situación con una llamada de REST. En principio, el productor del evento no espera una respuesta del consumidor, mientras que en el caso de una llamada REST, siempre habrá una respuesta. No hay respuesta significa que no es necesario bloquear la ejecución del código hasta que suceda algo más. En este caso, los eventos se vuelven asincrónicos por naturaleza, lo que elimina por completo el riesgo de atascarse en retrasos.



Los eventos ocurren como resultado de una acción, por lo que no hay un sistema de destino; No se puede decir que el servicio A active eventos en el servicio B; pero podemos decir que el servicio B está interesado en los eventos generados por el servicio A. Es cierto que puede haber otras "partes interesadas" en este sistema, por ejemplo, los servicios C o D.



¿Cómo podemos asegurarnos de que un evento iniciado en un determinado sistema llegue a todos? ¿Servicios "interesados"? Normalmente, estos sistemas se resuelven mediante intermediarios de mensajes. Un corredor es simplemente una aplicación que actúa como intermediario entre el emisor de eventos (la aplicación que generó el evento) y el consumidor de eventos. Por lo tanto, las aplicaciones se pueden separar perfectamente entre sí, ocupándose del problema de accesibilidad., que se discutió anteriormente en esta publicación. Si la aplicación no está disponible en este momento, entonces, al regresar en línea, comenzará a consumir eventos y procesarlos, compensando todos aquellos eventos que han ocurrido durante el período en que no estuvo disponible.



¿Qué pasa con el almacén de datos? ¿Se pueden almacenar los eventos en una base de datos o se requiere algo más en lugar de una base de datos? Ciertamente, los eventos se pueden almacenar en bases de datos, pero en este caso, se pierde su esencia de "evento". Una vez que ha ocurrido un evento, ya no podemos corregirlo, por lo tanto, los eventos son inherentemente inmutables. Las bases de datos, a su vez ... son mutables, después de ingresar los datos en la base de datos, se pueden cambiar.



Es mejor almacenar eventos en registros de eventos . Los registros de eventos no son más que centralizadosalmacén de datos, donde cada evento se registra como una secuencia de registros inmutables, el llamado "registro". Un registro se puede comparar con un registro, donde cada nuevo evento se agrega al final de la lista. Siempre puede recrear el estado más actual reproduciendo todos los eventos de registro desde el principio hasta el presente.



Entonces, hemos cubierto todos los problemas excepto la escalabilidad. Los servicios basados ​​en eventos siempre están diseñados para implementarse en múltiples instancias. Dado que el estado como tal se almacena en el registro de eventos, el servicio en sí no tendrá estado, lo que permite escalar con precisión quirúrgica cualquier servicio de interés.



La única excepción a este principio son los servicios diseñados para crear vistas materializadas.... En esencia, una vista materializada es un estado que describe un registro de eventos en un momento específico. Este enfoque se utiliza para facilitar la consulta de datos. Volviendo al tema de la escala, una vista materializada es simplemente una vista agregada de eventos que se asemeja a una tabla; pero ¿dónde almacenamos estas tablas? La mayoría de las veces, ve tales agregaciones en la memoria y, al mismo tiempo, nuestro servicio se convierte automáticamente en uno con estado. Una solución rápida y sencilla es proporcionar una base de datos local para cada servicio que crea vistas materializadas. De esta forma, el estado se almacena en la base de datos y el servicio se ejecuta sin estado.







Aunque la arquitectura impulsada por eventos ha existido durante más de 15 años, solo recientemente ha ganado una gran popularidad, y esto no es una coincidencia. La mayoría de las empresas atraviesan una etapa de " transformación digital " con demandas salvajes. Debido a la complejidad de estos requisitos, los ingenieros deben dominar nuevos enfoques para el diseño de software, lo que implica, en particular, debilitar el acoplamiento de los servicios entre sí y reducir el costo de mantenimiento de los servicios. EDA es una posible solución a estos problemas, pero no la única. Además, no espere que todos los problemas se resuelvan, solo necesita cambiar a EDA. Algunas características aún pueden requerir API REST robustas y antiguas o almacenar información en una base de datos. Elija el que mejor se adapte a sus necesidades y diséñelo correctamente.



All Articles