Executando verificação de segurança...
4

Multi tenancy com bancos de dados separados por cliente

Estou lidando com um projeto de Multi-Tenancy, onde adotamos a estratégia de cada cliente possuir seu próprio banco de dados, enquanto um banco central armazena informações gerais dos clientes, incluindo a referência para os respectivos bancos.

No contexto HTTP, através de um middleware, identifico qual é o cliente pelo hostname e realizo a conexão com o respectivo banco de dados.

Tenho dúvidas sobre como configurar as conexões com os bancos de dados dos clientes fora do contexto HTTP, como em tarefas agendadas (cron jobs) ou consumidores de filas. Alguém que já trabalhou nesse formato de multi tenancy com bancos de dados separados por cliente poderia compartilha como resolveram a questão de acessar os bancos fora do contexto de requisição?

Carregando publicação patrocinada...
1

A questão gira em torno mais da maneira como você obtém uma conexão a partir de algum identificador único do tenant do que da origem dessa informação (no caso, a requisição HTTP) propriamente dita. Trabalho hoje com um sistema multi tenant e dado o acoplamento do código legado (objeto request sendo um god object), tive que escrever uma nova base de código para os jobs, usando clean arch e padrões de projeto, nenhum framework. A ideia é construir uma lib desacoplada na nova base e incorporá-la à base antiga de maneira progressiva, o que é possível por serem bases TypeScript, de modo a extinguir o god object aos poucos. Ainda que isso nunca aconteça, a nova base já atende os novos executáveis da aplicação. Então, já há o benefício. No meu caso, o alto acoplamento justifica a reescrita. Tens que avaliar se é o mesmo caso com você.

0
1

No job, a resposta da pergunta "qual tenant?" entra como um argumento (de linha de comando, talvez, ou variável de ambiente, enfim). A questão é que para que isso funcione, a responsabilidade do seu middleware deve estar limitada a apenas responder a pergunta com base na requisição, não de fornecer acesso à infraestrutura correspondente. Uma vez que essa responsabilidade de acessar a infraestrutura (bancos de dados, armazenamento, etc.) esteja isolada, fora do middleware, pode ser utilizada tanto pelo contexto HTTP, quanto pelos jobs. Apenas a resposta de "qual tenant?" virá de fontes diferentes em cada caso, mas o acesso ao banco virá do mesmo código. O componente pode ser classe ou função (ou qualquer coisa) que execute "me forneça acesso ao banco do tenant X".

1

Eu tinha pensado em desenvolver o meu sistema onde cada cliente teria seu banco de dados e cada banco ficaria em um container docker, onde cada servidor poderia ter tipo uns 100 bancos ou mais, faria algum balanceamento para que todos os servidores tivessem a MSM quantidade de bancos, mas no final após analisar melhor a situação e algumas questões técnicas, não fizemos assim, talvez funcione, mas na época minha equipe apresentou alguns argumentos bons e mudamos para um banco de dados onde todos os clientes conectam.
Eu acho interessante esta ideia de separar os clientes por banco, mas assim teria uma complexidade a mais como ter senhas diferentes, portas diferentes para cada contêiner, recursos a mais de processamento para cada banco e etc.
Ai tem de ver se é viável ou não.
A necessidade e o retorno é maior nesta abordagem?

1
1

Uma possibilidade seria criar uma tabela no banco de dados central que armazena informações da base de dados dos clientes. Com isso, você precisaria simplesmente fazer uma SELECT nessa tabela, recuperar as informações necessárias para montar a ConnectionString, conectar nas bases e fazer o que tem de ser feito.

Apesar deu nunca ter feito filas e nem cron jobs nesse cenário de multi tenancy, trabalhei em uma empresa que seguiu essa abordagem e seria assim que eu resolveria essa questão.

0
1

Então, depende muito do que se trata o procedimento em si. Alguns exemplos que consigo pensar:

  1. Realizar o processamento de um pedido numa fila. Nesse caso, eu criaria uma tabela que representaria esse processamento em especifico na qual teria como uma de suas colunas o id dessa base de dados. Dai seria uma questão de recuperar esse registro, pegar o id da base e localizá-la na tabela do banco de dados central.
  2. Criar um Cron Job que faz backup dos pedidos dos clientes 1x ao dia: quando ocorrer o trigger desse job, simplesmente faz um SELECT nessa tabela que contêm todas as bases de dados e faz o procedimento de backup na tabela de pedidos em cada base.

É lógico que dependendo dos requerimentos não vai ser tão simples assim. Mas eu acho que ter uma tabela que me diz quais são as bases dos meus clientes é essencial para que eu consiga fazer algo, a não ser que os colegas da plataforma possam sugerir outras abordagens, claro.