Desde que comenzamos a escuchar el término microservicios muchas han sido las conversaciones que se han desencadenado acerca de su idoneidad, de sus ventajas, de sus implicaciones, pero, sobre todo, acerca del tamaño. El hecho de que se llamen micro-algo, lleva a muchos a pensar que un microservicio debe ser eso, micro. Cuando realmente lo que hay detrás de todo eso es mucho más complejo y amplio. En este post intentaremos entender qué quiere decir el tamaño cuando hablamos de servicios.

En esencia los microservicios son una estrategia arquitectónica que busca la agilidad en el desarrollo de software, a partir de dividir los alcances funcionales de un producto, de manera que cada agrupación funcional pueda ser desarrollada, evolucionada, desplegada y mantenida, independientemente de las demás, y soportada por un equipo especializado en dicha parcela funcional del negocio. Ahora, la clave está en definir correctamente esas separaciones o particiones que hacemos de la solución técnica, de manera que no incurramos en problemas que anteriormente (cuando todo estaba unido en un monolito) no teníamos. Veamos pues las diferencias que encontramos entre un monolito y un microservicio.

Monolito o microservicios

Comencemos por analizar una supuesta situación en la que se trata de buscar la mejor solución para un negocio complejo en el que existen muchos procesos. Los procesos tienen cierta independencia entre ellos, aunque también dialogan, y el correcto funcionamiento global depende de la perfecta coreografía de todos ellos. ¿Cuál sería la mejor solución arquitectónica para este caso?, ¿una solución basada en un monolito o una solución basada en microservicios? Veamos la diferencia de ambas opciones desde 9 ejes:

  • Separación de funciones técnicas: entendidas funciones técnicas como todo aquello que no es requerido directamente por negocio como gestión de logs, escalado, repositorio de servicios, enrutamiento, disponibilidad, monitorización, etc. ¿Cómo se entregan?
  • Latencia de la comunicación: ¿Qué retardo sufre la información cuando tiene que viajar entre distintas partes o módulos de la solución?
  • Consistencia de los datos: ¿Cuánto tiempo tarda los lectores de un dato en tener las actualizaciones de ese dato?¿qué capacidad hay de transaccionar cambios?
  • Facilidad de evolución: ¿Cómo afecta la evolución de un módulo a otros módulos?, ¿cómo de sencillo es evitar el riesgo de impactar en otros módulos?
  • Especialización de los equipos: ¿Podemos tener equipos especializados por proceso de negocio o tienen que saber de todos los procesos soportados por la solución?
  • Automatización: ¿Cómo de sencillo es automatizar el despliegue de la solución?
  • Quantum: ¿Cómo de grande es la unidad mínima de despliegue cuando se produce un cambio?
  • Observabilidad funcional: ¿Cómo de sencillo es observar el comportamiento funcional de la solución?
  • Monitorización técnica: ¿Es sencillo encontrar problemas de performance?

Veamos ahora la comparativa:

De la tabla anterior se desprende que, en el caso de tener un negocio con muchos procesos que han de ser soportados por una solución tecnológica, es preferible que dicha solución esté diseñada mediante una arquitectura de microservicios. Veamos por qué:

Separación de funciones técnicas

  • Desde el punto de vista de la separación de funciones técnicas, en el caso del monolito muchas de estas funciones ( como enrutado, por ejemplo) se resuelven en el framework de desarrollo que por definición supone un alto grado de acoplamiento entre la lógica de negocio y el propio framework. Esto da lugar a problemas conocidos de evolución del monolito debido al framework. Si el framework no evoluciona, el monolito puede que tampoco o, por el contrario, el monolito se puede ver obligado a evolucionar por el framework.
  • Al final todo esto se traduce en costes añadidos. En el caso de los microservicios, muchas de las funciones técnicas son entregadas por plataformas basadas mayoritariamente en Kubernetes que garantizan un grandísimo desacoplamiento de la lógica de negocio lo que favorece la adaptabilidad global de la solución. 1-0 para los microservicios.

Facilidad de evolución

  • La facilidad de evolución de un proceso sin afectar a los demás es mucho más evidente en el caso de los microservicios, pues es una arquitectura que, al menos a este nivel, garantiza la cohesión del software. Aspecto mucho más complicado de garantizar en el caso del monolito, sobre todo cuando este ya es un producto que lleva tiempo siendo evolucionado y corregido.

Especializar los equipo por procesos de negocio

  • Otra característica en la que los microservicios son ventajosos es la capacidad que nos entregan de poder especializar los equipos por procesos de negocio, lo que acerca a la capa de valor a los equipos de desarrollo. Esta necesidad se complica cuando se trata de un gran monolito con muchos procesos, donde un único equipo no puede especializarse en tantos procesos de negocio. Esto suele llevar al antipatrón de tener varios equipos, cada uno especializado en un proceso de negocio, escribiendo en el mismo monolito, es decir en el mismo código.

Quantum

  • El quantum de un monolito con muchos procesos es siempre muy grande, porque el código necesario para soportar muchos procesos tiene que ser necesariamente grande. Esto es un problema porque nos obliga a realizar despliegues de todo el código, incluso para cambios pequeños de código. Esta situación suele llevar a tomar la decisión de solo realizar despliegues cuando los cambios sean significativos, lo que redunda negativamente en la frecuencia de despliegues y en el time to market. Por el contrario, en el caso de los microservicios el quantum es mucho más pequeño, lo que significa que es preferible esta arquitectura también desde este punto de vista para situaciones de muchos procesos de negocio.

Monitorización técnica

  • La monitorización técnica es más sencilla de realizar en el caso de los microservicios que en el caso del monolito porque, a pesar de tener que monitorizar muchos más componentes, es más fácil identificar aquellos cuyo performance está degradado e, incluso, saber a qué procesos de negocio está afectando.

Latencia

  • Aunque es verdad por otro lado que los microservicios implican degradar la latencia, pues siempre será peor tener que acceder a la red para compartir información que hacerlo mediante la propia memoria de un proceso o la comunicación entre procesos de un mismo computador, como es el caso de los monolitos.

Consistencia de la información

  • Otro aspecto donde los microservicios complican el problema es en lo que se refiere a la consistencia de la información al ser arquitectura distribuida, pues no es posible asegurar la transaccionalidad de las operaciones entre varios microservicios, además de que la consistencia eventual no garantiza tiempos en la actualización distribuida de un dato. En este caso el monolito es la solución más adecuada.

Observabilidad funcional

  • La observabilidad funcional es otro aspecto que se complica en el caso de arquitecturas distribuidas. Cuando la ejecución completa de un proceso de negocio está distribuida entre componentes es difícil reconstruir el comportamiento para su descubrir anomalías, etc.

Automatización

  • Y finalmente también en el lado negativo para los microservicios, la automatización se complica cuando se trata de desplegar multitud de componentes cada uno con su pipeline, lo contrario de lo que pasa cuando solo es necesario desplegar pocos módulos como es el caso del monolito.

Como primera conclusión podemos decir que, en el caso de desarrollar una solución tecnológica que soporte numerosos procesos de negocio que tienen una dependencia relativa entre ellos debemos optar por una arquitectura basada en microservicios, pues favorece la adaptabilidad.

Esta explicación también justifica la transformación de un gran monolito en varios microservicios con el objetivo de mejorar la adaptabilidad de los procesos de negocio que lo requieran.

Ahora bien, qué quiere decir una dependencia relativa: dos procesos de negocio pueden implementarse en microservicios diferentes en tanto en cuanto acepten consistencia eventual para los datos que comparten y la latencia no sea un inconveniente.

Microlito o microservicios

Veamos qué pasa cuando nuestro problema de negocio consiste en pocos procesos y no requiere de grandes cantidades de código:

Para empezar, como no es un problema complejo (pues consiste en pocos procesos sencillos de negocio) ya no podemos decir que tenemos un monolito, en todo caso sería un microlito (un monolito pequeño).

En este caso, se puede observar en la tabla que la situación cambia. Ahora vemos que el microlito sí permite la especialización del único equipo que lo mantiene, porque son pocos procesos de negocio. Cómo tenemos poco código, la evolución de cada módulo es más sencilla y el quantum es pequeño. Sin embargo, los microservicios siguen presentando los mismos inconvenientes que que en caso anterior. Y la monitorización técnica sigue siendo más sencilla en el caso de los microservicios.

Ahora, cabe hacerse una pregunta: ¿no es verdad que el comienzo de todo desarrollo de software siempre empieza incrementalmente, proceso de negocio a proceso de negocio, de manera que siempre se comienza por soluciones pequeñas?

A partir de aquí podemos deducir la siguiente conclusión: el comienzo del desarrollo de una solución de software debería iniciarse siempre por un microlito y la labor de los arquitectos será estar pendientes para tomar la decisión de escindir el microlito a microservicios cuando este vaya cogiendo tamaño y hacerlo en el momento adecuado. ¿Cuándo es el momento de adecuado? Cuando el microlito comience a convertirse en un monolito, es decir cuando se degrade el time to market o la frecuencia de despliegue o cuando la complejidad funcional no pueda ser abordada por un único equipo y merezca la pena introducir la complejidad añadida por la consistencia eventual, la observabilidad y la latencia.

Conclusiones

Las soluciones para problemas de negocio consistentes en multitud de procesos tiene sentido que se implementen mediante una arquitectura basada en microservicios, pues con ello aseguramos la adaptabilidad.

Las transacciones y allí donde no se pueden asumir los problemas derivados de la consistencia eventual deben estar implementadas en el mismo microservicio.

El comienzo del desarrollo de una solución tecnológica debe partir de un microlito, y mantener siempre la posibilidad de crear otros microlitos/microservicios alrededor del primero o, incluso, la posibilidad de partir el primero en varios microservicios cuando la complejidad aumente y lo permita la consistencia y la latencia.

Cuéntanos qué te parece.

Los comentarios serán moderados. Serán visibles si aportan un argumento constructivo. Si no estás de acuerdo con algún punto, por favor, muestra tus opiniones de manera educada.