Una guía de viaje por el Continente de los Microservicios: Building Microservices, de Sam Newman

Desde hace unos años, en el ámbito de arquitectura de software, hay una palabra que destaca sobre todas las demás: "microservicios". Se trata de una forma de estructurar una aplicación, dividiéndola en múltiples aplicaciones más o menos independientes llamadas microservicios. La finalidad es la de lograr una arquitectura más desacoplada que permita adaptarse a los cambios de una forma más veloz. Al menos en teoría, ya que hay muchas críticas al respecto.

Ténicamente no va mucho más allá de partir una aplicación en decenas de aplicaciones más utilizando las mismas herramientas que conoces hasta ahora. Es cierto que han surgido nuevas librerías y tecnologías para facilitar el desarrollo, sobre todo porque conlleva algún problema nuevo (descubrimiento de servicios, circuits breakers…). Pero en esencia no es un problema técnico, sino que es un problema de toma de decisiones ante nuevos escenarios: olvida lo que has hecho hasta ahora y enfréntate a una nueva forma de hacer las cosas.

Para que veas a qué me refiero, te propongo una serie de preguntas a las que nos hemos tenido que enfrentar los que hemos adoptado (o al menos intentado) una arquitectura de microservicios:

  • Tengo una sola base de datos y varios microservicos ¿Se comparte?¿Qué tabla va a cada microservicio?
  • Para este nuevo proyecto… ¿Tengo que usar microservicios o mejor un monolito?
  • ¿Cómo hago el despliegue? ¿ A la vez o por microservicio? Y el versionado… ¿es individual?
  • Esta nueva operación… ¿Va en un microservicio nuevo? Si lo dejo en el mismo ¿no es ya demasiado grande? ¿Cuándo lo divido?
  • Estoy repitiendo código en varios microservicios ¿Creo una librería común que importen todos?
  • Tengo dos microservicios que se comunican entre sí… ¿Comparto los DTO de cliente y servidor?¿Cómo sé que no estoy rompiendo nada al hacer un cambio en la API?
  • Cada vez tengo más dependencias y cada microservicio parecen micromonolitos… ¿Por qué?
  • Los microservicios nos hacen ir más lentos y negocio nos presiona ¿Qué hemos hecho mal?
  • …(y me dejo decenas)

El problema de entrar en un mundo nuevo, es que hay que hacer camino al andar, por lo que las dudas que surgen son muchísimas. Y sobre todo complicadas: no son dudas técnicas que cualquiera puede resolver en StackOverflow, sino que son dudas de arquitectura, de gestión de la configuración, de despliegue, de organización de equipos para trabajar con microservicios… Son dudas particulares de cada proyecto que no pueden ser resueltas salvo desde la experiencia.

Y el problema de la toma de decisiones es que llevan asociadas unas consecuencias, y seguramente esas consecuencias sean mayores de lo que esperas en un principio: si no conoces la importancia de una decisión, tampoco conocerás el calado de las consecuencias. Es posible que un par de meses después te encuentres en un lío tremendo que dificulte la evolución de la arquitectura por una decisión sobre un problema que considerabas trivial desde el punto de vista de monolitos, pero no sobre microservicios.

Espero que hayas tomado conciencia de la dificultad que supone aplicar el paradigma de los microservicios. Ahora tienes dos opciones: la mejor y primera es dejar asesorarte por alguien que haya pasado por ese trago y te enseñe el camino adecuado, pero esto no es siempre posible. La otra es que lo descubras por tí mismo, pero al menos lleves una guía de viaje, que no es otra que este Building Microservices de Sam Newman.

Sam Newman es un consultor de la empresa Thoughtworks, que si no te suena de nada, te diré que es la empresa de consultoría en la que lleva trabajando muchos años gente como Martin Fowler. Aunque los microservicios no llevan con nosotros mucho más allá que desde 2008, parece que han tenido la oportunidad de aplicarlos en unos cuantos proyectos, por lo que este libro representa una síntesis de la experiencia en esta tecnología a través de 12 capítulos.

También tengo que advertirte que no es un libro práctico que contenga extractos de código, así que no compres el libro esperando que vas a poder montar un sistema de microservicios desde 0 en Java o en otro lenguaje. No trata de cómo usar librerías ni servidores, ni habla de tecnologías en concreto, aunque sí que da valiosas citas sobre productos que pueden encajar dentro de sus consejos: Hystrix, Eureka, Spring Boot, Pact… Por tanto, espera un compendio de consejos y reflexiones generales sobre la experiencia de Sam Newman y su equipo en el mundo de microservicios. A mí me parece más valiosa la experiencia que soluciones concretas que sólo se pueden aplicar a casos concretos, pero cada uno tiene sus necesidades.

Vamos a ver un pequeño resumen de lo que se ve en cada uno de los 12 capítulos de los que consta para que te hagas una idea de lo que te vas a encontrar:

  1. Microservicios: una introducción a la arquitectura de microservicios, comentando sus características, especialmente la descomposición frente al monolito y comparándolo con la división en librerías compartidas y módulos; y sus beneficios como la posibilidad de usar diferentes lenguajes, el escalado, despliegues, independencia de desarrollo. También se comenta la necesidad de tener una organización alineada con los microservicios, aunque posteriormente se ahondará en este tema.

  2. La arquitectura evolutiva: introduce el símil del arquitecto de software con el arquitecto urbano, que diseña los principios de las ciudades, pero que deja libertad a lo que sucede en cada uno de los solares: trabajar para dejar que el desarrollo urbano surja con el tiempo y necesidades. Lo relaciona con la necesidad de la arquitectura de microservicios de dar satisfacción a objetivos no sólo técnicos sino estratégicos de la organización. Trata aspectos transversales como la necesidad de monitorización, desarrollo de interfaces, deuda técnica, gestión de excepciones, o la "gobernanza" a través de plantillas de generación de microservicios que incorporen todo lo que necesitamos para que estén alineados con lo que se espera.

  3. Cómo modelar microservicios: Debate sobre qué principios definen un buen microservicio, como el clásico "bajo acoplamiento y alta cohesión". Establece el Bounded Context del Domain Driven Design(DDD) como arma para la división correcta de un problema en microservicios, aplicándolo a un ejemplo clásico que pone de relieve algunas dificultades a la hora de aplicar esta teoría a la práctica: ¿Qué pasa cuando dividimos en dos bounded context pero en ambos está presente cierto "modelo"?¿A qué bounded context pertenece?¿Estamos haciendo una descomposición prematura?¿Y si descompongo por tecnología? En mi experiencia estas alternativas que expone y organiza en el libro son muy valiosas.

  4. Integración: aquí habla sobre cómo se van a comunicar los microservicios. No es algo sencillo cuando hablamos de microservicios porque podemos estar tomando decisiones que inconscientemente nos van a condicionar en el futuro… ¿usamos REST, SOAP, Protocol Buffers, Event-driven? Si tenemos una sola base de datos compartida por varios microservicios… ¿Y si lo que uno escribe en una tabla el otro lo lee, estableciendo un canal de comunicación a través de la base de datos o sistema de caché? También introduce el concepto de comunicación asíncrona (eventos), y de las diferencias entre orquestar microservicios(un único director manda sobre los demás), frente a coreografía (cada uno sabe qué hacer cuando sucede un evento). Otro aspecto importantísimo que trata es que no es lo mismo una llamada en la misma máquina y memoria que una llamada de red… tiene repercusiones que no verás hasta que comience a fallar en producción si no tienes cuidado :). El versionado de microservicios o si compartimos o no código a través de librerías son otros de los conceptos que se tratan, junto con el diseño de API y su composición.

  5. Dividiendo el Monolito: los microservicios suelen surgir frente a los problemas de los monolitos, así que el caso clásico suele ser crear una nueva arquitectura basada en microservicios que sustituya a un monolito que está funcionando con problemas. Comienza dando las razones por las que deberíamos (o no) dividir un monolito: ritmo de los cambios, para reflejar la estructura del equipo, seguridad, posibilidad de usar tecnologías apropiadas por dominio… Posteriormente nos presenta unos consejos generales sobre problemas que se han encontrado: ¿Cómo dividimos una única base de datos en múltiples base de datos, una por microservicio? También otro aspecto importante es el concepto de "transacción": en un monolito es sencillo hacer transacciones.. pero ¿qué pasa cuando atañen a varios microservicios comunicados por red? Pasan a ser transacciones distribuídas y ese tipo de cosas no suele acabar bien. Finalmente trata el impacto en los sistema de reporting, y cómo se debería tratar en el mundo microserviciado para reunir toda la información y que reflejase el comportamiento de un sólo sistema.

  6. Despliegue: ahora hay decenas y quizá centenas de microservicios que deben ser tratados de forma individual frente a un único despliegue del monolito. Tiene sus ventajas de adaptación al cambio, pero la complejidad es exponencial, por lo que es vital la automatización en la diferentes fases: integración continua, sistema de aprovisionamiento, Ansible, Puppet, AWS… También discute ciertas estrategias como varios microservicios por host, uno por host o el uso de contenedores como Docker, Kubernetes.

  7. Testing: las pruebas tampoco se quedan fuera de los cambios que se producen por los microservicios. Además de los clásicos test unitarios de los desarrolladores, y test de integración y end-to-end, se hace necesario testear la interacción de los microservicios con otros elementos (inlcuyendo otros microservicios) a través de Consumer-Driven test. Introduce la lógica detrás de este concepto y propone algunas herramientas como Pact.

  8. Monitorización: a día de hoy están apareciendo ligados a los microservicios nuevas tecnologías que están dando la importancia a la monitorización que se merece, tanto monitorización técnica como de conceptos de negocio. Desde el punto de vista técnico, con microservicios todo se hace mucho más complejo: encontrar un problema en un monolito es relativamente sencillo porque está concentrado en un sólo código en ejecución, pero con microservicios son múltiples los códigos en ejecución. Se hace necesario algo más “inteligente” que permita navegar en un mar de datos en búsqueda de los problemas o el estado del sistema. Así introduce técnicas para facilitar la relación de la información entre microservicios como dotar de un identificador único a las acciones del usuario y que sea compartido por cada microservicios, o introducir nuevos sistemas como la suite Elastic Search+Logstash+Kibana (ELK).

  9. Seguridad: donde explica las peculiaridades que hay ahora en microservicios, haciendo necesario centralizar en un sistema de single-sign-on todo el control de acceso: OAuth2, OpenId, SAML, Certificados roles… son algunos de los conceptos que introduce en este tema junto con nuevas visiones: cuando un microservicio llama a otro ¿cómo se autentica? También trata de temas generales de sentido común.

  10. Ley de Conway, que viene a decir algo así como que el diseño de los sistemas software al final acaban pareciéndose al diseño de los departamentos que los creó. Expone diferentes casos y cómo se deberían organizar los desarrolladores para desarrollar microservicios: ¿Cada microservicio debe ser responsabilidad de un equipo?¿Si tengo dos equipos saldrán dos microservicios? Como nota curiosa indica que Netflix organizó a sus desarrolladores del modo en que querían que su arquitectura se desarrollase.

  11. Microservicios a escala: otro capítulo en el que reflexiona sobre su experiencia con microservicios y que seguramente te sea muy valioso cuando trabajes en este tipo de entornos. Todo está muy bien en ejemplos teóricos, o cuando empiezas y tienes 5 microservicios… pero ¿qué sucede cuando las cosas empiezan a crecer mucho?¿Cuando tengas 80 microservicios y una carga alta? ¿Qué pasa con los tiempos de respuesta?¿Y de puesta en producción?… También trata aspectos como: ¿Cómo empiezan a fallar los sistemas de microservicios? En general suelen degradarse poco a poco, y es complicado de tratar y de detectar: recuerda que todo lo que antes estaba centralizado, ahora está distribuído. Introduce diferentes conceptos para hacer nuestro sistema "Antifragil" (es decir, que se adapte a los cambios), como por ejemplo Circuit Breakers y los Bulkheads, o las operaciones idempotentes para protegernos frente a circunstancias adversas. También trata de forma superficial cómo escalar un sistema de microservicios: clústers de microservicios, qué hacer con la base de datos o cuál elegir (NoSQL, autoescalado, teorema CAP), CQRS, sistemas de caché, o descubrimiento de servicios automático (Eureka, Consul…)

  12. Juntando todo: típico capítulo final de resumen con los principios básicos del libro.

Como puedes comprobar, si has tenido la paciencia de leer mi "resumen", se trata de una serie de directrices y de puntos clave en la arquitectura de microservicios. Es más un relato de la experiencia, una guía de viaje en el desarrollo de una aplicación, con un mapa que nos indica los peligros a los que nos enfrentamos y qué armas tenemos que utilizar. El cómo se utilizan en detalle quedan para libros y tutoriales específicos.

En definitiva, "nadie escarmienta en carne ajena", pero está bien que leas al menos una vez este libro para que sepas a lo que te enfrentas cuando comiences tu proyecto de microservicios, o al menos tengas argumentos para negarte a emplearlos cuando no proceda.

ps:¡Insisto! No esperes una guía para ponerte a desarrollar microservicios desde un proyecto de Eclipse nuevo. Para eso está Spring Boot y otros libros y tutoriales más prácticos y técnicos.

Aquí te dejo el enlace por si lo quieres comprar en Amazon: