Share via


Estrutura da aplicação de cargas de trabalho críticas para a missão no Azure

Quando cria uma aplicação, os requisitos de aplicações funcionais e não funcionais são fundamentais. Esta área de design descreve padrões de arquitetura e estratégias de dimensionamento que podem ajudar a tornar a sua aplicação resiliente a falhas.

Importante

Este artigo faz parte da série de cargas de trabalho críticas para a missão do Azure Well-Architected Framework . Se não estiver familiarizado com esta série, recomendamos que comece com O que é uma carga de trabalho crítica para a missão?.

Arquitetura de unidades de escala

Todos os aspetos funcionais de uma solução têm de ser capazes de dimensionar para satisfazer as alterações na procura. Recomendamos que utilize uma arquitetura de unidades de escala para otimizar a escalabilidade ponto a ponto através da compartimentação e também para uniformizar o processo de adição e remoção da capacidade. Uma unidade de dimensionamento é uma unidade ou função lógica que pode ser dimensionada de forma independente. Uma unidade pode ser constituída por componentes de código, plataformas de alojamento de aplicações, selos de implementação que abrangem os componentes relacionados e até subscrições para suportar requisitos multi-inquilinos.

Recomendamos esta abordagem porque aborda os limites de dimensionamento de recursos individuais e toda a aplicação. Ajuda com cenários complexos de implementação e atualização, uma vez que uma unidade de escala pode ser implementada como uma unidade. Além disso, pode testar e validar versões específicas de componentes numa unidade antes de direcionar o tráfego do utilizador para o mesmo.

Suponha que a sua aplicação crítica para a missão é um catálogo de produtos online. Tem um fluxo de utilizador para processar comentários e classificações de produtos. O fluxo utiliza APIs para obter e publicar comentários e classificações e componentes de suporte, como um ponto final OAuth, arquivo de dados e filas de mensagens. Os pontos finais da API sem estado representam unidades funcionais granulares que têm de se adaptar às alterações a pedido. A plataforma de aplicações subjacente também tem de ser capaz de dimensionar em conformidade. Para evitar estrangulamentos de desempenho, os componentes a jusante e as dependências também têm de ser dimensionados para um nível adequado. Podem dimensionar de forma independente, como unidades de escala separadas ou em conjunto, como parte de uma única unidade lógica.

Unidades de dimensionamento de exemplo

A imagem seguinte mostra os âmbitos possíveis para unidades de dimensionamento. Os âmbitos vão desde pods de microsserviços a nós de cluster e selos de implementação regionais.

Diagrama que mostra vários âmbitos para unidades de escala.

Considerações de design

  • Âmbito. O âmbito de uma unidade de dimensionamento, a relação entre unidades de escala e os respetivos componentes devem ser definidos de acordo com um modelo de capacidade. Tenha em consideração os requisitos não funcionais para o desempenho.

  • Limites de dimensionamento. Os limites e quotas de dimensionamento de subscrições do Azure podem ter influência na conceção da aplicação, nas opções tecnológicas e na definição de unidades de dimensionamento. As unidades de dimensionamento podem ajudá-lo a ignorar os limites de dimensionamento de um serviço. Por exemplo, se um cluster do AKS numa unidade puder ter apenas 1000 nós, pode utilizar duas unidades para aumentar esse limite para 2000 nós.

  • Carga esperada. Utilize o número de pedidos para cada fluxo de utilizador, a taxa de pedidos de pico esperada (pedidos por segundo) e padrões de tráfego diário/semanal/sazonal para informar os requisitos de dimensionamento principais. Além disso, considere os padrões de crescimento esperados tanto para o tráfego como para o volume de dados.

  • Desempenho degradado aceitável. Determine se um serviço degradado com tempos de resposta elevados é aceitável sob carga. Quando está a modelar a capacidade necessária, o desempenho necessário da solução sob carga é um fator crítico.

  • Requisitos não funcionais. Os cenários técnicos e empresariais têm considerações distintas sobre resiliência, disponibilidade, latência, capacidade e observabilidade. Analise estes requisitos no contexto dos principais fluxos de utilizador ponto a ponto. Terá relativa flexibilidade na conceção, tomada de decisões e escolhas tecnológicas ao nível do fluxo de utilizador.

Recomendações de conceção

  • Defina o âmbito de uma unidade de dimensionamento e os limites que irão acionar a unidade para dimensionar.

  • Certifique-se de que todos os componentes da aplicação podem ser dimensionados de forma independente ou como parte de uma unidade de dimensionamento que inclua outros componentes relacionados.

  • Defina a relação entre unidades de dimensionamento, com base num modelo de capacidade e requisitos não funcionais.

  • Defina um selo de implementação regional para unificar o aprovisionamento, a gestão e o funcionamento dos recursos de aplicações regionais numa unidade de escala heterogénea mas interdependente. À medida que a carga aumenta, podem ser implementados selos adicionais, na mesma região do Azure ou em diferentes, para dimensionar horizontalmente a solução.

  • Utilize uma subscrição do Azure como unidade de dimensionamento para que os limites de dimensionamento numa única subscrição não restrinjam a escalabilidade. Esta abordagem aplica-se a cenários de aplicação de grande escala que têm um volume de tráfego significativo.

  • Modelar a capacidade necessária em torno dos padrões de tráfego identificados para garantir que a capacidade suficiente é aprovisionada em horas de pico para impedir a degradação do serviço. Em alternativa, otimize a capacidade fora das horas de ponta.

  • Medir o tempo necessário para efetuar operações de escalamento horizontal e aumento horizontal para garantir que as variações naturais no tráfego não criam um nível inaceitável de degradação do serviço. Controle as durações da operação de dimensionamento como uma métrica operacional.

Nota

Quando implementar numa zona de destino do Azure, certifique-se de que a subscrição da zona de destino é dedicada à aplicação para fornecer um limite de gestão claro e evitar o antipasta Ruidoso Vizinho.

Distribuição global

É impossível evitar falhas em qualquer ambiente altamente distribuído. Esta secção fornece estratégias para mitigar muitos cenários de falhas. A aplicação tem de ser capaz de suportar falhas regionais e zonais. Tem de ser implementado num modelo ativo/ativo para que a carga seja distribuída entre todas as regiões.

Veja este vídeo para obter uma descrição geral de como planear falhas em aplicações críticas para a missão e maximizar a resiliência:

Considerações de design

  • Redundância. A sua aplicação tem de ser implementada em várias regiões. Além disso, numa região, recomendamos vivamente que utilize zonas de disponibilidade para permitir a tolerância a falhas ao nível do datacenter. As zonas de disponibilidade têm um perímetro de latência inferior a 2 milissegundos entre zonas de disponibilidade. Para cargas de trabalho que são "chaty" entre zonas, esta latência pode introduzir uma penalização de desempenho e incorrer em custos de largura de banda para transferência de dados entre zonas.

  • Modelo ativo/ativo. Recomenda-se uma estratégia de implementação ativa/ativa porque maximiza a disponibilidade e fornece um contrato de nível de serviço composto (SLA) mais elevado. No entanto, pode introduzir desafios em torno da sincronização e consistência de dados para muitos cenários de aplicações. Resolva os desafios ao nível da plataforma de dados ao mesmo tempo que considera as compensações do aumento dos custos e do esforço de engenharia.

    Uma implementação ativa/ativa em vários fornecedores de cloud é uma forma de mitigar potencialmente a dependência de recursos globais num único fornecedor de cloud. No entanto, uma estratégia de implementação ativa/ativa multicloud introduz uma quantidade significativa de complexidade em torno da CI/CD. Além disso, dadas as diferenças nas especificações e capacidades de recursos entre os fornecedores de cloud, precisaria de selos de implementação especializados para cada cloud.

  • Distribuição geográfica. A carga de trabalho pode ter requisitos de conformidade para residência de dados geográficos, proteção de dados e retenção de dados. Considere se existem regiões específicas onde os dados têm de residir ou onde os recursos têm de ser implementados.

  • Origem do pedido. A proximidade geográfica e a densidade dos utilizadores ou dos sistemas dependentes devem informar as decisões de conceção sobre a distribuição global.

  • Conectividade. A forma como a carga de trabalho é acedida por utilizadores ou sistemas externos irá influenciar a sua conceção. Considere se a aplicação está disponível através da Internet pública ou redes privadas que utilizam circuitos VPN ou Azure ExpressRoute.

Para obter recomendações de design e opções de configuração ao nível da plataforma, veja Plataforma de aplicações: Distribuição global.

Arquitetura baseada em eventos vagamente acoplada

O acoplamento permite a comunicação entre serviços através de interfaces bem definidas. Um acoplamento solto permite que um componente da aplicação funcione de forma independente. Um estilo de arquitetura de microsserviços é consistente com os requisitos críticos da missão. Facilita a elevada disponibilidade ao evitar falhas em cascata.

Para acoplamento solto, recomendamos vivamente que incorpore a estrutura condicionada por eventos. O processamento de mensagens assíncronas através de um intermediário pode criar resiliência.

Diagrama que ilustra a comunicação assíncrona condicionada por eventos.

Em alguns cenários, as aplicações podem combinar acoplamentos soltos e apertados, consoante os objetivos empresariais.

Considerações de design

  • Dependências de runtime. Os serviços vagamente acoplados não devem ser limitados a utilizar a mesma plataforma de computação, linguagem de programação, runtime ou sistema operativo.

  • Dimensionamento. Os serviços devem ser capazes de dimensionar de forma independente. Otimizar a utilização de recursos de infraestrutura e plataforma.

  • Tolerância a falhas. As falhas devem ser processadas separadamente e não devem afetar as transações de cliente.

  • Integridade transacional. Considere o efeito da criação de dados e persistência que ocorre em serviços separados.

  • Rastreio distribuído. O rastreio ponto a ponto pode exigir orquestração complexa.

Recomendações de conceção

  • Alinhar limites de microsserviços com fluxos de utilizador críticos.

  • Utilize a comunicação assíncrona condicionada por eventos sempre que possível para suportar uma escala sustentável e um desempenho ideal.

  • Utilize padrões como a Caixa de Saída e a Sessão Transacional para garantir a consistência para que cada mensagem seja processada corretamente.

Exemplo: Abordagem condicionada por eventos

A implementação de referência Mission-Critical Online utiliza microsserviços para processar uma única transação empresarial. Aplica operações de escrita de forma assíncrona com um mediador de mensagens e um trabalhador. As operações de leitura são síncronas, com o resultado diretamente devolvido ao autor da chamada.

Diagrama que mostra a comunicação condicionada por eventos.

Padrões de resiliência e processamento de erros no código da aplicação

Uma aplicação crítica para a missão tem de ser concebida para ser resiliente para que resolva o maior número possível de cenários de falha. Esta resiliência maximiza a disponibilidade e a fiabilidade do serviço. A aplicação deve ter capacidades de auto-recuperação, que pode implementar com padrões de estrutura, como Repetições com Backoff e Disjuntor Automático.

Para falhas não transitórias que não pode mitigar totalmente na lógica da aplicação, o modelo de estado de funcionamento e os wrappers operacionais têm de tomar medidas corretivas. O código da aplicação tem de incorporar instrumentação e registo adequados para informar o modelo de estado de funcionamento e facilitar a resolução de problemas subsequente ou a análise da causa raiz, conforme necessário. Tem de implementar o rastreio distribuído para fornecer ao autor da chamada uma mensagem de erro abrangente que inclua um ID de correlação quando ocorre uma falha.

Ferramentas como o Application Insights podem ajudá-lo a consultar, correlacionar e visualizar rastreios de aplicações.

Considerações de design

  • Configurações adequadas. Não é incomum que problemas transitórios causem falhas em cascata. Por exemplo, tentar novamente sem o back-off adequado agrava o problema quando um serviço está a ser limitado. Pode espaçar os atrasos de repetição linearmente ou auscá-los exponencialmente para recuar através de atrasos crescentes.

  • Pontos finais de estado de funcionamento. Pode expor verificações funcionais no código da aplicação através de pontos finais de estado de funcionamento que as soluções externas podem consultar para obter o estado de funcionamento do componente da aplicação.

Recomendações de conceção

Seguem-se alguns padrões comuns de engenharia de software para aplicações resilientes:

Padrão Resumo
Redistribuição de Carga Baseada na Fila Introduz uma memória intermédia entre consumidores e recursos pedidos para garantir níveis de carga consistentes. À medida que os pedidos de consumidor são colocados em fila, um processo de trabalho processa-os relativamente ao recurso pedido a um ritmo definido pela função de trabalho e pela capacidade do recurso pedido para processar os pedidos. Se os consumidores esperarem respostas aos respetivos pedidos, terá de implementar um mecanismo de resposta separado. Aplique uma ordem priorizada para que as atividades mais importantes sejam executadas primeiro.
Disjuntor Automático Proporciona estabilidade ao aguardar recuperação ou rejeitar rapidamente pedidos em vez de bloquear enquanto aguarda por um serviço ou recurso remoto indisponível. Este padrão também processa falhas que podem demorar algum tempo a recuperar a partir do momento em que uma ligação é efetuada a um serviço ou recurso remoto.
Bulkhead Tentativas de partição de instâncias de serviço em grupos com base nos requisitos de carga e disponibilidade, isolando falhas para manter a funcionalidade do serviço.
Saga Gere a consistência de dados entre microsserviços que têm arquivos de dados independentes ao garantir que os serviços se atualizam entre si através de canais de eventos ou mensagens definidos. Cada serviço realiza transações locais para atualizar o seu próprio estado e publica um evento para acionar a próxima transação local na saga. Se uma atualização de serviço falhar, a saga executa transações de compensação para contrariar os passos de atualização do serviço anteriores. Os passos de atualização de serviços individuais podem implementar padrões de resiliência, como a repetição.
Monitorização do Ponto Final do Estado de Funcionamento Implementa verificações funcionais numa aplicação à qual as ferramentas externas podem aceder através de pontos finais expostos em intervalos regulares. Pode interpretar as respostas dos pontos finais ao utilizar as principais métricas operacionais para informar o estado de funcionamento da aplicação e acionar respostas operacionais, como emitir um alerta ou efetuar uma implementação de reversão compensatória.
Repetir Lida com falhas transitórias de forma elegante e transparente.
- Cancele se é pouco provável que a falha seja transitória e é improvável que seja bem-sucedida se a operação for novamente tentada.
- Tente novamente se a falha for invulgar ou rara e é provável que a operação seja bem-sucedida se for tentada novamente imediatamente.
- Repita após um atraso se a falha for causada por uma condição que poderá necessitar de um curto período de tempo para recuperar, como conectividade de rede ou falhas de carga elevada. Aplique uma estratégia de back-off adequada à medida que os atrasos de repetição aumentam.
Limitação Controla o consumo de recursos utilizados pelos componentes da aplicação, protegendo-os de ficarem sobrecarregados. Quando um recurso atinge um limiar de carga, adia as operações de prioridade inferior e degrada a funcionalidade não essencial para que a funcionalidade essencial possa continuar até que estejam disponíveis recursos suficientes para voltar ao funcionamento normal.

Seguem-se algumas recomendações adicionais:

  • Utilize SDKs fornecidos pelo fornecedor, como os SDKs do Azure, para ligar a serviços dependentes. Utilize capacidades de resiliência incorporadas em vez de implementar funcionalidades personalizadas.

  • Aplique uma estratégia de back-off adequada ao repetir chamadas de dependência falhadas para evitar um cenário de DDoS auto-infligido.

  • Defina critérios de engenharia comuns para todas as equipas de microsserviços de aplicações para impulsionar a consistência e a velocidade na utilização de padrões de resiliência ao nível da aplicação.

  • Implemente padrões de resiliência com pacotes padronizados comprovados, como Polly para C# ou Sentinel para Java.

  • Utilize IDs de correlação para todos os eventos de rastreio e mensagens de registo para os ligar a um determinado pedido. Devolva os IDs de correlação ao autor da chamada para todas as chamadas e não apenas pedidos falhados.

  • Utilize o registo estruturado para todas as mensagens de registo. Selecione um sink de dados operacional unificado para rastreios de aplicações, métricas e registos para permitir que os operadores depurem facilmente problemas. Para obter mais informações, veja Recolher, agregar e armazenar dados de monitorização para aplicações na cloud.

  • Certifique-se de que os dados operacionais são utilizados em conjunto com os requisitos empresariais para informar um modelo de estado de funcionamento da aplicação.

Seleção de linguagem de programação

É importante selecionar as linguagens e arquiteturas de programação corretas. Estas decisões são muitas vezes impulsionadas pelos conjuntos de competências ou pelas tecnologias padronizadas na organização. No entanto, é essencial avaliar o desempenho, a resiliência e as capacidades gerais de várias linguagens e arquiteturas.

Considerações de design

  • Capacidades do kit de desenvolvimento. Existem diferenças nas capacidades oferecidas pelos SDKs de serviço do Azure em vários idiomas. Estas diferenças podem influenciar a sua escolha de um serviço do Azure ou linguagem de programação. Por exemplo, se o Azure Cosmos DB for uma opção viável, o Go poderá não ser uma linguagem de desenvolvimento adequada porque não existe um SDK de primeira.

  • Atualizações de funcionalidades. Considere a frequência com que o SDK é atualizado com novas funcionalidades para o idioma selecionado. Os SDKs utilizados frequentemente, como bibliotecas .NET e Java, são atualizados com frequência. Outros SDKs ou SDKs para outros idiomas podem ser atualizados com menos frequência.

  • Várias linguagens ou arquiteturas de programação. Pode utilizar várias tecnologias para suportar várias cargas de trabalho compostas. No entanto, deve evitar a expansão porque introduz a complexidade da gestão e os desafios operacionais.

  • Opção de computação. O software legado ou proprietário pode não ser executado nos serviços PaaS. Além disso, poderá não conseguir incluir software legado ou proprietário em contentores.

Recomendações de conceção

  • Avalie todos os SDKs do Azure relevantes para as capacidades de que precisa e as linguagens de programação escolhidas. Verifique o alinhamento com requisitos não funcionais.

  • Otimizar a seleção de linguagens e arquiteturas de programação ao nível do microsserviço. Utilize várias tecnologias conforme adequado.

  • Priorize o SDK .NET para otimizar a fiabilidade e o desempenho. Normalmente, os SDKs do Azure .NET fornecem mais capacidades e são atualizados com frequência.

Passo seguinte

Reveja as considerações para a plataforma de aplicações.