Los microservicios están de moda desde hace muchos años, también vemos a muchos desarrolladores hablando sobre serverless y sus beneficios, y para muchas personas los monolitos son el pasado, debemos evitarlos. Pero, ¿has pensado cuál es mejor? Respuesta rápida, depende.
Y esa es la única verdad, nadie es mejor que los demás, porque depende del escenario y de los requisitos a cumplir.
Elegir la arquitectura equivocada –solo porque eliges la más de moda en el momento– puede llevarte a complejidades innecesarias o limitar las capacidades de tu aplicación. Por eso, es importante entender las ventajas y desventajas de los mismos, para tener un mejor criterio y tomar una decisión acertada.
Crear una aplicación utilizando una arquitectura monolítica no significa que sea un desarrollador que cree artefactos “obsoletos”. Significa que ha decidido que la arquitectura se ajusta mejor a los requisitos.
No, todas las empresas son Facebook, Google, Amazon, Netflix – probablemente usted no sea una de ellas-, y probablemente no tenga los mismos requisitos que ellas. Por lo tanto, tratar de aplicarles la misma arquitectura puede ser excesivo e innecesario si no se analiza correctamente.
Comencemos definiendo lo que cualquiera de esas arquitecturas
Monolitos
Esta es la más básica de las arquitecturas, su aplicación es una implementación única que contiene todo el código para que funcione, el código generalmente reside en un solo repositorio. Tradicional pero lejos de ser obsoleto.
- Un monolito no excluye que puedas modularizar el código. En realidad, es una buena idea pensar cómo hacer que el código sea modular, porque algunas aplicaciones monolíticas pueden crecer en número de clases o archivos.
- Un monolito no significa que su aplicación será un silo implementado en un servidor. No está aislado, puede exponer API a otros servicios, puede consumir API de otras aplicaciones.
- Una aplicación de monolito puede escalar horizontalmente, con algunas decisiones técnicas, puede hacer que su monolito se implemente en varios servidores. Hay servidores de aplicaciones que proporcionan agrupación en clústeres listos para usar.
- Puede aplicar alta disponibilidad, integración continua e implementación continua, implementaciones azules, caché y muchos otros principios utilizados en otras arquitecturas.
Pros:
- Desarrollo Fácil, Rápido y Económico: Por ser la arquitectura más simple, no implica complejidad en la toma de decisiones durante el desarrollo. El código reside en el mismo repositorio, es su código llamando a su código.
- Despliegue sencillo: implementar una aplicación monolítica es más fácil, simplemente implemente en un servidor de aplicaciones (o servidor web) como una unidad completa. No hay orquestación entre otros servicios.
- Manejo simple de transacciones: generalmente usan una sola base de datos para toda la aplicación, por lo tanto, es fácil manejar transacciones y mantener la integridad de los datos.
Contras:
- Código spaguetti: no significa que una aplicación monolítica sea un código spaguetti. Sin embargo, debido a que generalmente un solo repositorio contiene todo el código para su servicio, hay muchos desarrolladores involucrados en el código y la separación de preocupaciones entre capas y dominios no está configurada correctamente. Puede encontrar código que está acoplado de maneras que no deberíamos tener.
Una aplicación implementada como un monolito, pero modularizada internamente por dominio y diferentes capas, siguiendo un patrón de arquitectura limpio, no debería enfrentar este problema. - Escalado como una unidad completa: como se mencionó antes, es posible escalar una aplicación monolítica. Sin embargo, debe escalar toda la aplicación como una unidad. En algunos casos, es posible que necesite escalar procesos que no necesitan escalar. Hacer un uso no óptimo o eficiente de los recursos.
Sin embargo, en muchas de las aplicaciones el requisito de escalar es mínimo. Por ejemplo, un blog, o una aplicación interna de una empresa, donde el uso es constante y no hay picos de uso. Pero si tu aplicación es famosa y comienza a recibir mucho tráfico, esto es algo a tener en cuenta.
- Tecnologías del pasado: debido a que su aplicación es una unidad completa, si necesita migrar el idioma a otro, o entre versiones de los mismos idiomas, es posible que deba migrar todo.
Suponga que su aplicación está escrita en Node.js 11.2.0. ¿Cuánto tiempo llevará migrar todo el monolito con múltiples servicios debajo a Node.js 18.0.0? ¿Qué se debe hacer con las tareas requeridas para agregar nuevas funcionalidades? Es posible que la aplicación nunca se migre.
- Falta de adaptabilidad: cuando usa arquitectura monolítica, está limitado a las tecnologías que se usan dentro de su monolito. No se pueden utilizar otras herramientas, incluso si estas se adaptan mejor al problema en cuestión.
Para Netflix, Google o Facebook, la adaptabilidad es muy importante, necesitan mejorar y adaptarse rápidamente. Sin embargo, para la mayoría de las aplicaciones, la adaptabilidad no es relevante.
Si prestó atención, algunas de esas desventajas podrían no ser relevantes para sus requisitos. Por lo tanto, es posible que no tengan un gran impacto en su caso de uso.
Microservicios
Un microservicio es una aplicación que está estructurada como una colección de servicios, donde cada servicio tiene su responsabilidad única, y para completar la lógica comercial completa, los servicios se conectan entre sí. El nombre “micro” se refiere a la capacidad de la lógica comercial de un solo servicio y no al tamaño real de la porción; en otras palabras, un microservicio puede no ser una aplicación pequeña, sino una unidad del dominio para su aplicación.
Algunas características de los microservicios son:
- Cada servicio se implementa y vive de forma independiente.
- Cada servicio debe tener su propia base de datos. Los casos de uso para la base de datos compartida son limitados.
- Un solo servicio puede escalar hacia arriba o hacia abajo, independientemente de los demás. Digamos que su aplicación tiene un servicio a cargo de una funcionalidad que requiere muchos recursos, ese servicio puede escalar a más instancias, mientras que los demás se mantienen en un número mínimo deseado de instancias.
Pros:
- Flexibilidad de tecnologías: cada servicio puede decidir su propia pila tecnológica, algunas de ellas pueden estar en Java, otras en .Net, Python o NodeJS. Obviamente, tener muchas tecnologías puede requerir muchos desarrolladores y expertos, pero las puertas están abiertas para adaptarse según los casos de uso de su negocio. Empresas como Facebook, Google, Netflix, pueden hacerlo…
Tal vez en su empresa, solo hay un lenguaje, Java, pero sus servicios pueden usar los marcos según las necesidades, uno usando JDBC, otro JPA, usando Spring Boot o Micronaut, o usando diferentes versiones de Java 8, 11, 17. - Desarrollo Ágil: Por la naturaleza de los microservicios, el ciclo de vida del desarrollo se adapta muy bien al desarrollo ágil, utilizando Scrum o Kanban, y evitando metodologías como cascada. Por lo tanto, las nuevas funciones y avances en los servicios se pueden implementar muy rápidamente.
- Escalabilidad: los microservicios son modulares por naturaleza, deberían poder escalar de forma independiente según sus propias necesidades.
- Despliegue más rápido: tener microservicios requerirá automatizar las implementaciones mediante el despliegue usando “pipelines” de CI/CD, lo cual DEBE practicarse. Por lo tanto, una vez que la función esté lista, debería ser fácil ejecutar pruebas en esa función, pruebas de regresión en el servicio y estar listo para implementar haciendo clic en un botón en entornos superiores.
- Reduce el alcance de los cambios: la aplicación de un cambio en sus servicios no debería afectar a otros servicios no relacionados. Por lo tanto, en caso de ejecutar pruebas, solo se deben realizar pruebas para sus servicios o servicios relacionados de extremo a extremo. No es necesario probar toda la aplicación.
Contras:
- Desarrollo tolerante a fallas: – Desarrolle con el peor escenario en mente – Su servicio puede ser perfecto, nunca falla, siempre responde en el tiempo esperado, pero necesita consumir servicios de otros. Esos servicios pueden estar caídos en cualquier momento, o tener una respuesta lenta, la comunicación con ellos puede fallar en medio de una operación.
Por lo tanto, debe hacer que su aplicación sea tolerante a fallas, incluyendo: Comprobaciones de estado, Tiempos de espera, Interrupciones de circuito (Circuit Breakers), Reintentos, Respuestas predeterminadas ante fallas y algunos otros patrones. - Integridad de datos y transacciones: como el enfoque habitual es tener una base de datos por servicios, si una operación involucra más de un servicio, si ocurre un error, el manejo de transacciones es difícil de resolver. Por lo tanto, se deben considerar estrategias para mantener la integridad de los datos.
Por ejemplo: Supongamos que está realizando una compra que involucra los servicios de “pago”, “inventario” y “artículo”. Si el pago falla, pero el inventario ha sido modificado, ¿cómo manejar eso? - Latencia: cada servicio es independiente, ya no es su código el que llama a su código. Por lo general, es su código que llama a RestAPI o EventBus que solicita una operación en otro servicio. Por lo tanto, eso repercutirá en el tiempo de respuesta y provocará cierta latencia.
- Complejidad: imagine que necesita implementar una nueva característica que involucra más de un servicio, agrega complejidad para orquestar todo. Negocie con los equipos, priorice el esfuerzo, defina si todos los cambios deben implementarse en conjunto o pueden ser incrementales.
- Requerimientos de DevOps: Tener decenas de servicios y cientos de instancias requiere automatización, hacer todo de forma manual es imposible de manejar. Un sistema distribuido como los microservicios requiere una orquestación experta, que generalmente involucra a Kubernetes y otras herramientas y procesos de DevOps. Eso significa que lo más probable es que necesite emplear o contratar al menos un ingeniero de DevOps. Eso aumentará los costos y, con la demanda en aumento, los especialistas en DevOps pueden ser difíciles de contratar.
Serverless (Sin servidor)
El hecho de que se llame serverless no significa que “no tenga servidor”, obviamente hay un servidor, encargado de proporcionar toda la infraestructura y el tiempo de ejecución para ejecutar su aplicación, pero como desarrollador no le importa. El desarrollador solo se enfoca en el código que debe ejecutarse.
Pros
- Costos de computación en la nube: Pagas lo que usas… Si tu función no es llamada, no tiene costo. En monolitos, la aplicación o los servicios siempre están en ejecución, incluso si no se utilizan, por lo tanto, es un costo.
- No es necesario aprovisionar infraestructura: por lo general, elige un proveedor de la nube que proporciona la plataforma para ejecutar sus funciones y crear su aplicación sin servidor. GCP, Azure o AWS, pero puede tener algunas opciones locales como Fn-Project.
- Escalabilidad: dentro de los límites de las restricciones de concurrencia, las instancias de función se agregan o eliminan automáticamente en respuesta a las fluctuaciones en el tráfico.
- Triggerable: Hay muchos disparadores en ecosistemas de terceros, por ejemplo, es muy fácil ejecutar una función Lambda como un trabajo cron en AWS, o ejecutar una función cuando se agrega un nuevo archivo a S3.
Contras
- Vendor lock-in: Las aplicaciones que son completamente serverless o que incluyen funciones serverless están relativamente estrechamente vinculadas a la plataforma del proveedor. Si bien, la estructura de las “funciones” son similares en los diferentes proveedores de FaaS, cada uno de ellos proporciona características diferentes, y no son exactamente iguales e intercambiables.
- Complejidad: a pesar de que el proveedor “serverless” se ocupa de la infraestructura de la nube, lo que reduce la complejidad de la arquitectura, dividir la aplicación en funciones independientes significa que todavía consta de múltiples partes móviles más pequeñas, lo que la hace más compleja que un enfoque monolítico.
- Sin estado: en una arquitectura sin servidor, su equipo realmente no tiene un servidor, por lo tanto, no puede guardar su estado global. Debe diseñar sus funciones como una unidad sin estado y no depender de los estados en otros pasos.
Puede solucionar este problema agregando una base de datos en memoria a sus infraestructuras como Redis o Memcached para guardar el estado global y cada ejecución puede obtener el estado global desde allí. Pero agrega complejidad a su solución. - Solo tareas de corta duración: la arquitectura sin servidor solo funciona en procesos cortos en tiempo real. Si se trata de una operación a largo plazo, es posible que deba planificar la funcionalidad FaaS adicional. Por ejemplo, las funciones de AWS Lambda tienen un límite de 15 minutos por ejecución.
Conclusión
Los tres enfoques aportan sus fortalezas y debilidades y elegir uno u otro es siempre una compensación. No existe la mejor solución entre ellos, depende de sus necesidades.
La arquitectura monolítica es ideal para aplicaciones pequeñas debido a su rápido desarrollo, facilidad de prueba y depuración y bajo costo. Ideal para aplicaciones o negocios donde no se requiere adaptarse a cambios frecuentes a un ritmo vertiginoso. Es la forma tradicional de crear una aplicación y todavía funciona en muchos casos de uso, si el entorno es el correcto.
La arquitectura de microservicios es ideal para aplicaciones grandes con múltiples módulos o áreas de dominio. Las empresas o aplicaciones con alto volumen de usuarios, que requieren escalar dinámicamente bajo demanda y adaptarse a los cambios constantes en el negocio (nuevas características, nuevas tecnologías) son un buen caso de uso para ello. Sin embargo, introduce la complejidad de la orquestación, hay demasiados elementos trabajando juntos como una unidad.
La arquitectura sin servidor es ideal para nuevas empresas que intentan reducir costos. Ideal también para aprendizaje automático, cargas de trabajo de inteligencia comercial o tareas rápidas que se pueden reducir un par de funciones. También requiere algún diseño en la orquestación o los pasos debido a la naturaleza sin estado. Si su servidor necesita estar funcionando la mayor parte del tiempo, tal vez esta no sea la mejor opción, es adecuada para cargas de trabajo.
Ahora te toca a ti analizar y decidir cuál se adapta mejor a tus necesidades, pensar bien y usar la arquitectura equivocada solo porque está de moda. Si tomas la mejor decisión en el momento adecuado, te evitarás muchos quebraderos de cabeza.
Referencias
- https://medium.com/ni-tech-talk/monolith-vs-microservices-vs-serverless-and-what-to-choose-for-your-business-needs-49d58b9e91f1
- https://kruschecompany.com/microservices-vs-monolith-best-architectural-strategy/
- https://itnext.io/you-dont-need-microservices-2ad8508b9e27
- https://dev.to/aws-builders/monoliths-vs-microservices-vs-serverless-393m
- https://gorillalogic.com/blog/creating-your-own-serverless-cloud-with-fn-project/