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?
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.
tem um projeto muito bem estruturado para multi tenancy em dotnet c# + angular, caso for a stack que você usa pode te ajudar bastante, caso não for, pode te dar uma noção de como é feito, tem o fonte inteiro disponivel no github e vc pode baixar uma versão com seu nome direto do site deles: https://aspnetboilerplate.com/
sobre multi tenancy: https://aspnetboilerplate.com/Pages/Documents/Multi-Tenancy
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?
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ê.
o https://tenancyforlaravel.com/ , tem uma implementação bacana disto para o laravel, ele tem um banco de dados central, que é o db geral, aonde fica uma tabela tenants, com todos os dados, não sei exatamente como ele manipula essa coisa do contexto no cron job, mais essa implementação depende doq exatamente você quer fazer.
Jamais separe as tabelas por clientes. A manutenção vai ser impossível com o crescimento do software. Isso foi até viável no passado, mas com as ideias de arquitetura mais modernas, isso nem é mais cogitado.