Design de microsserviço para vários locatários

13

Estamos migrando um aplicativo monolítico para a arquitetura de microsserviço. Devido a alguns requisitos regulamentares, precisamos manter os dados do cliente de diferentes países em bancos de dados separados (específicos do país). Ou seja, EUA db para clientes nos EUA, UK db para clientes no Reino Unido ...

Os seguintes projetos que estamos considerando são os seguintes:

Opção 1: um aplicativo multilocatário com suporte a hibernação multilocatário que pode ser escalado para N número de vezes que depende da demanda (pense nos pods do kubernetes). Uma única instância deste aplicativo poderá se conectar a todos os bancos de dados.

Opção 2: implantar 1 instância de microsserviço por banco de dados do país. Com um gateway de API na frente deles, roteando o tráfego

Se você projetasse esse tipo de sistema, quais seriam suas escolhas?

Olá Mundo
fonte
3
Eu acho que vai depender de quais são seus requisitos funcionais e não funcionais específicos.
Robert Harvey
Bancos de dados diferentes, mas a mesma instância está lendo? Isso não viola também os requisitos regulamentares?
Jimmy T.
A opção 1 não parece muito alinhada com o estilo da arquitetura Microservices.
LAIV
Você mencionou o Kebernetes, mas não está claro se você está usando contêineres ou não. Se você estiver fazendo isso com o Docker (por exemplo), basta criar um aplicativo que se conecte a um banco de dados. Depois, quando você inicia o contêiner e especifica os detalhes da conexão por meio de parâmetros e / ou configuração. Ter um aplicativo que se conecta a muitos bancos de dados semelhantes cria apenas possíveis problemas. Não adiciona nada de bom ao design.
JimmyJames

Respostas:

4

Eu acho que a opção 2 não é ruim, mas pode não ser necessária. Os micro serviços são para permitir que você lide com as necessidades de vários aplicativos.

Um grande fator aqui é se existe alguma diferença entre os dois esquemas e se haverá no futuro.

Normalmente, acho desnecessário o uso de interfaces para repositórios; no entanto, pode valer a pena o esforço neste caso. Fábricas de repositório serão importantes para você.

Meu problema com a opção 1 é que é muito específico. Você deve poder ir da instalação descrita, para duas instâncias separadas, cada uma apontando para seu próprio banco de dados com facilidade. O aplicativo NÃO deve se importar de onde está obtendo seus dados.

Embora o esquema não seja diferente para seus dois bancos de dados diferentes, é possível que um repositório lide facilmente com ambos, sem que o aplicativo saiba a diferença:

public class MyEntityRepository : ISavesMyEntity, IGetsMyEntity
{
    public MyEntityRepository(string connectionString)
    {
       _connectionString = connectionString;
    }
}

public class MyEntitySaverFactory
{
    public ISavesMyEntity GetSaver(User user)
    {
        if (user.IsUK)
            return new MyEntityRepository(Config.Get("UKConnString"));
        if (user.IsUS)
            return new MyEntityRepository(Config.Get("USConnString"));
        throw new NotImplementedException();
    }
}

//USE
ISavesMyEntity saver = factory.GetSaver(currentUser);
saver.Save(myEntityInstance);

Se os esquemas de banco de dados se tornarem díspares entre os EUA e o Reino Unido, você poderá dividir a funcionalidade em dois repositórios completamente diferentes. Isso seria fácil, pois tudo o que você teria que fazer era mudar de fábrica.

TheCatWhisperer
fonte
1
Não entendo por que você precisa desta fábrica. Por que não apenas passar o caminho para os detalhes de configuração na inicialização? Com isso, você precisa modificar o código toda vez que quiser adicionar uma nova região / país.
precisa saber é o seguinte
1
O problema aqui não é lidar com usuários em países separados ... está lidando com bancos de dados diferentes. e se houver esquemas diferentes? Por que a classe consumidora deve ser responsável por descobrir onde obter a cadeia de conexão do banco de dados?
TheCatWhisperer
Eu não sei o que você quer dizer. Nada no código deve ser responsável por 'descobrir' onde obter a cadeia de conexão. É configuração. Não vejo por que isso seja diferente do que usar a configuração para bancos de dados de QA versus produção. Você não coloca instruções if no código, não é?
precisa saber é o seguinte
Este é um aplicativo que fala com dois bancos de dados.
TheCatWhisperer
Eu acho que você entendeu mal o problema: "temos que manter os dados do cliente de diferentes países em bancos de dados separados (específicos do país)". Não é necessário que uma única "instância" de aplicativo fale com dois bancos de dados. Duvido que sejam apenas dois DBs. O OP provavelmente significava "por exemplo," quando digitado "ie"
JimmyJames
0

Eu usaria a segunda opção, ela oferece menos atrito no desenvolvimento e na implantação.

Isso permitirá melhor escalabilidade e disponibilidade e melhores opções de implantação de tempo de inatividade zero, à medida que você distribuiu seu aplicativo para 1 (ou pelo menos uma) instância por região, em vez de pelo menos uma para o mundo inteiro.

À medida que os requisitos mudam, você pode ter mais lógica de negócios específica da região e possivelmente dados também alterados, eu tentaria dividir o código e os dados por região e evitar o compartilhamento da lógica de negócios específica da região (você pode acabar compartilhando algum código principal).

Faz sentido?

Sean Farmar
fonte