Conceção para recuperação automática
Criar a sua aplicação de forma a recuperar-se automaticamente quando ocorrem falhas
Em um sistema distribuído, é de se esperar que as falhas aconteçam. O hardware pode falhar. A rede pode sofrer falhas temporárias. Raramente um serviço inteiro, data center ou até mesmo uma região do Azure sofrerá uma interrupção, no entanto, mesmo esses devem ser projetados para sua arquitetura de carga de trabalho. A resiliência e a recuperação devem ser abordadas no início do projeto da carga de trabalho.
Portanto, projete um aplicativo que seja auto-recuperável quando ocorrerem falhas. Isto requer uma abordagem tripla:
- Detetar falhas.
- Responder a falhas corretamente.
- Registre e monitore falhas para fornecer informações operacionais.
A forma como você responde a um tipo específico de falha depende dos requisitos de disponibilidade do seu aplicativo. Por exemplo, se você precisar de alta disponibilidade, poderá implantar em várias zonas de disponibilidade em uma região. Para evitar interrupções, mesmo no caso improvável de uma região inteira do Azure sofrer interrupções, você pode fazer failover automaticamente para uma região secundária durante uma interrupção regional. No entanto, isso incorrerá em um custo mais alto e um desempenho potencialmente menor do que uma implantação de uma única região.
Além disso, não considere apenas grandes eventos como falhas regionais, que são geralmente raras. Deve focar-se tanto, se não mais, no processamento de falhas locais de curta duração, como falhas de conectividade de rede ou ligações falhadas de base de dados.
Recomendações
Use componentes dissociados que se comunicam de forma assíncrona. Idealmente, os componentes são dissociados em termos de tempo e espaço. Dissociados no tempo significa que os componentes não precisam estar presentes ao mesmo tempo para que a comunicação seja possível. Desacoplado no espaço significa que o emissor e o recetor não precisam correr no mesmo processo, mas podem onde for mais eficiente. Idealmente, os componentes dissociados usam eventos para se comunicar uns com os outros. Isso ajuda a minimizar a chance de falhas em cascata.
Repita as operações com falhas. Falhas transitórias podem ocorrer devido à perda momentânea de conectividade de rede, uma conexão de banco de dados interrompida ou um tempo limite quando um serviço está ocupado. Incorpore uma lógica de repetição na aplicação para processar falhas transitórias. Para vários serviços do Azure, o SDK de cliente implementa tentativas automáticas. Para obter mais informações, consulte Tratamento de falhas transitórias e o padrão Repetir.
Proteja os serviços remotos com falhas (Disjuntor Automático). É boa prática repetir após uma falha transitória, mas se a falha persistir, pode acabar por ficar com demasiados autores de chamadas a insistir num serviço com falhas. Isso pode levar a falhas em cascata à medida que as solicitações fazem backup. Use o padrão Disjuntor para falhar rapidamente (sem fazer a chamada remota) quando uma operação provavelmente falhará.
Isole os recursos críticos (Bulkhead). Por vezes, as falhas num subsistema podem propagar-se. Isso pode acontecer se uma falha fizer com que alguns recursos, como threads ou soquetes, não sejam liberados em tempo hábil, levando ao esgotamento dos recursos. Para evitar isso, use o padrão Bulkhead para particionar um sistema em grupos isolados para que uma falha em uma partição não derrube todo o sistema.
Efetue o nivelamento de carga. Os aplicativos podem enfrentar picos repentinos de tráfego que podem sobrecarregar os serviços no back-end. Para evitar isso, use o padrão de Nivelamento de Carga Baseado em Fila para enfileirar itens de trabalho para execução assíncrona. A fila funciona como uma memória intermédia que suaviza os picos da carga.
Efetue a ativação pós-falha. Se não for possível aceder uma instância, efetue a ativação pós-falha para outra instância. Para recursos sem estado, como um servidor Web, coloque várias instâncias por trás de um balanceador de carga ou gestor de tráfego. Para recursos que armazenam o estado, como uma base de dados, utilize réplicas e efetue a ativação pós-falha. Dependendo do armazenamento de dados e de como ele é replicado, o aplicativo pode ter que lidar com uma eventual consistência.
Compense transações falhadas. Em geral, evite transações distribuídas, pois requerem a coordenação em serviços e recursos. Em vez disso, componha uma operação de transações individuais mais pequenas. Se a operação falhar a meio, utilize Transações de Compensação para anular qualquer passo que já tiver sido concluído.
Utilize pontos de verificação para transações de longa duração. Os pontos de verificação podem fornecer resiliência se uma operação de longa duração falhar. Quando a operação reiniciar (por exemplo, é recolhida por outra VM), pode ser retomada a partir do último ponto de verificação. Considere a implementação de um mecanismo que registre informações de estado sobre a tarefa em intervalos regulares e salve esse estado em armazenamento durável que pode ser acessado por qualquer instância do processo que executa a tarefa. Dessa forma, se o processo for encerrado, o trabalho que ele estava executando pode ser retomado a partir do último ponto de verificação usando outra instância. Existem bibliotecas que fornecem essa funcionalidade, como NServiceBus e MassTransit. Eles persistem de forma transparente, onde os intervalos são alinhados com o processamento de mensagens de filas no Barramento de Serviço do Azure.
Degrade-se graciosamente e permaneça responsivo durante falhas. Por vezes, não é possível resolver um problema, mas pode fornecer funcionalidade reduzida, que é útil. Considere uma aplicação que mostra um catálogo de livros. Se a aplicação não conseguir obter a imagem em miniatura da capa, poderá mostrar uma imagem de marcador de posição. Subsistemas completos poderão não ser críticos para a aplicação. Por exemplo, em um site de comércio eletrônico, mostrar recomendações de produtos é provavelmente menos crítico do que processar pedidos.
Limite os clientes. Por vezes, um pequeno número de utilizadores cria uma carga excessiva, o que poderá reduzir a disponibilidade da aplicação para outros utilizadores. Nesta situação, limite o cliente para um determinado período de tempo. Consulte o padrão de limitação.
Bloqueie as pessoas mal-intencionadas. Limitar um cliente não implica que este não aja maliciosamente. Só significa que o cliente excedeu a respetiva quota de serviço. Mas, se um cliente exceder constantemente a sua quota ou se comportar incorretamente, pode bloqueá-lo. Defina um processo fora de banda para que o utilizador solicite o desbloqueio.
Utilize a eleição de coordenador. Quando precisar de coordenar uma tarefa, utilize a Eleição de Coordenador para selecionar um coordenador. Dessa forma, o coordenador não é um ponto único de falha. Se o coordenador falhar, é selecionado um novo. Em vez de implementar um algoritmo de eleição de coordenador do zero, considere uma solução pronta a utilizar, como o Zookeeper.
Teste com a inserção de falhas. Com muita frequência, o caminho para o sucesso é bem testado, mas o caminho para o fracasso não o é. Um sistema pode ser executado em produção por um longo período de tempo antes de o caminho para o fracasso ser executado. Utilize a inserção de falhas para testar a resiliência do sistema a falhas, ao acionar falhas reais ou simulando-las.
Adote a engenharia do caos. A engenharia do caos amplia a noção de injeção de falhas injetando aleatoriamente falhas ou condições anormais em instâncias de produção.
Use zonas de disponibilidade. Muitas regiões do Azure fornecem zonas de disponibilidade, que são conjuntos isolados de data centers dentro da região. Alguns serviços do Azure podem ser implantados zonalmente, o que garante que eles sejam colocados em uma zona específica e pode ajudar a reduzir a latência na comunicação entre componentes na mesma carga de trabalho. Como alternativa, alguns serviços podem ser implantados com redundância de zona, o que significa que o Azure replica automaticamente o recurso entre zonas para alta disponibilidade. Considere qual abordagem fornece o melhor conjunto de compensações para sua solução. Para saber mais sobre como projetar sua solução para usar zonas e regiões de disponibilidade, consulte Recomendações para usar zonas e regiões de disponibilidade.
Para obter uma abordagem estruturada para tornar seus aplicativos auto-recuperáveis, consulte Criar aplicativos confiáveis para o Azure.