Dicotomía de datos: repensar la relación con datos y servicios.

¡Hola a todos! Tenemos buenas noticias, en junio OTUS lanzará nuevamente el curso "Arquitecto de software" , en relación con el cual tradicionalmente compartimos material útil con usted.




Si encuentras toda esta historia con microservicios sin ningún contexto, entonces eres excusable para considerarla un poco extraña. Particionar la aplicación en fragmentos conectados por una red, por supuesto, significa agregar modos complejos de tolerancia a fallas al sistema distribuido resultante.

A pesar de que este enfoque incluye la división en muchos servicios independientes, el objetivo final es mucho más que la operación de estos servicios en diferentes máquinas. Estamos hablando de la interacción con el mundo exterior, que en su esencia también se distribuye. No en el sentido técnico, sino en el sentido de un ecosistema que consta de muchas personas, equipos, programas, y cada una de estas partes debe de alguna manera hacer su trabajo.

Las empresas, por ejemplo, son un conjunto de sistemas distribuidos que en conjunto contribuyen al logro de un determinado objetivo. Hemos ignorado este hecho durante décadas, tratando de lograr la unificación, transfiriendo archivos a través de FTP o utilizando herramientas de integración corporativa, mientras nos centramos en nuestros objetivos personales aislados. Pero con la llegada de los servicios, todo ha cambiado. Los servicios nos han ayudado a mirar más allá del horizonte y a ver el mundo de los programas interdependientes que trabajan juntos. Sin embargo, para trabajar con éxito, es necesario realizar y diseñar dos mundos fundamentalmente diferentes: el mundo exterior, donde vivimos en un ecosistema de muchos otros servicios, y nuestro mundo interno personal, donde gobernamos solos.



Tal mundo distribuido es diferente del que crecimos y al que estamos acostumbrados. Los principios de la construcción de la arquitectura monolítica tradicional no resisten las críticas. Por lo tanto, una comprensión correcta de tales sistemas es más que crear un diagrama de clase en una pizarra blanca o una buena prueba de concepto. Se trata de un sistema de este tipo que funciona con éxito durante mucho tiempo. Afortunadamente, los servicios han existido durante bastante tiempo, aunque se ven diferentes. Las lecciones de SOA siguen siendo relevantes, incluso con sabor a Docker, Kubernetes y barbas hipster ligeramente maltratadas.

Entonces, hoy observamos cómo han cambiado las reglas, por qué necesitamos repensar nuestro enfoque de los servicios y los datos que se transmiten entre sí, y por qué necesitamos herramientas completamente diferentes para esto.

La encapsulación no siempre será tu amiga


Los microservicios pueden funcionar independientemente uno del otro. Es esta propiedad la que les da el mayor valor. La misma propiedad permite que los servicios escalen y crezcan. No tanto en términos de escalar a miles de millones de usuarios o petabytes de datos (aunque aquí pueden ayudar), sino en términos de escalar desde el punto de vista de las personas, porque los equipos y las organizaciones están creciendo continuamente.



Sin embargo, la independencia es una espada de doble filo. Es decir, el servicio en sí puede girar de forma fácil y natural. Pero si una función se implementa dentro del servicio que requiere el uso de otro servicio, al final tenemos que hacer cambios en ambos servicios casi simultáneamente. En el monolito, esto es fácil de hacer, solo hace un cambio y lo envía a la versión, pero si sincroniza servicios independientes, habrá más problemas. La coordinación entre equipos y ciclos de lanzamiento destruye la flexibilidad.



Como parte del enfoque estándar, simplemente se evitan los molestos cambios de extremo a extremo, dividiendo claramente la funcionalidad entre los servicios. El servicio de inicio de sesión único aquí puede ser un buen ejemplo. Tiene un papel claramente definido que lo distingue de otros servicios. Una separación tan clara significa que en un mundo de requisitos rápidamente cambiantes para los servicios que lo rodean, es poco probable que cambie el servicio de inicio de sesión único. Existe dentro de un contexto estrictamente limitado.



El problema es que en el mundo real, los servicios empresariales no pueden mantener constantemente una separación igualmente limpia de roles. Por ejemplo, los mismos servicios empresariales funcionan más con datos provenientes de otros servicios similares. Si se dedica a la venta minorista en línea, el procesamiento del flujo de pedidos, el catálogo de productos o la información del usuario será un requisito para muchos de sus servicios. Cada uno de los servicios necesitará acceso a estos datos para funcionar.


La mayoría de los servicios empresariales utilizan el mismo flujo de datos, por lo que su trabajo siempre está entrelazado.

Entonces llegamos a un punto importante del que vale la pena hablar. Si bien los servicios funcionan bien para los componentes de infraestructura que funcionan en gran medida separados, la mayoría de los servicios empresariales están más entrelazados.

Dicotomía de datos


Es posible que ya existan enfoques orientados a los servicios, pero todavía tienen poca información sobre cómo intercambiar grandes cantidades de datos entre los servicios.

El principal problema es que los datos y los servicios son inseparables. Por un lado, la encapsulación nos anima a ocultar datos para que los servicios puedan separarse unos de otros y facilitar su crecimiento y otros cambios. Por otro lado, necesitamos poder compartir libremente y gobernar sobre datos generales, así como sobre cualquier otro. Se trata de poder comenzar a trabajar inmediatamente, tan libremente como en cualquier otro sistema de información.

Sin embargo, los sistemas de información tienen poco que ver con la encapsulación. De hecho, incluso lo contrario. Las bases de datos hacen todo lo posible para dar acceso a los datos almacenados en ellas. Vienen con una potente interfaz declarativa que le permite modificar los datos según lo necesite. Dicha funcionalidad es importante en la etapa de investigación preliminar, pero no para gestionar la creciente complejidad de un servicio en constante evolución.



Y aquí surge un dilema. Contradicción. Dicotomía. Después de todo, los sistemas de información se tratan de proporcionar datos, y los servicios se tratan de ocultar.

Estas dos fuerzas son fundamentales. Forman la base de la mayor parte de nuestro trabajo, luchando constantemente por la excelencia en los sistemas que creamos.

A medida que los sistemas de servicios crecen y evolucionan, vemos diferentes manifestaciones de los efectos de la dicotomía de datos. O bien, la interfaz de servicio crecerá, proporcionando una gama cada vez más amplia de funciones y comenzará a parecerse a una base de datos local muy maravillosa, o nos sentiremos decepcionados e implementaremos alguna forma de extraer o mover conjuntos de datos completos de un servicio a otro.



A su vez, crear algo que se parezca a una maravillosa base de datos local producirá una serie de problemas. No entraremos en detalles sobre qué es peligrosa la base de datos compartida , solo digamos que representa dificultades de ingeniería y operativas costosas para la compañía que está tratando de usarla.

Peor aún, los volúmenes de datos multiplican los problemas con los límites del servicio. Mientras más datos comunes estén dentro del servicio, más complicada será la interfaz y más difícil será combinar conjuntos de datos provenientes de diferentes servicios.

Un enfoque alternativo para extraer y mover conjuntos de datos completos también tiene sus problemas. Un enfoque común para este problema parece una simple extracción y almacenamiento de todo el conjunto de datos, y luego almacenarlo localmente en cada servicio al consumidor.



El problema es que diferentes servicios interpretan los datos que consumen de manera diferente. Estos datos están siempre a mano. Se modifican y procesan localmente. Muy rápidamente dejan de tener algo en común con los datos de la fuente.


Cuanto más mutables sean las copias, más variarán los datos con el tiempo.

Peor aún, tales datos son difíciles de corregir en retrospectiva ( MDM realmente puede venir al rescate aquí). De hecho, algunos de los problemas tecnológicos insolubles que enfrenta una empresa se deben a la multiplicación heterogénea de datos de una aplicación a otra.

Para encontrar una solución a este problema sobre los datos compartidos, debe pensar de manera diferente. Deben convertirse en objetos de primera clase en las arquitecturas que construimos. Pat hellandllama a tales datos "externos", y esta es una característica muy importante. Necesitamos encapsulación para no exponer la estructura interna del servicio, pero debemos facilitar el acceso de los servicios a los datos compartidos para que puedan realizar su trabajo correctamente.



El problema es que ninguno de los enfoques es relevante hoy en día, porque ni las interfaces de servicio, ni la mensajería, ni la Base de datos compartida ofrecen una buena solución para trabajar con datos externos. Las interfaces de servicio son poco adecuadas para intercambiar datos a cualquier escala. La mensajería mueve datos, pero no almacena su historial, por lo que los datos se corrompen con el tiempo. Las bases de datos compartidas se centran demasiado en un punto, lo que frena el progreso. Estamos inevitablemente atrapados en un ciclo de falla de datos:


Ciclo de insolvencia de datos

Streams: un enfoque descentralizado de datos y servicios


Idealmente, debemos cambiar el enfoque de cómo funcionan los servicios con datos compartidos. Por el momento, cualquier enfoque se enfrenta a la dicotomía antes mencionada, ya que no hay polen mágico que pueda ser generosamente rociado con él y hecho para que desaparezca. Sin embargo, podemos repensar el problema y llegar a un compromiso.

Este compromiso implica un cierto grado de centralización. Podemos usar el mecanismo de registro distribuido porque proporciona flujos escalables confiables. Ahora necesitamos servicios para poder unirnos y trabajar con estos hilos comunes, sin embargo, queremos evitar los complejos Servicios Dios centralizados que realizan este procesamiento. Por lo tanto, la mejor opción es incorporar el procesamiento de transmisión en cada servicio al consumidor. Por lo tanto, los servicios podrán combinar conjuntos de datos de diferentes fuentes y trabajar con ellos según lo necesiten.

Una forma de lograr este enfoque es utilizar una plataforma de transmisión. Hay muchas opciones, pero hoy consideraremos Kafka, ya que el uso de su procesamiento de flujo con estado nos permite resolver de manera efectiva el problema presentado.



El uso del mecanismo de registro distribuido nos permite seguir una ruta bien transitada y usar la mensajería para trabajar con arquitectura orientada a eventos . Se cree que este enfoque proporciona una mejor escala y separación que el mecanismo de solicitud-respuesta, porque le da el control del flujo al receptor, no al emisor. Sin embargo, tiene que pagar por todo en esta vida, y aquí necesita un corredor. Pero para sistemas grandes, esta compensación vale la pena (lo que no se puede decir sobre sus aplicaciones web promedio).

Si un corredor es responsable del registro distribuido, y no de un sistema de mensajería tradicional, puede aprovechar las características adicionales. El transporte se puede escalar linealmente casi tan bien como un sistema de archivos distribuido. Los datos se pueden almacenar en los registros durante mucho tiempo, por lo que no solo recibimos mensajes, sino también almacenamiento de información. Almacenamiento escalable sin temor a un estado general mutable.

Luego puede utilizar el mecanismo de procesamiento de flujo con estado para agregar herramientas de base de datos declarativas a los servicios al consumidor. Este es un punto muy importante. Si bien los datos se almacenan en secuencias compartidas a las que pueden acceder todos los servicios, la agrupación y el procesamiento que realiza el servicio son privados. Se encuentran aislados dentro de un contexto estrictamente limitado.


Deshágase de la dicotomía de datos dividiendo el flujo inmune de los estados. A continuación, agregue esta función a cada servicio mediante el procesamiento de flujo con estado.

Por lo tanto, si su servicio debe funcionar con pedidos, un catálogo de productos, un almacén, tendrá acceso total: solo usted decidirá qué datos combinar, dónde procesarlos y cómo deberían cambiar con el tiempo. A pesar de que los datos son generales, el trabajo con ellos está completamente descentralizado. Se realiza dentro de cada servicio, en un mundo donde todo va de acuerdo con sus reglas.


Comparta datos para que no se viole su integridad. Encapsula una función, no una fuente, en cada servicio que la necesite.

Sucede que los datos deben ser movidos masivamente. A veces, un servicio requiere un conjunto de datos históricos locales en un motor de base de datos seleccionado. El truco es que puede garantizar que, si es necesario, se puede restaurar una copia desde la fuente accediendo al mecanismo de registro distribuido. Los conectores en Kafka hacen un gran trabajo al respecto.

Entonces, el enfoque considerado hoy tiene varias ventajas:

  • Los datos se utilizan en forma de flujos compartidos que pueden almacenarse durante mucho tiempo en los registros, y el mecanismo para trabajar con datos compartidos está conectado en cada contexto individual, lo que permite que los servicios funcionen de manera rápida y fácil. De esta manera, puede equilibrar la dicotomía de los datos.
  • , , . .
  • Stateful Stream Processing , , .
  • , , , -.
  • , . , .
  • , .

Como puede ver, esto es más que solo REST. Tenemos un conjunto de herramientas que le permite trabajar con datos compartidos de manera descentralizada.

En el artículo de hoy, no todos los aspectos fueron revelados. Todavía tenemos que decidir cómo equilibrar entre el paradigma de solicitud-respuesta y el paradigma orientado a eventos. Pero nos ocuparemos de esto la próxima vez. Hay temas que necesita conocer mejor, por ejemplo, por qué Stateful Stream Processing es tan bueno. Hablaremos de esto en el tercer artículo. Y hay otros diseños poderosos que podemos usar si recurrimos a ellos, por ejemplo, Exactly Once Processing . Con su ayuda, se cambian las reglas del juego para los sistemas comerciales distribuidos, ya que este diseño proporciona garantías transaccionales para XAen forma escalable Esto se discutirá en el cuarto artículo. Finalmente, necesitaremos repasar los detalles de la implementación de estos principios.



Pero por ahora, solo recuerde lo siguiente: una dicotomía de datos es la fuerza que enfrentamos al crear servicios comerciales. Y debemos recordar esto. El truco consiste en poner todo al revés y comenzar a considerar los datos generales como objetos de primera clase. Stateful Stream Processing ofrece un compromiso único para esto. Evita que los "Componentes de Dios" centralizados frenen el progreso. Además, proporciona la velocidad, la escalabilidad y la tolerancia a fallas de los canales de transmisión de datos y los agrega a cada servicio. Por lo tanto, podemos centrarnos en la corriente general de conciencia, a la que cualquier servicio puede conectarse y trabajar con sus datos. Por lo tanto, los servicios son más escalables, intercambiables y autónomos. Por lo tanto, no solo se verán bien en las pizarras blancas y al probar hipótesis,pero también trabajar y desarrollarse durante décadas.



.



All Articles