Mejores prácticas para la arquitectura de microservicios basada en eventos

Si usted es un arquitecto empresarial, probablemente ha oído hablar de una arquitectura de microservicios y ha trabajado con ella. Y si bien es posible que en el pasado haya utilizado REST como su capa de comunicaciones de servicio, cada vez son más los proyectos que se mueven hacia una arquitectura basada en eventos. Profundicemos en los pros y los contras de esta arquitectura popular, algunas de las opciones de diseño clave que conlleva, y los anti-patrones comunes.

¿Qué es la arquitectura de microservicios basada en eventos?

En la arquitectura basada en eventos, cuando un servicio realiza algún trabajo que podría interesar a otros servicios, ese servicio produce un evento : un registro de la acción realizada. Otros servicios consumen esos eventos para que puedan realizar cualquiera de sus propias tareas necesarias como resultado del evento. A diferencia de REST, los servicios que crean peticiones no necesitan conocer los detalles de los servicios que consumen las peticiones.He aquí un ejemplo simple: Cuando se realiza un pedido en un sitio de comercio electrónico, se produce un único evento de “pedido realizado” y luego es consumido por varios microservicios:

  1. el servicio de pedidos que podría escribir un registro de un pedido en la base de datos
  2. el servicio de atención al cliente que podría crear el registro de cliente , y
  3. el servicio de pago que podría procesar el pago.

Los eventos pueden ser publicados de varias maneras. Por ejemplo, pueden publicarse en una cola que garantice la entrega del evento a los consumidores adecuados, o pueden publicarse en un flujo modelo “pub/sub” que publique el evento y permita el acceso a todas las partes interesadas. En cualquier caso, el productor publica el evento, y el consumidor recibe ese evento, reaccionando en consecuencia. Tenga en cuenta que en algunos casos, estos dos actores también pueden llamarse editor (el productor) y suscriptor (el consumidor).

Por qué utilizar una arquitectura basada en eventos

Una arquitectura basada en eventos ofrece varias ventajas sobre REST, entre las que se incluyen:

  • Asíncrono : las arquitecturas basadas en eventos son asíncronas sin bloqueo. Esto permite que los recursos pasen libremente a la siguiente tarea una vez que su unidad de trabajo esté completa, sin preocuparse por lo que sucedió antes o sucederá después. También permiten que los eventos se coloquen en colas o se almacenen en un búfer, lo que impide que los consumidores vuelvan a presionar a los productores o los bloqueen.
  • Acoplamiento suelto – los servicios no necesitan (y no deberían tener) conocimiento de, o dependencias de, otros servicios. Cuando se utilizan eventos, los servicios operan de forma independiente, sin conocimiento de otros servicios, incluyendo sus detalles de implementación y protocolo de transporte. Los servicios bajo un modelo de eventos pueden ser actualizados, probados e implementados de forma independiente y más fácil.
  • Escalado fácil – Dado que los servicios están desacoplados bajo una arquitectura basada en eventos, y dado que los servicios suelen realizar sólo una tarea, el seguimiento de los cuellos de botella de un servicio específico y el escalado de ese servicio (y sólo de ese servicio) resulta sencillo.
  • R ecovery support – Una arquitectura basada en eventos con una cola puede recuperar el trabajo perdido mediante la “repetición” de eventos del pasado. Esto puede ser valioso para evitar la pérdida de datos cuando un consumidor necesita recuperarse.

Por supuesto, las arquitecturas basadas en eventos también tienen sus inconvenientes. Son fáciles de sobreingeniería al separar preocupaciones que podrían ser más simples cuando están estrechamente acopladas; pueden requerir una inversión inicial significativa; y a menudo resultan en una complejidad adicional en infraestructura, contratos o esquemas de servicio, sistemas de construcción políglota y gráficos de dependencia.Tal vez el inconveniente y el desafío más importante sea la gestión de datos y transacciones. Debido a su naturaleza asincrónica, los modelos basados en eventos deben manejar cuidadosamente datos inconsistentes entre servicios, versiones incompatibles, estar atentos a eventos duplicados, y típicamente no soportan transacciones ACID, sino que soportan consistencia eventual que puede ser más difícil de rastrear o depurar. El pros escalable, libremente acoplado, diseño amigable para el desarrollo supera a los contras.

Cuándo usar REST

Hay, sin embargo, momentos en los que una interfaz REST/web puede seguir siendo preferible:

  • Necesita una interfaz de solicitud/respuesta con límite de tiempo
  • Soporte conveniente para transacciones
  • Su API está disponible al público
  • Su proyecto es pequeño (REST es mucho más sencillo de configurar e implementar)

Su opción de diseño más importante – Marco de trabajo de mensajería

Una vez que se haya decidido por una arquitectura basada en eventos, es el momento de elegir el marco de trabajo de su evento. La forma en que se producen y consumen sus eventos es un factor clave en su sistema. Existen docenas de marcos de trabajo y opciones probadas y la elección de la correcta lleva tiempo e investigación, y su elección básica se reduce al procesamiento de mensajes o al procesamiento de secuencias. Procesamiento de mensajes En el procesamiento de mensajes tradicional, un componente crea un mensaje y luego lo envía a un destino específico (y normalmente único). El componente de recepción, que ha estado sentado y esperando, recibe el mensaje y actúa en consecuencia. Normalmente, cuando llega el mensaje, el componente receptor realiza un único proceso. Un ejemplo típico de una arquitectura de procesamiento de mensajes es una cola de mensajes. Aunque la mayoría de los proyectos más nuevos utilizan el procesamiento de secuencias (como se describe a continuación), las arquitecturas que utilizan colas de mensajes (o eventos) siguen siendo populares. Las colas de mensajes suelen utilizar un sistema de “almacenar y reenviar” de corredores en el que los eventos viajan de un corredor a otro hasta que llegan al consumidor adecuado. ActiveMQ y RabbitMQ son dos ejemplos populares de estructuras de colas de mensajes. Ambos proyectos tienen años de uso probado y comunidades establecidas. Procesamiento de secuencias Por otro lado, en el procesamiento de secuencias, los componentes emiten eventos cuando alcanzan un estado determinado. Otros componentes interesados escuchan estos eventos en el flujo de eventos y reaccionan en consecuencia. En el procesamiento de secuencias, los componentes pueden reaccionar a múltiples eventos al mismo tiempo y aplicar operaciones complejas en múltiples secuencias y eventos. Con el procesamiento de secuencias, un sistema puede reproducir un historial de eventos, conectarse después de que ocurra el evento y seguir reaccionando ante él, e incluso realizar cálculos de ventanas deslizantes. Por ejemplo, podría calcular el uso medio de la CPU por minuto a partir de un flujo de eventos por segundo. Kafka es una solución madura y estable utilizada en muchos proyectos. Se puede considerar una solución de procesamiento de flujos de potencia industrial. Kafka tiene una gran base de usuarios, una comunidad útil y un conjunto de herramientas evolucionado. Otras opciones Existen otros marcos de trabajo que ofrecen una combinación de procesamiento de secuencias y mensajes o su propia solución única. Por ejemplo, Pulsar, una nueva oferta de Apache, es un sistema de mensajería pub/sub de código abierto que soporta tanto streams como colas de eventos, todos con un rendimiento extremadamente alto. Pulsar es rico en características, ofrece multi-tenancy y geo-replicación, y por lo tanto complejo. Se ha dicho que Kafka aspira a un alto rendimiento, mientras que Pulsar aspira a una latencia baja. NATS es un sistema alternativo de mensajería pub/sub con colas “sintéticas”. NATS está diseñado para enviar mensajes pequeños y frecuentes. Ofrece alto rendimiento y baja latencia. Sin embargo, NATS considera aceptable cierto nivel de pérdida de datos, priorizando el rendimiento por encima de las garantías de entrega.

Otras consideraciones de diseño

Una vez que haya seleccionado el marco de su evento, aquí hay varios otros desafíos a considerar: Event Sourcing Es difícil implementar una combinación de servicios sin conexión, almacenes de datos distintos y transacciones atómicas. Un patrón que puede ayudar es el Event Sourcing. En el Event Sourcing, las actualizaciones y los borrados nunca se realizan directamente sobre los datos, sino que los cambios de estado de una entidad se guardan como una serie de eventos. CQRS La determinación de fuente de aprovisionamiento del evento anterior introduce otro problema: La Segregación de la Responsabilidad de las Consultas de Comando (CQRS) es una solución de diseño que requiere modelos separados para las operaciones de inserción y las operaciones de lectura, ya que el estado necesita ser construido a partir de una serie de eventos. Descubrir información de eventos Uno de los mayores desafíos de la arquitectura basada en eventos es la catalogación de servicios y eventos. ¿Dónde se encuentran las descripciones y los detalles de los eventos? ¿Cuál es el motivo de un evento? ¿Qué equipo creó el evento? ¿Están trabajando activamente en ello? Cómo lidiar con el cambio ¿Cambiará el esquema de un evento? ¿Cómo se modifica un esquema de evento sin romper otros servicios? La forma en que responda a estas preguntas se vuelve crítica a medida que su número de servicios y eventos crece;
<br /> </ i> </ i>
Ser un buen consumidor de eventos significa codificar esquemas que cambian. Ser un buen productor de eventos significa ser consciente de cómo los cambios en su esquema impactan a otros servicios y crear eventos bien diseñados que estén claramente documentados. On Premise vs Hosted Deployment Independientemente de la estructura de su evento, también tendrá que decidir entre desplegar el framework usted mismo en la premisa (los corredores de mensajes no son triviales de operar, especialmente con alta disponibilidad), o usar un servicio alojado como Apache Kafka en Heroku.

Anti-Patrones

Como con la mayoría de las arquitecturas, una arquitectura basada en eventos viene con su propio conjunto de anti-patrones. Aquí hay algunos de los que hay que estar atentos. Demasiado de algo bueno Tenga cuidado de no entusiasmarse demasiado al crear eventos. La creación de demasiados eventos creará una complejidad innecesaria entre los servicios, aumentará la carga cognitiva para los desarrolladores, dificultará la implementación y las pruebas, y causará congestión para los consumidores de eventos. No todos los métodos tienen que ser un evento. Eventos genéricos No utilice eventos genéricos, ni en nombre ni en propósito. Usted quiere que otros equipos entiendan por qué existe su evento, para qué se debe usar y cuándo se debe usar. Los eventos deben tener un propósito específico y ser nombrados en consecuencia. Los eventos con nombres genéricos, o los eventos genéricos con banderas confusas, causan problemas. Gráficos de dependencias complejas Tenga cuidado con los servicios que dependen unos de otros y cree gráficos de dependencias complejas o bucles de retroalimentación. Cada salto de red añade latencia adicional a la solicitud original, en particular el tráfico de red norte/sur que sale del centro de datos;
Dependiendo del pedido garantizado, la entrega o los efectos secundarios Los eventos son asíncronos; por lo tanto, incluir suposiciones de pedidos o duplicados no sólo añadirá complejidad sino que negará muchos de los beneficios clave de la arquitectura basada en eventos. Si su consumidor tiene efectos secundarios, como añadir un valor en una base de datos, es posible que no pueda recuperarse repitiendo los eventos. Optimización prematura La mayoría de los productos comienzan pequeños y crecen con el tiempo. Si bien es posible que sueñe con necesidades futuras de escalar a una organización grande y compleja, si su equipo es pequeño, la complejidad añadida de las arquitecturas basadas en eventos puede ralentizarlo. En su lugar, considere diseñar su sistema con una arquitectura simple, pero incluya la separación necesaria de preocupaciones para que pueda cambiarla a medida que sus necesidades crecen. Esperar que la arquitectura basada en eventos arregle todo En un nivel menos técnico, no espere que la arquitectura basada en eventos arregle todos sus problemas. Aunque esta arquitectura puede ciertamente mejorar muchas áreas de disfunción técnica, no puede solucionar problemas fundamentales como la falta de pruebas automatizadas, una comunicación deficiente en equipo o prácticas de desarrollo anticuadas.

Más información

Entender los pros y los contras de las arquitecturas impulsadas por eventos, y algunas de sus decisiones y retos de diseño más comunes, es una parte importante para crear el mejor diseño posible.Si quieres saber más, echa un vistazo a esta arquitectura de referencia basada en eventos que hicimos en Heroku, que te permite desplegar un proyecto de trabajo en Heroku con un solo clic. Esta arquitectura de referencia crea una tienda web que vende productos ficticios de café Los clics de los productos se registran como eventos y se almacenan en Kafka. Luego, son consumidos por un tablero de informes. El código es de código abierto para que puedas modificarlo según tus necesidades y realizar tus propios experimentos.

Etiquetas

MicroserviciosArquitecturaDirigido por EventosDesarrollo de SoftwareCodificaciónProgramaciónArquitectura de Microservicios Dirigida por EventosHackernoon Top Story

Comentarios

VictorGil19 de septiembre de 2019

Artículo muy completo.

Con respecto a los microservicios basados en eventos basados en streams que utilizan Kafka, sólo añadiría que permiten vistas materializadas locales que le permiten mantener el estado de la aplicación cerca de los servicios sin problemas, puede comprobar mi post .

máxima del 21 de septiembre de 2019

Yo añadiría orquestación como otro enfoque a la arquitectura de servicios basada en eventos. En el gran conjunto de casos de uso es mucho mejor que la coreografía descrita en este artículo. Mira el ejemplo del comienzo del artículo:

  1. el servicio de pedidos que podría escribir un registro de un pedido en la base de datos
  2. el servicio de atención al cliente que podría crear el registro de cliente , y
  3. el servicio de pago que podría procesar el pago.

Una aplicación real nunca crearía registros de pagos, clientes y pedidos basados en un único mensaje, ya que los tres servicios anteriores tienen que coordinarse entre sí para lograr el objetivo empresarial. Por ejemplo, el pago debe ser procesado sólo después de que el pedido es enviado y no procesado si no hay suficiente inventario. La orquestación resuelve este problema mucho más limpio ya que permite especificar que toda la transacción comercial es un componente centralizado.

Yo recomendaría ver el Cadence Workflow, que es un orquestador de código abierto y fácil de usar desarrollado por Uber. Por ejemplo, se utiliza para procesar solicitudes de propinas en la aplicación Uber.

Disclamer : Soy el jefe técnico del proyecto Cadence.

fmvilas30 de septiembre de 2019

Gran artículo, Jason. Disfruté leyéndolo.

Añadiría que ahora es posible documentar su arquitectura basada en eventos con AsyncAPI. Descargo de responsabilidad: Soy el creador de AsyncAPI.

Continúe la discusión