Arquitetura micro-serviços com base de dados distribuída

Olá pessoal,
Estou projetando uma arquitetura de micro-serviços para uma solução que irá abranger vários módulos que poderão trabalhar separadamente ou podem ser plugáveis de acordo com a aquisição.
O meu problema de definição arquitetural/infra de dados está no seguinte ponto: apenas como exemplo(não é a solução real), vamos considerar que fosse uma solução completa para gerenciamento de reservas com seguintes módulos:

Módulo Reserva Hotel
Módulo Reserva de Entretenimento(eventos diversos: teatro, shows musicais etc)
Módulo Reserva Veículo
Módulo Venda de passagem aérea

Cada módulo teria seu próprio domínio: integrações, regras e base de dados do seu domínio, o problema que estou tentando resolver nessa modelagem de serviços/armazenamento é como separar as partes comum num barramento de serviços e reutilizá-lo para todos módulos mas sem criar um modelo de dados único, exemplo:
em todos estes módulos eu terei uma base de usuários(haverá outros pontos comuns), qual melhor abordagem pra eu ter um armazenamento de dados de usuários únicos mas independente aos modelos de cada módulo de serviços?

Pensei nas seguintes opções:

1 - Ter um barramento de serviços para gerenciar usuários numa base de dados comum e cada módulo teria uma referência à FK do usuário no seu schema diretamente pelo banco de dados.
Utilizando essa abordagem https://www.akadia.com/services/ora_references_constraint.html
Mas qual o impacto de por exemplo realizar JOIN entre schemas? Pode inviabilizar?

2 - Ter um barramento de serviços para gerenciar usuários numa base de dados comum e seria replicado os dados via serviços para cada módulo, cada um destes teria sua própria base de usuários.
Problema seria várias bases de usuários dentro da mesma solução.

Cada módulo tem seus próprios serviços e modelos de dados, não quero criar um único modelo de armazenamento para todos os módulos. Não é um sistema grande com várias partes, é uma solução com vários sistemas independentes mas plugáveis entre si.

A primeira opção me parece melhor, mas não estou confortável pensando numa arquitetura moderna.

O que sugerem sobre essa arquitetura, uma solução NoSQL seria mais adequada?

Qualquer dica é bem vinda.

Independente de ser micro serviço ou não, usa schema diferente. Você não especificou qual SGDB, mas eu nunca tive problemas com joins nos bancos que trabalhei.

Não trabalho com micro serviços pra tudo como ta na moda, e sim sistemas modulares para cada rotina da empresa, como sempre foi. Serviço só quando realmente necessário, maioria das informações são compartilhadas por views e SP, é muito mais produtivo e performático. Você deveria se preocupar mais com o overhead entre micro serviços do que joins que são feitos diretamente no SGDB.

Se vai começar uma arquitetura dessas do zero, não pense em FK’s. Cada microserviço deve ter o seu schema e a interação entre os dados deve ser feita pelos serviços. Se começar a fazer alguma integração via banco, isso pode causar problemas no futuro e foge da ideia dessa arquitetura.

Obrigado pela resposta.
Diante do cenário, a sua sugestão é que eu tenha por exemplo a mesma base de usuário replicada para cada módulo, ainda que seja uma replicação idêntica da base dentro da solução?

De forma alguma. Para o negócio que vc está criando esse sistema, imagino que “Usuário” se encaixa em algum boundary context. Um microserviço responsável por controlar as regras negociais envolvendo o recursos humanos, por exemplo. Seguindo esse exemplo, os dados dos usuários ficariam no schema desse microserviço e seria criado endpoints para fornecer as informações desses usuários para os outros microserviços.

Entendi, esse cenário é exatamente o que descrevi considerando a opção 1.
O problema é justamente como fazer o relacionamento destes usuários com as funcionalidades específicas dos módulos. Exemplo considerando o cenário hipotético:

Microserviço de Usuários(clientes utilizando a solução) - CRUD, regras específicas etc.

Módulo Reserva Hotel - Quando for realizar a reserva(com suas regras do domínio) preciso associar quem é o usuário(este dado está no microserviço) que está reservando.

Módulo Venda Passagem - Quando o usuário comprar passagem(com suas regras do domínio) será necessário associar o usuário(que está no microserviço) ao produto comprado.

A questão que estou tentando achar uma solução adequada do ponto de vista arquitetural é como relacionar o usuário de um sistema(microserviço com sua base) com outro sistema por exemplo de reserva de hotel(microserviço com sua base também).
Por isso a minha ideia na proposta 1 era ter o microserviço de usuário e em cada módulo(outros micro serviços) ter a FK em sua base para realizar os relacionamento sem a necessidade de replicar o cadastro do usuário e nem possuir uma única base tal como um sistema monolítico.

Pois é, com microserviço, o ID do usuário ficará associado, sem FK, com a reserva. A integridade deverá ser controlada pelo microserviço. É ele quem deverá controlar, verificar, validar, etc., essa relação entre usuário e reserva (usuário e venda, etc.).

Esse trecho e todo o resto da conversa me dão uma convicção grande no que eu vou lhe dizer a seguir.

Meu conselho, perceba, CONSELHO (não sou dono da verdade) é que se você está ainda está com um monte de “talvez”, “eu acho”, “não é um sistema grande” e com as respostas do tipo “imagino que”, eu aconselho que você dê um reset na ideia de usar micro serviços. Não, longe de mim de dizer que não é a solução pro seu problema e nem que você não deve estudar a arquitetura, mas é que nos anos desenvolvendo sistemas, uma coisa que eu vi que é muito clara quando se usa micro serviços é que isso é uma arquitetura emergente do seu problema e das suas dores.

É muito caro desfazer microservices, muito mais caro do que criá-los conforme sua necessidade. Se eu estivesse no seu lugar, eu começaria pensando em fazer o que eu @javaflex lhe indicou, modularizar o sistema, mas ainda não descolar em serviços apartados e conforme sua maturidade no negócio e percepções dos problemas que você está enfrentando forem crescendo, você vai aos poucos criando os pedacinhos que podem viver isolados. O seu negócio, seus problemas e seus clientes vão lhe dizer implicitamente o que pode e o que deve virar um serviço.

Por hora, que você ainda nem começou, você pode estar fazendo uma arquitetura robusta, que muito em breve vai cobrar seu preço de manutenção, para algo que talvez não precise desse tipo de solução.

Eu entendo sua preocupação, ela é válida, você já consegue enxergar algumas fronteiras e elas parecem fazer muito sentido nesse momento, mas acredite em mim, prefira decompor um monolítico em pedaços claros que precisam ser separados do que ter que juntar 2 micro serviços em uma única unidade de domínio de negócio, pois essa segunda é bem mais cara.

Outro sinal que você deve estar atento: qual o tamanho da sua equipe?

Essa pergunta acima é tão importante quanto o número de módulos que você está enxergando. Uma característica que reforça e abrange o uso dos micro serviços é você ter um time que cuida daquele trecho do domínio do seu negócio, ou seja, pessoas cuidando apenas da saúde daquele pedacinho e cuidando pra não entrar nada que não faça parte do domínio. Quando a sua equipe é uma só cuidando de vários serviços, a chance de você extrapolar seus domínios e enfiar neles coisas que não são aderentes a eles, cresce bastante.

Perceba que arquitetura de micro serviços vai muito mais além de “separar meu código em vários projetos que expõe endpoints” e muito mais para separar meu NEGÓCIO em áreas de domínios que fazem sentidos viverem separadas. Todos os grandes que hoje são players de mercado que evangelizam microserviços começaram monolíticos, porque eles sabem do risco de separar antes de validar.

Seu caso me parece ser um dos alguns muitos que já ví, que estão nascendo com a arquitetura precoce antes de amadurecer a solução.

De novo, não sou o dono da verdade, estou expondo minha opinião com base no que já vivi e o tanto que já estudei e quebrei a cara ao adotar arquiteturas de micro serviços. Espero ter contribuído com algo :wink:

1 curtida

Concordo com o que o @adriano_si disse. E recomendo a leitura deste artigo do Martin Fowler, com pré requisitos pra usar micro serviços: https://martinfowler.com/bliki/MicroservicePrerequisites.html

Pegando um gancho no que o @Lucas_Camara falou sobre bounded contexts, você já pode fazer o design do seu projeto pensando nessas separaçoes, mesmo num monolito. Daí se um dia, eventualmente, precisar migrar pra isso, já torna tudo mais fácil. E de quebra tem um monolito bem organizado.

Antes de pensar em micro serviços, eu faria mais questao de ter uma boa estratégia de CI e CD funcionando, uma boa estratégia de testes, uma forma simples e fácil de documentar as decisoes do projeto e de negócio, esse tipo de coisa.

Tem que ter muito cuidado em não entrar nessa só por moda, pode trazer mais complexidade, overhead, com soluções para problemas que nem existem. Pelo menos até então não vi um motivo forte.

Perfeito… Isso mais do que tudo, senão é o início do buraco da própria cova :+1: