Descomposición de Monolitos: Patrones de Arquitectura aplicados en AWS (Segunda Parte)

En la primera parte de este artículo, hablamos del patrón Stragler fig y como el servicio de AWS Migration Hub Refactor nos podía ayudar a crear la infraestructura y a aplicar las buenas prácticas de AWS para poder usar ese patrón.

Nos quedamos con la pregunta de si durante el proceso de migración, desde el monolito también se realiza una llamada al servicio que acabamos de migrar. ¿Cómo podemos solucionar este problema? En este caso necesitamos exponer la funcionalidad dentro del monolito para que se pueda llamar desde el nuevo microservicio. Pero el monolito puede ser una aplicación legacy, antigua y además de migración a microservicios, hemos modernizado el servicio y hemos actualizado su protocolo de comunicación y puede que también su contrato. Para evitar que la comunicación entre el monolito y el servicio impacten en la implementación de los servicios, se puede otro patrón de arquitectura llamado Anticorruption Layer.

Patron Anticorruption Layer

El patrón de Anticorruption Layer (ACL) es un diseño arquitectónico utilizado para aislar y traducir las interacciones entre dos sistemas que utilizan modelos de datos diferentes, especialmente cuando se integra un sistema heredado o externo con otro sistema nuevo. La capa de anticorrupción actúa como una barrera protectora (parecido al patrón adapter), asegurándose de que las interacciones entre los dos sistemas sean fluidas y evitando la contaminación de los modelos de datos entre sí. Este patrón fue descrito por Eric Evans en su libro sobre Domain-Driven Design.

El Patrón de Anticorruption Layer (ACL) a menudo se relaciona con el Patrón Strangler Fig cuando se está modernizando una aplicación monolítica a una arquitectura basada en microservicios. A medida que los nuevos microservicios reemplazan gradualmente partes de la aplicación monolítica, es posible que existan diferencias significativas en los modelos de datos y las interfaces de comunicación entre los dos sistemas.

Cómo el uso de ACL puede ser beneficioso junto con el Patrón Strangler Fig:

  • Aislamiento de Complejidad: Al implementar microservicios nuevos y modernos en el marco del Patrón Strangler Fig, es posible que estos microservicios utilicen modelos de datos y formatos de comunicación más actualizados y eficientes. El ACL actúa como una capa de traducción y aislamiento, permitiendo que los microservicios se comuniquen con el monolito sin que los modelos de datos divergentes afecten la coherencia del sistema en su conjunto.
  • Evitar Contaminación del Monolito: A medida que se desarrollan microservicios, es posible que se eviten características obsoletas o problemas en el monolito original. Sin embargo, debido a las diferencias en los modelos de datos y las interacciones, los microservicios podrían verse afectados negativamente. El ACL asegura que estas diferencias no contaminen el monolito y permita que ambos sistemas coexistan.
  • Traducción y Adaptación: El ACL se encarga de traducir y adaptar las peticiones y respuestas entre los microservicios y el monolito. Puede convertir formatos de datos, normalizar terminologías y proporcionar una interfaz común que facilite la comunicación coherente entre los sistemas, independientemente de las diferencias internas.
  • Flexibilidad en la Modernización: Al permitir que el monolito y los microservicios se comuniquen a través de un ACL, se gana flexibilidad en la modernización. Los microservicios pueden evolucionar más rápidamente sin afectar el monolito, lo que permite una transición más segura y controlada bajo el Patrón Strangler Fig.

Branch by Abstraction:

El patrón Branch by Abstraction implica agregar abstracciones en el código para permitir que partes del monolito coexistan con nuevas funcionalidades. Con el tiempo, la funcionalidad del monolito se va reemplazando por completo por los servicios individuales.

Se utiliza principalmente cuando se necesita realizar cambios significativos en un sistema existente, como la modernización de componentes o la introducción de nuevas funcionalidades.

  • Migraciones Graduales: Cuando se desea migrar de una tecnología obsoleta a una más moderna y se quiere hacerlo de manera gradual sin interrupciones en la funcionalidad.
  • Introducción de Nuevas Funcionalidades: Cuando se desea agregar nuevas características o funcionalidades a un sistema existente sin afectar la operación actual.
  • Coexistencia de Versiones: Cuando se necesita coexistir con una versión existente del sistema mientras se desarrolla una nueva versión.
  • Reducción de Riesgos: Para minimizar los riesgos asociados con cambios importantes, al permitir una migración paso a paso y validación continua.

Pasos para Implementar el Patrón Strangler Fig:

  1. Crear la abstracción: Lo primero que hace falta es crear una abstracción del modulo que vamos a reemplazar.
  2. Cambiar los clientes para que usen la nueva abstracción. Refactorizar el código del monolito para que la implementación actual implementen la abstracción.
  3. Crear una nueva implementación. Crea la nueva implementación que irá al nuevo microservicio.
  4. Cambia la implementación. Una vez que se haya validado que la nueva implementación funciona correctamente, se cambia la implementación configurada en la abstracción para que cambie a la nueva.
  5. Limpiar. Cuando el nuevo mecanismo este funcionando correctamente, se debería limpiar la antigua implementación.

Este patrón se puede usar junto a las feature toggles/flags que permiten cambiar la implementación de una funcionalidad sin cambiar el código a través de un fichero de configuración. Esto reduce el riesgo de fallo, al tiempo que tarde en cambiar dinámicamente la configuración de la feature flag.

Digital Lover

AWS también nos puede ayudar con la gestión y configuración de feature flags con el servicio que lanzó el año pasado (15/03/2022) AWS AppConfig Feature Flags.

AWS AppConfig Feature Flags

La experiencia gestionada que ofrece AWS AppConfig brinda a los clientes una forma fluida y eficiente de implementar configuraciones de feature flags en sus aplicaciones.

Esta característica capacita a los usuarios para establecer y administrar rápidamente diversos feature flags, definir atributos específicos de los feature flags, establecer restricciones para validar los valores de los atributos de los feature flags e introducir nuevas características en sus aplicaciones durante la ejecución.

Puedes utilizar AWS AppConfig para implementar configuraciones y "feature flags" en aplicaciones alojadas en Amazon Elastic Compute Cloud (EC2), contenedores, servidores locales, dispositivos IoT y aplicaciones móviles.

Para nuestro ejemplo, se requiere instalar el agente de AWS AppConfig que de forma nativa recupera y resuelve las feature flags de AWS AppConfig.

Por ejemplo: $ curl "http://localhost:2772/applications/application_name/environments/environ..."

Las feature flags de AWS AppConfig te permiten implementar cambios en producción con confianza al agregar medidas de seguridad a tus feature flags. Primero, AWS AppConfig te permite establecer validadores y restricciones para cada una. Si los datos de una feature flag no son booleanos (por ejemplo, un número), los clientes pueden configurar un valor mínimo y máximo opcional para ese número para asegurarse de que algún valor de bandera accidental no cause un problema o incluso una interrupción en producción.

Además, puedes desplegar tus feature flags de forma rápida o gradual al establecer una estrategia de implementación para las actualizaciones. Las actualizaciones pueden implementarse al instante o, incluso mejor, a lo largo de horas, limitando así el alcance de cualquier cambio inesperado. Por último, AWS AppConfig revertirá automáticamente cualquier actualización de feature flag si se activa una alarma de CloudWatch.

Parallel Run

Otra forma de reducir el riesgo de errores en las migraciones para validar el correcto funcionamiento de nuestra nueva implementación hay una variante de este patrón llamado Verify Branch By Abstraction en la que existe una implementación de verificación en la cual se llama a los dos componentes y valida si se producen las mismas salidas (Parallel run). Como siempre esto tiempo sus desventajas también, ya que será necesario mantener este nuevo componente y su coste asociado.

Decorating Collaborator Pattern

Por último, todos los patrones que hemos comentado son útiles cuando la funcionalidad ya estaba presente en el monolito. Ahora, imaginemos que necesitamos extender el comportamiento del monolito pero que no es posible modificarlo.

Supongamos que queremos añadir un nuevo servicio de fidelidad, añadiendo puntos cada vez que una compra es realizada con éxito. En vez de interceptar las llamadas entrantes antes de que lleguen al monolito, permitimos la llamada de forma normal, pero con el resultado de la petición y basado en ese resultado, realizamos una nueva llamada al servicio adicional.

Este patrón está inspirado en el conocido patrón decorador, y al igual que es el caso del patrón strangler, se necesita un proxy para interceptar las llamadas y llamar al nuevo servicio.

Este patrón debería solo usarse cuando todos los datos requeridos ya están presentes en la petición o en la respuesta. En caso de no estar presentes, nuestro nuevo microservicio tendría que conectar con la base de datos del monolito, creando un acoplamiento entre el nuevo servicio y la base de datos del monolito lo cual no es una buena idea, ya que generaríamos más acoplamiento que es una de las cosas que queremos evitar al usar microservicios.

Conclusión

En resumen, los microservicios ofrecen numerosas ventajas cuando se implementan correctamente. La transformación de una aplicación monolítica a microservicios no es un proceso que ocurra en un día. Se requiere una gran dosis de análisis, de conocer el dominio y la estructura del monolito para tomar las mejores decisiones arquitectónicas.

 

A lo largo de este artículo, hemos explorado diversos patrones que pueden ser empleados en este viaje de descomposición de monolitos y como AWS nos puede ayudar en el camino. En muchas ocasiones, será necesario elegir múltiples patrones para llevar a cabo la conversión completa de una aplicación monolítica a microservicios. Hay que dedicar tiempo a planificar la estrategia y esta inversión de tiempo y esfuerzo definitivamente valdrá la pena a medida que se observen los beneficios.

En última instancia, la migración a microservicios es un proceso desafiante, conocer y saber aplicar los patrones discutidos y tomarse el tiempo necesario para diseñar una estrategia sólida, mejorará las posibilidades de una migración exitosa.

Links y referencias:

https://docs.aws.amazon.com/prescriptive-guidance/latest/cloud-design-pa...

https://martinfowler.com/bliki/FeatureFlag.html

https://docs.aws.amazon.com/appconfig/latest/userguide/appconfig-creatin...

https://catalog.us-east-1.prod.workshops.aws/workshops/2ee2fc71-0618-479...

https://martinfowler.com/bliki/BranchByAbstraction.html

https://www.stevesmith.tech/blog/application-pattern-verify-branch-by-ab...

https://docs.aws.amazon.com/es_es/prescriptive-guidance/latest/moderniza...

https://www.oreilly.com/library/view/monolith-to-microservices/978149204...

webinar AWS

Tags

AWS
Guía de posibilidades profesionales sobre AWS
He leído y acepto la política de privacidad
Acepto recibir emails sobre actividades de recruiting NTT DATA