Asociaciones de muchos a muchos en microservicios

13

Actualmente tengo dos microservicios. Los llamaremos Ay B.

La base de datos bajo microservicio Atiene la siguiente tabla:

A
|-- users

La base de datos bajo microservicio Btiene la siguiente tabla:

B
|-- trackers

Los requisitos establecen eso usersy trackerstienen una relación de muchos a muchos.

No estoy seguro de cómo manejar esto adecuadamente dentro de una arquitectura de microservicios.

Pude ver esto funcionando de tres maneras:

  1. Se user_trackersagrega una tabla al microservicio A. Esto actúa de forma similar a una tabla de combinación que contiene "claves foráneas" para usersy trackers.
  2. Se ownersagrega una tabla al microservicio B. Esta tabla actúa de forma similar a una tabla de unión polimórfica. Esto permitiría a cualquier servicio crear una asociación con un rastreador. Esto puede verse más o menos así: B |-- trackers |-- owners |-- owner_id |-- owner_type |-- tracker_id
  3. Mantenga registros para usersy trackersen cada microservicio. Manténgalos sincronizados con algún tipo de sistema pubsub.

Originalmente iba a ir con la opción 2 porque me gustaba que conservara los límites de las transacciones. Puedo crear un rastreador y asociarlo con algo atómicamente. Sin embargo, parece estar fuera del alcance del microservicio B. ¿Por qué el microservicio debería Bpreocuparse de que el microservicio Aquiera crear una asociación?

Siento que probablemente hay un buen patrón aquí del que no estoy al tanto. ¿Alguna de las opciones que expuse tiene sentido? ¿Hay alguna otra opción que tenga más sentido?

anthonator
fuente

Respuestas:

12

En primer lugar, comenzaría con la descripción del dominio. No has mencionado de qué se trata (puedo adivinar, pero sería solo una suposición). Después de eso, trataría de descomponerlo mediante el análisis de la cadena de valor o el mapeo de la capacidad empresarial . Y solo después de eso pensaría en la implementación.

Teniendo en cuenta su problema, lo primero que se me ocurre es que identificó incorrectamente los límites de su servicio, simplemente porque necesitan los datos del otro. No quieres terminar con un monolito distribuido , ¿verdad?

La segunda cosa es que probablemente no has trabajado a través de tu dominio lo suficientemente bien. ¿Qué concepto se representa con userstabla? ¿Es un registered user, con toda la información y el comportamiento necesarios para el registro? ¿Está seguro de que es el concepto correcto para comunicarse con trackers(lo que sea que sea)? Entonces, si entendí bien, su opción 2 es exactamente sobre eso: presentar el ownerconcepto que está mucho más cerca de su dominio. Si realmente es así, también estoy para la opción 2.

Sin embargo, parece estar fuera del alcance del microservicio B. ¿Por qué el microservicio B debe preocuparse de que el microservicio A quiera crear una asociación?

Se trata de límites. Supongo que quieres formar microservicios alrededor de entidades. Ahí es donde SOA falló con su arquitectura de servicio en capas . El mejor enfoque es crear servicios que representen alguna función comercial, de modo que encapsulen tanto los datos como el comportamiento. Desde un punto de vista más práctico, se trata de crear servicios en torno a procesos comerciales o casos de uso. Por ejemplo, podría tener un servicio para el registro de usuarios. Contiene los datos y el comportamiento del usuario necesarios para registrar un usuario. Por lo tanto, el concepto de userse forma naturalmente, y pertenece solo al servicio A. Y esto me lleva al siguiente punto: la otra forma de pensar en los servicios es el contexto acotado . Es una buena práctica alinear servicios y contextos limitados.

Cuando el usuario está registrado, UserCreatedse puede emitir un evento. Supongo que su segundo servicio está interesado en él. Entonces, al recibirlo, se podría crear una entidad completamente diferente, por ejemplo, Ownerentidad (sea lo que sea, tampoco). Estoy bastante seguro de que hay muchas colaboraciones interesantes entre él y la trackerentidad: manténgalas en un solo servicio.

Sea extremadamente cauteloso con la opción 3. Si copia datos, sigue la funcionalidad. Da como resultado un acoplamiento apretado. Y no cubra con el término CQRS , no se trata de sincronización de datos entre servicios a través de eventos.

Zapadlo
fuente
Me encanta el término "monolito distribuido", pero la forma en que se define en el enlace que da parece no estar directamente relacionada con la pregunta aquí. La forma en que creo que lo está utilizando está relacionada con el acoplamiento entre servicios y el artículo se centra en las dependencias binarias. Creo que la forma en que está utilizando es superior, pero estoy luchando por encontrar una referencia que la defina claramente de esa manera.
JimmyJames
Siempre he incluido servicios habladores en la categoría "monolito distribuido", que no está muy difundido, de manera común.
Zapadlo
6

La respuesta de Zapadlo tiene mucha buena información y razonamiento. Voy a agregar un pequeño consejo práctico aquí que puede facilitar el trabajo a través de sus problemas y los consejos en esa respuesta.

La forma en que ha formulado su pregunta de diseño es en torno a las estructuras de la base de datos y cómo encajar un nuevo requisito para sus estructuras en eso. Esto implica que está construyendo el diseño del servicio a partir de su modelo de datos. Por ejemplo, lo que no veo es cómo se debe acceder o utilizar la relación entre usuarios y rastreadores.

En el diseño de servicios, la estructura de la interfaz es lo más importante del diseño. De hecho, la implementación es casi irrelevante en comparación, particularmente en el caso de los microservicios. La razón es que una vez que establezca su servicio, todas las dependencias de su servicio deberían existir solo en la interfaz. Si lo hace bien, debería poder reescribir completamente la implementación sin ningún consumidor. Y ese es el principal beneficio de la autonomía. A nadie le importa cómo lo construiste. Solo lo necesitan para funcionar de la manera en que lo comunicaste.

Antes de que alguien pueda determinar cómo se ve esto en la base de datos o dónde quiere esto, realmente necesita explicar cómo se usará esta información. ¿Es esto algo que se expondrá a través de un servicio o es algún tipo de datos que desea mezclar para el análisis?

En una nota al margen, evitaría las dependencias bidireccionales a casi todos los costos. Si tiene dependencias, realmente quiere que solo un lado sepa sobre el otro. Una vez que las dependencias están en ambas direcciones, los servicios se convierten esencialmente en una unidad atómica.

JimmyJames
fuente
0

Mucho de esto se reduce al dominio mismo. Si un usuario con cero rastreadores no tiene sentido, entonces el servicio de usuario necesita saber sobre rastreadores. Si un rastreador debe tener un usuario, entonces los rastreadores deben saber sobre los usuarios. Si algo como tener un rastreador con múltiples propietarios o poder transferir un rastreador de un usuario a otro tiene sentido, entonces tal vez esta información pertenezca a otro servicio.

Firmar
fuente
0

Pregunta: ¿Por qué se separan sus datos en tablas de datos?

Me inclinaría por la opción 3: los servicios están totalmente separados y pueden responder las preguntas respectivas que puedan necesitar responder. Además, son mucho más resistentes. Pero tenga cuidado, sus servicios podrían desincronizarse si pierden eventos, pero eso se puede resolver a través de la consistencia eventual.

Además, podría considerar fusionar ambos servicios: si ambos no pueden responder sin conocerse, simplemente los fusionaría, ya que probablemente sean parte de un solo dominio.

Christian Sauer
fuente
Esto es parte de la religión de los microservicios, que cada servicio necesita autonomía total. Thomas Erl lo describe como uno de los principios de orientación al servicio en "Principios del diseño del servicio" c. 2008.
JimmyJames
@JimmyJames Como alguien que escribe una arquitectura ms yo mismo: hay mucho debate sobre la cuestión de qué tan grande debe ser un ms. En este caso, es posible que el tamaño ni siquiera importe porque los servicios pueden no estar separados correctamente, por ejemplo, no corte las tablas ni los dominios comerciales.
Christian Sauer
Derecha. El problema es que hay un gran culto a la carga en torno a los microservicios en este momento. Veo a muchas personas implementando microservicios porque eso es lo que hacen los chicos geniales y no consideran ni entienden las compensaciones. Por ejemplo, tengo la sensación de que mucha gente piensa que la autonomía de la EM se trata de tecnología y 'la nube'. Lo veo como una solución más a un problema de organización. La desreferencia de puntero comercial para IO de red es extremadamente costosa. No puede simplemente aplicar esto sin pensar y esperar que las cosas salgan bien.
JimmyJames
@JimmyJames Creo que también puede tratarse de tecnología, especialmente cuando las tecnologías certian son adecuadas para algunos dominios, pero no para otros. Utilizamos C # y Python para nuestros MS. Algo de eso se debe a problemas organizativos ("¡He programado c # durante 20 años, no necesito aprender nuevos idiomas sin tipo!"). - pero también debido a la naturaleza de nuestro sistema. Las partes de ciencia de datos se realizan mejor en python, mientras que algunas tareas de infraestructura y web se realizan mejor en C #.
Christian Sauer
Claro, esa es una razón bastante válida para hacerlo. El problema que veo es que la gente querrá dividir cada servicio en un nodo separado simplemente porque "estamos haciendo microservicios", incluso si todo está escrito con el mismo código en la misma plataforma y hay un montón de dependencias entre los servicios. Realmente no hay mucho beneficio para los microservicios en ese caso y ha agregado un conjunto completo de problemas nuevos.
JimmyJames