Be Software Architecture Wise
Be Wise Apps

Read in English · Lire en français · Auf Deutsch lesen

Sección 6.3 de 6.8 · Avanzado · 26 min de lectura

Microservicios: principios, beneficios y costos

Videolección

5 min · narrado en inglés, con subtítulos
Solo escuchar (audio)
Leer la transcripción

De los microservicios se habla mucho, y es fácil equivocarse con ellos. Aprenderás qué son de verdad, qué tamaño debe tener un servicio y cuánto cuestan.

Imagina un gran mercado gastronómico en lugar de un único restaurante grande. Cada puesto tiene su propio equipo pequeño, su propia cocina y su propia carta, y puede cambiar sus recetas sin preguntar a los demás puestos. Los clientes piden en un mostrador común, que envía cada pedido al puesto que corresponde. El mercado puede crecer añadiendo puestos, y si se quema la cocina de un puesto, los demás no cierran. Pero alguien tiene que gestionar el mostrador, las entregas, la limpieza y los controles de seguridad de todos los puestos, y una comida de tres puestos exige una coordinación cuidadosa. Los microservicios son el mercado gastronómico.

Los microservicios construyen una aplicación como un conjunto de servicios pequeños. Cada uno se ejecuta en su propio proceso, se construye en torno a una capacidad de negocio, puede desplegarse por sí solo mediante maquinaria automatizada y se comunica con los demás mediante mecanismos ligeros, como API HTTP o mensajería. La pregunta más difícil es dónde trazar las líneas entre los servicios.

La mejor respuesta es alinear cada servicio con un contexto delimitado: una parte del negocio en la que un modelo y su lenguaje son coherentes. Un pedido significa un carrito en pedidos, pero una recogida y una entrega en despacho. Un contexto suele ser lo que un solo equipo puede poseer. La propiedad que los define es la desplegabilidad independiente: un equipo puede lanzar su servicio sin lanzar ningún otro. Eso depende de los contratos, no de los contenedores: cambios compatibles hacia atrás y pruebas de contrato. Cada servicio es propietario de sus datos, y ningún otro servicio los lee ni los escribe directamente. El precio es alto. Los joins se convierten en llamadas entre servicios, y una transacción se convierte en una saga que solo es eventualmente consistente. Y la lógica de negocio pertenece a los servicios. La red y el intermediario de mensajes solo transportan mensajes: extremos inteligentes y tuberías tontas.

Esta es la plataforma de reparto de comida como microservicios. Arriba hay tres clientes: la app del cliente, la tableta del restaurante y la app del repartidor. Las solicitudes pasan por un API gateway, un único punto de entrada que se encarga del cifrado, la autenticación, los límites de tasa y el enrutamiento. Mantén la lógica de negocio fuera de él, o volverás a construir el viejo bus de servicios. Después viene un backend for frontend para cada tipo de cliente: un backend delgado, propiedad del equipo de ese cliente, que llama a los servicios y da forma a las respuestas. Luego, los servicios: pedidos, carta, precios, despacho y pagos. Cada uno es propietario de su propia base de datos, y cada uno puede elegir el tipo de almacén que le conviene. En la parte inferior hay un intermediario de mensajes que transporta eventos como OrderPlaced. Cada pieza de apoyo resuelve un problema real, pero es una cosa más que operar.

Entonces, ¿qué tamaño debe tener un servicio? No hay un tamaño correcto en líneas de código ni en personas. Una herramienta mejor es sopesar las fuerzas que actúan sobre la granularidad de los servicios. Seis fuerzas empujan a dividir: el alcance del servicio, la frecuencia con la que cambia su código, necesidades de escalado muy diferentes, la tolerancia a fallos, la seguridad y la extensibilidad. Cuatro empujan a mantener las cosas juntas: transacciones que deben tener éxito o fallar como una sola, flujos de trabajo que se convertirían en largas cadenas de llamadas, código compartido y datos estrechamente relacionados. La granularidad es un equilibrio que se decide caso por caso.

Este es el equilibrio en la práctica. Un servicio de Precios calcula los totales del carrito, incluidas las tarifas de envío y las promociones. Las promociones cambian varias veces por semana, y cada lanzamiento vuelve a probar el cálculo de tarifas. Alguien propone una división. La volatilidad del código argumenta con fuerza a favor. Las promociones cambian cada semana; las reglas de tarifas, cada trimestre. La tolerancia a fallos argumenta moderadamente a favor. Una regla de promoción defectuosa ha hecho caer Precios dos veces. Por separado, un fallo podría significar simplemente que no se muestra ningún descuento. El flujo de trabajo argumenta moderadamente en contra. Cada total del carrito necesita ambas, así que una división añade un salto síncrono y sus modos de fallo. La decisión: extraer Promociones, con cuidado. Precios lo llama con un timeout de ciento cincuenta milisegundos y, si falla, calcula el precio del carrito sin descuentos y lo recalcula en el proceso de pago.

El fallo más grave es el monolito distribuido: servicios que comparten una base de datos, se llaman entre sí en largas cadenas o deben lanzarse juntos. Todos los costos de la distribución, nada de la independencia. Los servicios de entidad llevan nombres de sustantivos, como cliente o pedido, y ofrecen poco más que guardar y recuperar registros, así que cada proceso de negocio tiene que llamar a varios de ellos. Los servicios conversadores convierten una solicitud de usuario en decenas de llamadas, así que la latencia crece con cada funcionalidad. El estilo también necesita primero lo básico: aprovisionamiento rápido, monitorización de cada servicio y despliegue automatizado con un rollback sencillo. Y los equipos deben operar lo que construyen, con guardias. Así que los microservicios encajan con muchos equipos y dominios bien entendidos. No encajan con un equipo pequeño, ni con un producto nuevo cuyo dominio todavía se está descubriendo. Son una herramienta con un costo, no un destino.

La sección completa incluye cada fuerza de granularidad con un ejemplo y la lista completa de antipatrones. A continuación, en la Sección seis punto cuatro, veremos la arquitectura dirigida por eventos. Nos vemos allí.

Lo que necesitas saber

Definición y origen

Los microservicios son un estilo arquitectónico en el que una aplicación se construye como un conjunto de servicios pequeños, cada uno ejecutándose en su propio proceso, cada uno construido en torno a una capacidad de negocio, cada uno desplegable de forma independiente mediante maquinaria automatizada, que se comunican mediante mecanismos ligeros como API HTTP o mensajería, con un mínimo de gestión centralizada. Ese resumen sigue el artículo que definió el término para la mayor parte del sector: Microservices, de James Lewis y Martin Fowler, publicado en martinfowler.com en marzo de 2014. El artículo señala que el nombre se discutió en un taller de arquitectos de software cerca de Venecia en mayo de 2011 y que el grupo lo adoptó en mayo de 2012; empresas como Amazon y Netflix ya trabajaban así.

Lewis y Fowler no dieron una definición formal. Describieron nueve características comunes, y los profesionales todavía las usan como lista de comprobación: componentización mediante servicios; organización en torno a capacidades de negocio; productos en lugar de proyectos; extremos inteligentes y tuberías tontas; gobernanza descentralizada; gestión de datos descentralizada; automatización de la infraestructura; diseño para el fallo; y diseño evolutivo. Los apartados siguientes tratan una a una las más significativas desde el punto de vista arquitectónico.

Servicios alineados con contextos delimitados

La pregunta más difícil en los microservicios es dónde trazar las líneas. La respuesta más fiable viene del diseño estratégico guiado por el dominio (Capítulo 5): un contexto delimitado es una parte del negocio dentro de la cual un modelo y su lenguaje son coherentes. En el reparto de comida, 'pedido' significa un carrito que se está pagando en Pedidos, una comanda que cocinar en el contexto de la cocina del restaurante y una recogida y una entrega en Despacho. Cada contexto es un candidato natural a un servicio, o a un pequeño número de servicios propiedad de un solo equipo.

Alinear los servicios con los contextos delimitados les da una cohesión alta (lo que cambia junto vive junto) y un acoplamiento bajo (los contextos se comunican a través de unos pocos contratos explícitos, traducidos en los bordes). También los alinea con los equipos, porque un contexto delimitado suele tener el tamaño de algo que un solo equipo puede entender y poseer. Los servicios trazados en torno a capas técnicas o a tablas de la base de datos carecen de ambas propiedades, y los antipatrones que se ven más adelante en esta sección son en su mayoría el resultado.

Desplegabilidad independiente: la propiedad que los define

Si una propiedad define los microservicios, es la desplegabilidad independiente: un equipo puede cambiar su servicio y lanzarlo a producción sin cambiar, probar ni lanzar ningún otro servicio al mismo tiempo. Sam Newman, en Building Microservices (segunda edición, 2021), la trata como la propiedad que hay que proteger por encima de todas las demás, porque casi todos los otros beneficios dependen de ella. La entrega más rápida, un radio de impacto menor, el escalado selectivo y la autonomía de los equipos desaparecen si los lanzamientos deben coordinarse.

La desplegabilidad independiente es una propiedad de los contratos, no de los contenedores. Dos servicios que se despliegan por separado pero que siempre deben lanzarse juntos, porque un cambio en uno rompe el otro, no son desplegables de forma independiente. Protegerla exige cambios de interfaz compatibles hacia atrás (añadir campos, nunca eliminarlos ni renombrarlos sin un periodo de obsolescencia), pruebas de contrato dirigidas por el consumidor y API versionadas, todo lo cual se trata en comunicación y API.

Una base de datos por servicio, y extremos inteligentes con tuberías tontas

La gestión de datos descentralizada de Lewis y Fowler se convierte, en la práctica, en la regla de una base de datos por servicio: cada servicio es propietario de sus datos, y ningún otro servicio los lee ni los escribe directamente. Los demás servicios obtienen los datos a través de la API del propietario o de los eventos que el propietario publica. La regla es lo que convierte un servicio en un cuanto independiente: su esquema puede cambiar, y puede escalarse, respaldarse y restaurarse, sin pedir permiso a nadie. Cada servicio puede además elegir el almacén que le conviene (una base de datos relacional para los pedidos, un almacén clave-valor para las sesiones, un motor de búsqueda para las cartas), lo que se llama persistencia políglota.

El precio es alto y hay que pagarlo con conocimiento de causa. Las consultas que antes eran un join SQL entre tablas ahora atraviesan servicios. Los cambios que antes eran una sola transacción ahora necesitan una saga y pasan a ser eventualmente consistentes. Los informes necesitan un pipeline aparte. El Capítulo 7 trata en profundidad la propiedad de los datos.

La otra característica con mayores consecuencias arquitectónicas son los extremos inteligentes y tuberías tontas (smart endpoints and dumb pipes). La lógica de negocio pertenece a los servicios; la red y el intermediario de mensajes (message broker) solo transportan mensajes. Es una reacción directa contra el bus de servicios empresarial de la SOA clásica, donde las reglas de enrutamiento, las transformaciones y los procesos se acumulaban en un middleware central.

Una topología de microservicios para el reparto de comida

Topología de microservicios para el reparto de comida: tres apps cliente llaman a un API gateway, que enruta a un backend for frontend por cliente; los BFF llaman a servicios de grano fino, cada uno con su almacén de datos, que también intercambian eventos mediante un broker de mensajesApp clienteTableta restauranteApp repartoAPI gateway: TLS, autenticación, límites de tasa, enrutamientoBFF clienteBFF restauranteBFF repartocada servicio tiene sus datosPedidossu BDCartasu BDPreciossu BDDespachosu BDPagossu BDBroker de mensajes: OrderPlaced, PaymentAuthorised, CourierAssigned ...Flechas continuas: llamadas síncronas. Discontinuas: eventos publicados en el broker y leídos de él.
Los clientes llegan a los servicios a través de un gateway y un backend for frontend cada uno; cada servicio es propietario de sus datos, y los eventos fluyen a través de un broker.

Patrones de apoyo

En torno al estilo ha surgido un conjunto de patrones de apoyo. Cada uno resuelve un problema real y cada uno añade un componente que hay que operar, así que adóptalos cuando aparezca el problema y no todos a la vez.

Patrones de apoyo habituales

PatrónProblema que resuelveQué esAtención a
API gateway (puerta de enlace de API)Los clientes no deberían conocer las direcciones de decenas de servicios ni repetir la autenticación ante cada uno.Un único punto de entrada que termina TLS, autentica, aplica límites de tasa y enruta las solicitudes a los servicios; puede combinar varias llamadas en una sola respuesta.Lógica de negocio que se cuela en el gateway y recrea un ESB; un punto único de fallo que necesita alta disponibilidad.
Backend for frontend (BFF)Una app móvil, una app web y una API para socios necesitan datos con formas distintas; una API general no sirve bien a ninguna.Un backend independiente y delgado por cada tipo de cliente, propiedad del equipo de ese cliente, que llama a los servicios y da forma a las respuestas. El nombre es de Phil Calçado, de SoundCloud; Sam Newman popularizó el patrón en 2015.Lógica duplicada entre los BFF; un BFF que se convierte en un minimonolito.
Descubrimiento de serviciosLas instancias de los servicios arrancan, se detienen y se mueven constantemente; las direcciones no pueden configurarse a mano.Un registro de las instancias sanas en cada momento, que consultan los clientes o un balanceador de carga. Kubernetes lo proporciona mediante nombres DNS para los Services.Entradas del registro obsoletas; clientes que guardan en caché las direcciones demasiado tiempo.
Service mesh (malla de servicios)Todos los servicios necesitan TLS mutuo, reintentos, timeouts, desvío de tráfico y telemetría; implementarlos en cada lenguaje es un desperdicio.Una capa de infraestructura de proxies (tradicionalmente un sidecar junto a cada instancia del servicio) controlada de forma centralizada, como Istio o Linkerd.Una complejidad operativa considerable; los reintentos configurados a la vez en la malla y en el código multiplican la carga.

Los requisitos previos de Fowler y los costos organizativos

En agosto de 2014, Martin Fowler enumeró tres cosas que una organización debería tener antes siquiera de construir microservicios. Aprovisionamiento rápido: la capacidad de crear un servidor o un entorno nuevo en horas, lo que implica automatización. Monitorización básica: tanto medidas técnicas (errores, latencia, disponibilidad) como medidas de negocio (pedidos por minuto) para cada servicio, de modo que los problemas se detecten rápido. Despliegue rápido de aplicaciones: un pipeline automatizado que lleva un servicio a pruebas y a producción rápidamente, con un rollback sencillo. Sin esto, muchos servicios pequeños multiplican el trabajo manual. Su idea complementaria, la prima de los microservicios (microservice premium, 2015), es que el estilo conlleva un costo fijo en complejidad y productividad que solo compensa en sistemas lo bastante complejos como para necesitarlo.

Los costos organizativos son tan reales como los técnicos. El estilo presupone equipos estables que son propietarios de sus servicios en producción, el principio que Werner Vogels, CTO de Amazon, describió en 2006 como You build it, you run it (quien lo construye, lo opera). Eso significa que cada equipo necesita habilidades operativas y un turno de guardias. Necesita una plataforma: pipelines de despliegue, observabilidad, gestión de secretos y plantillas de servicio, normalmente proporcionada por un equipo de plataforma (Capítulo 10). Necesita acuerdos sobre estándares transversales (formato de logging, identificadores de correlación, convenciones de API) sin aprobación central de cada cambio. Y necesita que la ley de Conway se use deliberadamente: los límites de los equipos y los de los servicios deben coincidir; de lo contrario, cada cambio exige que se coordinen varios equipos.

Granularidad: ¿qué tamaño debe tener un servicio?

No hay un tamaño correcto en líneas de código ni en personas. Lewis y Fowler encontraron equipos de alrededor de una docena de personas propietarios de un servicio y equipos de unas seis personas propietarios de seis servicios, y lamentaron que la palabra 'micro' centre la atención en el tamaño. Ford, Richards, Sadalage y Dehghani ofrecen una herramienta mejor en Software Architecture: The Hard Parts (2021): sopesar las fuerzas que empujan a dividir un servicio, que llaman desintegradores de granularidad, frente a las que empujan a mantenerlo unido, los integradores.

Fuerzas que actúan sobre la granularidad de los servicios

Seis desintegradores de granularidad empujan a dividir un servicio y cuatro integradores empujan a mantenerlo unidoGranularidad¿dónde trazar la línea?Desintegradores: dividirIntegradores: mantener juntosÁmbito y función del servicioVolatilidadEscalabilidad y rendimientoTolerancia a fallosSeguridadExtensibilidadTransacciones de BDFlujo y coreografíaCódigo comúnRelaciones de datosFuerzas de Ford, Richards, Sadalage y Dehghani, Software Architecture: The Hard Parts (2021)
Seis desintegradores abogan por servicios más pequeños; cuatro integradores, por servicios más grandes. La granularidad es un equilibrio que se decide caso por caso.

Desintegradores e integradores de granularidad, con ejemplos del reparto de comida

FuerzaDirecciónPreguntaEjemplo
Ámbito y función del servicioDividir¿El servicio hace una sola cosa cohesionada o varias cosas sin relación?Un servicio de Notificaciones que además calcula los puntos de fidelidad está haciendo dos trabajos.
VolatilidadDividir¿Hay una parte que cambia mucho más a menudo que el resto?Las reglas de Promociones cambian cada semana; el resto de Precios cambia cada trimestre.
Escalabilidad y rendimientoDividir¿Las partes necesitan capacidades muy diferentes?Las actualizaciones de ubicación de los repartidores llegan miles de veces por segundo; las altas de repartidores, unas pocas veces al día.
Tolerancia a fallosDividir¿Un fallo en una parte haría caer otra sin necesidad?Una caída del generador de recibos en PDF no debería impedir que se hagan pedidos.
SeguridadDividir¿Las partes necesitan controles de acceso o auditorías diferentes?Tokens de tarjeta almacenados frente a datos públicos de la carta.
ExtensibilidadDividir¿Se añadirán variantes nuevas con frecuencia?Nuevos métodos de pago cada pocos meses, cada uno como una unidad desplegable independiente.
Transacciones de BDMantener juntos¿Estos cambios deben tener éxito o fallar de forma atómica?Crear un pedido y reservar su franja de entrega.
Flujo y coreografíaMantener juntos¿Dividir crearía largas cadenas de llamadas para las solicitudes corrientes?El carrito, el proceso de pago y el estado del pedido se llaman entre sí en cada solicitud.
Código comúnMantener juntos¿Las partes comparten una lógica de negocio importante que cambia a la vez?Carta y Precios comparten reglas complejas sobre las opciones de los platos.
Relaciones de datosMantener juntos¿Los datos están estrechamente relacionados, con joins y claves foráneas?Los pedidos y sus líneas; separarlos no aporta nada.

Ejemplo práctico

Ejemplo práctico: ¿conviene dividir Precios?

La plataforma de reparto de comida tiene un servicio de Precios que calcula los totales del carrito: precios de los platos, recargos por opciones, tarifas de envío (que dependen de la distancia y de la demanda) y promociones (cupones, descuentos en el primer pedido, ofertas de restaurantes). El equipo de promociones lanza cambios varias veces por semana, y cada lanzamiento de Precios necesita una ejecución completa de regresión del cálculo de tarifas. Alguien propone dividir Precios en los servicios Tarifas y Promociones. El arquitecto sopesa las fuerzas.

Volatilidad del código (dividir)Fuerte: las promociones cambian cada semana; las reglas de tarifas, cada trimestre. Separarlas permitiría lanzar las promociones sin volver a probar las tarifas.
Escalabilidad (dividir)Débil: ambas se llaman una vez por cada visualización del carrito, al mismo ritmo.
Tolerancia a fallos (dividir)Moderada: una regla de promoción defectuosa ha hecho caer Precios dos veces. Si Promociones fuera independiente, un fallo podría degradarse a 'no se muestra el descuento' mientras las tarifas siguen funcionando.
Seguridad (dividir)Débil: la misma sensibilidad de los datos.
Transacciones de base de datos (mantener)Débil: ninguna escritura necesita abarcar ambas; un cupón se canjea cuando se hace el pedido, en Pedidos.
Flujo de trabajo (mantener)Moderada: cada total del carrito necesita ambas. Tras la división, Precios (o un BFF) debe llamar a Promociones de forma síncrona en cada visualización del carrito, lo que añade un salto y sus modos de fallo.
Código compartido (mantener)Moderada: ambas necesitan el modelo del carrito y las reglas de redondeo de divisas, que cambian rara vez.
Relaciones entre datos (mantener)Débil: las promociones se refieren a los restaurantes y los platos solo por su identificador.
DecisiónDividir, con cuidado: extraer Promociones; Precios lo llama con un timeout de 150 ms y, si falla, calcula el precio del carrito sin descuentos y lo marca para recalcularlo en el proceso de pago. Compartir solo una biblioteca pequeña y versionada del modelo del carrito.

La decisión se apoya en dos desintegradores fuertes (la volatilidad y el aislamiento de fallos) que pesan más que unos integradores moderados. Si las promociones hubieran tenido que actualizar las mismas filas que el cálculo de tarifas en una sola transacción, la respuesta probablemente habría sido otra.

Poner las fuerzas por escrito convierte una cuestión de gusto en un argumento que otros pueden comprobar, y ese registro corresponde a un registro de decisiones de arquitectura.

Antipatrones

La mayoría de los programas de microservicios que fracasan lo hacen de formas reconocibles. La más grave es el monolito distribuido: un sistema con todos los costos de la distribución y nada de la independencia, porque sus servicios comparten una base de datos, se llaman entre sí en largas cadenas síncronas o dependen de las mismas bibliotecas desplegables.

Antipatrones de los microservicios

AntipatrónSíntomaCausa y remedio
Monolito distribuidoLos servicios deben lanzarse juntos en un orden fijo; la caída de un servicio los detiene a todos.Base de datos compartida, cadenas síncronas y bibliotecas desplegables compartidas. Remedio: volver a trazar los límites en torno a contextos delimitados, dar a cada servicio sus datos, pasar las llamadas a eventos o volver a fusionarlos en un monolito modular.
Servicios de entidadServicios con nombres de sustantivos (Cliente, Pedido, Restaurante) con operaciones de creación, lectura, actualización y borrado; cada proceso de negocio llama a varios de ellos.Límites trazados en torno a los datos en lugar del comportamiento. Michael Nygard lo llama el antipatrón del servicio de entidad. Remedio: organizar en torno a las capacidades y los procesos de negocio.
Servicios conversadoresUna sola solicitud de un usuario provoca decenas de llamadas entre servicios; la latencia y las tasas de fallo aumentan con cada funcionalidad.Los límites atraviesan un flujo de trabajo cohesionado, o las interfaces son demasiado finas. Remedio: API más gruesas, copias locales de los datos de referencia, fusionar los servicios que siempre cambian juntos.
Bibliotecas compartidas que acoplan los desplieguesUn cambio en una biblioteca común obliga a todos los servicios a recompilarse y volver a desplegarse; las versiones se van separando.Lógica de negocio o modelos de dominio situados en código compartido. Remedio: compartir solo bibliotecas técnicas y estables; duplicar pequeñas cantidades de código de negocio; versionar todo lo que se comparta y permitir que haya varias versiones en uso.
Envidia de microserviciosUn equipo pequeño con un producto nuevo empieza con treinta servicios y dedica la mayor parte de su tiempo a la infraestructura.Elegir el estilo por moda o por su valor en el currículum en lugar de por los impulsores. Remedio: empezar con un monolito modular y extraer servicios cuando aparezca un impulsor.
NanoserviciosServicios tan pequeños que la mayor parte de su código es fontanería; una funcionalidad necesita cambios en cinco de ellos.Aplicar 'pequeño' en exceso. Remedio: usar los integradores de granularidad; dimensionar los servicios por su cohesión, no por las líneas de código.

Características de los microservicios

CaracterísticaValoraciónRazón
DesplegabilidadAltoCada servicio se lanza por sí solo, muchas veces al día, con un radio de impacto pequeño.
Escalabilidad y elasticidadAltoCada servicio escala de forma independiente; los servicios pequeños arrancan rápido y escalan en pasos finos.
Tolerancia a fallosAlto (si se diseña para ello)Los fallos pueden aislarse por servicio, pero solo con timeouts, bulkheads, alternativas de respaldo (fallbacks) y comunicación asíncrona; de lo contrario, los defectos se propagan en cascada.
Capacidad de evoluciónAltoLos servicios pequeños y bien delimitados pueden reescribirse o sustituirse uno a uno.
Capacidad de prueba de un servicioAltoCada servicio es pequeño; las pruebas de contrato comprueban sus interacciones.
Probar el conjuntoBajoEl comportamiento de extremo a extremo surge de muchos servicios y es difícil de reproducir en un entorno de pruebas.
RendimientoBaja a mediaLos saltos de red, la serialización y los controles de seguridad añaden latencia a cada interacción.
Consistencia de los datosBajoNo hay transacciones compartidas; las invariantes de negocio que abarcan varios servicios dependen de la consistencia eventual y de las sagas.
SimplicidadBajoMuchas piezas móviles, muchos modos de fallo, mucha infraestructura.
Costo globalBajo (costoso)Plataforma, herramientas, observabilidad y personas para operar decenas de servicios.

Cuándo encajan los microservicios y cuándo no

Los microservicios encajan en organizaciones con muchos equipos que trabajan en un mismo producto y necesitan lanzar de forma independiente, en sistemas cuyas partes tienen necesidades realmente distintas de escalabilidad, disponibilidad o seguridad, y en dominios que se entienden lo bastante bien como para trazar límites estables. Necesitan inversión en una plataforma y en habilidades operativas antes de separar el primer servicio.

No encajan en un equipo pequeño, en un producto nuevo cuyo dominio todavía se está descubriendo (los límites trazados demasiado pronto son costosos de mover a través de la red), en un sistema cuyos flujos de trabajo principales necesitan una consistencia transaccional fuerte en la mayor parte de sus datos, ni en una organización sin despliegue y monitorización automatizados. El consejo MonolithFirst de Fowler (Capítulo 5) y las marchas atrás que algunas empresas han documentado, como la consolidación que hizo Segment en 2018 de más de 140 servicios de destino de nuevo en uno solo, muestran que el estilo es una herramienta con un costo, no un destino.

Comprueba lo que has entendido

Dos servicios se despliegan en contenedores separados, pero siempre deben lanzarse juntos. ¿Son desplegables de forma independiente?

No. La desplegabilidad independiente consiste en poder cambiar y lanzar uno sin el otro; un contrato acoplado o una base de datos compartida los convierte en una sola unidad a efectos de lanzamiento.

¿Qué diferencia hay entre un API gateway y un backend for frontend?

Un gateway es un punto de entrada general que se encarga de inquietudes transversales como TLS, la autenticación, la limitación de tasa y el enrutamiento; un BFF es un backend específico de un cliente que da forma a los datos para un tipo de frontend y es propiedad del equipo de ese frontend.

¿Qué integrador de granularidad argumenta con más fuerza en contra de dividir dos partes que deben actualizar datos de forma atómica?

Las transacciones de base de datos: dividirlas sustituiría una transacción ACID por un flujo de trabajo distribuido, como una saga.

¿Por qué es una señal de alarma tener servicios llamados Cliente, Pedido y Restaurante con solo operaciones de creación, lectura, actualización y borrado?

Son servicios de entidad: límites en torno a los datos en lugar del comportamiento, así que cada proceso de negocio tiene que llamar a varios servicios, lo que crea interacciones conversadoras y fuertemente acopladas.

Siguiente · 6.4Dirigida por eventosEventos, comandos y mensajes; las topologías de intermediario (broker) y de mediador; los cuatro patrones de eventos de Fowler; cómo funcionan las particiones, los offsets y los grupos de consumidores de Kafka; las garantías de entrega, los consumidores idempotentes, los esquemas y las colas de mensajes fallidos (dead-letter queues).Continuar →

Fuentes y lecturas recomendadas

¿Tienes una pregunta sobre esta sección? ArchitectBot, el asistente de estudio con IA del curso, responde primero a partir del curso.

Pregunta: “Tenemos 25 microservicios y cada lanzamiento exige que se coordinen cuatro equipos. ¿Cómo sé si tenemos un monolito distribuido, y qué deberíamos corregir primero?”