Partilhar via


Resiliência da plataforma Azure

Gorjeta

Este conteúdo é um excerto do eBook, Architecting Cloud Native .NET Applications for Azure, disponível no .NET Docs ou como um PDF transferível gratuito que pode ser lido offline.

Miniatura da capa dos aplicativos .NET nativos da nuvem para eBook do Azure.

Criar um aplicativo confiável na nuvem é diferente do desenvolvimento tradicional de aplicativos locais. Embora historicamente você tenha comprado hardware mais avançado para aumentar a escala, em um ambiente de nuvem você expande. Em vez de tentar evitar falhas, o objetivo é minimizar seus efeitos e manter o sistema estável.

Dito isto, as aplicações na nuvem fiáveis apresentam características distintas:

  • São resilientes, recuperam graciosamente dos problemas e continuam a funcionar.
  • Eles são altamente disponíveis (HA) e funcionam conforme projetado em um estado saudável sem tempo de inatividade significativo.

Entender como essas características funcionam juntas - e como elas afetam o custo - é essencial para criar um aplicativo nativo da nuvem confiável. Em seguida, veremos maneiras de criar resiliência e disponibilidade em seus aplicativos nativos da nuvem aproveitando os recursos da nuvem do Azure.

Design com resiliência

Dissemos que a resiliência permite que seu aplicativo reaja a falhas e ainda permaneça funcional. O whitepaper, Resiliência no Azure, fornece orientação para alcançar resiliência na plataforma Azure. Eis algumas recomendações-chave:

  • Falha de hardware. Crie redundância no aplicativo implantando componentes em diferentes domínios de falha. Por exemplo, certifique-se de que as VMs do Azure sejam colocadas em racks diferentes usando Conjuntos de Disponibilidade.

  • Falha do datacenter. Crie redundância no aplicativo com zonas de isolamento de falhas em datacenters. Por exemplo, certifique-se de que as VMs do Azure sejam colocadas em diferentes datacenters isolados por falhas usando as Zonas de Disponibilidade do Azure.

  • Fracasso regional. Replique os dados e componentes em outra região para que os aplicativos possam ser recuperados rapidamente. Por exemplo, use o Azure Site Recovery para replicar VMs do Azure para outra região do Azure.

  • Carga pesada. Balanceamento de carga entre instâncias para lidar com picos de uso. Por exemplo, coloque duas ou mais VMs do Azure atrás de um balanceador de carga para distribuir o tráfego para todas as VMs.

  • Exclusão acidental de dados ou corrupção. Faça backup dos dados para que possam ser restaurados se houver alguma exclusão ou corrupção. Por exemplo, use o Backup do Azure para fazer backup periódico de suas VMs do Azure.

Design com redundância

As falhas variam em termos de âmbito de impacto. Uma falha de hardware, como um disco com falha, pode afetar um único nó em um cluster. Uma falha no switch de rede pode afetar um rack de servidor inteiro. Falhas menos comuns, como perda de energia, podem interromper todo um datacenter. Raramente, uma região inteira fica indisponível.

A redundância é uma maneira de fornecer resiliência de aplicativos. O nível exato de redundância necessário depende dos requisitos de negócios e afetará o custo e a complexidade do sistema. Por exemplo, uma implantação de várias regiões é mais cara e mais complexa de gerenciar do que uma implantação de região única. Você precisará de procedimentos operacionais para gerenciar failover e failback. O custo adicional e a complexidade podem ser justificados para alguns cenários de negócios, mas não para outros.

Para arquitetar redundância, você precisa identificar os caminhos críticos em seu aplicativo e, em seguida, determinar se há redundância em cada ponto do caminho? Se um subsistema falhar, o aplicativo fará failover para outra coisa? Por fim, você precisa de uma compreensão clara dos recursos incorporados à plataforma de nuvem do Azure que você pode aproveitar para atender aos seus requisitos de redundância. Aqui estão recomendações para arquitetar redundância:

  • Implante várias instâncias de serviços. Se seu aplicativo depende de uma única instância de um serviço, ele cria um único ponto de falha. O provisionamento de várias instâncias melhora a resiliência e a escalabilidade. Ao hospedar no Serviço Kubernetes do Azure, você pode configurar declarativamente instâncias redundantes (conjuntos de réplicas) no arquivo de manifesto do Kubernetes. O valor da contagem de réplicas pode ser gerenciado programaticamente, no portal ou por meio de recursos de dimensionamento automático.

  • Alavancagem de um balanceador de carga. O balanceamento de carga distribui as solicitações do aplicativo para instâncias de serviço íntegras e remove automaticamente as instâncias não íntegras da rotação. Ao implantar no Kubernetes, o balanceamento de carga pode ser especificado no arquivo de manifesto do Kubernetes na seção Serviços.

  • Planeje a implantação em várias regiões. Se você implantar seu aplicativo em uma única região e essa região ficar indisponível, seu aplicativo também ficará indisponível. Isso pode ser inaceitável sob os termos dos contratos de nível de serviço do seu aplicativo. Em vez disso, considere implantar seu aplicativo e seus serviços em várias regiões. Por exemplo, um cluster do Serviço Kubernetes do Azure (AKS) é implantado em uma única região. Para proteger seu sistema de uma falha regional, você pode implantar seu aplicativo em vários clusters AKS em diferentes regiões e usar o recurso Regiões Emparelhadas para coordenar atualizações de plataforma e priorizar os esforços de recuperação.

  • Habilite a replicação geográfica. A replicação geográfica para serviços como o Banco de Dados SQL do Azure e o Cosmos DB criará réplicas secundárias de seus dados em várias regiões. Embora ambos os serviços repliquem automaticamente os dados dentro da mesma região, a replicação geográfica protege contra uma interrupção regional, permitindo que você faça failover para uma região secundária. Outra prática recomendada para replicação geográfica centra-se no armazenamento de imagens de contêiner. Para implantar um serviço no AKS, você precisa armazenar e extrair a imagem de um repositório. O Azure Container Registry integra-se com o AKS e pode armazenar imagens de contêiner com segurança. Para melhorar o desempenho e a disponibilidade, considere replicar geograficamente suas imagens para um registro em cada região onde você tem um cluster AKS. Em seguida, cada cluster AKS extrai imagens de contêiner do registro de contêiner local em sua região, como mostra a Figura 6-4:

Recursos replicados entre regiões

Figura 6-4. Recursos replicados entre regiões

  • Implemente um balanceador de carga de tráfego DNS.O Azure Traffic Manager fornece alta disponibilidade para aplicativos críticos por meio do balanceamento de carga no nível DNS. Ele pode rotear o tráfego para diferentes regiões com base na geografia, no tempo de resposta do cluster e até mesmo na integridade do ponto de extremidade do aplicativo. Por exemplo, o Azure Traffic Manager pode direcionar os clientes para o cluster AKS e a instância de aplicativo mais próximos. Se você tiver vários clusters AKS em regiões diferentes, use o Gerenciador de Tráfego para controlar como o tráfego flui para os aplicativos executados em cada cluster. A Figura 6-5 mostra esse cenário.

AKS e Azure Traffic Manager

Figura 6-5. AKS e Azure Traffic Manager

Design para escalabilidade

A nuvem prospera com o dimensionamento. A capacidade de aumentar/diminuir os recursos do sistema para lidar com o aumento/diminuição da carga do sistema é um princípio fundamental da nuvem do Azure. Mas, para dimensionar efetivamente um aplicativo, você precisa entender os recursos de dimensionamento de cada serviço do Azure que você inclui em seu aplicativo. Aqui estão recomendações para implementar efetivamente o dimensionamento em seu sistema.

  • Design para dimensionamento. Um aplicativo deve ser projetado para dimensionamento. Para começar, os serviços devem ser sem monitoração de estado para que as solicitações possam ser roteadas para qualquer instância. Ter serviços sem estado também significa que adicionar ou remover uma instância não afeta negativamente os usuários atuais.

  • Particionar cargas de trabalho. A decomposição de domínios em microsserviços independentes e independentes permite que cada serviço seja dimensionado independentemente dos outros. Normalmente, os serviços terão necessidades e requisitos de escalabilidade diferentes. O particionamento permite dimensionar apenas o que precisa ser dimensionado sem o custo desnecessário de dimensionar um aplicativo inteiro.

  • Favoreça o scale-out. Os aplicativos baseados em nuvem favorecem a expansão de recursos em vez da expansão. A expansão (também conhecida como dimensionamento horizontal) envolve a adição de mais recursos de serviço a um sistema existente para atender e compartilhar um nível desejado de desempenho. A expansão (também conhecida como dimensionamento vertical) envolve a substituição de recursos existentes por hardware mais poderoso (mais disco, memória e núcleos de processamento). A expansão pode ser invocada automaticamente com os recursos de dimensionamento automático disponíveis em alguns recursos de nuvem do Azure. A expansão em vários recursos também adiciona redundância ao sistema geral. Finalmente, a expansão de um único recurso é normalmente mais cara do que a expansão em muitos recursos menores. A Figura 6-6 mostra as duas abordagens:

Aumentar a escala versus reduzir a escala

Figura 6-6. Aumentar a escala versus reduzir a escala

  • Escala proporcional. Ao dimensionar um serviço, pense em termos de conjuntos de recursos. Se você expandisse drasticamente um serviço específico, que impacto isso teria nos armazenamentos de dados back-end, caches e serviços dependentes? Alguns recursos, como o Cosmos DB, podem ser dimensionados proporcionalmente, enquanto muitos outros não. Você deseja garantir que não dimensione um recurso até um ponto em que ele esgote outros recursos associados.

  • Evite a afinidade. Uma prática recomendada é garantir que um nó não exija afinidade local, muitas vezes chamada de sessão pegajosa. Um pedido deve poder ser encaminhado para qualquer instância. Se você precisar persistir o estado, ele deve ser salvo em um cache distribuído, como o cache Redis do Azure.

  • Aproveite os recursos de dimensionamento automático da plataforma. Use recursos internos de dimensionamento automático sempre que possível, em vez de mecanismos personalizados ou de terceiros. Sempre que possível, use regras de dimensionamento agendado para garantir que os recursos estejam disponíveis sem um atraso de inicialização, mas adicione o dimensionamento automático reativo às regras, conforme apropriado, para lidar com mudanças inesperadas na demanda. Para obter mais informações, consulte Diretrizes de dimensionamento automático.

  • Dimensione agressivamente. Uma prática final seria escalar agressivamente para que você possa atender rapidamente aos picos imediatos de tráfego sem perder negócios. E, em seguida, dimensionar (ou seja, remover instâncias desnecessárias) de forma conservadora para manter o sistema estável. Uma maneira simples de implementar isso é definir o período de resfriamento, que é o tempo de espera entre as operações de dimensionamento, para cinco minutos para adicionar recursos e até 15 minutos para remover instâncias.

Repetição integrada em serviços

Incentivamos as melhores práticas de implementação de operações de repetição programática em uma seção anterior. Lembre-se de que muitos serviços do Azure e seus SDKs de cliente correspondentes também incluem mecanismos de repetição. A lista a seguir resume os recursos de repetição em muitos dos serviços do Azure discutidos neste livro:

  • Azure Cosmos DB. A classe DocumentClient da API do cliente tenta automaticamente novas tentativas com falha. O número de novas tentativas e o tempo máximo de espera são configuráveis. As exceções lançadas pela API do cliente são solicitações que excedem a política de repetição ou erros não transitórios.

  • Cache Redis do Azure. O cliente Redis StackExchange usa uma classe de gerenciador de conexões que inclui novas tentativas em tentativas com falha. O número de tentativas, a política de repetição específica e o tempo de espera são configuráveis.

  • Barramento de Serviço do Azure. O cliente do Service Bus expõe uma classe RetryPolicy que pode ser configurada com um intervalo de back-off, contagem de repetições e TerminationTimeBuffer, que especifica o tempo máximo que uma operação pode levar. A política padrão é de nove tentativas máximas com um período de backoff de 30 segundos entre as tentativas.

  • Base de Dados SQL do Azure. O suporte a novas tentativas é fornecido ao usar a biblioteca principal do Entity Framework.

  • Armazenamento do Azure. A biblioteca do cliente de armazenamento suporta operações de nova tentativa. As estratégias variam entre tabelas, blobs e filas de armazenamento do Azure. Além disso, as novas tentativas alternativas alternam entre os locais dos serviços de armazenamento primário e secundário quando o recurso de redundância geográfica está habilitado.

  • Hubs de Eventos do Azure. A biblioteca de cliente do Hub de Eventos apresenta uma propriedade RetryPolicy, que inclui um recurso de backoff exponencial configurável.