¿Formas de compartir DTO a través de microservicios?

33

Mi escenario es el siguiente.

Estoy diseñando un sistema diseñado para recibir datos de varios tipos de sensores, y convertirlos y luego persistir para que sean utilizados por varios servicios de front-end y análisis más adelante.

Estoy tratando de diseñar cada servicio para que sea lo más independiente posible, pero tengo algunos problemas. El equipo ha decidido un DTO que nos gustaría usar. Los servicios externos (destinatarios de datos del sensor) recibirán los datos de su propia manera única, luego los convertirán en un objeto JSON (el DTO) y los enviarán a Message Broker. Los consumidores de los mensajes sabrán exactamente cómo leer los mensajes de datos del sensor.

El problema es que estoy usando el mismo DTO en algunos servicios diferentes. Se debe implementar una actualización en varias ubicaciones. Obviamente, lo hemos diseñado de tal manera que algunos campos adicionales o faltantes en el DTO aquí y allí no sean un gran problema hasta que los servicios se hayan actualizado, pero todavía me molesta y me hace sentir que estoy cometiendo un error. Fácilmente podría convertirse en un dolor de cabeza.

¿Me estoy equivocando al diseñar el sistema? Si no, ¿cuáles son algunas formas de evitar esto, o al menos para aliviar mis preocupaciones?

nbaughman
fuente
¿Qué tipo de DTO está compartiendo y qué protocolo está utilizando entre servicios? Está bien compartir, por ejemplo, el protoarchivo para gRPC o el avroesquema para Kafka y generar los DTO en ambos servicios, pero no compartiría una biblioteca compartida entre dos proyectos.
Vincent Savard
Cadenas JSON codificadas y AMQP. Preferiría no usar nada específico del idioma.
nbaughman

Respuestas:

38

¿Mi consejo? No comparta estos DTO entre las aplicaciones en ningún tipo de biblioteca. O al menos no hagas esto ahora.

Lo sé, parece muy contrario a la intuición. Estás duplicando el código, ¿verdad? Pero esta no es una regla comercial, por lo que puede ser más flexible.

El servicio que envía el DTO debe ser rígido en su contrato de mensaje, como una API Rest. El servicio no puede cambiar el DTO de una manera que pueda romper los otros servicios que ya están consumiendo la información del DTO.

Cuando se agrega un nuevo campo a DTO, solo actualiza los otros servicios que consumen este DTO si necesitan el nuevo campo. De lo contrario, olvídalo. Al usar JSON como tipo de contenido, tiene la flexibilidad de crear y enviar nuevos atributos sin romper el código de los servicios que no asignan estos nuevos campos en sus versiones reales de DTO.

Pero si esta situación realmente te molesta, puedes seguir la regla de los tres :

Hay dos "Reglas de tres" en la reutilización: (a) Es tres veces más difícil construir componentes reutilizables que los componentes de un solo uso, y (b) un componente reutilizable debe probarse en tres aplicaciones diferentes antes de que sea lo suficientemente general aceptar en una biblioteca de reutilización.

Por lo tanto, intente esperar un poco más antes de compartir este DTO entre los servicios.

Dherik
fuente
1
Muy apreciado. Esta es realmente una de las pocas preocupaciones importantes que tengo en el futuro. No es suficiente para mantenerme despierto por la noche, pero sí lo suficiente como para preocuparme.
nbaughman
44
Los DTO duplicados (en servicios diferentes y muy independientes) no violan DRY. Eso es.
Laiv
3
Presumiblemente, entonces no hay razón para no copiar el código fuente DTO directamente de un proyecto a otro, como una operación única, aunque entonces cualquier parte no requerida en el nuevo proyecto probablemente debería eliminarse.
bdsl
1
Incluso un servicio completo podría eliminarse sin causar problemas importantes a todo el sistema. Idealmente.
Laiv
44
Para aclarar la esencia de la respuesta, al desarrollar microservicios, cada servicio debe desarrollarse como si no conocieran los otros servicios, excepto los contratos reales que pueda requerir.
Jonathan van de Veen
12

Cuando se trata de microservicios, los ciclos de vida de desarrollo de los servicios también deberían ser independientes. * *

Diferentes SLDC y diferentes equipos de desarrollo

En un sistema de EM real, podría haber varios equipos involucrados en el desarrollo del ecosistema, cada uno de los cuales está a cargo de uno o más servicios. A su vez, estos equipos pueden estar ubicados en diferentes oficinas, ciudades, países, planes ... Quizás, ni siquiera se conocen entre sí, lo que hace que compartir conocimiento o código sea muy difícil (si es posible). Pero esto podría ser muy conveniente porque el código compartido también implica una especie de razonamiento compartido y algo importante para recordar es que, lo que tenga sentido para un equipo específico, no tiene que hacerlo para otro equipo. Por ejemplo, dado el Cliente DTO , podría ser diferente dependiendo del servicio en juego, porque los clientes son interpretados (o vistos) de manera diferente a cada servicio.

Diferentes necesidades, diferentes tecnologías.

Los SLDC aislados también permiten a los equipos elegir la pila que mejor se adapte a sus necesidades. La imposición de DTO implementados en una tecnología específica limita la capacidad de los equipos para elegir.

Los DTO no son reglas comerciales ni contratos de servicios.

¿Qué son realmente los DTO? Objetos simples sin otro objetivo que mover datos de un lado a otro. Bolsas de captadores y colocadores. No es el tipo de "conocimiento" que vale la pena reutilizar, en general porque no hay ningún conocimiento en absoluto. Su volatilidad también los convierte en malos candidatos para el acoplamiento.

Contrariamente a lo que Dherik ha declarado, debe ser posible que un servicio cambie sus DTO sin tener que hacer que otros servicios cambien al mismo tiempo. Los servicios deben ser lectores tolerantes, escritores tolerantes y tolerantes a fallas . De lo contrario, provocan el acoplamiento de tal manera que la arquitectura del servicio no tiene sentido. Una vez más, y contrario a la respuesta de Dherik, si tres servicios necesitan exactamente los mismos DTO, es probable que algo haya salido mal durante la descomposición de los servicios.

Diferentes negocios, diferentes interpretaciones

Si bien podría haber (y habrá) conceptos transversales entre los servicios, no significa que tengamos que imponer un modelo canónico para obligar a todos los servicios a interpretarlos de la misma manera.

Caso de estudio

Digamos que nuestra empresa tiene tres departamentos, Servicio al Cliente , Ventas y Envíos . Digamos que cada uno de estos lanzamientos de uno o más servicios.

Servicio al cliente, debido a su lenguaje de dominio , implementa servicios en torno al concepto de clientes, donde los clientes son personas . Por ejemplo, los clientes se modelan como nombre , apellido , edad , sexo , correo electrónico , teléfono , etc.

Ahora, digamos, Ventas y Envíos modelan sus servicios de acuerdo con sus respectivos idiomas de dominio también. En estos idiomas, el concepto de cliente también aparece pero con una sutil diferencia. Para ellos, los clientes no son (necesariamente) personas . Para ventas , los clientes son una serie de documentos de una tarjeta de crédito y una dirección de facturación , para el envío de un nombre completo y una dirección de envío también.

Si obligamos a Ventas y envíos a adoptar el modelo de datos canónicos del Servicio al cliente , los estamos obligando a tratar con datos innecesarios que podrían terminar introduciendo una complejidad innecesaria si tienen que mantener toda la representación y mantener los datos del cliente sincronizados con el servicio al cliente. .

Enlaces relacionados


* Aquí es donde se encuentran los puntos fuertes de esta arquitectura

Laiv
fuente
¡Gracias! Los estudios de casos son en realidad lo que me ayudó a determinar si compartir DTO o no. Ahora estoy seguro de por qué no quería compartirlos.
Igor
8

Estoy tratando de diseñar cada servicio para que sea lo más independiente posible

Deberías estar publicando eventos . Los eventos son cierto tipo de mensajes que representan un hecho sólido sobre algo que ha sucedido en un momento determinado.

Cada servicio debe tener una responsabilidad muy bien definida, y debe tener la responsabilidad de publicar los eventos relacionados con esa responsabilidad.

Además, desea que sus eventos representen eventos relacionados con el negocio, no eventos técnicos. Por ejemplo, prefiera un OrderCancelledevento a un OrderUpdatedcon status: "CANCELLED".

De esa manera, cuando un servicio necesita reaccionar a una orden cancelada, solo necesita escuchar un tipo particular de mensaje, que solo contiene datos relevantes para ese evento. Por ejemplo, un OrderCancelledprobablemente solo necesita un order_id. Cualquier servicio que necesite reaccionar a esto ya ha almacenado todo lo que necesita saber sobre el pedido en su propio almacén de datos.

Pero si el servicio solo tuviera OrderUpdatedeventos para escuchar, entonces necesitaría interpretar el flujo de eventos, y ahora dependía del pedido de entrega para concluir correctamente cuando se cancelaba un pedido.

En su caso, sin embargo, como su están publicando datos de los sensores, podría tener sentido para tener un servicio, detectar los eventos y publicar una nueva corriente de "eventos de negocios", por ejemplo TemperatureThresholdExceeded, TemperatureStabilised.

Y tenga cuidado al crear demasiados microservicios. Los microservicios pueden ser una excelente forma de encapsular la complejidad, pero si no descubre los límites de servicio adecuados, su complejidad está en la integración del servicio. Y eso es una pesadilla para mantener.

Es mejor tener muy pocos servicios, demasiado grandes, que tener demasiados servicios demasiado pequeños.

Pete
fuente
Definitivamente estoy de acuerdo. Los datos del sensor llegan directamente a un microservicio que analiza el mensaje y lo transforma en un formato acordado en toda la organización antes de publicarlo en el intermediario. Tendremos algunos servicios que leen el mensaje y lo conservan en una base de datos, y otros que realizan el análisis del mensaje y hacen lo suyo con él. Cada servicio, por naturaleza del negocio, no tiene mucho que hacer, lo que lleva a (con suerte) servicios bastante simples.
nbaughman
2
@ Nickdb93: en su caso, como está publicando datos de sensores, podría tener sentido tener un servicio, escuchar los eventos y publicar una nueva secuencia de "eventos comerciales", por ejemplo, TemperatureThresholdExceeded, TemperatureStabilised. (agregado a la respuesta)
Pete