Abordagens arquitetônicas para computação em soluções multilocatárias
A maioria das soluções baseadas em nuvem é composta por recursos de computação de algum tipo, como camadas da Web e de aplicativos, processadores em lote, trabalhos agendados e até mesmo recursos especializados, como GPUs e computação de alto desempenho (HPC). As soluções multilocatárias geralmente se beneficiam de recursos de computação compartilhados, porque uma maior densidade de locatários para a infraestrutura reduz o custo operacional e o gerenciamento. Você deve considerar os requisitos de isolamento e as implicações da infraestrutura compartilhada.
Este artigo fornece orientação sobre as considerações e os requisitos essenciais para os arquitetos de soluções considerarem ao planejar uma camada de computação multilocatário. Isso inclui alguns padrões comuns para aplicar multilocação a serviços de computação, juntamente com alguns antipadrões a serem evitados.
Principais considerações e requisitos
A multilocação e o modelo de isolamento selecionado afetam o dimensionamento, o desempenho, o gerenciamento de estado e a segurança dos recursos de computação. Nesta seção, analisamos algumas das principais decisões que você deve tomar ao planejar uma solução de computação multilocatário.
Escala
Os sistemas têm de funcionar adequadamente em função da evolução da procura. À medida que o número de inquilinos e a quantidade de tráfego aumentam, poderá ter de aumentar a capacidade dos seus recursos, acompanhar o número crescente de inquilinos e manter uma taxa de desempenho aceitável. Da mesma forma, quando o número de usuários ativos ou a quantidade de tráfego diminui, você deve reduzir automaticamente a capacidade de computação para reduzir custos, mas deve reduzir a capacidade com impacto mínimo para os usuários.
Se você implantar recursos dedicados para cada locatário, terá a flexibilidade de dimensionar os recursos de cada locatário de forma independente. Em uma solução em que os recursos de computação são compartilhados entre vários locatários, se você dimensionar esses recursos, todos esses locatários poderão usar a nova escala. No entanto, todos eles também sofrerão quando a balança for insuficiente para lidar com a sua carga total. Para obter mais informações, consulte o problema do vizinho barulhento.
Ao criar soluções em nuvem, você pode escolher se deseja dimensionar horizontal ou verticalmente. Em uma solução multilocatária com um número crescente de locatários, o dimensionamento horizontal normalmente oferece maior flexibilidade e um teto de escala geral mais alto.
Os problemas de desempenho geralmente não são detetados até que um aplicativo esteja sob carga. Você pode usar um serviço totalmente gerenciado, como o Teste de Carga do Azure, para saber como seu aplicativo se comporta sob estresse.
Gatilhos de escala
Seja qual for a abordagem usada para dimensionar, normalmente você precisa planejar os gatilhos que fazem com que seus componentes sejam dimensionados. Quando você tiver componentes compartilhados, considere os padrões de carga de trabalho de cada locatário que usa os recursos, a fim de garantir que sua capacidade provisionada possa atender à capacidade total necessária e minimizar a chance de um locatário enfrentar o problema do vizinho barulhento. Você também pode planejar sua capacidade de dimensionamento considerando o número de locatários. Por exemplo, se você medir os recursos que usa para atender 100 locatários, à medida que integrar mais locatários, poderá planejar a escala de modo que seus recursos dupliquem para cada 100 locatários adicionais.
Estado
Os recursos de computação podem ser sem monitoração de estado ou com monitoração de estado. Os componentes sem estado não mantêm dados entre solicitações. De uma perspetiva de escalabilidade, os componentes sem monitoração de estado geralmente são fáceis de dimensionar porque você pode adicionar rapidamente novos trabalhadores, instâncias ou nós, e eles podem começar imediatamente a processar solicitações. Se sua arquitetura permitir, você também poderá redefinir o propósito de instâncias atribuídas a um locatário e alocá-las a outro locatário.
Os recursos estatais podem ainda ser subdivididos, com base no tipo de estado que mantêm. Estado persistente são dados que precisam ser armazenados permanentemente. Em soluções de nuvem, você deve evitar armazenar um estado persistente em sua camada de computação. Em vez disso, use serviços de armazenamento, como bancos de dados ou contas de armazenamento. O estado transitório são dados armazenados temporariamente e inclui caches na memória somente leitura e o armazenamento de arquivos temporários em discos locais.
O estado transitório geralmente é útil para melhorar o desempenho da camada de aplicativos, reduzindo o número de solicitações para serviços de armazenamento de back-end. Por exemplo, quando você usa um cache na memória, pode ser capaz de atender a solicitações de leitura, sem se conectar a um banco de dados e sem executar uma consulta intensiva que você executou recentemente quando atendeu outra solicitação.
Em aplicativos sensíveis à latência, o custo da hidratação do cache pode se tornar significativo. Uma solução multilocatária pode exacerbar esse problema, se cada locatário exigir que dados diferentes sejam armazenados em cache. Para atenuar esse problema, algumas soluções usam afinidade de sessão para garantir que todas as solicitações para um usuário ou locatário específico sejam processadas pelo mesmo nó de trabalho de computação. Embora a afinidade de sessão possa melhorar a capacidade da camada de aplicativo de usar seu cache de forma eficaz, ela também dificulta o dimensionamento e o equilíbrio da carga de tráfego entre os trabalhadores. Este compromisso tem de ser cuidadosamente considerado. Para muitos aplicativos, a afinidade de sessão não é necessária.
Também é possível armazenar dados em caches externos, como o Cache do Azure para Redis. Os caches externos são otimizados para recuperação de dados de baixa latência, mantendo o estado isolado dos recursos de computação, para que possam ser dimensionados e gerenciados separadamente. Em muitas soluções, os caches externos permitem melhorar o desempenho do aplicativo, enquanto você mantém a camada de computação sem monitoração de estado.
Importante
Evite vazar dados entre locatários, sempre que usar caches na memória ou outros componentes que mantenham o estado. Por exemplo, considere antecipar um identificador de locatário a todas as chaves de cache, para garantir que os dados sejam separados para cada locatário.
Isolamento
Ao projetar uma camada de computação multilocatário, você geralmente tem muitas opções a considerar para o nível de isolamento entre locatários, incluindo a implantação de recursos de computação compartilhados, a serem usados por todos os locatários, recursos de computação dedicados para cada locatário ou algo entre esses extremos. Cada opção vem com compensações. Para ajudá-lo a decidir qual opção se adequa melhor à sua solução, considere seus requisitos de isolamento.
Você pode estar preocupado com o isolamento lógico dos locatários e como separar as responsabilidades ou políticas de gerenciamento que são aplicadas a cada locatário. Como alternativa, talvez seja necessário implantar configurações de recursos distintas para locatários específicos, como implantar uma SKU de máquina virtual específica para se adequar à carga de trabalho de um locatário.
Seja qual for o modelo de isolamento selecionado, certifique-se de verificar se os dados do locatário permanecem adequadamente isolados, mesmo quando os componentes estão indisponíveis ou funcionando mal. Considere usar o Azure Chaos Studio como parte de seu processo de teste automatizado regular para introduzir deliberadamente falhas que simulam interrupções do mundo real e verificar se sua solução não vaza dados entre locatários e está funcionando corretamente, mesmo sob pressão.
Abordagens e padrões a considerar
Dimensionamento Automático
Os serviços de computação do Azure fornecem diferentes recursos para dimensionar suas cargas de trabalho. Muitos serviços de computação suportam dimensionamento automático, o que exige que você considere quando deve dimensionar e seus níveis mínimo e máximo de escala. As opções específicas disponíveis para dimensionamento dependem dos serviços de computação que você usa. Veja os seguintes exemplos de serviços:
- Serviço de Aplicativo do Azure: especifique regras de dimensionamento automático que dimensionam sua infraestrutura, com base em suas necessidades.
- Azure Functions: selecione entre várias opções de escala, incluindo um modelo de dimensionamento controlado por eventos que é dimensionado automaticamente, com base no trabalho que suas funções executam.
- Aplicativos de Contêiner do Azure: use o dimensionamento automático controlado por eventos para dimensionar seu aplicativo, com base no trabalho que ele executa e em sua carga atual.
- Serviço Kubernetes do Azure (AKS): para acompanhar as demandas do seu aplicativo, talvez seja necessário ajustar o número de nós que executam suas cargas de trabalho. Além disso, para dimensionar rapidamente cargas de trabalho de aplicativos em um cluster AKS, você pode usar nós virtuais.
- Máquinas virtuais: um conjunto de dimensionamento de máquina virtual pode aumentar ou diminuir automaticamente o número de instâncias de VM que executam seu aplicativo.
Padrão de selos de implantação
Para obter mais informações sobre como o padrão de Carimbos de Implantação pode ser usado para dar suporte a uma solução multilocatário, consulte Visão geral.
Padrão de Consolidação de Recursos de Computação
O padrão de Consolidação de Recursos de Computação ajuda a obter uma maior densidade de locatários para a infraestrutura de computação, compartilhando os recursos de computação subjacentes. Ao compartilhar recursos de computação, muitas vezes você pode reduzir o custo direto desses recursos. Além disso, os custos de gerenciamento geralmente são mais baixos porque há menos componentes para gerenciar.
No entanto, a consolidação de recursos de computação aumenta a probabilidade do problema do vizinho barulhento. A carga de trabalho de qualquer locatário pode consumir uma quantidade desproporcional da capacidade de computação disponível. Muitas vezes, você pode reduzir esse risco garantindo que dimensiona sua solução adequadamente e aplicando controles como cotas e limites de API, para evitar locatários que consomem mais do que sua parte justa da capacidade.
Esse padrão é alcançado de maneiras diferentes, dependendo do serviço de computação que você usa. Veja os seguintes exemplos de serviços:
- Serviço de Aplicativo do Azure e Azure Functions: implante planos compartilhados do Serviço de Aplicativo, que representam a infraestrutura do servidor de hospedagem.
- Azure Container Apps: implante ambientes compartilhados.
- Serviço Kubernetes do Azure (AKS): implante pods compartilhados, com um aplicativo com reconhecimento de multilocação.
- Máquinas virtuais: implante um único conjunto de máquinas virtuais para todos os locatários usarem.
Recursos de computação dedicados por locatário
Você também pode implantar recursos de computação dedicados para cada locatário. Os recursos dedicados reduzem o risco do problema do vizinho barulhento, garantindo que os recursos de computação de cada locatário sejam isolados dos outros. Ele também permite que você implante uma configuração distinta para os recursos de cada locatário, com base em seus requisitos. No entanto, os recursos dedicados normalmente vêm com um custo mais alto, porque você tem uma densidade menor de locatários para recursos.
Dependendo dos serviços de computação do Azure que você usa, você precisa implantar diferentes recursos dedicados, da seguinte maneira:
- Serviço de Aplicativo do Azure e Azure Functions: implante planos separados do Serviço de Aplicativo para cada locatário.
- Aplicativos de Contêiner do Azure: implante ambientes separados para cada locatário.
- Serviço Kubernetes do Azure (AKS): implante clusters dedicados para cada locatário.
- Máquinas virtuais: implante máquinas virtuais dedicadas para cada locatário.
Recursos de computação semi-isolados
As abordagens semi-isoladas exigem que você implante aspetos da solução em uma configuração isolada, enquanto compartilha os outros componentes.
Ao trabalhar com o Serviço de Aplicativo e o Azure Functions, você pode implantar aplicativos distintos para cada locatário e pode hospedar os aplicativos em planos compartilhados do Serviço de Aplicativo. Essa abordagem reduz o custo da sua camada de computação, porque os planos do Serviço de Aplicativo representam a unidade de cobrança. Ele também permite que você aplique configurações e políticas distintas para cada aplicativo. No entanto, esta abordagem introduz o risco do problema do vizinho barulhento.
Os Aplicativos de Contêiner do Azure permitem implantar vários aplicativos em um ambiente compartilhado e, em seguida, usar o Dapr e outras ferramentas para configurar cada aplicativo separadamente.
O Serviço Kubernetes do Azure (AKS) e o Kubernetes de forma mais ampla fornecem uma variedade de opções para multilocação, incluindo o seguinte:
- Namespaces específicos do locatário, para isolamento lógico de recursos específicos do locatário, que são implantados em clusters compartilhados e pools de nós.
- Nós específicos do locatário ou pools de nós em um cluster compartilhado.
- Pods específicos do locatário que podem usar o mesmo pool de nós.
O AKS também permite que você aplique governança no nível do pod para mitigar o problema do vizinho barulhento. Para obter mais informações, consulte Práticas recomendadas para desenvolvedores de aplicativos gerenciarem recursos no Serviço Kubernetes do Azure (AKS).
Também é importante estar ciente dos componentes compartilhados em um cluster do Kubernetes e como esses componentes podem ser afetados pela multilocação. Por exemplo, o servidor de API do Kubernetes é um serviço compartilhado que é usado em todo o cluster. Mesmo que você forneça pools de nós específicos do locatário para isolar as cargas de trabalho do aplicativo dos locatários, o servidor de API poderá enfrentar contenção de um grande número de solicitações entre os locatários.
Antipadrões a evitar
Antipadrão de vizinho barulhento
Sempre que você implanta componentes que são compartilhados entre locatários, o problema do vizinho barulhento é um risco potencial. Certifique-se de incluir a governança e o monitoramento de recursos para reduzir o risco de a carga de trabalho de computação de um locatário ser afetada pela atividade de outros locatários.
Fuga de dados entre inquilinos
As camadas de computação podem estar sujeitas a vazamento de dados entre locatários, se não forem tratadas corretamente. Isso geralmente não é algo que você precisa considerar quando estiver usando um serviço multilocatário no Azure, porque a Microsoft fornece proteções na camada de plataforma. No entanto, ao desenvolver seu próprio aplicativo multilocatário, considere se quaisquer recursos compartilhados (como caches de disco local, RAM e caches externos) podem conter dados que outro locatário pode exibir ou modificar inadvertidamente.
Antipadrão Front-end ocupado
Para evitar o antipadrão de Front-End Ocupado, evite que sua camada de front-end faça muito do trabalho que poderia ser manipulado por outros componentes ou camadas de sua arquitetura. Esse antipadrão é particularmente importante quando você cria front-ends compartilhados para uma solução multilocatário, porque um front-end ocupado degradará a experiência de todos os locatários.
Em vez disso, considere o uso de processamento assíncrono usando filas ou outros serviços de mensagens. Essa abordagem também permite que você aplique controles de qualidade de serviço (QoS) para diferentes locatários, com base em suas necessidades. Por exemplo, todos os locatários podem compartilhar uma camada de front-end comum, mas os locatários que pagam por um nível de serviço mais alto podem ter um conjunto maior de recursos dedicados para processar o trabalho a partir de suas mensagens de fila.
Dimensionamento inelástico ou insuficiente
As soluções multilocatárias geralmente estão sujeitas a padrões de escala bursty. Os componentes compartilhados são particularmente suscetíveis a esse problema, porque o escopo para burst é maior e o impacto é maior quando você tem mais locatários com padrões de uso distintos.
Certifique-se de fazer bom uso da elasticidade e da escala da nuvem. Considere se você deve usar o dimensionamento horizontal ou vertical e o dimensionamento automático para lidar automaticamente com picos de carga. Teste sua solução para entender como ela se comporta sob diferentes níveis de carga. Certifique-se de incluir os volumes de carga esperados na produção e o crescimento esperado. Você pode usar um serviço totalmente gerenciado, como o Teste de Carga do Azure, para saber como seu aplicativo se comporta sob estresse.
Anti-padrão Sem Colocação em Cache
O antipadrão Sem Cache é quando o desempenho da sua solução é prejudicado porque a camada de aplicativo solicita ou recalcula repetidamente informações que podem ser reutilizadas entre solicitações. Se você tiver dados que podem ser compartilhados, seja entre locatários ou entre usuários dentro de um único locatário, provavelmente vale a pena armazená-los em cache para reduzir a carga em sua camada de back-end/banco de dados.
Estado desnecessário
O corolário do antipadrão Sem Cache é que você também deve evitar armazenar estado desnecessário em sua camada de computação. Seja explícito sobre onde você mantém o estado e por quê. As camadas de front-end ou aplicativo com monitoração de estado podem reduzir sua capacidade de escala. As camadas de computação com estado normalmente também exigem afinidade de sessão, o que pode reduzir sua capacidade de balancear efetivamente a carga do tráfego, entre trabalhadores ou nós.
Considere as compensações para cada parte do estado que você mantém em sua camada de computação e se isso afeta sua capacidade de dimensionar ou crescer à medida que os padrões de carga de trabalho dos locatários mudam. Você também pode armazenar o estado em um cache externo, como o Cache do Azure para Redis.
Contribuidores
Este artigo é mantido pela Microsoft. Foi originalmente escrito pelos seguintes contribuidores.
Principais autores:
- Dixit Arora - Brasil | Engenheiro de Clientes Sênior, FastTrack for Azure
- John Downs - Brasil | Engenheiro de Software Principal
Outros contribuidores:
- Arsen Vladimirskiy - Brasil | Engenheiro de Clientes Principal, FastTrack for Azure
Próximos passos
Analise as orientações específicas do serviço para seus serviços de computação: