Las aplicaciones pequeñas no son microservicios

En esta entrada abordaremos un tema poco tratado en la bibliografía, aunque forme parte ¿natural? en el proceso de transformación de un monolito en microservicios, estaremos hablando de microlitos.

En el ámbito de la historia/geografía, un microlito se define como:

Los microlitos son artefactos líticos tallados intencionalmente por el ser humano, sobre todo durante la prehistoria, de tamaño extremadamente pequeño, pero lo suficientemente elaborados como para no ser considerados desechos ni accidentes de talla.

Tomado de wikipedia

Si tuviéramos que llevar esta definición al entorno de transición de los monolitos a microservicios, el timeline sería aproximadamente:

Etapas de transición de un monolito a piedra preciosa (microservicios)

Como se observa arriba, un microlito no es, aún, la piedra preciosa a la que queremos llegar: los microservicios. Pero tampoco podemos decir que son tan “malos” como el monolito, difícil de cargar con él. La oración anterior, es pura filosofía, vamos al grano.

Microservicios

Bastante hemos hablado en este blog de microservicios, sin embargo volvamos a retomar el artículo original de Martin Fownler y vamos a extraer algunos elementos claves de la amplia disertación dada por Fownler.

Una arquitectura microservicios, cumple (o debe cumplir las siguientes características):

  • Es una aplicación que se desarrolla como un grupo de pequeños servicios.
  • Dichos servicios se ejecutan en su propio proceso.
  • Usan mecanismos ligeros de comunicación.
  • Puede desarrollarse con algún grado de independencia/gestión.
  • Existe un mínimo de gestión centralizada.
  • Se caracteriza por puntos finales inteligentes y tuberías tontas (Esto queda poco claro, pero básicamente se puede interpretar como que la comunicación entre los microservicios no debe tener tanto peso en el funcionamiento integral, los microservicios, que son los puntos finales deben depender lo menos posible de las tuberías).
  • Deben poderse escalar de forma independiente.

Ya que dejamos las cartas claras sobre lo que son los microservicios, vamos a poner un ejemplo, del caso más común que tiene lugar cuando descomponemos un monolito para llevarlo a microservicios, veremos (y los que han tenido la experiencia coincidirán) el resultado primario y a veces final al que llegamos.

Acá tenemos el monolito, de una solución integral de venta de productos.

Monolito

Cuando este monolito, lo descomponemos, vamos a llegar, con mucha posibilidad a lo que creemos es una arquitectura “microservicios”, y obtendremos algo mas o menos así:

Microlito / Microservicios

Si vemos la imagen anterior pudiéramos pensar que hemos llegado a la piedra preciosa … pero no sé Rick, parece ser falso, en realidad ahí no tenemos una arquitectura microservicios aún, tenemos un microlito.

Microlitos en la arquitectura microservicios

Antes de analizar el resultado que obtuvimos en la sección anterior vamos a dejar claro, que mientras no podamos escalar con libertad nuestra aplicación no podemos hablar de microservicios, el otro punto esta relacionado con la comunicación, y aunque es más discutible, un servicio no debería depender de los datos de otro para sus funciones básicas, por ejemplo: Si el servicio que envía los mails tiene que hacer una petición al de usuarios solo para obtener el email del usuario, eso está mal, muy mal. El servicio de mails debe poseer las direcciones de correo de los usuarios.

Partiendo de las premisas anteriores, hay al menos dos elementos que influyen en que nuestra arquitectura no sea la piedra preciosa y nos falte un poco para llegar a eso.

Problemas de infraestructura: En este punto existen elementos de infraestructura compartida que no dejan a los servicios ser totalmente independientes, o lo que es peor aún, comparten infraestructura, por ej: base de datos, nodo de hosting, sistema de manejo de cache, etc.

Problema de comunicación: Aunque es más permisible, la dependencia en la comunicación en los microservicios debe ser la mínima necesaria. Los microservicios no son CRUDs para acceder a la base de datos, deben estar organizados de acuerdo a las capacidad del negocio y deben gestionar “inteligentemente” los datos necesarios para su función principal.

Veamos ahora lo que se obtuvo arriba que problemas tiene.

Microlito

Si arrancamos a mirar el resumen de la definición de microservicios que vimos un rato antes a la primera podemos pensar que todo anda bien y que coronamos.

  • (BIEN) Es una aplicación que se desarrolla como un grupo de pequeños servicios.
  • (BIEN) Dichos servicios se ejecutan en su propio proceso.
  • (REGULAR) Usan mecanismos ligeros de comunicación.
  • (BIEN) Puede desarrollarse con algún grado de independencia/gestión.
  • (BIEN) Existe un mínimo de gestión centralizada.
  • (REGULAR) Se caracteriza por puntos finales inteligentes y tuberías tontas (Esto queda poco claro, pero básicamente se puede interpretar como que la comunicación entre los microservicios no debe tener tanto peso en el funcionamiento integral, los microservicios, que son los puntos finales deben depender lo menos posible de las tuberías).
  • (MAL) Deben poderse escalar de forma independiente.

Los puntos que le dimos regular son los asociados a la interacción o comunicación porque a ciencia cierta no se puede precisar en el diagrama, pero lo más común sin lugar a dudas es que se elija HTTP/REST para la comunicación ¿está mal?, pues -depende- … en este caso tenemos una sola base de datos, ¿Qué sentido tiene que el servicio de email le pida al de clientes la información del email cuando ya el esta conectado a la base de datos y la puede obtener de ahí mismo?. Lo correcto sería la aplicación del patrón “Una base de datos por servicio” y cada cual tuviera sus datos independientes. Siguiendo el tema de las llamadas HTTP/REST, más allá de este escenario, traen problemas, muchos problemas y por eso deben minimizarse (los invito a leer sobre Las 8 falacias de la computación distribuida). Siempre pueden buscarse soluciones como Retry, Circuit Breaker, Bulkhead, etc; pero mejor evitar usarlas siempre que sea necesario; al final todas “mueren” en un fallback que degrada seguramente la calidad se servicio. Aplicar algún patrón del tipo EDA (Event Driving Architecture) puede ayudar, teniendo “puntos finales inteligentes” a mantener las bases de datos de cada microservicio al día.

El otro punto que no deja a esto ser una arquitectura microservicios, es el elemento más común que se repite en las migraciones de monolito a microservicios: “la base de datos compartida”, y si que es un problema muy serio, todo a nivel de aplicación puede escalar verticalmente, pero a nivel de infraestructura esta muy limitado, y a la larga, pasa factura.

No podemos decir que tenemos una arquitectura microservicios, cuando no podemos escalar libremente cada servicio por separado sin que sus efectos impacten sobre el resto.

Te dejamos un vídeo en el que abordamos el tema un poco más en profundidad.