Al comienzo de un proyecto de software hay que tomar muchas decisiones. Decisiones que marcarán cómo se va a desarrollar el proyecto, qué es lo que va a recibir el cliente y cuál es el valor que se aporta.
En las primeras fases del proyecto, hay que realizar un diseño de lo que se va a hacer: una arquitectura del sistema. Para que el desarrollo e implantación del proyecto sean lo más óptimos posible, es muy recomendable que esta arquitectura sea robusta y adaptable a las necesidades del cliente. Aquí es donde los microservicios pueden ser útiles. Te contamos todas sus ventajas y cómo empezar a utilizarlos.
Los sistemas monolíticos son historia
Hubo un tiempo en el que los ordenadores eran poco más que calculadoras gigantes que se usaban para realizar operaciones matemáticas complicadas a una velocidad nunca antes vista. Según estos sistemas fueron evolucionando y generalizándose, siendo capaces de realizar tareas cada vez más complejas, la organización lógica interna de los mismos se fue complicando.
La industria y la sociedad cada vez demandaban programas más complejos y con requisitos más exigentes. Esto llevó a la llamada “Crisis del software” a final de los años 80 y principios de los 90: los sistemas software que se desarrollaban sin una buena planificación, estimaciones y diseño acababan saliendo mucho más caros de lo que se esperaba, ya sea por tiempo de desarrollo o por coste de recursos hardware o humanos.
Fue entonces cuando se vio la importancia de realizar ese diseño o una arquitectura de los sistemas antes de empezar a implementarlos, pues ayudaba en ese proceso y los costes y los tiempos se veían reducidos.
A pesar de la existencia de estos estudios y de ser enseñados en las escuelas de ingeniería, muchas veces el resultado de un proyecto acaba siendo monolítico. Decimos que un sistema es monolítico cuando el software se compone de una sola pieza que se encarga de llevar a cabo las operaciones de la aplicación desde el inicio hasta su fin, sin dejar apenas trazas intermedias.
Este tipo de sistemas resultan sencillos de entender para el desarrollador cuando el proyecto es pequeño y está en sus primeras fases, pero según crece y se complica, su mantenimiento se vuelve cada vez más complejo. Todo se convierte en una gran construcción de software que hay que entender y conocer para saber qué pieza hay que tocar si se detecta un fallo.
Por el lado de la operación, ocurre una situación parecida: cuando hay que reiniciar la aplicación o instalar una nueva versión, hay que tener en cuenta todo el conjunto del software que la compone para no dejar procesos sin atender que puedan generar inconsistencias en el sistema en el futuro. Además, cuanto más complejos se vuelven estos sistemas, más hardware requieren, por lo que las máquinas donde se ejecutan se hacen cada vez más grandes y más costosas de mantener.
Divide y vencerás: aplicaciones basadas en microservicios
Una de las estrategias para resolver esta problemática es diseñar las aplicaciones informáticas orientadas a servicios independientes. En vez de montar un gran sistema que se encargue de toda la lógica (recepción de datos, procesamiento de los mismos, almacenamiento y formación de la salida), es mejor montar varios sistemas más pequeños que se encarguen de cada una de estas tareas de manera individual. Esto se conoce como arquitecturas software orientadas a microservicios.

Fig. 1. Sistema monolítico vs. sistema basado en servicios.
Entre sus ventajas, los sistemas con una arquitectura basada en microservicios son:
- Más sencillos de desarrollar: Los microservicios deben responder a una tarea concreta dentro del sistema. Además, las salidas y entradas deben estar bien definidas desde el principio, lo que hace que haya menos dudas de los requisitos.
- Más fiables, ya que es más fácil crear tests automáticos para probarlos.
- Mayor reusabilidad. Al ser módulos independientes, es fácil volver a utilizarlos en diferentes proyectos.
- Más sencillos de desplegar y operar. Al ser módulos cerrados, se suelen desarrollar nativamente dentro de contenedores Docker. Esto permite un despliegue y operación más sencillos. Además, si ocurriese algún problema con el módulo, el problema queda limitado a ese contenedor.
- Mejor escalabilidad: Docker permite lanzar estos contenedores como servicios con varias réplicas, por lo que es sencillo poner más copias del mismo contenedor si hubiese un cambio en las necesidades de respuesta del producto.
Comunicación entre microservicios con una API
Comúnmente, la comunicación entre los diferentes microservicios se realiza a través de una API (Application Programming Interface, interfaz de programación de aplicaciones). Una API permite a los desarrolladores hacer llamadas al servicio desde otros programas o interfaces gráficas utilizando un protocolo de llamadas HTTP.
Para poder interactuar con el servicio en cuestión, los datos de entrada y salida suelen estar en lenguajes de definición de datos genéricos como JSON o XML. Una de las principales ventajas de usar una API es que la definición de los endpoints (direcciones web para hacer llamadas a la API), junto con sus entradas y salidas, está clara desde el principio.

Fig. 2. Esquema de funcionamiento de una API.
En el Instituto de Ingeniería del Conocimiento (IIC) disponemos de varios servicios, como el de análisis de sentimiento o el de predicción de claridad de textos, que se pueden consumir en forma de API para poder ser integrados de manera sencilla en otros productos software y así aumentar el valor de la solución del cliente.
Llevándolo a producción con Docker
Una de las principales ventajas de la arquitectura basada en microservicios es que estos son independientes y pueden ejecutarse dentro de un contenedor Docker. Un contenedor Docker permite hacer una abstracción del sistema operativo donde va a estar instalado el programa, dejando dentro del contenedor únicamente aquellas dependencias que necesite el programa para funcionar.
Esto hace que ni las actualizaciones que reciba el sistema operativo del servidor, ni el movimiento del contenedor a otro servidor con otro sistema operativo diferente y paquetes instalados con otras versiones, afecten a lo que haya dentro del contenedor.
Además, cuando se desarrolla una aplicación dentro de un contenedor Docker, esta aplicación puede ser “compilada” o paquetizada en una imagen Docker. Esta imagen se puede almacenar en un repositorio local o público para poder utilizarla fácilmente en otros proyectos y poder construir sobre ella.
También es posible conectar este repositorio a procesos de integración continua y despliegue continuo, dentro de herramientas como Gitlab o Jenkins. Esto permite crear un camino de procesos automáticos que se ejecutan cuando una desarrolladora o un desarrollador hace un cambio en su repositorio de código. Este camino comienza con la revisión del código que se ha cambiado o creado. Después, pasan los test automáticos y se compilan a una imagen Docker. Finalmente, se despliega la actualización en los servidores que hagan falta.
¿Cómo me paso a los microservicios?
Hay que tener en cuenta que acometer todos estos cambios no es tarea fácil. Muchas veces pasar de un sistema monolítico a uno basado en microservicios es muy costoso. Separar los procesos que lo forman en otros más pequeños no es siempre trivial.
Una estrategia que se puede seguir es hacer que todos los nuevos desarrollos de un proyecto se planteen desde el principio como microservicios dockerizados y, por otro lado, ir acometiendo los cambios sobre el sistema monolítico, desgranándolo en servicios más pequeños y delimitados. Este es un proceso que puede durar años si el sistema que se quiere actualizar es muy grande, pero conlleva grandes ventajas a largo plazo en términos de mantenibilidad y costes de desarrollo y operación.