Associações muitos-para-muitos em microsserviços

5

Atualmente tenho dois microservices. Vamos chamá-los de A e B .

O banco de dados sob microservice A tem a seguinte tabela:

A
|-- users

O banco de dados sob microservice B tem a seguinte tabela:

B
|-- trackers

Os requisitos indicam que users e trackers têm um relacionamento muitos-para-muitos.

Não sei como lidar corretamente com isso em uma arquitetura de microsserviços.

Eu pude ver isso funcionando de três maneiras:

  1. Uma tabela user_trackers é adicionada ao microservice A . Isso age semelhante a uma tabela de junção contendo "chaves estrangeiras" para users e trackers .
  2. Uma tabela owners é adicionada ao microservice B . Esta tabela age de forma semelhante para uma tabela de junção polimórfica. Isso permitiria que qualquer serviço criasse associação com um rastreador. Isso pode parecer um pouco assim: %código%
  3. Mantenha os registros de B |-- trackers |-- owners |-- owner_id |-- owner_type |-- tracker_id e users em cada microsserviço. Mantê-los em sincronia com algum tipo de sistema pubsub.

Eu estava indo originalmente com a opção 2 porque gostei que ela preservasse os limites da transação. Eu posso criar um rastreador e associá-lo a algo atomicamente. No entanto, parece fora do escopo para microservice trackers . Por que o microservice B precisa que o microservice B queira criar uma associação?

Eu sinto que provavelmente há um bom padrão que eu não conheço. Alguma das opções que eu coloquei faz sentido? Existe outra opção que possa fazer mais sentido?

    
por anthonator 07.12.2017 / 14:05
fonte

4 respostas

4

Primeiro de tudo, eu começaria com a descrição do domínio. Você não mencionou sobre o que é (eu posso imaginar, mas seria apenas um palpite). Depois disso, tentaria decompô-lo usando análise de cadeia de valor ou mapeamento de capacidade comercial . E só depois disso eu pensaria em implementação.

Considerando o seu problema, a primeira coisa que me vem à mente é que você identificou seus limites de serviço errados, simplesmente porque eles precisam dos dados uns dos outros. Você não quer acabar com o monolito distribuído , né?

A segunda coisa é que você provavelmente não trabalhou bem no seu domínio. Qual conceito é representado com users table? É um registered user , com todas as informações e comportamentos necessários para o registro? Você tem certeza de que é o conceito certo para se comunicar com trackers (seja o que for)? Então, se eu entendi direito, sua opção 2 é exatamente isso: introduzir o conceito owner que é muito mais próximo do seu domínio. Se realmente é assim, eu sou para a opção 2 também.

However, it seems out of scope for microservice B. Why should microservice B care that microservice A wants to create an association?

É tudo sobre limites. Eu acho que você quer formar microservices em torno de entidades. É onde SOA falhou com seu Arquitetura de serviço de camadas . A melhor abordagem é criar serviços que representem alguma função de negócios, para que eles encapsulem os dados e o comportamento. Do ponto de vista mais prático, trata-se de criar serviços em torno de processos de negócios ou casos de uso. Por exemplo, você pode ter um serviço para o registro do usuário. Ele contém os dados e o comportamento do usuário necessários para registrar um usuário. Assim, o conceito de user é formado naturalmente, e pertence apenas ao serviço A. E isso me leva ao próximo ponto: a outra maneira de pensar sobre os serviços é conectado vinculado . É uma boa prática alinhar serviços e contextos limitados.

Quando o usuário é registrado, o evento UserCreated pode ser emitido. Seu segundo serviço, acho que está interessado nisso. Assim, ao recebê-lo, uma entidade completamente diferente poderia ser criada, digamos, Owner entity (seja lá o que for, também). Tenho certeza de que existem muitas colaborações interessantes entre ele e tracker entity - mantenha-as em um único serviço.

Seja extremamente cauteloso com a opção 3. Se você copiar dados, segue-se a funcionalidade. Isso resulta em acoplamento apertado. E não cubra com o termo CQRS , não se trata de sincronização de dados entre serviços via eventos.

    
por 07.12.2017 / 16:16
fonte
0

Muito disso se resume ao próprio domínio. Se um usuário com zero rastreador não fizer sentido, o serviço do usuário precisa saber sobre rastreadores. Se um rastreador precisa ter um usuário, os rastreadores precisam saber sobre os usuários. Se algo como ter um rastreador com vários proprietários ou ser capaz de transferir um rastreador de um usuário para outro faz sentido, então talvez essa informação pertença a outro serviço.

    
por 07.12.2017 / 14:26
fonte
0

Pergunta: Por que seus dados são separados por Datatables?

Eu tenderia a escolher a opção 3: os serviços são totalmente separados e podem responder às questões que eles precisam responder. Além disso, eles são muito mais resistentes. Mas tenha cuidado, seus serviços podem desassociar se perderem eventos, mas isso pode ser resolvido com consistência eventual.

Além disso, você poderia considerar a fusão dos dois serviços - se os dois não puderem responder sem se conhecerem um ao outro, eu os mesclaria, já que provavelmente fazem parte de um único domínio.

    
por 07.12.2017 / 15:31
fonte
0

A resposta de Zapadlo tem muita informação boa e raciocínio nela. Vou adicionar aqui alguns conselhos práticos que podem facilitar o trabalho sobre os seus problemas e os conselhos nessa resposta.

A forma como você moldou sua questão de design é em torno de estruturas de banco de dados e como ajustar um novo requisito para suas estruturas. Isso significa que você está criando o design do serviço a partir do seu modelo de dados. Por exemplo, o que não vejo é como o relacionamento entre usuários e rastreadores deve ser acessado ou usado.

No design de serviços, a estrutura da interface é a coisa mais importante sobre o design. De fato, a implementação é quase irrelevante em comparação, particularmente no caso de microsserviços. A razão é que, uma vez que você coloque seu serviço no lugar, todas as dependências do seu serviço devem existir apenas na interface. Se você acertar, você deve ser capaz de reescrever completamente a implementação sem qualquer consumidor. E esse é o principal benefício da autonomia. Ninguém se importa como você construiu. Eles só precisam que funcione da maneira que você comunicou que acontecerá.

Antes que alguém possa determinar como isso fica no banco de dados ou onde você quer isso, você realmente precisa explicar como esta informação será usada. Isso é algo que será exposto por meio de um serviço ou algum tipo de dado que você deseja alterar para análise?

Em uma nota lateral, eu evitaria dependências bidirecionais a quase todos os custos. Se você tem dependências, você realmente quer apenas um lado para saber sobre o outro. Uma vez que as dependências estão em ambas as direções, eles se tornam essencialmente uma unidade atômica.

    
por 07.12.2017 / 19:32
fonte