Está en la página 1de 26

Capítulo 1.

 ¿Qué son los microservicios?

TRABAJO EN CURSO

Tenga en cuenta que el texto siguiente se está reelaborando actualmente para la 2ª edición del
libro, y no está en un estado completo. Este será el Capítulo 1 del libro final.

Si usted tiene algún comentario sobre el libro, o sugerencias para la 2ª edición, entonces por
favor póngase en contacto conmigo en book-feedback@samnewman.io.

Los microservicios se han convertido en una opción de arquitectura cada vez más popular en
los cinco años desde que escribí la primera edición de este libro. No puedo reclamar crédito
por la explosión posterior en popularidad, pero la prisa de la gente por hacer uso de
arquitecturas de microservicios significa que mientras que muchas de las ideas que capturé
anteriormente ahora son probadas y probadas, nuevas ideas también han entrado en la
mezcla, al mismo tiempo que las prácticas anteriores han caído en desgracia. Así que una vez
más es hora de destilar la esencia de la arquitectura de microservicios, destacando los
conceptos básicos que los hacen funcionar.

Este libro en su conjunto está diseñado para dar una visión general amplia del impacto que los
microservicios tienen en varios aspectos de la entrega de software. Para empezar, este
capítulo echará un vistazo a las ideas básicas detrás de los microservicios, el arte anterior que
nos trajo aquí, y explorará algunas de las razones por las que estas arquitecturas se están
utilizando tan ampliamente.

Microservicios de un vistazo

Los microservicios son servicios liberados de forma independiente que se modelan en torno a


un dominio empresarial. Un servicio encapsula la funcionalidad y la hace accesible a otros
servicios a través de redes: se construye un sistema más complejo a partir de estos bloques de
creación. Un servicio puede representar inventario, otra gestión de pedidos y otro envío, pero
juntos podrían constituir todo un sistema de comercio electrónico. Los microservicios son una
opción de arquitectura que se centra en darle muchas opciones para resolver los problemas a
los que podría enfrentarse.

Son un tipo de arquitectura orientada a servicios, aunque se opina sobre cómo se deben
dibujar los límites de servicio y una en la que la implementación independiente es clave. Son
agnósticos de la tecnología, que es una de las ventajas que ofrecen.

Desde el exterior, un único microservicio se trata como una caja negra. Hospeda funcionalidad
empresarial en uno o varios puntos de conexión de red (por ejemplo, una cola o una API de
REST, como se muestra en la figura 1-1),sobre los protocolos más adecuados. Los
consumidores, ya sean otros microservicios u otro tipo de programas, accedan a esta
funcionalidad a través de estos puntos de conexión en red. Los detalles internos de la
implementación (por ejemplo, como la tecnología en la que se escribe el servicio o la forma en
que se almacenan los datos) están completamente ocultos del mundo exterior. Esto significa
que las arquitecturas de microservicios evitan el uso de bases de datos compartidas en la
mayoría de las circunstancias; en su lugar, cada microservicio encapsula su propia base de
datos cuando sea necesario.
Figura 1-1. Un microservicio que expone su funcionalidad a través de una API de REST y una cola

Los microservicios adoptan el concepto de ocultación de información.1 La ocultación de


información describe ocultar tanta información como sea posible dentro de un componente y
exponer lo menos posible a través de interfaces externas. Esto permite una separación clara
entre lo que puede cambiar fácilmente y lo que es más difícil de cambiar. La implementación
que está oculta a terceros externos se puede cambiar libremente siempre y cuando las
interfaces en red que expone el microservicio no cambien de forma incompatible con
versiones anteriores. Los cambios dentro de un límite de microservicio (como se muestra en la
figura 1-1)no deben afectar a un consumidor ascendente, lo que permite la liberación
independiente de la funcionalidad. Esto es esencial para permitir que nuestros microservicios
se funcionen de forma aislada y se liberen bajo demanda. Tener límites de servicio claros y
estables que no cambian cuando cambia la implementación interna da como resultado
sistemas que tienen acoplamiento más flexible y una cohesión más fuerte.

¿LA ARQUITECTURA ORIENTADA AL SERVICIO Y LOS MICROSERVICIOS SON DIFERENTES?

La arquitectura orientada a servicios (SOA) es un enfoque de diseño en el que varios servicios


colaboran para proporcionar un determinado conjunto final de capacidades. Un servicio aquí
normalmente significa un proceso de sistema operativo completamente independiente. La
comunicación entre estos servicios se produce a través de llamadas a través de una red en
lugar de llamadas de método dentro de un límite de proceso.

SOA surgió como un enfoque para combatir los desafíos de las grandes aplicaciones
monolíticas. Es un enfoque que tiene como objetivo promover la reutilización del software;
dos o más aplicaciones de usuario final, por ejemplo, podrían usar los mismos servicios. Su
objetivo es facilitar el mantenimiento o reescritura de software, ya que teóricamente podemos
sustituir un servicio por otro sin que nadie lo sepa, siempre y cuando la semántica del servicio
no cambie demasiado.

Soa en su corazón es una idea sensata. Sin embargo, a pesar de muchos esfuerzos, hay una
falta de un buen consenso sobre cómo hacerlo bien. En mi opinión, gran parte de la industria
no ha mirado holísticamente el problema y presenta una alternativa convincente a la narrativa
establecida por varios proveedores en este espacio.

Muchos de los problemas que se ponen en la puerta de SOA son en realidad problemas con
cosas como protocolos de comunicación (por ejemplo, SOAP), middleware de proveedores,
falta de orientación sobre la granularidad del servicio o la orientación incorrecta sobre la
selección de lugares para dividir su sistema. Un cínico podría sugerir que los vendedores
cooptados (y en algunos casos condujeron) el movimiento SOA como una forma de vender
más productos, y esos productos de autosamo al final socavaron el objetivo de SOA.

Gran parte de la sabiduría convencional alrededor de SOA no te ayuda a entender cómo dividir
algo grande en algo pequeño. No se habla de lo grande que es demasiado grande. No habla lo
suficiente sobre el mundo real, formas prácticas para garantizar que los servicios no se acoplan
demasiado. El número de cosas que no se dijeron es donde se originan muchos de los escollos
asociados con soa.

He visto un montón de ejemplos de SOA donde los equipos se esforzaban por hacer los
servicios más pequeños, pero todavía tenía todo acoplado a una base de datos y tenía que
implementar todo juntos. ¿Orientado al servicio? Sí. Pero no son microservicios.

El enfoque de microservicio ha surgido del uso del mundo real, tomando nuestra mejor
comprensión de los sistemas y la arquitectura para hacer bien a SOA. Debe pensar en los
microservicios como un enfoque específico para SOA de la misma manera que Extreme
Programming (XP) o Scrum son enfoques específicos para el desarrollo de software Agile.

Conceptos clave de microservicios

Algunas ideas básicas son importantes de entender al explorar microservicios. Dado que
algunos de estos aspectos a menudo se pasan por alto, creo que es vital explorar estos
conceptos aún más para ayudar a asegurar que usted entienda mejor lo que es lo que hace
que los microservicios funcionen.

Implementación independiente

La implementación independiente es la idea de que podemos realizar un cambio en un


microservicio, implementarlo y liberar ese cambio a nuestros usuarios, sin tener que
implementar ningún otro servicio. Más importante, no es sólo el hecho de que podemos hacer
esto, es que esta es realmente la forma en que administra las implementaciones en su sistema.
Es una disciplina que adoptas como enfoque de lanzamiento predeterminado. Esta es una idea
simple que, sin embargo, es compleja en ejecución.

PROPINA

Si solo toma una cosa de este libro y el concepto de microservicios en general, debe ser esto:
asegúrese de adoptar el concepto de implementación independiente de sus microservicios.
Tenga el hábito de implementar y liberar cambios en un solo microservicio en producción sin
tener que implementar nada más. A partir de esto, seguirán muchas cosas buenas.

Para garantizar una implementación independiente, tenemos que asegurarnos de que


nuestros servicios estén vagamente acoplados: necesitamos ser capaces de cambiar un
servicio sin tener que cambiar nada más. Esto significa que necesitamos contratos explícitos,
bien definidos y estables entre servicios. Algunas opciones de implementación lo hacen difícil:
el uso compartido de bases de datos, por ejemplo, es especialmente problemático.

La implementación independiente en sí misma es claramente increíblemente valiosa. Pero


para lograr una implementación independiente, hay tantas otras cosas que tienes que hacer
bien que a su vez tienen sus propios beneficios. Así que también puede ver el enfoque en la
implementación independiente como una función de forzamiento - centrándose en esto como
un resultado que también logrará una serie de beneficios auxiliares.
El deseo de servicios ligeramente combinados con interfaces estables guía nuestro
pensamiento sobre cómo encontramos límites de servicio en primer lugar.

Modelado alrededor de un dominio empresarial

Técnicas como el diseño basado en dominios pueden permitirle estructurar su código para
representar mejor el dominio del mundo real en el que opera el software.2 Con las
arquitecturas de microservicios, usamos esta misma idea para definir nuestros límites de
servicio. Mediante el modelado de servicios en torno a dominios empresariales, podemos
facilitar la implementación de nuevas funcionalidades y facilitar la recombinación de
microservicios de diferentes maneras para ofrecer nuevas funcionalidades a nuestros usuarios.

Implementar una característica que requiera cambios en uno o varios microservicios es


costoso. Debe coordinar el trabajo en cada servicio (y potencialmente entre equipos
independientes) y administrar cuidadosamente el orden en que se implementan las nuevas
versiones de estos servicios. Eso requiere mucho más trabajo que hacer el mismo cambio
dentro de un solo servicio (o, para el caso, un monolito). Por lo tanto, de ello se deduce que
queremos encontrar maneras de realizar cambios entre servicios lo más poco frecuentes
posible.

A menudo veo arquitecturas en capas, como se tipifica en la Figura 1-2 por la arquitectura de
tres niveles. Aquí, cada capa de esta arquitectura representa un límite de servicio diferente,
con cada límite de servicio basado en la funcionalidad técnica relacionada. Si necesito hacer un
cambio sólo a la capa de presentación en este ejemplo, eso sería bastante eficiente. Sin
embargo, la experiencia ha demostrado que los cambios en la funcionalidad suelen abarcar
varias capas en este tipo de arquitecturas, lo que requiere cambios en los niveles de
presentación, aplicación y datos. Este problema se agrava si la arquitectura está aún más en
capas que el ejemplo simple de la Figura 1-2; a menudo, cada nivel puede dividirse en otras
capas.

Figura 1-2. Una arquitectura tradicional de tres niveles

Al hacer que nuestros servicios sean sectores de funcionalidad empresarial de extremo a


extremo, como se muestra en la Figura 1-3,nos aseguramos de que nuestra arquitectura esté
dispuesta para que los cambios en la funcionalidad del negocio sean lo más eficientes posible.
Cada servicio, si es necesario, puede encapsular la presentación, la lógica empresarial y el
almacenamiento de datos. Podría decirse que con los microservicios hemos tomado la decisión
de priorizar la alta cohesión de la funcionalidad empresarial sobre la alta cohesión de la
funcionalidad técnica.

Figura 1-3. Cada microservicio, si es necesario, puede encapsular la presentación, la lógica


empresarial y la funcionalidad de almacenamiento de datos

Volvemos a la interacción del diseño basado en dominios y cómo esto interactúa con el diseño
organizacional más adelante en este capítulo.

Poseer su propio estado

Una de las cosas con las que veo que la gente lo está pasando mal es la idea de que los
microservicios no deben compartir bases de datos. Si un servicio desea acceder a los datos en
poder de otro servicio, debe ir y pedir a ese servicio los datos que necesita. Esto le da al
servicio la capacidad de decidir lo que se comparte y lo que está oculto. Esto nos permite
separar claramente la funcionalidad que puede cambiar libremente (nuestra implementación
interna) de la funcionalidad que queremos cambiar con poca frecuencia (el contrato externo
que utilizan los consumidores).

Si queremos hacer realidad la implementación independiente, tenemos que asegurarnos de


limitar la realización de cambios inconsibles hacia atrás en nuestros microservicios. Si
rompemos la compatibilidad con los consumidores ascendentes, también los obligaremos a
cambiar. Tener una delineación limpia entre el detalle de implementación interna y un
contrato externo para un microservicio puede ayudar a reducir la necesidad de cambios
inconsofitas hacia atrás.

Ocultar el estado interno en un microservicio es análogo con la práctica de encapsulación en la


programación orientada a objetos (OO). La encapsulación de datos en sistemas OO es un
ejemplo de información que se oculta en acción.

PROPINA
No comparta bases de datos a menos que realmente lo necesite. E incluso entonces, haz todo
lo posible para evitarlo. En mi opinión, compartir bases de datos es una de las peores cosas
que puede hacer si está tratando de lograr una implementación independiente.

Como se describe en la sección anterior, queremos pensar en nuestros servicios como sectores
de extremo a extremo de la funcionalidad empresarial que, en su caso, encapsulan la interfaz
de usuario (UI), la lógica empresarial y los datos. Esto se debe a que queremos reducir el
esfuerzo necesario para cambiar la funcionalidad relacionada con el negocio. La encapsulación
de datos y comportamiento de esta manera nos da una alta cohesión de la funcionalidad del
negocio. Al ocultar la base de datos que respalda nuestro servicio, también nos aseguramos de
reducir el acoplamiento. Volvemos al acoplamiento y la cohesión en el Capítulo 2.

tamaño

"¿Qué tan grande debe ser un microservicio?" es una de las preguntas más comunes que
escucho. Teniendo en cuenta que la palabra "micro" está justo ahí en el nombre, esto no es
una sorpresa. Sin embargo, cuando se entra en lo que hace que los microservicios funcionen
como un tipo de arquitectura, el concepto de tamaño es en realidad una de las cosas menos
interesantes.

¿Cómo se mide el tamaño? ¿Líneas de código? Eso no tiene mucho sentido para mí. Algo que
podría requerir 25 líneas de código en Java podría escribirse en 10 líneas de Clojure. Eso no
quiere decir que Clojure sea mejor o peor que Java; es simplemente que algunos idiomas son
más expresivos que otros.

James Lewis, director técnico de ThoughtWorks, ha sido conocido por decir que "un
microservicio debe ser tan grande como mi cabeza". A primera vista, esto no parece
terriblemente útil. Después de todo, ¿qué tan grande es exactamente la cabeza de James? La
razón detrás de esta instrucción es que un microservicio debe mantenerse al tamaño donde se
puede entender fácilmente. El desafío aquí, por supuesto, es que la capacidad de la gente para
entender algo no es la misma, y como tal tendrás que hacer tu propio juicio con respecto a qué
tamaño funciona para ti. Un equipo experimentado puede ser capaz de administrar mejor una
base de código más grande que otra. Así que tal vez la cita de James lee aquí como "Un
microservicio debería ser tan grande como tu cabeza".

Lo más cerca que creo que lléveme al "tamaño" teniendo algún significado en términos de
microservicios es algo que el autor de Microservice Patterns Chris Richardson dijo una vez: que
el objetivo de los microservicios es tener "una interfaz lo más pequeña posible". Eso se alinea
con el concepto de información que se oculta de nuevo, pero representa un intento de
encontrar significado en el término "microservicios" que no estaba allí inicialmente. Cuando el
término se utilizó por primera vez para definir estas arquitecturas, el foco, al menos
inicialmente, no estaba específicamente en el tamaño de las interfaces.

En última instancia, el concepto de tamaño es altamente contextual. Hable con una persona
que ha trabajado en un sistema durante 15 años, y sentirá que su sistema con 100.000 líneas
de código es realmente fácil de entender. Pregunta la opinión de alguien nuevo en el proyecto,
y sentirán que es demasiado grande. Del mismo modo, pregúntele a una empresa que acaba
de embarcarse en su transición de microservicios, que tiene tal vez 10 o menos microservicios,
y obtendrá una respuesta diferente a la que obtendría de una empresa de tamaño similar
donde los microservicios han sido la norma durante muchos años, y ahora tiene cientos.
Insto a la gente a no preocuparse por el tamaño. Cuando empiezas por primera vez, es mucho
más importante que te centres en dos cosas clave. En primer lugar, ¿cuántos microservicios
puede manejar? A medida que tenga más servicios, la complejidad de su sistema aumentará, y
tendrá que aprender nuevas habilidades (y tal vez adoptar nuevas tecnologías) para hacer
frente a esto. Es por esta razón que soy un firme defensor de la migración incremental a una
arquitectura de microservicios. En segundo lugar, ¿cómo se definen los límites de los
microservicios para sacar el máximo partido a ellos, sin que todo se convierta en un desastre
horriblemente acoplado? Estos son los temas en los que es mucho más importante centrarse
cuando comienzas tu viaje.

flexibilidad

James Lewis, se sabe que dice que "los microservicios te compran opciones". Lewis estaba
siendo deliberado con sus palabras, te compran opciones. Tienen un costo, y usted debe
decidir si el costo vale la pena las opciones que desea tomar. La flexibilidad resultante en una
serie de ejes (organizacionales, técnicos, de escala, robustez) puede ser increíblemente
atractiva.

No sabemos lo que nos depara el futuro, así que nos gustaría una arquitectura que
teóricamente pueda ayudarnos a resolver cualquier problema que podamos enfrentar más
adelante. Encontrar un equilibrio entre mantener sus opciones abiertas y soportar el costo de
arquitecturas como esta puede ser un verdadero arte.

Piense en adoptar microservicios como menos como mover un interruptor, y más bien girar
una esfera. A medida que sube el dial y tiene más microservicios, ha aumentado la flexibilidad.
Pero es probable que también aumentes los puntos de dolor. Esta es otra razón por la que
defiendo firmemente la adopción incremental de microservicios. Al subir la esfera
gradualmente, usted es más capaz de evaluar el impacto a medida que avanza, y detener si es
necesario.

Alineación de la arquitectura y la organización

Music Corp, una empresa de comercio electrónico que vende CDs en línea, utiliza la
arquitectura simple de tres niveles mostrada anteriormente y representada de nuevo en la
Figura 1-4. Hemos decidido mover Music Corp pateando y gritando en el siglo XXI, y como
parte de eso, estamos evaluando la arquitectura del sistema existente. Tenemos una interfaz
de usuario basada en web, una capa de lógica empresarial en forma de back-end monolítico y
almacenamiento de datos en una base de datos tradicional. Estas capas, como es común, son
propiedad de diferentes equipos. Volveremos a las pruebas y tribulaciones de Music Corp a lo
largo del libro.
Figura 1-4.  Los sistemas de Music Corp como arquitectura tradicional de tres niveles

Queremos hacer un cambio sencillo en nuestra funcionalidad: queremos permitir que nuestros
clientes especifiquen su género musical favorito. Este cambio requiere que cambiemos la
interfaz de usuario para mostrar la interfaz de usuario de elección de género, el servicio back-
end para permitir que el género aparezca en la interfaz de usuario y que se cambie el valor y
que la base de datos acepte este cambio. Estos cambios deberán ser gestionados por cada
equipo e implementados en el orden correcto, como se describe en la Figura 1-5.

Figura 1-5. Hacer un cambio en los tres niveles está más involucrado

Ahora esta arquitectura no es mala. Toda la arquitectura termina optimizándose en torno a un


conjunto de objetivos. La arquitectura de tres niveles es tan común en parte porque es
universal, todo el mundo ha oído hablar de ella. Así que elegir una arquitectura común que
usted podría haber visto en otro lugar es a menudo una razón por la que seguimos viendo este
patrón. Pero creo que la razón más grande por la que vemos esta arquitectura una y otra vez
es porque se basa en cómo organizamos nuestros equipos.

La ahora famosa ley de Conway establece lo siguiente:

Cualquier organización que diseñe un sistema... inevitablemente producirá un diseño cuya


estructura es una copia de la estructura de comunicación de la organización

Melvin Conway, ¿cómo inventan los comités?


La arquitectura de tres niveles es un buen ejemplo de esto en acción. En el pasado, la forma
principal en que las organizaciones de TI agrupaban a las personas era en términos de su
competencia principal: los administradores de bases de datos estaban en un equipo con otros
administradores de bases de datos; Los desarrolladores de Java estaban en equipo con otros
desarrolladores de Java; y los desarrolladores frontend (que hoy en día saben cosas exóticas
como JavaScript y el desarrollo de aplicaciones móviles nativas) estaban en otro equipo.
Agrupamos a personas en función de su competencia principal, por lo que creamos activos de
TI que se pueden alinear con esos equipos.

Así que eso explica por qué esta arquitectura es tan común. No está mal; está optimizado en
torno a un conjunto de fuerzas: cómo tradicionalmente agrupamos a la gente, en torno a la
familiaridad. Pero las fuerzas han cambiado. Nuestras aspiraciones en torno a nuestro
software han cambiado. Ahora agrupamos a personas en equipos polidebilidos, para reducir
las entregas y los silos. Queremos enviar software mucho más rápido que nunca. Eso nos está
impulsando a tomar diferentes decisiones sobre la forma en que organizamos nuestros
equipos, y por lo tanto a organizarlos en términos de la forma en que separamos nuestros
sistemas.

La mayoría de los cambios que se nos piden que hagamos a nuestro sistema se relacionan con
cambios en la funcionalidad del negocio. Pero en la Figura 1-5,nuestra funcionalidad
empresarial se distribuye, en efecto, en los tres niveles, lo que aumenta la posibilidad de que
un cambio en la funcionalidad cruce capas. Se trata de una arquitectura que tiene una alta
cohesión de la tecnología relacionada pero con una baja cohesión de la funcionalidad
empresarial. Si queremos facilitar la realojación de cambios, en cambio necesitamos cambiar la
forma en que agrupamos el código: elegimos la cohesión de la funcionalidad empresarial en
lugar de la tecnología. Cada servicio puede o no terminar conteniendo una mezcla de estas
tres capas, pero eso es una preocupación de implementación de servicio local.

Comparemos esto con una arquitectura alternativa potencial, ilustrada en la Figura 1-
6. Contamos con un servicio de atención al cliente dedicado, que expone una interfaz de
usuario para permitir a los clientes actualizar su información, y el estado del cliente también se
almacena dentro de este servicio. La elección de un género favorito está asociada con un
cliente determinado, por lo que este cambio está mucho más localizado. En la Figura 1-
6,también mostramos la lista de géneros disponibles que se están recuperando de un servicio
de catálogo, probablemente algo que ya estaría en su lugar. También vemos un nuevo servicio
de recomendaciones que accede a nuestra información de género favorita, algo que podría
seguir fácilmente en un lanzamiento posterior.

Figura 1-6. Un servicio de atención al cliente dedicado puede hacer que sea mucho más fácil grabar el
género musical favorito para un cliente
En tal situación, nuestro servicio de atención al cliente encapsula un sector fino de cada uno de
los tres niveles (tiene un poco de interfaz de usuario, un poco de lógica de aplicación y un poco
de almacenamiento de datos), pero todas estas capas están encapsuladas en el único servicio.
Nuestro dominio empresarial se convierte en la fuerza principal que impulsa la arquitectura de
nuestro sistema, con la esperanza de facilitar la realización de cambios, además de facilitarnos
la alineación de nuestros equipos con las líneas de negocio dentro de la organización.

El Monolito

Hemos hablado de microservicios, pero los microservicios se discuten con mayor frecuencia
como un enfoque arquitectónico que es una alternativa a la arquitectura monolítica. Para
ayudar mejor a distinguir la arquitectura de microservicios, y para ayudarle a entender mejor si
vale la pena considerar los microservicios, también debo discutir lo que quiero decir
exactamente con monolitos.

Cuando hablo de monolitos a lo largo de este libro, me refiero principalmente a una unidad de
despliegue. Cuando todas las funciones de un sistema deben implementarse juntas, lo
consideramos un monolito. Podría decirse que múltiples arquitecturas se ajustan a esta
definición, pero voy a discutir las que veo más a menudo: el monolito de un solo proceso, el
monolito modular y el monolito distribuido.

El monolito de un solo proceso

El ejemplo más común que viene a la mente al discutir monolitos es un sistema en el que todo
el código se implementa como un solo proceso,como en la Figura 1-7. Es posible que tenga
varias instancias de este proceso por motivos de robustez o escalado, pero fundamentalmente
todo el código se empaqueta en un único proceso. En realidad, estos sistemas de un solo
proceso pueden ser simples sistemas distribuidos por derecho propio porque casi siempre
terminan leyendo datos o almacenando datos en una base de datos, o presentando
información a aplicaciones web o móviles.

Figura 1-7. En un monolito de un solo proceso, todo el código se empaqueta en un solo proceso

Aunque esto se ajusta a la comprensión de la mayoría de la gente de un monolito clásico, la


mayoría de los sistemas que encuentro son algo más complejos que esto. Es posible que tenga
dos o más monolitos que estén estrechamente acoplados entre sí, potencialmente con algún
software de proveedor en la mezcla.

El monolito modular

Como subconjunto del monolito de un solo proceso, el monolito modular es una variación en
la que el proceso único consta de módulos separados. Cada uno se puede trabajar de forma
independiente, pero todos todavía necesitan combinarse para la implementación, como se
muestra en la Figura 1-8. El concepto de dividir el software en módulos no es nada nuevo; el
software modular tiene sus raíces en el trabajo realizado en torno a la programación
estructurada de la década de 1970, e incluso más atrás que eso. Sin embargo, este no es
todavía un enfoque con el que veo suficientes organizaciones participar adecuadamente.

Figura 1-8. En un monolito modular, el código dentro del proceso se divide en módulos

Para muchas organizaciones, el monolito modular puede ser una excelente opción. Si los
límites del módulo están bien definidos, puede permitir un alto grado de trabajo paralelo,
evitando al mismo tiempo los desafíos de la arquitectura de microservicios más distribuida al
tener una topología de implementación mucho más simple. Shopify es un gran ejemplo de una
organización que ha utilizado esta técnica como alternativa a la descomposición de
microservicios, y parece funcionar muy bien para esa empresa.3

Uno de los desafíos de un monolito modular es que la base de datos tiende a carecer de la
descomposición que encontramos en el nivel de código, lo que conduce a desafíos
significativos si desea separar el monolito en el futuro. He visto a algunos equipos intentar
impulsar aún más la idea del monolito modular, haciendo que la base de datos se
descomponga en la misma línea que los módulos, como se muestra en la Figura 1-9.

Figura 1-9. Un monolito modular con una base de datos descompuesta

El monolito distribuido

Un sistema distribuido es aquel en el que el error de un equipo que ni siquiera sabías que
existía puede hacer que tu propio equipo sea inutilizable.4

Leslie Lamport

Un monolito distribuido es un sistema que consta de varios servicios, pero por cualquier razón,
todo el sistema debe implementarse juntos. Un monolito distribuido bien podría cumplir con la
definición de un SOA, pero con demasiada frecuencia, no cumple con las promesas de SOA. En
mi experiencia, los monolitos distribuidos tienen todas las desventajas de un sistema
distribuido, y las desventajas de un monolito de un solo proceso, sin tener suficientes ventajas
de ninguno de los dos. Encontrar una serie de monolitos distribuidos en mi trabajo ha influido
en gran parte en mi propio interés en la arquitectura de microservicios.

Los monolitos distribuidos suelen surgir en un entorno en el que no se prestaba suficiente


atención a conceptos como la ocultación de información y la cohesión de la funcionalidad
empresarial. En su lugar, las arquitecturas altamente acopladas hacen que los cambios ondee a
través de los límites del servicio y los cambios aparentemente inocentes que parecen ser
locales en el ámbito rompen otras partes del sistema.

Monolitos y contención de entrega

A medida que más y más personas trabajan en el mismo lugar, se meten en el camino del otro.
Por ejemplo, diferentes desarrolladores que desean cambiar la misma pieza de código;
diferentes equipos que desean insertar funcionalidad en vivo en diferentes momentos (o
retrasar las implementaciones); confusión en torno a quién es el dueño de qué, y quién toma
decisiones. Se han realizado multitud de estudios que muestran los desafíos de las líneas
confusas de propiedad.5 Me refiero a este problema como contención de entrega .

Tener un monolito no significa que definitivamente te enfrentarás a los desafíos de la


contención de entrega más que tener una arquitectura de microservicios significa que nunca
enfrentarás el problema. Pero una arquitectura de microservicios le da límites más concretos
alrededor de los cuales las líneas de propiedad se pueden dibujar en un sistema, lo que le da
mucha más flexibilidad con respecto a cómo reducir este problema.

Ventajas de los monolitos

Algunos monolitos, como el monolito de un solo proceso o modular, también tienen una gran
cantidad de ventajas. Su topología de implementación mucho más simple puede evitar muchos
de los escollos asociados con los sistemas distribuidos. Esto puede dar lugar a flujos de trabajo
de desarrolladores mucho más simples, y la supervisión, la solución de problemas y actividades
como las pruebas de extremo a extremo también se pueden simplificar en gran medida.

Los monolitos también pueden simplificar la reutilización de código dentro del propio
monolito. Si queremos reutilizar código dentro de un sistema distribuido, tenemos que decidir
si queremos copiar código, separar bibliotecas o insertar la funcionalidad compartida en un
servicio. Con un monolito, nuestras elecciones son mucho más simples, y a mucha gente le
gusta esa simplicidad: todo el código está ahí; sólo úsalo!

Desafortunadamente, la gente ha llegado a ver el monolito como algo que debe evitarse, como
algo inherentemente problemático. He conocido a varias personas para las que el
término monolito es sinónimo de legado. Esto es un problema. Una arquitectura monolítica es
una opción, y una válida en eso. Iría más lejos y diría que en mi opción es la opción
predeterminada sensata como estilo arquitectónico. En otras palabras, estoy buscando una
razón para estar convencido de usar microservicios, en lugar de buscar una razón para no
usarlos.

Si caemos en la trampa de socavar sistemáticamente el monolito como una opción viable para
entregar nuestro software, corremos el riesgo de no hacerlo bien por nosotros mismos o por
los usuarios de nuestro software.
Tecnología habilitadora

Como toqué anteriormente, no creo que necesites adoptar mucha tecnología nueva cuando
empiezas a usar microservicios por primera vez. De hecho, eso puede ser contraproducente.
En su lugar, a medida que aumenta la arquitectura de microservicios, debe estar
constantemente atento a los problemas causados por su sistema cada vez más distribuido y, a
continuación, buscar tecnología que pueda ayudar.

Dicho esto, la tecnología ha jugado un papel importante en la adopción de microservicios


como concepto. Subestimar las herramientas que están disponibles para ayudar a sacar el
máximo partido a esta arquitectura va a ser una parte clave para hacer que cualquier
implementación de microservicios sea un éxito. De hecho, llegaría tan lejos como para decir
que los microservicios requieren una comprensión de la tecnología de apoyo hasta tal punto
que las distinciones anteriores entre arquitectura lógica y física pueden ser problemáticas - si
usted está involucrado en ayudar a dar forma a una arquitectura de microservicios, necesitará
una amplia gama de comprensión de estos dos mundos.

Exploraremos gran parte de esta tecnología en detalle en capítulos posteriores, pero antes de
eso, vamos a presentar brevemente parte de la tecnología de habilitación que podría ayudarle
en caso de que decida hacer uso de microservicios.

Agregación de registros y seguimiento distribuido

Con el número de procesos que está gestionando aumentando, puede ser difícil entender
cómo se comporta su sistema en una configuración de producción. Esto, a su vez, puede
dificultar mucho más la solución de problemas. Exploraremos estas ideas más a fondo en el
Capítulo 9,pero como mínimo, abogo firmemente por la implementación de un sistema de
agregación de registros como requisito previo para adoptar una arquitectura de
microservicios.

PROPINA

Tenga cuidado al asumir demasiada tecnología nueva cuando comience con microservicios.
Dicho esto, una herramienta de agregación de registros es tan esencial que debe considerarla
un requisito previo para adoptar microservicios.

Estos sistemas le permiten recopilar y agregar registros de todos sus servicios,


proporcionándole un lugar central desde el que se pueden analizar los registros e incluso
formando parte de un mecanismo de alerta activo. Muchas opciones en este espacio pueden
atender numerosas situaciones. Soy un gran fan de Humio por varias razones, pero los
servicios de registro simples proporcionados por los principales proveedores de nube pública
pueden ser lo suficientemente buenos como para comenzar.

Estas herramientas de agregación de registros se pueden hacer aún más útiles mediante la
implementación de identificadores de correlación, en los que se utiliza un único
IDENTIFICADOR para un conjunto relacionado de llamadas de servicio, por ejemplo, la cadena
de llamadas que se pueden desencadenar debido a la interacción del usuario. Al registrar este
ID como parte de cada entrada de registro, aislar los registros asociados con un flujo
determinado de llamadas se vuelve mucho más fácil, lo que facilita mucho la solución de
problemas.
A medida que su sistema crece en complejidad, se vuelve esencial considerar herramientas
que le permitan explorar mejor lo que su sistema está haciendo, proporcionando la capacidad
de analizar rastros en múltiples servicios, detectar cuellos de botella y hacer preguntas de su
sistema que no sabía que desea hacer en primer lugar. Las herramientas de código abierto
pueden proporcionar algunas de estas características. Un ejemplo es Jaeger, que se centra en
el lado de trazado distribuido de la ecuación.

Pero productos como LightStep y Honeycomb (que se muestra en la Figura 1-10),llevan estas


ideas más lejos. Representan una nueva generación de herramientas que van más allá de los
enfoques de monitoreo tradicionales, lo que hace que sea mucho más fácil explorar el estado
de su sistema en ejecución. Es posible que ya tenga herramientas más convencionales en su
lugar, pero realmente debe mirar las capacidades que estos productos proporcionan. Se han
construido desde cero para resolver el tipo de problemas que los operadores de arquitecturas
de microservicios tienen que lidiar.

Figura 1-10. Un seguimiento distribuido que se muestra en Honeycomb, que le permite identificar
dónde se está dedicando el tiempo para operaciones que pueden abarcar varios microservicios

Contenedores y Kubernetes

Idealmente, desea ejecutar cada instancia de microservicio de forma aislada. Esto garantiza
que los problemas en un microservicio no pueden afectar a otro, por ejemplo, engullindo toda
la CPU. La virtualización es una forma de crear entornos de ejecución aislados en hardware
existente, pero las técnicas de virtualización normales pueden ser bastante pesadas si tenemos
en cuenta el tamaño de nuestros microservicios. Los contenedores,por otro lado, proporcionan
una forma mucho más ligera de aprovisionar la ejecución aislada para instancias de servicio, lo
que resulta en tiempos de puesta en marcha más rápidos para las nuevas instancias de
contenedor, además de ser mucho más rentables para muchas arquitecturas.

Después de empezar a jugar con contenedores, también te darás cuenta de que necesitas algo
que te permita administrar estos contenedores en muchas máquinas subyacentes. Plataformas
de orquestación de contenedores como Kubernetes hacen exactamente eso, lo que le permite
distribuir instancias de contenedor de tal manera que proporcione la robustez y el rendimiento
que necesita su servicio, todo ello al tiempo que le permite hacer un uso eficiente de las
máquinas subyacentes. En el Capítulo 7 volveremos y exploraremos los conceptos de
aislamiento operativo, contenedores y kubernetes.

No sientas la necesidad de apresurarte a adoptar Kubernetes, o incluso contenedores, para el


caso. Ofrecen ventajas significativas sobre las técnicas de implementación más tradicionales,
pero es difícil justificar si solo tiene unos pocos servicios. Después de que la sobrecarga de la
administración de la implementación comience a convertirse en un dolor de cabeza
significativo, comience a considerar la contenedorización del servicio y el uso de Kubernetes.
Pero si termina haciendo eso, haga todo lo posible para asegurarse de que otra persona está
ejecutando el clúster de Kubernetes para usted, tal vez haciendo uso de un servicio
administrado en un proveedor de nube pública. ¡Ejecutar su propio clúster de Kubernetes
puede ser una cantidad significativa de trabajo!

streaming

Aunque con los microservicios nos estamos alejando de las bases de datos monolíticas, todavía
necesitamos encontrar maneras de compartir datos entre servicios. Esto está sucediendo al
mismo tiempo que las organizaciones quieren alejarse de las operaciones de informes por
lotes, hacia comentarios más en tiempo real, lo que les permite reaccionar más rápidamente.
Por lo tanto, los productos que permiten el fácil streaming y procesamiento de lo que a
menudo pueden ser grandes volúmenes de datos se han vuelto populares entre las personas
que utilizan arquitecturas de microservicios.

Apache Kafka se ha convertido en la opción de facto para muchos para transmitir datos en un


entorno de microservicios, y por una buena razón. Capacidades como la permanencia de
mensajes, la compactación y la capacidad de escalar para manejar grandes volúmenes de
mensajes pueden ser increíblemente útiles. Kafka también ha comenzado a agregar
capacidades de procesamiento de secuencias en forma de KSQL, pero también puede utilizarlo
con soluciones dedicadas de procesamiento de secuencias como Apache Flink. Debezium es
una herramienta de código abierto desarrollada para ayudar a transmitir datos de fuentes de
datos existentes a través de Kafka, ayudando a garantizar que los orígenes de datos
tradicionales puedan formar parte de una arquitectura basada en secuencias. En el Capítulo
3 veremos cómo la tecnología de streaming puede desempeñar un papel en la integración de
microservicios.

Nube pública y sin servidor

Los proveedores de nube pública o, más concretamente, los tres principales (Google Cloud,
Microsoft Azure y Amazon Web Services (AWS) proporcionan una gran variedad de servicios
administrados y opciones de implementación para administrar la aplicación. A medida que la
arquitectura de microservicios crece, cada vez se realizará más trabajo en el espacio operativo.
Los proveedores de nube pública ofrecen una serie de servicios administrados, desde
instancias de bases de datos administradas o clústeres de Kubernetes, hasta intermediarios de
mensajes o sistemas de archivos distribuidos. Al hacer uso de estos servicios administrados,
está descargando una gran cantidad de este trabajo a un tercero que posiblemente sea más
capaz de lidiar con estas tareas.

De particular interés entre las ofertas de nube pública se encuentran los productos que se
sientan bajo el estandarte de sin servidor. Estos productos ocultan las máquinas subyacentes,
lo que le permite trabajar a un mayor nivel de abstracción. Algunos ejemplos de productos sin
servidor son los agentes de mensajes, las soluciones de almacenamiento y las bases de datos.
Las plataformas de función como servicio (FaaS) son de especial interés porque proporcionan
una buena abstracción en torno a la implementación de código. En lugar de preocuparse por
cuántos servidores necesita para ejecutar el servicio, solo tiene que implementar el código y
dejar que la plataforma subyacente controle las instancias giratorias del código a petición.
Veremos a la servleresa con más detalle en el Capítulo 7.

Ventajas de los microservicios

Las ventajas de los microservicios son muchas y variadas. Muchos de estos beneficios se
pueden poner en la puerta de cualquier sistema distribuido. Los microservicios, sin embargo,
tienden a lograr estos beneficios en mayor medida principalmente porque toman una postura
más opinada en la forma en que se definen los límites del servicio. Al combinar los conceptos
de ocultación de información y diseño basado en dominios junto con el poder de los sistemas
distribuidos, pueden ayudar a ofrecer ganancias significativas sobre otras formas de
arquitecturas distribuidas.

Heterogeneidad tecnológica

Con un sistema compuesto por múltiples servicios colaboradores, podemos decidir utilizar
diferentes tecnologías dentro de cada uno. Esto nos permite elegir la herramienta adecuada
para cada trabajo en lugar de tener que seleccionar un enfoque más estandarizado y único que
a menudo termina siendo el denominador común más bajo.

Si una parte de nuestro sistema necesita mejorar su rendimiento, podríamos decidir utilizar
una pila de tecnología diferente que sea más capaz de alcanzar los niveles de rendimiento
requeridos. También podemos decidir que la forma en que almacenamos nuestros datos
necesita cambiar para diferentes partes de nuestro sistema. Por ejemplo, para una red social,
podríamos almacenar las interacciones de nuestros usuarios en una base de datos orientada a
gráficos para reflejar la naturaleza altamente interconectada de un gráfico social, pero tal vez
las publicaciones que hacen los usuarios podrían almacenarse en un almacén de datos
orientado a documentos, dando lugar a una arquitectura heterogénea como la que se muestra
en la Figura 1-11.

Figura 1-11. Los microservicios pueden permitirle adoptar más fácilmente diferentes tecnologías
Con los microservicios, también somos capaces de adoptar más rápidamente la tecnología y
entender cómo los nuevos avances podrían ayudarnos. Una de las mayores barreras para
probar y adoptar nuevas tecnologías son los riesgos asociados con ella. Con una aplicación
monolítica, si quiero probar un nuevo lenguaje de programación, base de datos o marco de
trabajo, cualquier cambio afectará a gran parte de mi sistema. Con un sistema que consta de
múltiples servicios, tengo varios lugares nuevos para probar una nueva pieza de tecnología.
Puedo elegir un servicio que tal vez sea de menor riesgo y utilizar la tecnología allí, sabiendo
que puedo limitar cualquier impacto negativo potencial. Muchas organizaciones consideran
que esta capacidad de absorber más rápidamente las nuevas tecnologías es una ventaja real.

Adoptar múltiples tecnologías no viene sin sobrecarga, por supuesto. Algunas organizaciones
optan por imponer algunas restricciones a las opciones de idioma. Netflix y Twitter, por
ejemplo, utilizan principalmente la Máquina Virtual Java (JVM) como plataforma porque esas
empresas tienen una muy buena comprensión de la fiabilidad y el rendimiento de ese sistema.
También desarrollan bibliotecas y herramientas para la JVM que facilitan mucho el
funcionamiento a escala, pero dificultan la tarea de los servicios o clientes no basados en Java.
Pero ni Twitter ni Netflix utilizan una sola pila de tecnología para todos los trabajos.

robustez

Un concepto clave para mejorar la robustez de la aplicación es el mamparo. Si se produce un


error en un componente de un sistema, pero ese error no se produce en cascada, puede aislar
el problema y el resto del sistema puede seguir funcionando. Los límites de servicio se
convierten en sus mamparos obvios. En un servicio monolítico, si se produce un error en el
servicio, todo deja de funcionar. Con un sistema monolítico, podemos ejecutarnos en varias
máquinas para reducir nuestras posibilidades de fallo, pero con los microservicios, podemos
crear sistemas que manejen el fallo total de algunos de los servicios constituyentes y degradar
la funcionalidad en consecuencia.

Sin embargo, tenemos que tener cuidado. Para asegurarnos de que nuestros sistemas de
microservicios puedan adoptar correctamente esta robustez mejorada, necesitamos
comprender las nuevas fuentes de fracaso con las que los sistemas distribuidos tienen que
lidiar. Las redes pueden y fallarán, al igual que las máquinas. Necesitamos saber cómo manejar
esto y qué impacto (si los hay) esos fallos deben tener en los usuarios finales de nuestro
software.

escalada

Con un servicio grande y monolítico, necesitamos escalar todo juntos. Tal vez una pequeña
parte de nuestro sistema general está limitado en rendimiento, pero si ese comportamiento
está bloqueado en una aplicación monolítica gigante, necesitamos manejar el escalado de todo
como una pieza. Con servicios más pequeños, podemos escalar solo aquellos servicios que
necesitan escalado, lo que nos permite ejecutar otras partes del sistema en hardware más
pequeño y menos potente, como se ilustra en la Figura 1-12.
Figura 1-12.  Puede dirigirse al escalado en solo los microservicios que lo necesitan

Gilt, un minorista de moda en línea, adoptó microservicios por esta razón exacta. A partir de
2007, con una aplicación de carriles monolíticos, en 2009 el sistema de Gilt no pudo hacer
frente a la carga que se le estaba colocando. Al dividir las partes principales de su sistema, Gilt
fue más capaz de lidiar con sus picos de tráfico, y hoy en día tiene más de 450 microservicios,
cada uno funcionando en múltiples máquinas separadas.

Al adoptar sistemas de aprovisionamiento bajo demanda como los proporcionados por AWS,
incluso podemos aplicar este escalado a la demanda de aquellas piezas que lo necesiten. Esto
nos permite controlar nuestros costos de manera más eficaz. No es frecuente que un enfoque
arquitectónico pueda estar tan estrechamente correlacionado con un ahorro de costes casi
inmediato.

Facilidad de despliegue

Un cambio de una línea en una aplicación monolítica de un millón de líneas requiere que se
implemente toda la aplicación para liberar el cambio. Eso podría ser un despliegue de alto
impacto y alto riesgo. En la práctica, despliegues como estos terminan ocurriendo con poca
frecuencia debido al miedo comprensible. Desafortunadamente, esto significa que nuestros
cambios continúan acumulando entre versiones, hasta que la nueva versión de nuestra
aplicación que entra en producción tiene masas de cambios. Y cuanto más grande sea el delta
entre lanzamientos, mayor será el riesgo de que nos equivoquemos!

Con los microservicios, podemos realizar un cambio en un único servicio e implementarlo


independientemente del resto del sistema. Esto nos permite implementar nuestro código más
rápido. Si se produce un problema, se puede aislar rápidamente a un servicio individual, lo que
facilita la reversión rápida. También significa que podemos llevar nuestra nueva funcionalidad
a los clientes más rápido. Esta es una de las principales razones por las que organizaciones
como Amazon y Netflix utilizan estas arquitecturas, para asegurarse de que eliminan tantos
impedimentos como sea posible para sacar el software por la puerta.

Alineación organizativa

Muchos de nosotros hemos experimentado los problemas asociados con equipos grandes y
grandes bases de código. Estos problemas pueden agravarse cuando se distribuye el equipo.
También sabemos que los equipos más pequeños que trabajan en bases de código más
pequeñas tienden a ser más productivos.

Los microservicios nos permiten alinear mejor nuestra arquitectura con nuestra organización,
ayudándonos a minimizar el número de personas que trabajan en cualquier base de código
para llegar al punto dulce del tamaño y la productividad del equipo. Los microservicios
también nos permiten cambiar la propiedad de los servicios a medida que cambia la
organización, lo que nos permite mantener la alineación entre la arquitectura y la organización
en el futuro.

Composabilidad

Una de las principales promesas de los sistemas distribuidos y las arquitecturas orientadas al
servicio es que abrimos oportunidades para la reutilización de la funcionalidad. Con los
microservicios, permitimos que nuestra funcionalidad se consuma de diferentes maneras para
diferentes propósitos. Esto puede ser especialmente importante cuando pensamos en cómo
nuestros consumidores utilizan nuestro software.

Atrás quedaron el momento en que podíamos pensar por poco sobre nuestro sitio web de
escritorio o aplicación móvil. Ahora tenemos que pensar en las innumerables maneras en que
podríamos querer tejer capacidades para la web, la aplicación nativa, la web móvil, la
aplicación para tabletas o el dispositivo portátil. A medida que las organizaciones pasan de
pensar en términos de canales estrechos a conceptos más holísticos de la participación del
cliente, necesitamos arquitecturas que puedan mantenerse al día.

Con los microservicios, piense en nosotros abriendo costuras en nuestro sistema que son
direccionables por terceros. A medida que cambian las circunstancias, podemos crear
aplicaciones de diferentes maneras. Con una aplicación monolítica, a menudo tengo una
costura de grano grueso que se puede utilizar desde el exterior. Si quiero romper eso para
conseguir algo más útil, ¡necesitaré un martillo!

Puntos de dolor de microservicio

Las arquitecturas de microservicios traen una serie de beneficios, como ya hemos visto. Pero
también traen una gran cantidad de complejidad. Si está considerando adoptar una
arquitectura de microservicios, es importante que lo haga siendo capaz de comparar lo bueno
con lo malo. En realidad, la mayoría de estos puntos de dolor se pueden colocar en la puerta
de los sistemas distribuidos, por lo que es tan probable que sea evidente en un monolito
distribuido como una arquitectura de microservicios.

Vamos a cubrir muchos de estos temas en profundidad a lo largo del resto del libro - de hecho,
yo diría que la mayor parte de este libro se trata de lidiar con el dolor, el sufrimiento y el
horror de poseer una arquitectura de microservicios.

Experiencia de desarrollador

A medida que tenga más y más servicios, la experiencia del desarrollador puede comenzar a
sufrir. Tiempos de ejecución más intensivos en recursos, como la JVM, pueden limitar el
número de microservicios que se pueden ejecutar en un único equipo desarrollador.
Probablemente podría ejecutar cuatro o cinco microservicios basados en JVM como procesos
separados en mi computadora portátil, pero ¿podría ejecutar 10 o 20? Probablemente no.
Incluso con tiempos de ejecución con menos impuestos, hay un límite en el número de cosas
que puede ejecutar localmente, lo que inevitablemente iniciará conversaciones sobre qué
hacer cuando no puede ejecutar todo el sistema en un equipo. Esto puede complicarse aún
más si utiliza servicios en la nube que no puede ejecutar localmente.
Las soluciones extremas pueden implicar el "desarrollo en la nube", donde los desarrolladores
se alejan de poder desarrollarse localmente. No soy un fan de esto, porque los ciclos de
retroalimentación pueden sufrir mucho. En cambio, creo que limitar el alcance de las partes de
un sistema en las que un desarrollador necesita trabajar es probable que sea un enfoque
mucho más sencillo. Sin embargo, esto podría ser problemático si desea adoptar más de un
modelo de "propiedad colectiva" en el que se espera que cualquier desarrollador trabaje en
cualquier parte del sistema.

Sobrecarga tecnológica

El gran peso de las nuevas tecnologías que han surgido para permitir la adopción de
arquitecturas de microservicios puede ser abrumador. Seré honesto y diré que gran parte de
esta tecnología acaba de ser re-tachada de "amigable con los microservicios", pero algunos
avances han ayudado legítimamente a lidiar con la complejidad de este tipo de arquitecturas.
Existe el peligro, sin embargo, de que esta riqueza de juguetes nuevos pueda conducir a una
forma de fetichismo tecnológico. He visto tantas empresas adoptando arquitectura de
microservicios también decidiendo que ahora es el mejor momento para introducir vastas
gamas de tecnologíanueva, y a menudo alienígena.

Los microservicios bien pueden darle la opción de que cada microservicio se escriba en un
lenguaje de programación diferente, que se ejecute en un tiempo de ejecución diferente o que
use una base de datos diferente, pero se trata de opciones, no de requisitos. Usted tiene que
equilibrar cuidadosamente la amplitud y complejidad de la tecnología que utiliza contra los
costos que una amplia gama de tecnología puede traer.

Cuando empiece a adoptar microservicios, algunos desafíos fundamentales son ineludibles:


tendrá que dedicar mucho tiempo a comprender problemas relacionados con la coherencia de
los datos, la latencia, el modelado de servicios y similares. Si estás tratando de entender cómo
estas ideas cambian la forma en que piensas sobre el desarrollo de software al mismo tiempo
que estás adoptando una gran cantidad de nuevas tecnologías, lo pasarás mal. También vale la
pena señalar que el ancho de banda tomado tratando de entender toda esta nueva tecnología
también reducirá el tiempo que tiene para realmente enviar características a sus usuarios.

A medida que (gradualmente) aumente la complejidad de la arquitectura de microservicios,


busque introducir nuevas tecnologías a medida que la necesite. ¡No necesita un clúster de
Kubernetes cuando tiene tres servicios! Además de asegurarse de que no está sobrecargado
con la complejidad de estas nuevas herramientas, este aumento gradual tiene el beneficio
adicional de permitirle obtener nuevas y mejores formas de hacer cosas que sin duda surgirán
con el tiempo.

Informes

Con un sistema monolítico, normalmente tiene una base de datos monolítica. Esto significa
que las partes interesadas que desean analizar todos los datos juntos, que a menudo implican
grandes operaciones de combinación entre datos, tienen un esquema listo para ejecutar sus
informes. Simplemente pueden ejecutarlos directamente contra la base de datos monolítica,
tal vez contra una réplica de lectura, como se muestra en la Figura 1-13.
Figura 1-13.  Informes realizados directamente en la base de datos de un monolito

Con una arquitectura de microservicios, hemos roto este esquema monolítico. Eso no significa
que la necesidad de informar en todos nuestros datos haya desaparecido; lo hemos hecho
mucho más difícil porque ahora nuestros datos están dispersos en múltiples esquemas
lógicamente aislados.

Los enfoques más modernos para la generación de informes, como el uso de streaming para
permitir informes en tiempo real sobre grandes volúmenes de datos, pueden funcionar bien
con una arquitectura de microservicios, pero normalmente requieren la adopción de nuevas
ideas y tecnología asociada. Como alternativa, es posible que simplemente deba publicar datos
de los microservicios en bases de datos de informes centrales (o quizás lagos de datos menos
estructurados) para permitir la notificación de casos de uso.

Supervisión y solución de problemas

Con una aplicación monolítica estándar, podemos tener un enfoque bastante simplista para el
monitoreo. Tenemos un pequeño número de máquinas de las que preocuparnos, y el modo de
error de la aplicación es algo binario: la aplicación es a menudo todo hacia arriba o todo hacia
abajo. Con una arquitectura de microservicios, ¿entendemos el impacto si solo se reduce una
sola instancia de un servicio?

Con un sistema monolítico, si nuestra CPU está atascada al 100% durante mucho tiempo,
sabemos que es un gran problema. Con una arquitectura de microservicios con decenas o
cientos de procesos, ¿podemos decir lo mismo? ¿Necesitamos despertar a alguien a las 3 a.m.
cuando solo un proceso está atascado al 100% cpu?

Afortunadamente, hay toda una serie de ideas en este espacio que pueden ayudar. Si desea
explorar este concepto con más detalle, recomiendo la observabilidad de
sistemas  distribuidos  por Cindy Sridharan (O'Reilly) como un excelente punto de partida,
aunque también vamos a echar nuestro propio vistazo en el capítulo 9.

seguridad

Con un sistema monolítico de un solo proceso, gran parte de nuestra información fluyó dentro
de ese proceso. Ahora, más información fluye a través de las redes entre nuestros servicios.
Esto puede hacer que nuestros datos sean más vulnerables a ser observados en tránsito, pero
también potencialmente manipulados como parte de los ataques del hombre en el medio. Esto
significa que es posible que deba dirigir más atención a la protección de los datos en tránsito y
a garantizar que los puntos de conexión de microservicios estén protegidos de modo que solo
las partes autorizadas puedan hacer uso de ellos. [Link to Come] se dedica enteramente a
mirar los desafíos en este espacio.

ensayo

Con cualquier tipo de prueba funcional automatizada, tiene un delicado acto de equilibrio.
Cuanto más funcionalidad se ejecute una prueba,más amplio será el alcance de la prueba, más
confianza tendrá en la aplicación. Por otro lado, cuanto mayor sea el alcance de la prueba, más
difícil será configurar los datos de prueba y los accesorios de soporte, más tiempo puede
tardar en ejecutarse y más difícil puede ser averiguar lo que se rompe cuando falla. En el
Capítulo 8 compartiré una serie de técnicas para hacer que las pruebas funcionen en este
entorno más desafiante.

Las pruebas de extremo a extremo para cualquier tipo de sistema están en el extremo final de
la escala en términos de funcionalidad que cubren, y estamos acostumbrados a que sean más
problemáticos para escribir y mantener que las pruebas unitarias de menor alcance. A menudo
esto vale la pena, sin embargo, porque queremos la confianza que proviene de tener una
prueba de extremo a extremo utilizar nuestros sistemas de la misma manera que un usuario
podría.

Pero con una arquitectura de microservicios, el alcance de nuestras pruebas de extremo a


extremo se vuelve muy grande. Ahora tendríamos que ejecutar pruebas en varios servicios,
todos los cuales deben implementarse y configurarse adecuadamente para los escenarios de
prueba. También debemos estar preparados para los falsos negativos que se producen cuando
los problemas ambientales, como la muerte de instancias de servicio o el tiempo de inactividad
de la red de implementaciones fallidas, provocan que nuestras pruebas fallen.

Estas fuerzas significan que a medida que la arquitectura de microservicios crece, obtendrá un
rendimiento de la inversión cada vez menor cuando se trata de pruebas de extremo a extremo.
Las pruebas costarán más, pero no lograrán darle el mismo nivel de confianza que en el
pasado. Esto le impulsará hacia nuevas formas de pruebas, como pruebas basadas en
contratos, así como explorar técnicas de corrección de lanzamientos e ideas como pruebas en
producción.

latencia

Con una arquitectura de microservicios, el procesamiento que se pudo haber realizado


localmente en un procesador ahora puede terminar dividido en varios microservicios
independientes. La información que fluyó anteriormente dentro de un solo proceso ahora
debe serializarse, transmitirse y deserializarse a través de redes que podría
estar ejercitando más que nunca. Todo esto puede resultar en un empeoramiento de la
latencia de su sistema.

Aunque puede ser difícil medir el impacto exacto en la latencia de las operaciones en la fase de
diseño o codificación, esta es otra razón por la que es importante llevar a cabo cualquier
migración de microservicios de forma incremental. Realice un pequeño cambio y, a
continuación, mida el impacto. Esto supone que tiene alguna manera de medir la latencia de
extremo a extremo para las operaciones que le importan: las herramientas de seguimiento
distribuidas como Jaeger pueden ayudar aquí. Pero también debe tener una comprensión de lo
que es la latencia aceptable para estas operaciones también. A veces hacer una operación más
lenta es perfectamente aceptable, siempre y cuando todavía sea lo suficientemente rápido!

Coherencia de los datos

Pasar de un sistema monolítico, en el que los datos se almacenan y gestionan en una sola base
de datos, a un sistema mucho más distribuido, en el que varios procesos administran el estado
en diferentes bases de datos, provoca posibles desafíos con respecto a la coherencia de los
datos. Mientras que en el pasado es posible que haya confiado en las transacciones de base de
datos para administrar los cambios de estado, deberá comprender que no se puede
proporcionar fácilmente una seguridad similar en un sistema distribuido. El uso de
transacciones distribuidas en la mayoría de los casos resulta ser altamente problemático para
coordinar los cambios de estado.

En su lugar, es posible que deba empezar a usar conceptos como sagas (algo que detallaré
extensamente en el Capítulo 3)y una consistencia final para administrar y razonar sobre el
estado en su sistema. Estas ideas pueden requerir cambios fundamentales en la forma en que
piensa sobre los datos en sus sistemas, algo que puede ser bastante desalentador al migrar los
sistemas existentes. Una vez más, esta es otra buena razón para ser cauteloso en la rapidez
con la que descompone la aplicación. Es muy importante adoptar un enfoque incremental para
la descomposición para que pueda evaluar el impacto de los cambios en su arquitectura en la
producción.

¿Debo usar microservicios?

A pesar de la unidad en algunos trimestres para hacer de las arquitecturas de microservicios el


enfoque predeterminado para el software, siento que debido a los numerosos desafíos que he
descrito, adoptarlos todavía requiere un pensamiento cuidadoso. Debe evaluar su propio
espacio problemático, habilidades y panorama tecnológico y comprender lo que está tratando
de lograr antes de decidir si los microservicios son adecuados para usted. Son un enfoque
arquitectónico, no el enfoque arquitectónico. Su propio contexto debe desempeñar un papel
importante en la decisión de si desea ir por ese camino.

Dicho esto, quiero esbozar algunas situaciones que normalmente me alejarían de los
microservicios o hacia él.

Para quién podrían no trabajar

Dada la importancia de definir límites de servicio estables, siento que las arquitecturas de
microservicios suelen ser una mala opción para productos o startups nuevos. En cualquier
caso, el dominio con el que está trabajando suele sufrir cambios significativos a medida que
itera sobre los fundamentos de lo que está intentando compilar. Este cambio en los modelos
de dominio, a su vez, dará lugar a que se realicen más cambios en los límites de servicio, y
coordinar los cambios a través de los límites del servicio es una empresa costosa. En general,
me parece más apropiado esperar hasta que suficiente del modelo de dominio se haya
estabilizado antes de buscar definir los límites del servicio.

Veo una tentación para las startups de ir al microservicio primero. El razonamiento dice: "Si
tenemos mucho éxito, ¡tendremos que escalar!" El problema es que no necesariamente sabes
si alguien va a querer usar tu nuevo producto. E incluso si tienes el éxito suficiente para
requerir una arquitectura altamente escalable, lo que terminas entregando a tus usuarios
podría ser muy diferente de lo que empezaste a construir en primer lugar. Uber inicialmente
se centró en las limusinas, y Flickr se separó de los intentos de crear un juego multijugador en
línea. El proceso de encontrar un ajuste en el mercado de productos significa que podrías
terminar con un producto muy diferente al final que el que pensabas que construirías cuando
empezaste.

Las startups también suelen tener menos personas disponibles para crear el sistema, lo que
crea más desafíos con respecto a los microservicios. Los microservicios traen consigo fuentes
de nuevo trabajo y complejidad, y esto puede atar un ancho de banda valioso. Cuanto más
pequeño sea el equipo, más pronunciado será este costo. Cuando trabajo con equipos más
pequeños con sólo un puñado de desarrolladores, siempre estoy muy reacio a sugerir
microservicios por esta razón.

El desafío de los microservicios para startups se ve agravado por el hecho de que normalmente
su mayor restricción son las personas. Para un equipo pequeño, una arquitectura de
microservicios puede ser difícil de justificar porque se requiere trabajo solo para controlar la
implementación y administración de los propios microservicios. Algunas personas han descrito
esto como el "impuesto a los microservicios". Cuando esa inversión beneficia a mucha gente,
es más fácil de justificar. Pero si una persona de su equipo de cinco personas está pasando su
tiempo en estos temas, eso es mucho tiempo valioso para no pasar la construcción de su
producto. Es mucho más fácil pasar a los microservicios más adelante, después de comprender
dónde están las restricciones en su arquitectura y cuáles son sus puntos de dolor, entonces
puede enfocar su energía en el uso de microservicios en los lugares más sensatos.

Por último, encuentro un número sorprendente de organizaciones que crean software que
será implementado y administrado por sus clientes. Como ya hemos cubierto, las arquitecturas
de microservicios pueden insertar mucha complejidad en el dominio operativo y de
implementación. Si usted mismo está ejecutando el software, usted es capaz de compensar
esta nueva complejidad mediante la adopción de nuevas tecnologías, el desarrollo de nuevas
habilidades y el cambio de prácticas de trabajo. Esto no es algo que pueda esperar que hagan
sus clientes. Si están acostumbrados a recibir su software como instalador de Windows, va a
ser un terrible shock para ellos cuando envíe la próxima versión de su software y diga:
"¡Simplemente coloque estos 20 pods en su clúster de Kubernetes!" Con toda probabilidad, no
tendrán idea de lo que es una vaina, Kubernetes o un clúster.

Donde funcionan bien

Probablemente la razón más grande por la que veo que las organizaciones adoptan
microservicios es permitir que más desarrolladores trabajen en el mismo sistema sin
interfirarse entre sí. Haga bien su arquitectura y límites organizativos, y permite que más
personas trabajen independientemente unas de otras, lo que reduce la contención de entrega.
Es probable que una startup de cinco personas encuentre una arquitectura de microservicios
un arrastre. Es probable que una ampliación de cien personas que está creciendo rápidamente
encuentre que su crecimiento es mucho más fácil de acomodar con una arquitectura de
microservicios debidamente alineada en torno a sus esfuerzos de desarrollo de productos.

Las aplicaciones de software como servicio (SaaS) también son, en general, una buena opción
para una arquitectura de microservicios. Normalmente se espera que estos productos
funcionen 24-7, lo que crea desafíos a la hora de implementar cambios. La liberabilidad
independiente de las arquitecturas de microservicios es una gran bendición en esta área.
Además, los microservicios se pueden escalar hacia arriba o hacia abajo, según sea necesario.
Esto significa que a medida que establece una línea base sensata para las características de
carga de su sistema, obtendrá más control sobre cómo asegurarse de que puede escalar su
sistema de la manera más rentable posible.

La naturaleza tecnológica de los microservicios garantiza que puede sacar el máximo partido a
las plataformas en la nube. Los proveedores de nube pública proporcionan una amplia gama
de servicios y mecanismos de implementación para el código. Puede hacer coincidir mucho
más fácilmente los requisitos de servicios específicos con los servicios en la nube que mejor le
ayudarán a implementarlos. Por ejemplo, puede decidir implementar un servicio como un
conjunto de funciones, otro como una máquina virtual administrada (VM) y otro en una
plataforma administrada como plataforma de servicio (PaaS).

Aunque vale la pena señalar que adoptar una amplia gama de tecnología a menudo puede ser
un problema, ser capaz de probar nuevas tecnologías fácilmente es una buena manera de
identificar rápidamente nuevos enfoques que podrían producir beneficios. La creciente
popularidad de las plataformas FaaS es uno de esos ejemplos. Para las cargas de trabajo
adecuadas, puede reducir drásticamente la cantidad de sobrecarga operativa, pero en la
actualidad, no es un mecanismo de implementación que sería adecuado en todos los casos.

Los microservicios también presentan beneficios claros para las organizaciones que buscan
proporcionar servicios a sus clientes a través de una variedad de nuevos canales. Muchos
esfuerzos de transformación digital parecen implicar tratar de desbloquear la funcionalidad
oculta en los sistemas existentes. El deseo es crear nuevas experiencias de cliente que puedan
soportar las necesidades de los usuarios a través de cualquier mecanismo de interacción que
tenga más sentido.

Sobre todo, una arquitectura de microservicios es una que puede darle mucha flexibilidad a
medida que continúa evolucionando su sistema. Esa flexibilidad tiene un costo, por supuesto,
pero si desea mantener sus opciones abiertas con respecto a los cambios que podría querer
hacer en el futuro, podría ser un precio que vale la pena pagar.

resumen

Las arquitecturas de microservicios pueden darle un enorme grado de flexibilidad en la


elección de la tecnología, el manejo de la robustez y el escalado, la organización de equipos y
mucho más. Esta flexibilidad es en parte la razón por la que muchas personas están adoptando
arquitecturas de microservicios. Pero los microservicios traen consigo un grado significativo de
complejidad, y debe asegurarse de que esta complejidad está justificada. Para muchos, se han
convertido en una arquitectura de sistema predeterminada, que se utilizará en prácticamente
todas las situaciones. Por el contrario, sigo pensando que son una elección arquitectónica cuyo
uso debe estar justificado por los problemas que está tratando de resolver; a menudo,
enfoques más simples pueden ofrecer mucho más fácilmente.

Sin embargo, muchas organizaciones, especialmente las más grandes, han demostrado cuán
eficaces pueden ser los microservicios. Cuando los conceptos básicos de los microservicios se
entienden e implementan correctamente, pueden ayudar a crear arquitecturas productivas y
empoderadoras que pueden ayudar a los sistemas a ser más que la suma de sus partes.

Espero que este capítulo haya servido como una buena introducción a estos temas. A
continuación, vamos a ver cómo definimos los límites de microservicios, explorando los temas
de programación estructurada y diseño basado en dominios en el camino.
1 Este concepto fue esbozado por primera vez por David Parnas en 1971, en"Information
Distributions Aspects of Design Methodology", Proceedings of IFIP Congress '71.

2 Para obtener una introducción detallada al diseño basado en dominios, consulte Diseño
basado en dominios de Eric Evans (Addison-Wesley Professional), o para obtener una visión
general más condensada, Diseño basado en dominios destilado por Vaughn Vernon (Addison-
Wesley Professional).

3 Para obtener una visión general del pensamiento de Shopify detrás del uso de un monolito
modular en lugar de microservicios,"Deconstruir el Monolito"de Kirsten Westeinde tiene
algunas ideas útiles.

4 Mensaje de correo electrónico enviado a un tablón de anuncios de DEC SRC a las 12:23:29


PDT el 28 de mayo de 1987.

5 Microsoft Research ha llevado a cabo estudios en este espacio, y recomiendo todos ellos,
pero como punto de partida, sugiero "¡No toques mi código! Examinando los efectos de la
propiedad en la calidad del software" por Christian Bird, et al.

También podría gustarte