Editor – Esta serie de siete artículos ya está completa:
También puede descargar el conjunto completo de artículos, además de información sobre la implementación de microservicios utilizando NGINX Plus, como un libro electrónico: Microservicios: Desde el diseño hasta la implementación . Y consulte nuestra serie sobre la Arquitectura de referencia de microservicios y la página de Soluciones de microservicios .
Este es el séptimo y último artículo de mi serie sobre la creación de aplicações con microservicios. El primer artículo presenta el patrón de arquitectura de microservicios y analiza los beneficios y desventajas de utilizar microservicios. Los siguientes artículos analizan diferentes aspectos de la arquitectura de microservicios: uso de una API Gateway<.htmla>, comunicación entre procesos , descubrimiento de servicios , gestión de datos basada en eventos e implementación de microservicios . En este artículo, analizamos estrategias para migrar una aplicação monolítica a microservicios.
Espero que esta serie de artículos te haya proporcionado una buena comprensión de la arquitectura de microservicios, sus beneficios y desventajas, y cuándo usarla. Quizás la arquitectura de microservicios sea una buena opción para su organización.
Sin embargo, es bastante probable que esté trabajando en una aplicação monolítica grande y compleja. Su experiencia diaria de desarrollo e implementación de su aplicação es lenta y dolorosa. Los microservicios parecen un nirvana lejano. Afortunadamente, existen estrategias que puedes utilizar para escapar del infierno monolítico. En este artículo, describo cómo refactorizar incrementalmente una aplicação monolítica en un conjunto de microservicios.
El proceso de transformar una aplicação monolítica en microservicios es una forma de modernización de aplicação . Eso es algo que los desarrolladores han estado haciendo durante décadas. Como resultado, hay algunas ideas que podemos reutilizar al refactorizar una aplicação en microservicios.
Una estrategia que no se debe utilizar es la reescritura del “Big Bang”. Ahí es cuando concentras todos tus esfuerzos de desarrollo en construir una nueva aplicação basada en microservicios desde cero. Aunque suene atractivo, es extremadamente arriesgado y probablemente terminará en fracaso. Como dijo Martin Fowler, "¡lo único que garantiza una reescritura del Big Bang es un Big Bang!"
En lugar de reescribir de manera Big Bang, deberías refactorizar de forma incremental tu aplicação monolítica. Construye gradualmente una nueva aplicação que consta de microservicios y la ejecuta junto con su aplicação monolítica. Con el tiempo, la cantidad de funcionalidad implementada por la aplicação monolítica se reduce hasta que desaparece por completo o se convierte en otro microservicio. Esta estrategia es similar a realizar el mantenimiento de su automóvil mientras conduce por una autopista a 112 km/h: es un desafío, pero mucho menos riesgoso que intentar reescribir el Big Bang.
Martin Fowler se refiere a esta estrategia de modernización de aplicação como la Aplicação Strangler . El nombre proviene de la enredadera estranguladora (también conocida como higuera estranguladora) que se encuentra en las selvas tropicales. Una enredadera estranguladora crece alrededor de un árbol para alcanzar la luz del sol por encima del dosel del bosque. A veces, el árbol muere, dejando una enredadera con forma de árbol. La modernización de aplicação sigue el mismo patrón. Construiremos una nueva aplicação que constará de microservicios alrededor de la aplicação heredada, que eventualmente morirá.
Veamos diferentes estrategias para hacer esto.
La Ley de los Agujeros dice que siempre que estés en un agujero debes dejar de cavar. Este es un gran consejo a seguir cuando su aplicação monolítica se ha vuelto inmanejable. En otras palabras, deberías dejar de hacer más grande el monolito. Esto significa que cuando estás implementando una nueva funcionalidad no debes agregar más código al monolito. En cambio, la gran idea de esta estrategia es poner ese nuevo código en un microservicio independiente. El siguiente diagrama muestra la arquitectura del sistema después de aplicar este enfoque.
Además del nuevo servicio y el monolito heredado, hay otros dos componentes. El primero es un enrutador de solicitudes, que maneja las solicitudes entrantes (HTTP). Es similar a la puerta de enlace API descrita en un artículo anterior<.htmla>. El enrutador envía solicitudes correspondientes a nuevas funcionalidades al nuevo servicio. Enruta solicitudes heredadas al monolito.
El otro componente es el código de pegamento, que integra el servicio con el monolito. Un servicio rara vez existe de forma aislada y a menudo necesita acceder a datos propiedad del monolito. El código de unión, que reside en el monolito, en el servicio o en ambos, es responsable de la integración de datos. El servicio utiliza el código de pegamento para leer y escribir datos propiedad del monolito.
Hay tres estrategias que un servicio puede utilizar para acceder a los datos del monolito:
Al código de pegamento a veces se le denomina capa anticorrupción . Esto se debe a que el código de pegamento evita que el servicio, que tiene su propio modelo de dominio prístino, se contamine con conceptos del modelo de dominio del monolito heredado. El código de pegamento se traduce entre los dos modelos diferentes. El término capa anticorrupción apareció por primera vez en el libro de lectura obligada Domain Driven Design de Eric Evans y luego se perfeccionó en un informe técnico . Desarrollar una capa anticorrupción puede ser una tarea nada trivial. Pero es esencial crear uno si quieres salir del infierno monolítico.
Implementar una nueva funcionalidad como un servicio liviano tiene un par de beneficios. Evita que el monolito se vuelva aún más inmanejable. El servicio se puede desarrollar, implementar y escalar independientemente del monolito. Experimenta los beneficios de la arquitectura de microservicios con cada nuevo servicio que crees.
Sin embargo, este enfoque no soluciona en nada los problemas del monolito. Para solucionar esos problemas es necesario romper el monolito. Veamos estrategias para lograrlo.
Una estrategia que reduce la aplicação monolítica es dividir la capa de presentación de las capas de lógica de negocios y acceso a datos. Una aplicação empresarial típica consta de al menos tres tipos diferentes de componentes:
Generalmente existe una separación clara entre la lógica de presentación de un lado y la lógica comercial y de acceso a datos del otro. El nivel empresarial tiene una API de grano grueso que consta de una o más fachadas, que encapsulan componentes de lógica empresarial. Esta API es una costura natural a lo largo de la cual puedes dividir el monolito en dos aplicações más pequeñas. Una aplicação contiene la capa de presentación. La otra aplicação contiene la lógica empresarial y de acceso a datos. Después de la división, la aplicação de lógica de presentación realiza llamadas remotas a la aplicação de lógica de negocios. El siguiente diagrama muestra la arquitectura antes y después de la refactorización.
Dividir un monolito de esta manera tiene dos beneficios principales. Le permite desarrollar, implementar y escalar las dos aplicações independientemente una de la otra. En particular, permite a los desarrolladores de la capa de presentación iterar rápidamente en la interfaz de usuario y realizar fácilmente pruebas A/B, por ejemplo. Otro beneficio de este enfoque es que expone una API remota que puede ser llamada por los microservicios que usted desarrolle.
Esta estrategia, sin embargo, es sólo una solución parcial. Es muy probable que una o ambas aplicações sean un monolito inmanejable. Para eliminar el o los monolitos restantes debes utilizar la tercera estrategia.
La tercera estrategia de refactorización es convertir los módulos existentes dentro del monolito en microservicios independientes. Cada vez que se extrae un módulo y se convierte en un servicio, el monolito se reduce. Una vez que hayas convertido suficientes módulos, el monolito dejará de ser un problema. O bien desaparece por completo o se vuelve tan pequeño que se convierte en un servicio más.
Una aplicação monolítica grande y compleja consta de decenas o cientos de módulos, todos los cuales son candidatos para la extracción. Descubrir qué módulos convertir primero suele ser un desafío. Un buen enfoque es comenzar con unos pocos módulos que sean fáciles de extraer. Esto le brindará experiencia con los microservicios en general y el proceso de extracción en particular. Después de esto debes extraer aquellos módulos que te brindarán el mayor beneficio.
Convertir un módulo en un servicio suele llevar mucho tiempo. Desea clasificar los módulos según el beneficio que recibirá. Generalmente es beneficioso extraer módulos que cambian con frecuencia. Una vez que haya convertido un módulo en un servicio, podrá desarrollarlo e implementarlo independientemente del monolito, lo que acelerará el desarrollo.
También es beneficioso extraer módulos que tengan requisitos de recursos significativamente diferentes a los del resto del monolito. Es útil, por ejemplo, convertir un módulo que tiene una base de datos en memoria en un servicio, que luego puede implementarse en hosts con grandes cantidades de memoria. De manera similar, puede valer la pena extraer módulos que implementen algoritmos computacionalmente costosos, ya que el servicio puede luego implementarse en hosts con muchas CPU. Al convertir módulos con requisitos de recursos particulares en servicios, puede hacer que su aplicação sea mucho más fácil de escalar.
A la hora de decidir qué módulos extraer, es útil buscar límites de grano grueso existentes (también conocidos como costuras). Hacen que sea más fácil y más barato convertir módulos en servicios. Un ejemplo de dicho límite es un módulo que sólo se comunica con el resto de la aplicação a través de mensajes asincrónicos. Puede resultar relativamente barato y sencillo convertir ese módulo en un microservicio.
El primer paso para extraer un módulo es definir una interfaz de grano grueso entre el módulo y el monolito. Lo más probable es que sea una API bidireccional, ya que el monolito necesitará datos propiedad del servicio y viceversa. A menudo resulta complicado implementar una API de este tipo debido a las dependencias enredadas y los patrones de interacción detallados entre el módulo y el resto de la aplicação. La lógica empresarial implementada utilizando el patrón de modelo de dominio es especialmente difícil de refactorizar debido a las numerosas asociaciones entre las clases del modelo de dominio. A menudo será necesario realizar cambios importantes en el código para romper estas dependencias. El siguiente diagrama muestra la refactorización.
Una vez que se implementa la interfaz de grano grueso, se convierte el módulo en un servicio independiente. Para ello, debe escribir código para permitir que el monolito y el servicio se comuniquen a través de una API que utiliza un mecanismo de comunicación entre procesos (IPC). El siguiente diagrama muestra la arquitectura antes, durante y después de la refactorización.
En este ejemplo, el módulo Z es el módulo candidato a extraer. Sus componentes son utilizados por el Módulo X y éste utiliza el Módulo Y. El primer paso de refactorización es definir un par de API de grano grueso. La primera interfaz es una interfaz de entrada que utiliza el Módulo X para invocar el Módulo Z. La segunda es una interfaz de salida que utiliza el Módulo Z para invocar el Módulo Y.
El segundo paso de refactorización convierte el módulo en un servicio independiente. Las interfaces de entrada y salida se implementan mediante código que utiliza un mecanismo IPC. Lo más probable es que necesites construir el servicio combinando el Módulo Z con un marco de Microservice Chassis que maneje cuestiones transversales como el descubrimiento de servicios.
Una vez que haya extraído un módulo, tendrá otro servicio que se puede desarrollar, implementar y escalar independientemente del monolito y de cualquier otro servicio. Incluso puede reescribir el servicio desde cero; en este caso, el código API que integra el servicio con el monolito se convierte en una capa anticorrupción que traduce entre los dos modelos de dominio. Cada vez que extraes un servicio, das otro paso en la dirección de los microservicios. Con el tiempo, el monolito se reducirá y tendrá un número cada vez mayor de microservicios.
El proceso de migrar una aplicação existente a microservicios es una forma de modernización de la aplicação . No deberías migrar a microservicios reescribiendo tu aplicação desde cero. En lugar de ello, debería refactorizar de forma incremental su aplicação en un conjunto de microservicios. Hay tres estrategias que puedes utilizar: implementar nuevas funcionalidades como microservicios; dividir los componentes de presentación de los componentes comerciales y de acceso a datos; y convertir los módulos existentes en el monolito en servicios. Con el tiempo, la cantidad de microservicios crecerá y la agilidad y velocidad de su equipo de desarrollo aumentarán.
Editor – Esta serie de siete artículos ya está completa:
También puede descargar el conjunto completo de artículos, además de información sobre la implementación de microservicios utilizando NGINX Plus, como un libro electrónico: Microservicios: Desde el diseño hasta la implementación . Y consulte nuestra serie sobre la Arquitectura de referencia de microservicios y la página de Soluciones de microservicios .
El bloguero invitado Chris Richardson es el fundador del CloudFoundry.com original, una de las primeras PaaS (plataforma como servicio) de Java para Amazon EC2. Ahora asesora a organizaciones para mejorar la forma en que desarrollan e implementan aplicações. También escribe periódicamente sobre microservicios en https://microservices.io
"Esta publicación de blog puede hacer referencia a productos que ya no están disponibles o que ya no reciben soporte. Para obtener la información más actualizada sobre los productos y soluciones F5 NGINX disponibles, explore nuestra familia de productos NGINX . NGINX ahora es parte de F5. Todos los enlaces anteriores de NGINX.com redirigirán a contenido similar de NGINX en F5.com.