Hola Habr!
La traducción de hoy toca no solo y no tanto microservicios, un tema que todos tienen en sus labios hoy, sino que también recuerda lo importante que es llamar a las cosas por su nombre. La transición a la arquitectura de microservicios a veces es necesaria, pero, como lo subraya una vez más el autor, requiere una cuidadosa consideración de las consecuencias. ¡Disfruta y una lectura fructífera!

De vez en cuando hago la misma pregunta.
¿Existe una verdad tan importante que solo unos pocos estén de acuerdo con usted? - Peter Thiel
Antes de sentarme para esta publicación, probé este tema durante mucho tiempo con un tema, que hoy está en una tendencia seria: se trata de microservicios. Creo que ahora tengo algo que contar; Algunos hallazgos se basan en la reflexión, otros en la experiencia práctica. Entonces te digo.
Comencemos con una verdad importante que nos servirá como punto de referencia en el camino como una estrella polar.
La mayoría de las implementaciones de microservicios no son más que monolitos distribuidos.
Era de los monolitos
Cualquier sistema comenzó como una aplicación monolítica. No entraré en detalles sobre este tema aquí, muchos ya han escrito sobre muchos. Sin embargo, la mayor parte de la información sobre los monolitos se dedica a cuestiones tales como la productividad y la escalabilidad del desarrollador, al tiempo que deja entre corchetes el activo más valioso de cualquier empresa de Internet: los datos.
Arquitectura de aplicación monolítica típicaSi los datos son tan importantes, ¿por qué se presta tanta atención a otros temas, pero no a ellos? La respuesta, en general, es simple: porque no son tan dolorosas como la pregunta de datos.
Quizás el monolito es la única etapa en el ciclo de vida del sistema donde usted:
- Comprenda completamente su modelo de datos;
- Puede cooperar con los datos (se supone que su base de datos está seleccionada correctamente para su aplicación).
En términos de datos, el monolito es ideal. Y dado que los datos son el activo más valioso de cualquier compañía, es mejor no romper el monolito, a menos que tenga una muy buena razón, o una combinación de tales razones. En la mayoría de los casos, la razón decisiva para esto es la necesidad de escalar (ya que vivimos en el mundo real con sus limitaciones físicas).
Cuando llega este momento, lo más probable es que su sistema entre en una nueva hipóstasis: se
convierte en un monolito distribuido .
La era de los monolitos distribuidos
Digamos que las cosas van bien en su empresa y la aplicación necesita crecer. Tiene cada vez más clientes importantes y sus requisitos de facturación e informes han cambiado tanto en términos de un conjunto de oportunidades como de su volumen.
Al abordar seriamente la demolición del monolito, en particular, intentará implementar dos pequeños servicios, uno de los cuales proporcionará informes y el segundo, la facturación. Lo más probable es que estos nuevos servicios proporcionen una API HTTP y tengan una base de datos dedicada para el almacenamiento de estado a largo plazo. Después de muchas confirmaciones, usted, como nosotros en
Unbabel , puede obtener algo similar a la siguiente ilustración.
Una vista generalizada de la arquitectura del sistema después de separar los servicios de facturación e informes de la aplicación monolítica principalTodo va según lo planeado.
- El equipo continúa dividiendo el monolito en sistemas más pequeños;
- Los transportadores de integración / entrega continua funcionan como un reloj;
- El clúster de Kubernetes es saludable, los ingenieros son productivos y felices con todo.
La vida es bella
Pero, ¿y si digo que en este momento las viles conspiraciones teje contra ti?
Ahora, mirando su sistema, encontrará que los datos se han distribuido en muchos sistemas diferentes. Comenzó con la etapa cuando tenía una base de datos única donde se almacenaban todos los objetos de datos, y ahora sus objetos de datos se han extendido a diferentes lugares. Quizás piense que no hay ningún problema, ya que se necesitan microservicios para crear abstracciones y sellar datos, ocultando la complejidad interna del sistema.
Tienes toda la razón. Pero con el aumento de la escala, surgen problemas más complejos: ahora, en cualquier momento, se ve obligado a cumplir con los requisitos comerciales (por ejemplo, para realizar un seguimiento de alguna métrica), lo que requiere el acceso a los datos ubicados en más de un sistema.
Que hacer De hecho, hay muchas opciones. Pero a toda prisa, también debe atender a una gran fraternidad de clientes que se han registrado recientemente con usted, por lo que debe encontrar un equilibrio entre "rápido" y "bueno". Habiendo discutido los detalles, usted decide construir un sistema adicional que realice un cierto trabajo ETL, contribuyendo a la solución de las tareas finales. Este sistema tendrá que tener acceso a todas las réplicas de lectura que contienen la información que necesita. La siguiente figura muestra cómo podría funcionar un sistema de este tipo.
Un ejemplo generalizado de un sistema analítico ETL (en Unbabel lo llamamos análisis de traducción automática)En Unbabel, utilizamos este enfoque, ya que:
- No afecta demasiado el rendimiento de cada microservicio;
- No requiere cambios importantes en la infraestructura (solo agregue un nuevo microservicio);
- Pudimos satisfacer lo suficientemente rápido nuestros requisitos comerciales.
La experiencia sugiere que durante algún tiempo este enfoque funcionará, hasta alcanzar una cierta escala. En Unbabel, nos sirvió muy bien hasta hace muy poco, cuando comenzamos a enfrentar desafíos cada vez más serios. Aquí hay algunas cosas que se convirtieron en un dolor de cabeza para nosotros:
1. Cambios de datosUna de las principales ventajas de los microservicios es la encapsulación. La representación interna de los datos puede cambiar, pero esto no afecta a los clientes del sistema, ya que se comunican a través de una API externa. Sin embargo, nuestra estrategia requería acceso directo a la representación interna de los datos y, por lo tanto, tan pronto como el equipo solo realizó algunos cambios en la presentación de los datos (por ejemplo, cambiar el nombre de un campo o cambiar el tipo de
text
a
uuid
), también tuvimos que cambiar y volver a implementar nuestro ETL- servicio
2. La necesidad de procesar muchos esquemas de datos diferentesA medida que aumentaba la cantidad de sistemas a los que necesitábamos conectarnos, tuvimos que lidiar con formas cada vez más heterogéneas de presentar datos. Era obvio que no podíamos escalar todos estos esquemas, las relaciones entre ellos y sus representaciones.
La raíz de todo malPara obtener una imagen completa de lo que está sucediendo en el sistema, tuvimos que detenernos en un enfoque parecido a un monolito. La diferencia era que no teníamos un sistema y una base de datos, sino docenas de esos pares, cada uno con su propia representación de datos; Además, en algunos casos, los mismos datos se replicaron en varios sistemas.
Prefiero llamar a este sistema un monolito distribuido. Por qué Dado que es completamente inadecuado para rastrear cambios en el sistema, y la única forma de mostrar el estado del sistema es recopilar un servicio que se conecte directamente a los almacenes de datos de todos los microservicios. Es interesante ver cuántos colosos de Internet también enfrentaron desafíos similares en algún momento de su desarrollo. Un buen ejemplo en este caso que siempre me gusta dar es la red de LinkedIn.
Este es el tipo de error de datos que los flujos de información de Linkedin representaron alrededor de 2011 - fuenteEn este momento, se preguntarán: "¿qué van a hacer con todo esto?" La respuesta es simple: debe comenzar a rastrear los cambios y realizar un seguimiento de las acciones importantes a medida que ocurren.
Romper un monolito distribuido utilizando Event SourcingComo prácticamente el resto del mundo, los sistemas en Internet son receptivos. Por lo tanto, una solicitud a la API puede conducir a la inserción de un nuevo registro en la base de datos. Actualmente, en la mayoría de los casos, estos detalles no nos molestan, ya que estamos interesados principalmente en actualizar el estado de la base de datos. La actualización del estado de una base de datos es una consecuencia condicional de algún evento (en este caso, una solicitud de API). El fenómeno del evento es simple y, sin embargo, el potencial de los eventos es muy grande: incluso se pueden usar para destruir un monolito distribuido.
Un evento no es más que un hecho inmutable de alguna modificación que ocurrió en su sistema . En la arquitectura de microservicios, los eventos se vuelven críticos y ayudan a comprender los flujos de datos, y sobre la base de deducir el estado agregado de varios sistemas. Cada microservicio que realiza una acción que es interesante desde el punto de vista de todo el sistema debe generar un evento junto con toda la información esencial relacionada con el hecho de que este evento representa.
Quizás tengas una pregunta:
"¿Cómo pueden los microservicios que generan eventos ayudarme a resolver el problema del monolito distribuido?"
Si tiene sistemas que generan eventos, puede haber un registro de hechos con las siguientes propiedades:
- Falta de enlace a cualquier almacén de datos: los eventos generalmente se serializan utilizando formatos binarios como JSON, Avro o Protobufs;
- Inmutabilidad: tan pronto como se genera un evento, es imposible cambiarlo;
- Reproducibilidad: se puede restaurar el estado del sistema en cualquier momento dado; Para hacer esto, simplemente "reproduzca" el registro de eventos.
Con este registro, puede mostrar el estado utilizando cualquier tipo de lógica a nivel de aplicación. Ya no está asociado con ningún conjunto de microservicios y
N formas en que se presentan los datos. La única fuente de verdad y su único almacén de datos es ahora el repositorio donde se almacenan sus eventos.
Aquí hay algunas razones por las cuales el registro de eventos me parece la forma de ayudar a romper el Monolito Distribuido:
1. La única fuente de verdadEn lugar de mantener N fuentes de datos que pueden ser necesarias para conectarse a (múltiples) bases de datos heterogéneas, en este nuevo escenario, la verdad última se almacena exactamente en un repositorio: el registro de eventos.
2. Formato de datos universalEn la versión anterior del sistema, teníamos que lidiar con muchos formatos de datos, ya que estábamos directamente conectados a la base de datos. En el nuevo diseño, podemos actuar de manera mucho más flexible.
Digamos que te gustó una foto de Instagram publicada por uno de tus amigos. Tal acción se puede describir: "Al
usuario X le gustó la imagen P ". Y aquí hay un evento que representa este hecho:
Un evento correspondiente al enfoque AVO (Actor, Verbo, Objeto), simulando el hecho de que el usuario selecciona la imagen que le gusta.3. Debilitar la comunicación entre productores y consumidores.Por último, pero no menos importante, una de las mayores ventajas de las operaciones de eventos es el debilitamiento efectivo de la comunicación entre los productores de datos y los consumidores. Esta situación no solo simplifica el escalado, sino que también reduce el número de dependencias entre ellos. El único contrato que queda entre los sistemas en este caso es el diagrama de eventos.
Al comienzo de este artículo se planteó la pregunta: ¿Existe una verdad tan importante en la que solo unos pocos estén de acuerdo con usted?
Permítanme volver al final de esta excursión. Creo que la mayoría de las empresas no consideran los datos como "entidades de primera clase" cuando comienzan la migración a la arquitectura de microservicios. Se argumenta que todos los cambios de datos aún se pueden realizar a través de la API, pero este enfoque en última instancia conduce a una complicación constante del servicio en sí.
Creo que el único enfoque verdadero para capturar los cambios de datos en una arquitectura de microservicio es hacer que los sistemas emitan eventos de acuerdo con un contrato estrictamente definido. Tener un registro de eventos correctamente compilado le permite mostrar una gran cantidad de datos en función de cualquier conjunto de requisitos empresariales. En este caso, solo tiene que aplicar diferentes reglas a los mismos hechos. En algunos casos, dicha fragmentación de datos puede evitarse si su empresa (especialmente sus gerentes de producto) trata los datos como un producto. Sin embargo, este es un tema para otro artículo.