La historia del desarrollo de software está plagada de historias de grandes proyectos de desarrollo que, después de una inversión de millones de dólares y cientos de miles de horas de desarrollador de software, y con muchas de las mejores y más brillantes mentes de la industria trabajando en ellos, de alguna manera nunca lograron para entregar algo de valor a sus clientes y literalmente colapsó bajo su propia complejidad y peso.
Estos proyectos gigantescos tendían a seguir metodologías de desarrollo en cascada grandes y tradicionales que insistían en que todos los requisitos y el diseño de la aplicación se definieran al comienzo del proyecto. Se puso tanto énfasis en conseguir que todas las especificaciones del software fueran “correctas” que hubo poco margen para cumplir con los nuevos requisitos comerciales, o refactorizar y aprender de los errores cometidos en las primeras etapas de desarrollo.
Sin embargo, la realidad es que el desarrollo de software no es un proceso lineal de definición y ejecución, sino más bien evolutivo en el que se necesitan varias iteraciones de comunicación, aprendizaje y entrega al cliente antes de que el equipo de desarrollo realmente comprenda el problema.
Para agravar los desafíos del uso de metodologías tradicionales, es que muchas veces la granularidad de los artefactos de software que se entregan estos proyectos:
- Estrechamente acoplado: la invocación de la lógica empresarial se realiza a nivel del lenguaje de programación en lugar de a través de protocolos como SOAP and REST. Esto aumenta en gran medida la posibilidad de que incluso un pequeño cambio en un componente de la aplicación pueda romper otras partes de la aplicación e introducir nuevos errores.
- Fugas: la mayoría de las aplicaciones de software grandes administran diferentes tipos de datos. Por ejemplo, una aplicación de gestión de relaciones con el cliente (CRM) puede gestionar información sobre clientes, ventas y productos. En un modelo tradicional, estos datos se mantienen en el mismo modelo de datos y dentro del mismo almacén de datos. Aunque existen límites obvios entre los datos, con demasiada frecuencia resulta tentador salir de un dominio para acceder directamente a los datos que pertenecen a otro equipo. Este fácil acceso a los datos crea dependencias ocultas y permite que los detalles de implementación de las estructuras de datos internas de un componente se filtren a través de toda la aplicación. Incluso pequeños cambios en una sola tabla de base de datos pueden requerir un número significativo de cambios de código y pruebas de regresión en toda la aplicación.
- Monolítico: debido a que la mayoría de los componentes de una aplicación tradicional residen en una única base de código que se comparte entre varios equipos, cada vez que se realiza un cambio en el código, se debe volver a compilar la aplicación completa, volver a ejecutar durante un ciclo de prueba completo, y redistribuido. Incluso los pequeños cambios en el código base de la aplicación, ya sean nuevos requisitos del cliente o correcciones de errores, se vuelven costosos y requieren mucho tiempo, y los grandes cambios se vuelven casi imposible de hacer de manera oportuna.
Una arquitectura basada en microservicios adopta un enfoque diferente para brindar funcionalidad. Específicamente, las arquitecturas basadas en microservicios tienen estas características:
- Restringido: los microservicios tienen un único conjunto de responsabilidades y su alcance es limitado. Los microservicios adoptan la filosofía UNIX de que una aplicación no es más que una colección de servicios donde cada servicio hace una cosa y hace esa cosa realmente bien.
- Poco acoplado: una aplicación basada en microservicios es una colección de pequeños servicios que solo interactúan entre sí a través de una especificación y no de implementación. Cada microservicio tiene una interfaz bien definida, utilizando un protocolo de invocación no propietario (por ejemplo, HTTP y REST). Siempre que la interfaz del servicio no cambie, los propietarios del microservicio tienen más libertad para realizar modificaciones en el servicio que en una arquitectura de aplicación tradicional.
- Abstración: los microservicios poseen por completo sus estructuras y fuentes de datos. Los datos que pertenecen a un microservicio solo pueden ser modificados por ese servicio. El control de acceso a la base de datos que contiene los datos del microservicio se puede bloquear para permitir que solo el servicio acceda a ella.
- Independiente: cada microservicio en una aplicación de microservicio se puede compilar e implementar independientemente de los otros servicios utilizados en la aplicación. Esto significa que los cambios se pueden aislar y probar mucho más fácilmente que con una aplicación monolítica.
¿Por qué estos atributos de la arquitectura de microservicios son importantes para el desarrollo basado en la nube? Las aplicaciones basadas en la nube en general tienen :
- Una base de usuarios grande y diversa: los diferentes clientes desean funciones diferentes y no quieren tener que esperar un ciclo de lanzamiento de aplicaciones prolongado antes de poder comenzar a usar estas funciones. Los microservicios permiten que las características se entreguen rápidamente, porque cada servicio tiene un alcance pequeño y se accede a él a través de una interfaz bien definida.
- Requisitos de tiempo de actividad extremadamente altos: debido a la naturaleza descentralizada de los microservicios, las aplicaciones basadas en microservicios pueden aislar más fácilmente fallas y problemas apartes de una aplicación sin eliminar la aplicación completa. Esto reduce el tiempo de inactividad general de las aplicaciones y las hace más resistentes a los problemas.
- Requisitos de volumen desiguales: las aplicaciones tradicionales implementadas dentro de las cuatro paredes de un centro de datos corporativo generalmente tienen patrones de uso consistentes que emergen con el tiempo. Esto simplifica la planificación de la capacidad para este tipo de aplicaciones. Pero en una aplicación basada en la nube, un simple tweet en Twitter o una publicación en Slashdot puede impulsar la demanda de una aplicación basada en la nube por las nubes.
Debido a que las aplicaciones de microservicio se dividen en pequeños componentes que se pueden implementar de forma independiente entre sí, es mucho más fácil enfocarse en los componentes que están bajo carga y escalen esos componentes horizontalmente en varios servidores en una nube.
Aunque se necesita más que personal técnico para entregar una aplicación completa, creo que la base para el desarrollo exitoso de microservicios comienza con las perspectivas de tres roles críticos:
- El arquitecto: el trabajo del arquitecto es ver el panorama general y comprender cómo se puede descomponer una aplicación en microservicios individuales y cómo los microservicios interactuarán para ofrecer una solución.
- El desarrollador de software: el desarrollador de software escribe el código y comprende en detalle cómo funcionarán el lenguaje y los marcos de desarrollo del lenguaje.
- El ingeniero de DevOps: el ingeniero de DevOps aporta inteligencia sobre cómo se implementan y administran los servicios no solo en la producción, sino también en todos los los entornos de no producción. Las palabras clave del ingeniero de DevOps son coherencia y repetibilidad en todos los entornos.