Projetar aplicações para que múltiplos clientes, normalmente de diferentes empresas, as acessem de forma segura e isolada, porém com uso ótimo de recursos não é problema recente. Desde os mainframes existe a demanda por compartilhar recursos computacionais para diferentes grupos de usuários. Porém, com a popularização de modelos de negócios SaaS as arquiteturas para multitenancy ganham relevância especial.
Devemos compartilhar uma única instância de banco de dados entre clientes de diferentes empresas? Como devemos tratar o escalonamento de recursos? Essas, são apenas duas questões fundamentais que devem ser consideradas na concepção arquitetônica.
Multitenancy
Multitenancy is a reference to the mode of operation of software where multiple independent instances of one or multiple applications operate in a shared environment. The instances (tenants) are logically isolated, but physically integrated. The degree of logical isolation must be complete, but the degree of physical integration will vary.
Fonte: Gartner
Estratégias Arquiteturais
Existem ao menos três estratégias principais para abordar essa problemática: aplicações single-tenant, multi-tenant e uma abordagem híbrida. Cada uma dessa possui seus prós e contras e, como arquitetos, é fundamental que analisemos as restrições, requisitos não funcionais e características do negócio para determinar a solução arquitetural mais aderente.
Single-tenant
Esta estratégia preconiza por total isolamento dos dados e aplicações. Dessa forma, mitiga significativamente os riscos de vazamento de dados entre clientes diferentes na medida que bugs na aplicação não produzem esse tipo de vulnerabilidade.
Essa estratégia arquitetural é tentadora por ser muito próxima da implementação que fazemos normalmente para aplicações que atendem apenas um cliente. Com ela, há pouco impacto no código. Também é fácil determinar o custo, geralmente mais alto, para cada cliente.
O principal problema dessa estratégia, porém, é que cada novo cliente “adquirido” exige que levantemos instâncias novas do servidor de aplicação e de banco de dados. Todo ganho que tivemos no desenvolvimento se converte em dificuldades para a operação, sobretudo para atividades de deploy.
Essa estratégia restringe consideravelmente a elaboração de modelos de negócio escaláveis.
Multi-tenant
Em uma estratégia multi-tenant todos clientes acessam uma mesma aplicação e ela é capaz de definir quais dados o usuário possui acesso. A ênfase, nessa estratégia, é otimizar a utilização de recursos computacionais. Dessa vez, entretanto, há um aumento considerável de riscos de “vazamento” de dados entre tenants e é necessário muito mais cuidado no desenvolvimento.
Nesta estratégia a segregação é estritamente lógica. Ou seja, tanto o banco de dados quanto a aplicação são compartilhados. Por isso, é necessário cuidado redobrado é necessário estremo cuidado no código que trata as permissões dos usuários para vazar os dados de um cliente para outro.
No geral, problemas mais graves acontecem quando aplicações “tornam-se” multi-tenant depois de muito tempo, geralmente como tentativa de superar as “dores” de operação de aplicações single-tenant.
Aplicações multi-tenant tem escala horizontal mais complexa e, geralmente, para grandes volumes de dados, implicam em alguma estratégia de sharding.
Esta estratégia é mais alinhada com negócios com escala rápida, sobretudo SaaS.
Solução Híbrida
Há algum tempo vem ganhando força uma abordagem híbrida, onde cada cliente possui uma instância isolada de banco de dados, porém compartilha uma mesma estrutura de servidores de aplicação.
Neste modelo há isolamento dos dados. Se um banco concentra carga significativa de processamento, é possível o escalar horizontalmente de maneira mais simples. Os riscos de vazamento de dados ficam restritos a falhas mais grosseiras de implementação.
A abordagem híbrida é, em geral, mais fácil de escalar e modelar que a estratégia multi-tenant pura, com dados e aplicação apartados.
Os custos associados podem ser maiores, ou não, dependendo do modelo de licenciamento, sobretudo do motor de banco de dados.
Qual a estratégia mais adequada?
A decisão sobre qual estratégia arquitetural adotar depende de vários fatores, porém entendemos como um bom ponto de partida garantir que estes 7 aspectos estejam sendo levados em consideração na sua análise:
- Políticas de segurança
- Nível de isolamento desejado dos dados;
- Nível de isolamento imposto pelas políticas de segurança dos seus clientes;
- Nível de isolamento imposto por regulações específicas do domínio
- Custo
- Custo admitido por cliente;
- Sensibilidade a custo no desenvolvimento e custo na operação;
- Especificidades do modelo de negócio
- Escalabilidade e Elasticidade
- Número de tenants;
- Banco de dados ou esquemas por tenant;
- Volume de dados e velocidade para aquisição de dados;
- Volume de requisições por tenant;
- Custo computacional por requisição do tenant tanto na aplicação quanto no banco
- Custo da mudança e custo da oportunidade
- Complexidade para evolução do software atual;
- Experiência do time para isolar regras de permissão de maneira eficiente e segura.
- Requisitos funcionais
- Necessidade de análise compartilhada tais como: relatórios de benchmarks comparando clientes; super usuários capazes de gerenciar várias empresas/clientes ao mesmo tempo.
- Operações
- Ferramentas, técnicas e práticas para monitoramento e observabilidade;
- Gerenciamento de performance da aplicação e bancos de dados;
- Manutenção de backups e recuperação de desastre;
- Tamanho do time de operações;
- Customização Necessidade de customização por cliente na aplicação e estrutura de banco.
De maneira geral, as soluções que ajudamos a desenvolver são híbridas.
Ótimo artigo, eu já arquitetei uma solução que usava arquitetura hibrida e deu muito certo no nosso cenário, ficou um bom custo benefício e não teve todos os riscos de uma solução puramente multi-tenant, é um bom meio termo.
Muito obrigado, Maicon. Legal ter compartilhado o feedback do seu cenário também.
Excelente artigo. Nossa experiência também coincide com o cenário híbrido sendo um sucesso nas nossas operações. Por aqui, em geral, tenants são separados em pools e colocados em bancos com isolamento apenas lógico. Aplicação compartilhada e escalada horizontalmente. Caso um tenant pertencente a um pool fique grande demais ou deseje planos com isolamento do banco, seus dados são separados para um banco exclusivo e o controlador de sharding sabe para qual banco isolado as requisições deste cliente devem ser direcionadas.
Também existe a opção de implantar mais uma camada de Protecao em bancos compartilhados através do isolamento de tenants por “predicados” de banco. O Sql server por exemplo tem funções para predicates por tabela, por exemplo, na tabela products a coluna de separação lógica pode ser tenant_id e toda query destinada a esta tabela o SQL automaticamente injetará um “and” para esta separação lógica sem que a aplicação precise se preocupar com este “and tenant_id=12345”.