Comparamos las caracter铆sticas del microservicio y la arquitectura monol铆tica, sus ventajas y desventajas. El art铆culo fue preparado para Habr basado en los materiales de nuestro meta
Hot Backend , que se celebr贸 en Samara el 9 de febrero de 2019. Consideramos los factores de la elecci贸n de la arquitectura en funci贸n de la tarea espec铆fica.
Incluso hace 5 a帽os, nadie hab铆a o铆do hablar de microservicios. Sin embargo, su popularidad aumenta de a帽o en a帽o, seg煤n las
estad铆sticas de Google Trends.

Monolito y microservicios: ejemplos
Si el proyecto usa una arquitectura monol铆tica, entonces el desarrollador solo tiene una aplicaci贸n, cuyos componentes y m贸dulos funcionan con una sola base.

La arquitectura de microservicios implica la descomposici贸n en m贸dulos que se ejecutan como procesos separados y pueden tener servidores separados. Cada microservicio funciona con su propia base de datos y todos estos servicios pueden comunicarse entre s铆 de forma s铆ncrona (http) y as铆ncrona. Adem谩s, para optimizar la arquitectura, es deseable minimizar la relaci贸n entre los servicios.
El siguiente diagrama est谩 simplificado, refleja, en primer lugar, los componentes del negocio.

Microservicios: beneficios
Existen al menos cuatro ventajas de la arquitectura de microservicios:
Escalado e implementaci贸n independientesSe proporciona una implementaci贸n independiente para cada microservicio, y esto es conveniente al actualizar m贸dulos individuales. Si la carga en el m贸dulo aumenta, el microservicio correspondiente se puede escalar sin afectar a los dem谩s. Esto le permite distribuir de manera flexible la carga y ahorrar recursos.
Desarrollo independienteCada microservicio (por ejemplo, un m贸dulo de memoria) puede ser desarrollado por un equipo para aumentar la velocidad de creaci贸n de un producto de software.
SostenibilidadLa falla de un microservicio no afecta el desempe帽o de otros m贸dulos.
HeterogeneidadCada equipo es libre de elegir su propio idioma y tecnolog铆a para implementar microservicios, sin embargo, es deseable que tengan interfaces compatibles.
Entre los desarrolladores, puede escuchar la opini贸n de que la arquitectura monol铆tica est谩 desactualizada, es dif铆cil de mantener y escalar, crece r谩pidamente en un "gran trozo de tierra" y es pr谩cticamente antipatr贸n, es decir, su presencia en el c贸digo es indeseable. Las grandes empresas, como Netflix, que cambiaron a la arquitectura de microservicios en sus proyectos, a menudo se citan como evidencia de esta opini贸n.
驴Veamos si todos realmente deber铆an cambiar de un monolito a microservicios siguiendo el ejemplo de las marcas m谩s grandes?
Cambiar a microservicios: posibles dificultades
Problema uno: descomposici贸nIdealmente, la aplicaci贸n debe dividirse en microservicios para que interact煤en entre s铆 lo menos posible, de lo contrario, la aplicaci贸n ser谩 dif铆cil de mantener. Al mismo tiempo, la descomposici贸n es dif铆cil de implementar al comienzo del desarrollo, cuando los problemas comerciales y el 谩rea tem谩tica a煤n pueden cambiar con la llegada de nuevos requisitos. Refactorizar es costoso.
Si se hace necesario transferir parte de las funciones del servicio A al servicio B, puede haber dificultades: por ejemplo, los servicios se ejecutan en diferentes idiomas, las llamadas internas a los servicios se convierten en red, necesita conectar otras bibliotecas. Podemos verificar la correcci贸n de la refactorizaci贸n solo con la ayuda de las pruebas.
Problema dos: transaccionesOtro problema es que los microservicios no tienen el concepto de transacciones distribuidas. Podemos garantizar la integridad arquitect贸nica de una operaci贸n comercial solo dentro de un microservicio. Si la operaci贸n involucra varios microservicios, se pueden usar diferentes bases de datos all铆, y dicha transacci贸n tendr谩 que ser abandonada. Para resolver este problema, existen varios m茅todos utilizados en los negocios cuando la accesibilidad es m谩s importante que la integridad. Al mismo tiempo, se proporcionan mecanismos de compensaci贸n en caso de que algo salga mal. Por ejemplo, si los productos no est谩n en stock, debe realizar un reembolso en la cuenta del comprador.
Si un monolito nos da integridad arquitect贸nica autom谩ticamente, entonces con microservicios debe crear su propio mecanismo y usar bibliotecas con soluciones listas para usar. Al distribuir una operaci贸n entre servicios, es mejor solicitar datos sincr贸nicamente y realizar acciones posteriores de forma asincr贸nica. Si es imposible acceder a uno de los servicios, el equipo se pondr谩 en cola tan pronto como est茅 disponible nuevamente.
En este sentido, es necesario revisar el enfoque de la interfaz de usuario. Se debe notificar al usuario que algunas acciones no se realizan de inmediato, sino dentro de un tiempo determinado. Cuando se procesa la solicitud, recibe una invitaci贸n para ver los resultados.
Problema tres: informesSi utilizamos una arquitectura monol铆tica con una sola base de datos, para crear un informe complejo puede escribir seleccionar y extraer varias etiquetas de datos: tarde o temprano se mostrar谩n. Sin embargo, en microservicios, estos datos se pueden dispersar en diferentes bases.
Por ejemplo, necesitamos enumerar compa帽铆as con m茅tricas espec铆ficas. Con una simple lista de empresas, todo funciona. 驴Y si necesita agregar m茅tricas que se encuentran en otra base de datos? S铆, podemos hacer una solicitud adicional y solicitar m茅tricas por TIN. 驴Y si esta lista necesita ser filtrada y ordenada? La lista de empresas puede ser muy grande, y luego tenemos que introducir un servicio adicional con su propia base de datos: informes.
Problema cuatro: alta complejidad de desarrolloEl trabajo en servicios distribuidos es m谩s complicado: todas las solicitudes se realizan a trav茅s de la red y se pueden desactivar, debe proporcionar un mecanismo de devoluci贸n de llamada (驴volver谩 a hacer la llamada? 驴Cu谩ntas veces?). Estos son los "ladrillos" que se acumulan gradualmente y contribuyen a aumentar la complejidad del proyecto.
Los servicios pueden ser desarrollados por varios equipos diferentes, y debe documentarlos, mantener la documentaci贸n actualizada y advertir a otros equipos cuando cambie la versi贸n. Estos son costos laborales adicionales.
Si cada equipo tiene una implementaci贸n independiente, debe mantener al menos la versi贸n anterior y deshabilitarla solo despu茅s de que todos los consumidores del servicio hayan cambiado a la nueva API.
Por supuesto, podemos llevar todas las API a alg煤n tipo de artefacto que estar谩 disponible p煤blicamente. Pero, en primer lugar, los servicios se pueden escribir en diferentes idiomas y, en segundo lugar, esto no se recomienda. Por ejemplo, en uno de nuestros proyectos, rechazamos esto a pedido del cliente, relacionado con consideraciones de seguridad. Cada microservicio tiene un repositorio separado y el cliente no les da acceso.
En el proceso de desarrollo, todo puede funcionar correctamente, y luego, no. Sucede que, en caso de excepciones, la aplicaci贸n intenta procesarlos infinitamente, y esto genera una gran carga: todo el sistema "se despliega". Para evitar tales situaciones, debe configurar todo, por ejemplo, para limitar el n煤mero de intentos, no devolver esta llamada a la cola en el mismo segundo, etc.

El quinto problema: la complejidad de las pruebas, el rastreo y la depuraci贸nPara probar un problema, debe descargar todos los microservicios involucrados. La depuraci贸n se convierte en una tarea no trivial, y todos los registros deben recopilarse en alg煤n lugar en un solo lugar. En este caso, necesita tantos registros como sea posible para descubrir qu茅 sucedi贸. Para rastrear el problema, debe comprender todo el camino que ha recorrido el mensaje. Las pruebas unitarias no son suficientes aqu铆, ya que es probable que haya errores en la uni贸n de los servicios. Al realizar cambios, es posible verificar la operatividad solo despu茅s de ejecutar en el soporte. Podemos limitar cada microservicio a una cierta cantidad de memoria (por ejemplo, 500 megabytes), pero hay momentos de carga m谩xima cuando se necesitan hasta dos gigabytes. Hay momentos en que el sistema comienza a ralentizarse. Como resultado, los recursos se pueden gastar en algo que no pertenece a las tareas inmediatas del cliente: por ejemplo, solo hay dos microservicios comerciales, y la mitad de los recursos se gastan en tres microservicios adicionales que respaldan el trabajo de los dem谩s.

Microservicio o monolito: criterios de selecci贸n
Al elegir entre arquitectura monol铆tica y microservicio, en primer lugar, debe proceder de la complejidad del 谩rea tem谩tica y la necesidad de escalar.
Si el 谩rea tem谩tica es simple y no se espera un aumento global en el n煤mero de usuarios, entonces los microservicios se pueden usar sin ninguna duda. En otros casos, es mejor comenzar el desarrollo en un monolito y ahorrar recursos si no se requiere escalar. Si el 谩rea tem谩tica es compleja, y en la etapa inicial no se definen los requisitos finales, tambi茅n es mejor comenzar con un monolito, para no volver a hacer los microservicios varias veces. Con el desarrollo posterior del proyecto, es posible distinguir sus partes individuales en microservicios.

Una ventaja es la presencia de l铆mites al comienzo del proyecto, ya que esto ayudar谩 a no romperlos durante el proceso de desarrollo. Tambi茅n tiene sentido comenzar con una base de datos, pero definir un esquema para cada m贸dulo (por ejemplo, un esquema de pago). Posteriormente, esto ayudar谩 a simplificar la divisi贸n de m贸dulos en microservicios. En este caso, observamos los l铆mites de los m贸dulos y podemos usar microservicios.
Cada m贸dulo debe tener su propia API, para que luego se pueda asignar y convertir el m贸dulo en un microservicio.

Una vez determinados los l铆mites de los m贸dulos, puede proceder a la descomposici贸n en microservicios, si es necesario. En aproximadamente el 90% de los casos ser谩 posible permanecer en el monolito, pero si es necesario, ser谩 m谩s f谩cil y econ贸mico cambiar la arquitectura.
En nuestra pr谩ctica de trabajar con monolitos y microservicios, llegamos a las siguientes conclusiones:
- No cambie a microservicios solo porque los usa Netflix, Twitter, Facebook
- Comience con dos o tres microservicios que interact煤en entre s铆, resuelva en detalle todos los requisitos no funcionales (seguridad, tolerancia a fallas, escalabilidad, etc.) y solo luego pase a otros servicios
- Automatiza todo lo posible
- Configurar monitoreo
- Escribir autotests
- No utilice transacciones distribuidas (pero esta no es una raz贸n para rechazar la garant铆a de integridad de los datos).
- Si desea utilizar la arquitectura de microservicios, prep谩rese para el hecho de que el desarrollo puede costarle aproximadamente 3 veces m谩s que en un monolito. Sin embargo, ambas tecnolog铆as tienen sus propias desventajas y ventajas; cada una de ellas tiene su propio nicho.