Padrão confiável de aplicativo Web para .NET

Azure App Service
Azure Front Door
Azure Cache for Redis
.NET

Este artigo fornece orientação sobre como implementar o padrão Reliable Web App. Esse padrão descreve como modificar (replataformar) aplicativos Web para migração para nuvem. Ele oferece arquitetura prescritiva, código e orientação de configuração alinhados com os princípios do Well-Architected Framework.

Por que o padrão Reliable Web App para .NET?

O padrão Reliable Web App é um conjunto de princípios e técnicas de implementação que definem como você deve reformular aplicativos Web ao migrar para a nuvem. Ele se concentra nas atualizações mínimas de código que você precisa fazer para ter sucesso na nuvem. A orientação a seguir usa a implementação de referência como exemplo e segue a jornada de replataforma da empresa fictícia, Relecloud, para fornecer contexto de negócios para sua jornada. Antes de implementar o padrão Reliable Web App para .NET, o Relecloud tinha um aplicativo Web monolítico de tíquete local que usava a estrutura ASP.NET.

Gorjeta

Logótipo do GitHubuma implementação de referência (exemplo) do padrão Reliable Web App. Ele representa o estado final da implementação do Reliable Web App para uma empresa fictícia chamada Relecloud. É um aplicativo Web de nível de produção que apresenta todas as atualizações de código, arquitetura e configuração discutidas neste artigo. Implante e use a implementação de referência para orientar sua implementação do padrão Reliable Web App.

Como implementar o padrão Reliable Web App

Este artigo inclui arquitetura, código e orientação de configuração para implementar o padrão Reliable Web App. Use os links a seguir para navegar até a orientação específica de que precisa:

  • Contexto de negócios: alinhe essa orientação com o contexto do seu negócio e aprenda a definir metas imediatas e de longo prazo que impulsionam as decisões de replataforma.
  • Orientação de arquitetura: saiba como selecionar os serviços de nuvem certos e projetar uma arquitetura que atenda às suas necessidades de negócios.
  • Orientação de código: implemente três padrões de design para melhorar a confiabilidade e a eficiência de desempenho do seu aplicativo Web na nuvem: padrões Retry, Circuit-Breaker e Cache-Aside
  • Orientação de configuração: configure autenticação e autorização, identidades gerenciadas, ambientes com direitos, infraestrutura como código e monitoramento.

Contexto empresarial

O primeiro passo na replataforma de um aplicativo Web é definir seus objetivos de negócios. Você deve definir metas imediatas, como objetivos de nível de serviço e metas de otimização de custos, bem como metas futuras para seu aplicativo Web. Estes objetivos influenciam a sua escolha de serviços na nuvem e a arquitetura da sua aplicação Web na nuvem. Defina um SLO de destino para seu aplicativo Web, como 99,9% de tempo de atividade. Calcule o SLA composto para todos os serviços que afetam a disponibilidade do seu aplicativo Web.

Por exemplo, a Relecloud tem uma previsão de vendas positiva e antecipa o aumento da demanda em seu aplicativo web de emissão de tíquetes. Para atender a essa demanda, eles definiram as metas para a aplicação web:

  • Aplique alterações de código de baixo custo e alto valor
  • Atingir um objetivo de nível de serviço (SLO) de 99,9%
  • Adote práticas de DevOps
  • Crie ambientes otimizados em termos de custos
  • Melhorar a fiabilidade e a segurança

A infraestrutura local do Relecloud não era uma solução econômica para atingir esses objetivos. Então, eles decidiram que migrar seu aplicativo Web para o Azure era a maneira mais econômica de alcançar seus objetivos imediatos e futuros.

Orientações para a arquitetura

O padrão Reliable Web App tem alguns elementos arquitetônicos essenciais. Você precisa de DNS para gerenciar a resolução de pontos finais, um firewall de aplicativo Web para bloquear tráfego HTTP mal-intencionado e um balanceador de carga para proteger e rotear solicitações de entrada de usuários. A plataforma do aplicativo hospeda o código do seu aplicativo Web e faz chamadas para todos os serviços de back-end por meio de pontos de extremidade privados em uma rede virtual. Uma ferramenta de monitoramento de desempenho de aplicativo captura métricas e logs para entender seu aplicativo Web.

Diagrama mostrando os elementos de arquitetura essenciais do padrão Reliable Web App.

Figura 1. Elementos arquitetónicos essenciais do padrão Reliable Web App.

Conceber a arquitetura

Projete sua infraestrutura para dar suporte às métricas de recuperação, como RTO (Recovery Time Objetive, objetivo de tempo de recuperação) e RPO (Recovery Point Objetive, objetivo de ponto de recuperação). O RTO afeta a disponibilidade e deve suportar seu SLO. Determine um RPO (Recovery Point Objetive, objetivo de ponto de recuperação) e configure a redundância de dados para atender ao RPO.

  • Escolha a confiabilidade da infraestrutura. Determine quantas zonas e regiões de disponibilidade você precisa para atender às suas necessidades de disponibilidade. Adicione zonas e regiões de disponibilidade até que o SLA composto atenda ao seu SLO. O padrão Reliable Web App suporta várias regiões para uma configuração ativa-ativa ou ativa-passiva. Por exemplo, a implementação de referência usa uma configuração ativo-passivo para atender a um SLO de 99,9%.

    Para um aplicativo Web de várias regiões, configure seu balanceador de carga para rotear o tráfego para a segunda região para oferecer suporte a uma configuração ativa-ativa ou ativa-passiva, dependendo da sua necessidade comercial. As duas regiões exigem os mesmos serviços, exceto se uma região tiver uma rede virtual de hub que conecta as regiões. Adote uma topologia de rede hub-and-spoke para centralizar e compartilhar recursos, como um firewall de rede. Se você tiver máquinas virtuais, adicione um host bastion à rede virtual do hub para gerenciá-las com segurança (consulte a figura 2).

    Diagrama mostrando o padrão Reliable Web App com uma segunda região e uma topologia hub-and-spoke.

    Figura 2. O padrão Reliable Web App com uma segunda região e uma topologia hub-and-spoke.

  • Escolha uma topologia de rede. Escolha a topologia de rede certa para seus requisitos da Web e de rede. Se você planeja ter várias redes virtuais, use uma topologia de rede hub and spoke. Ele fornece benefícios de custo, gerenciamento e segurança com opções de conectividade híbrida para redes locais e virtuais.

Escolha os serviços do Azure certos

Ao mover um aplicativo Web para a nuvem, você deve selecionar os serviços do Azure que atendem aos seus requisitos de negócios e se alinham com os recursos atuais do aplicativo Web local. O alinhamento ajuda a minimizar o esforço de replataforma. Por exemplo, use serviços que permitem manter o mesmo mecanismo de banco de dados e oferecer suporte a middleware e estruturas existentes. As seções a seguir fornecem orientação para selecionar os serviços do Azure certos para seu aplicativo Web.

Por exemplo, antes da mudança para a nuvem, o aplicativo Web de emissão de tíquetes do Relecloud era um aplicativo local, monolítico e ASP.NET. Ele era executado em duas máquinas virtuais e tinha um banco de dados Microsoft SQL Server. O aplicativo Web sofreu desafios comuns em escalabilidade e implantação de recursos. Esse ponto de partida, seus objetivos de negócios e SLO impulsionaram suas escolhas de serviço.

  • Plataforma de aplicativo: use o Serviço de Aplicativo do Azure como sua plataforma de aplicativo. A Relecloud escolheu o Serviço de Aplicativo do Azure como a plataforma de aplicativo pelos seguintes motivos:

    • Acordo de alto nível de serviço (SLA): Possui um SLA alto que atende ao SLO do ambiente de produção de 99,9%.
    • Sobrecarga de gerenciamento reduzida: é uma solução totalmente gerenciada que lida com dimensionamento, verificações de integridade e balanceamento de carga.
    • Suporte ao .NET: Ele suporta a versão do .NET na qual o aplicativo está escrito.
    • Capacidade de conteinerização: o aplicativo Web pode convergir para a nuvem sem fazer conteinerização, mas a plataforma de aplicativo também dá suporte à conteinerização sem alterar os serviços do Azure.
    • Dimensionamento automático: o aplicativo Web pode ser dimensionado automaticamente com base no tráfego do usuário e nas definições de configuração. A plataforma também suporta escalonamento para cima ou para baixo para acomodar diferentes requisitos de hospedagem.
  • Gerenciamento de identidade: use o Microsoft Entra ID como sua solução de gerenciamento de identidade e acesso. A Relecloud escolheu o Microsoft Entra ID pelos seguintes motivos:

    • Autenticação e autorização: O aplicativo precisa autenticar e autorizar funcionários de call center.
    • Escalável: é dimensionado para suportar cenários maiores.
    • Controle de identidade do usuário: os funcionários do call center podem usar suas identidades corporativas existentes.
    • Suporte ao protocolo de autorização: Ele suporta OAuth 2.0 para identidades gerenciadas.
  • Banco de dados: use um serviço que permita manter o mesmo mecanismo de banco de dados. Use a árvore de decisão do armazenamento de dados. O aplicativo Web do Relecloud usava o SQL Server local. Então, eles queriam usar o esquema de banco de dados existente, procedimentos armazenados e funções. Vários produtos SQL estão disponíveis no Azure, mas a Relecloud escolheu o Banco de Dados SQL do Azure pelos seguintes motivos:

    • Confiabilidade: A camada de uso geral fornece um SLA alto e redundância de várias regiões. Ele pode suportar uma alta carga de usuário.
    • Sobrecarga de gerenciamento reduzida: fornece uma instância de banco de dados SQL gerenciada.
    • Suporte à migração: ele oferece suporte à migração de banco de dados do SQL Server local.
    • Consistência com configurações locais: Ele suporta os procedimentos armazenados, funções e exibições existentes.
    • Resiliência: Suporta backups e restauração point-in-time.
    • Experiência e retrabalho mínimo: o Banco de dados SQL aproveita a experiência interna e requer trabalho mínimo para ser adotado.
  • Monitoramento de desempenho de aplicativos: use o Application Insights para analisar a telemetria em seu aplicativo. A Relecloud optou por usar o Application Insights pelos seguintes motivos:

    • Integração com o Azure Monitor: fornece a melhor integração com o Azure Monitor.
    • Deteção de anomalias: Deteta automaticamente anomalias de desempenho.
    • Resolução de problemas: ajuda-o a diagnosticar problemas na aplicação em execução.
    • Monitoramento: Ele coleta informações sobre como os usuários estão usando o aplicativo e permite que você acompanhe facilmente eventos personalizados.
    • Lacuna de visibilidade: a solução local não tinha a solução de monitoramento de desempenho de aplicativos. O Application Insights oferece fácil integração com a plataforma e o código do aplicativo.
  • Cache: escolha se deseja adicionar cache à arquitetura do seu aplicativo Web. O Cache Redis do Azure é a principal solução de cache do Azure. É um armazenamento de dados gerenciado na memória baseado no software Redis. A carga do aplicativo Web do Relecloud é fortemente enviesada para a visualização de shows e detalhes do local, e adicionou o Cache do Azure para Redis pelos seguintes motivos:

    • Despesas gerais de gerenciamento reduzidas: é um serviço totalmente gerenciado.
    • Velocidade e volume: Possui alta taxa de transferência de dados e leituras de baixa latência para dados comumente acessados e de mudança lenta.
    • Capacidade de suporte diversificada: é um local de cache unificado para todas as instâncias do aplicativo Web usarem.
    • Armazenamento de dados externo: os servidores de aplicativos locais executaram o cache local da VM. Essa configuração não descarregava dados muito frequentados e não podia invalidar dados.
    • Sessões não aderentes: a externalização do estado da sessão suporta sessões não aderentes.
  • Balanceador de carga: os aplicativos Web que usam soluções PaaS devem usar o Azure Front Door, o Azure Application Gateway ou ambos com base na arquitetura e nos requisitos do aplicativo Web. Use a árvore de decisão do balanceador de carga para escolher o balanceador de carga correto. O Relecloud precisava de um balanceador de carga de camada 7 que pudesse rotear o tráfego em várias regiões. A Relecloud precisava de um aplicativo Web multirregião para atender ao SLO de 99,9%. A Relecloud escolheu o Azure Front Door pelos seguintes motivos:

    • Balanceamento de carga global: é um balanceador de carga de camada 7 que pode rotear o tráfego em várias regiões.
    • Firewall de aplicativo Web: ele se integra nativamente ao Firewall de Aplicativo Web do Azure.
    • Flexibilidade de roteamento: Permite que a equipe do aplicativo configure as necessidades de entrada para suportar alterações futuras no aplicativo.
    • Aceleração de tráfego: usa anycast para chegar ao ponto de presença do Azure mais próximo e encontrar a rota mais rápida para o aplicativo Web.
    • Domínios personalizados: Suporta nomes de domínio personalizados com validação de domínio flexível.
    • Sondas de integridade: o aplicativo precisa de monitoramento inteligente de sonda de integridade. O Azure Front Door usa respostas da sonda para determinar a melhor origem para rotear solicitações de clientes.
    • Suporte de monitoramento: Ele suporta relatórios integrados com um painel tudo-em-um para portas frontais e padrões de segurança. Você pode configurar alertas que se integram ao Azure Monitor. Ele permite que o aplicativo registre cada solicitação e testes de integridade com falha.
    • Proteção contra DDoS: Possui proteção contra DDoS de camada 3-4 integrada.
    • Rede de entrega de conteúdo: Posiciona a Relecloud para usar uma rede de entrega de conteúdo. A rede de entrega de conteúdo fornece aceleração do site.
  • Firewall de aplicativos Web: use o Firewall de Aplicativo Web do Azure para fornecer proteção centralizada contra vulnerabilidades e explorações da Web comuns. A Relecloud usou o Firewall de Aplicativo Web do Azure pelos seguintes motivos:

    • Proteção global: fornece proteção aprimorada de aplicativos Web globais sem sacrificar o desempenho.
    • Proteção contra botnets: a equipe pode monitorar e definir configurações para resolver problemas de segurança relacionados a botnets.
    • Paridade com o local: a solução local estava sendo executada atrás de um firewall de aplicativo Web gerenciado pela TI.
    • Facilidade de uso: o Web Application Firewall integra-se ao Azure Front Door.
  • Armazenamento de configuração: escolha se deseja adicionar armazenamento de configuração de aplicativo ao seu aplicativo Web. A Configuração de Aplicativo do Azure é um serviço para gerenciar centralmente configurações de aplicativos e sinalizadores de recursos. Analise as práticas recomendadas de Configuração do Aplicativo para decidir se esse serviço é adequado para seu aplicativo. O Relecloud queria substituir a configuração baseada em arquivos por um armazenamento de configuração central que se integrasse com a plataforma e o código do aplicativo. Eles adicionaram a Configuração do Aplicativo à arquitetura pelos seguintes motivos:

    • Flexibilidade: Suporta sinalizadores de funcionalidades. Os sinalizadores de recursos permitem que os usuários aceitem e desativem os recursos de visualização antecipada em um ambiente de produção sem reimplantar o aplicativo.
    • Suporta pipeline Git: A fonte da verdade para os dados de configuração precisava ser um repositório Git. O pipeline precisava atualizar os dados no repositório de configuração central.
    • Suporta identidades gerenciadas: Ele suporta identidades gerenciadas para simplificar e ajudar a proteger a conexão com o repositório de configuração.
  • Gerenciador de segredos: use o Azure Key Vault se tiver segredos para gerenciar no Azure. Você pode incorporar o Cofre da Chave em aplicativos .NET usando o objeto ConfigurationBuilder. O aplicativo Web local do Relecloud armazenava segredos em arquivos de configuração de código, mas é uma prática de segurança melhor armazenar segredos em um local que ofereça suporte a RBAC e controles de auditoria. Embora as identidades gerenciadas sejam a solução preferida para se conectar aos recursos do Azure, o Relecloud tinha segredos de aplicativos que precisavam gerenciar. A Relecloud usou o Key Vault pelos seguintes motivos:

    • Encriptação: Suporta encriptação em repouso e em trânsito.
    • Suporte de identidade gerenciada: os serviços de aplicativo podem usar identidades gerenciadas para acessar o armazenamento secreto.
    • Monitoramento e registro: facilita o acesso à auditoria e gera alertas quando os segredos armazenados mudam.
    • Integração: fornece integração nativa com o repositório de configuração do Azure (Configuração do Aplicativo) e a plataforma de hospedagem na Web (Serviço de Aplicativo).
  • Solução de armazenamento: analise as opções de armazenamento do Azure para escolher a solução de armazenamento certa com base nos seus requisitos. O aplicativo Web local do Relecloud tinha armazenamento em disco montado em cada servidor Web, mas a equipe queria usar uma solução de armazenamento de dados externo. A Relecloud escolheu o Armazenamento de Blobs do Azure pelos seguintes motivos:

    • Acesso seguro: o aplicativo Web pode eliminar pontos de extremidade para acessar o armazenamento exposto à Internet pública com acesso anônimo.
    • Encriptação: encripta dados em repouso e em trânsito.
    • Resiliência: suporta armazenamento com redundância de zona (ZRS). O armazenamento com redundância de zona replica dados de forma síncrona em três zonas de disponibilidade do Azure na região primária. Cada zona de disponibilidade está em um local físico separado que tem energia, resfriamento e rede independentes. Essa configuração deve tornar as imagens de tíquete resilientes contra perdas.
  • Segurança do ponto de extremidade: utilize a ligação privada do Azure para aceder a soluções de plataforma como serviço através de um ponto de extremidade privado na sua rede virtual. O tráfego entre a sua rede virtual e o serviço viaja através da rede de backbone da Microsoft. A Relecloud escolheu o Private Link pelos seguintes motivos:

    • Comunicação de segurança aprimorada: permite que o aplicativo acesse serviços de forma privada na plataforma Azure e reduz a pegada de rede dos armazenamentos de dados para ajudar a proteger contra vazamento de dados.
    • Esforço mínimo: os endpoints privados suportam a plataforma de aplicativo Web e a plataforma de banco de dados que o aplicativo Web usa. Ambas as plataformas espelham as configurações locais existentes para alterações mínimas.
  • Segurança de rede: use o Firewall do Azure para controlar o tráfego de entrada e saída no nível da rede. Use o Azure Bastion para se conectar a máquinas virtuais com segurança sem expor portas RDP/SSH. A Relecloud adotou uma topologia de rede hub and spoke e queria colocar serviços de segurança de rede compartilhados no hub. O Firewall do Azure melhora a segurança inspecionando todo o tráfego de saída dos raios para aumentar a segurança da rede. O Relecloud precisava do Azure Bastion para implantações seguras de um host de salto na sub-rede DevOps.

Orientação de código

Para mover com êxito um aplicativo Web para a nuvem, você precisa atualizar o código do aplicativo Web com o padrão Repetir, o padrão Disjuntor e o padrão de design Cache-Side.

Diagrama mostrando o papel dos padrões de design na arquitetura confiável essencial do aplicativo Web.

Figura 3. Papel dos padrões de design.

Cada padrão de design fornece benefícios de design de carga de trabalho que se alinham com um dos mais pilares do Well-Architected Framework. Aqui está uma visão geral dos padrões que você deve implementar:

  1. Padrão de repetição: o padrão de repetição lida com falhas transitórias repetindo operações que podem falhar intermitentemente. Implemente esse padrão em todas as chamadas de saída para outros serviços do Azure.

  2. Padrão de disjuntor: o padrão de disjuntor impede que um aplicativo tente novamente operações que não são transitórias. Implemente esse padrão em todas as chamadas de saída para outros serviços do Azure.

  3. Padrão Cache-Side: O padrão Cache-Aside adiciona e recupera de um cache com mais frequência do que um armazenamento de dados. Implemente esse padrão em solicitações para o banco de dados.

Padrão de estruturação Fiabilidade (RE) Segurança (SE) Otimização de Custos (CO) Excelência Operacional (OE) Eficiência de desempenho (PE) Apoiar os princípios do WAF
Padrão de Repetição RE:07
Padrão do disjuntor RE:03
RE:07
PE:07
PE:11
Padrão Cache Aside RE:05
PE:08
PE:12

Implementar o padrão Retry

Adicione o padrão Repetir ao código do aplicativo para resolver interrupções temporárias do serviço. Essas interrupções são chamadas de falhas transitórias. Falhas transitórias geralmente se resolvem em segundos. O padrão Repetir permite reenviar solicitações com falha. Ele também permite que você configure os atrasos de solicitação e o número de tentativas antes que a falha seja concedida.

  • Usar mecanismos de repetição internos Use o mecanismo de repetição interno que a maioria dos serviços do Azure tem para agilizar a implementação. Por exemplo, a implementação de referência usa a resiliência de conexão no Entity Framework Core para aplicar o padrão Retry em solicitações ao Banco de Dados SQL do Azure (consulte o código a seguir).

    services.AddDbContextPool<ConcertDataContext>(options => options.UseSqlServer(sqlDatabaseConnectionString,
        sqlServerOptionsAction: sqlOptions =>
        {
            sqlOptions.EnableRetryOnFailure(
            maxRetryCount: 5,
            maxRetryDelay: TimeSpan.FromSeconds(3),
            errorNumbersToAdd: null);
        }));
    
  • Use bibliotecas de programação repetitivas. Para comunicações HTTP, integre uma biblioteca de resiliência padrão, como Polly ou Microsoft.Extensions.Http.Resilience. Essas bibliotecas oferecem mecanismos abrangentes de repetição que são cruciais para gerenciar comunicações com serviços Web externos. Por exemplo, a implementação de referência usa Polly para impor o padrão Retry toda vez que o código constrói um objeto que chama o IConcertSearchService objeto (consulte o código a seguir).

    private void AddConcertSearchService(IServiceCollection services)
    {
        var baseUri = Configuration["App:RelecloudApi:BaseUri"];
        if (string.IsNullOrWhiteSpace(baseUri))
        {
            services.AddScoped<IConcertSearchService, MockConcertSearchService>();
        }
        else
        {
            services.AddHttpClient<IConcertSearchService, RelecloudApiConcertSearchService>(httpClient =>
            {
                httpClient.BaseAddress = new Uri(baseUri);
                httpClient.DefaultRequestHeaders.Add(HeaderNames.Accept, "application/json");
                httpClient.DefaultRequestHeaders.Add(HeaderNames.UserAgent, "Relecloud.Web");
            })
            .AddPolicyHandler(GetRetryPolicy())
            .AddPolicyHandler(GetCircuitBreakerPolicy());
        }
    }
    
    private static IAsyncPolicy<HttpResponseMessage> GetRetryPolicy()
    {
        var delay = Backoff.DecorrelatedJitterBackoffV2(TimeSpan.FromMilliseconds(500), retryCount: 3);
        return HttpPolicyExtensions
          .HandleTransientHttpError()
          .OrResult(msg => msg.StatusCode == System.Net.HttpStatusCode.NotFound)
          .WaitAndRetryAsync(delay);
    }
    

Implementar o padrão de disjuntor

Use o padrão Disjuntor para lidar com interrupções de serviço que não sejam falhas transitórias. O padrão de disjuntor impede que um aplicativo tente acessar continuamente um serviço que não responde. Ele libera o aplicativo e evita o desperdício de ciclos de CPU para que o aplicativo mantenha sua integridade de desempenho para os usuários finais.

Por exemplo, a implementação de referência aplica o padrão Disjuntor em todas as solicitações à API. Ele usa a HandleTransientHttpError lógica para detetar solicitações HTTP que pode repetir com segurança, mas limita o número de falhas agregadas durante um período de tempo especificado (consulte o código a seguir).

private static IAsyncPolicy<HttpResponseMessage> GetCircuitBreakerPolicy()
{
    return HttpPolicyExtensions
        .HandleTransientHttpError()
        .OrResult(msg => msg.StatusCode == System.Net.HttpStatusCode.NotFound)
        .CircuitBreakerAsync(5, TimeSpan.FromSeconds(30));
}

Implementar o padrão Cache-Aside

Adicione o padrão Cache-Aside ao seu aplicativo Web para melhorar o gerenciamento de dados na memória. O padrão atribui ao aplicativo a responsabilidade de lidar com solicitações de dados e garantir a consistência entre o cache e um armazenamento persistente, como um banco de dados. Ele reduz os tempos de resposta, melhora a taxa de transferência e reduz a necessidade de mais escala. Ele também reduz a carga no armazenamento de dados primário, melhorando a confiabilidade e a otimização de custos. Para implementar o padrão Cache-Side, siga estas recomendações:

  • Configure o aplicativo para usar um cache. Os aplicativos de produção devem usar o Cache Redis Distribuído porque ele melhora o desempenho reduzindo as consultas de banco de dados e permite sessões não aderentes para que o balanceador de carga possa distribuir o tráfego uniformemente. Por exemplo, a implementação de referência usa cache Redis distribuído. O AddAzureCacheForRedis método configura o aplicativo para usar o Cache Redis do Azure (consulte o código a seguir).

    private void AddAzureCacheForRedis(IServiceCollection services)
    {
        if (!string.IsNullOrWhiteSpace(Configuration["App:RedisCache:ConnectionString"]))
        {
            services.AddStackExchangeRedisCache(options =>
            {
                options.Configuration = Configuration["App:RedisCache:ConnectionString"];
            });
        }
        else
        {
            services.AddDistributedMemoryCache();
        }
    }
    
  • Armazene em cache dados de alta necessidade. Aplique o padrão Cache-Aside em dados de alta necessidade para ampliar sua eficácia. Use o Azure Monitor para controlar a CPU, a memória e o armazenamento do banco de dados. Essas métricas ajudam a determinar se você pode usar uma SKU de banco de dados menor depois de aplicar o padrão Cache-Side. Por exemplo, a implementação de referência armazena em cache dados de alta necessidade que suportam a página Próximos concertos. O GetUpcomingConcertsAsync método extrai dados do Banco de dados SQL para o cache Redis e preenche o cache com os dados de concertos mais recentes (consulte o código a seguir).

    public async Task<ICollection<Concert>> GetUpcomingConcertsAsync(int count)
    {
        IList<Concert>? concerts;
        var concertsJson = await this.cache.GetStringAsync(CacheKeys.UpcomingConcerts);
        if (concertsJson != null)
        {
            // There is cached data. Deserialize the JSON data.
            concerts = JsonSerializer.Deserialize<IList<Concert>>(concertsJson);
        }
        else
        {
            // There's nothing in the cache. Retrieve data 
            // from the repository and cache it for one hour.
            concerts = await this.database.Concerts.AsNoTracking()
                .Where(c => c.StartTime > DateTimeOffset.UtcNow && c.IsVisible)
                .OrderBy(c => c.StartTime)
                .Take(count)
                .ToListAsync();
            concertsJson = JsonSerializer.Serialize(concerts);
            var cacheOptions = new DistributedCacheEntryOptions {
                AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(1)
            };
            await this.cache.SetStringAsync(CacheKeys.UpcomingConcerts, concertsJson, cacheOptions);
        }
        return concerts ?? new List<Concert>();
    }
    
  • Mantenha os dados de cache atualizados. Agende atualizações regulares de cache para sincronizar com as alterações mais recentes do banco de dados. Determine a taxa de atualização ideal com base na volatilidade dos dados e nas necessidades do usuário. Essa prática garante que o aplicativo use o padrão Cache-Aside para fornecer acesso rápido e informações atuais. Por exemplo, a implementação de referência armazena dados em cache apenas por uma hora e usa o CreateConcertAsync método para limpar a chave de cache quando os dados são alterados (consulte o código a seguir).

    public async Task<CreateResult> CreateConcertAsync(Concert newConcert)
    {
        database.Add(newConcert);
        await this.database.SaveChangesAsync();
        this.cache.Remove(CacheKeys.UpcomingConcerts);
        return CreateResult.SuccessResult(newConcert.Id);
    }
    
  • Garanta a consistência dos dados. Implemente mecanismos para atualizar o cache imediatamente após qualquer operação de gravação do banco de dados. Use atualizações controladas por eventos ou classes dedicadas de gerenciamento de dados para garantir a coerência do cache. A sincronização consistente do cache com as modificações do banco de dados é fundamental para o padrão Cache-Side. Por exemplo, a implementação de referência usa o UpdateConcertAsync método para manter os dados no cache consistentes (consulte o código a seguir).

    public async Task<UpdateResult> UpdateConcertAsync(Concert existingConcert), 
    {
       database.Update(existingConcert);
       await database.SaveChangesAsync();
       this.cache.Remove(CacheKeys.UpcomingConcerts);
       return UpdateResult.SuccessResult();
    }
    

Diretrizes de configuração

As seções a seguir fornecem orientação sobre como implementar as atualizações de configurações. Cada seção se alinha com um ou mais pilares da estrutura bem arquitetada.

Configuração Fiabilidade (RE) Segurança (SE) Otimização de Custos (CO) Excelência Operacional (OE) Eficiência de desempenho (PE) Apoiar os princípios do WAF
Configurar autenticação de usuário e autorização SE:05
OE:10
Implementar identidades gerenciadas SE:05
OE:10
Ambientes de tamanho certo CO:05
CO:06
Implementar dimensionamento automático RE:06
CO:12
PE:05
Automatizar a implementação de recursos OE:05
Implementar monitorização OE:07
PE:04

Configurar autenticação e autorização de usuário

Ao migrar aplicativos Web para o Azure, configure os mecanismos de autenticação e autorização do usuário. Siga estas recomendações:

  • Use uma plataforma de identidade. Use a plataforma Microsoft Identity para configurar a autenticação de aplicativos Web. Esta plataforma suporta aplicações de inquilino único e multi-inquilino, permitindo que os utilizadores iniciem sessão com as suas identidades Microsoft ou contas sociais.

  • Crie um registro de aplicativo. O Microsoft Entra ID requer um registro de aplicativo no locatário principal. O registro do aplicativo garante que os usuários que obtêm acesso ao aplicativo Web tenham identidades no locatário principal.

  • Use os recursos da plataforma. Minimize a necessidade de código de autenticação personalizado usando recursos de plataforma para autenticar usuários e acessar dados. Por exemplo, o Serviço de Aplicativo fornece suporte de autenticação interno, para que você possa entrar em usuários e acessar dados escrevendo pouco ou nenhum código em seu aplicativo Web.

  • Impor a autorização no aplicativo. Use controles de acesso baseados em função (RBAC) para atribuir privilégios mínimos a funções de aplicativo. Defina funções específicas para diferentes ações do usuário para evitar sobreposições e garantir clareza. Mapeie os usuários para as funções apropriadas e garanta que eles só tenham acesso aos recursos e ações necessários.

  • Prefira o acesso temporário ao armazenamento. Use permissões temporárias para proteger contra acesso não autorizado e violações, como assinaturas de acesso compartilhado (SASs). Use as SASs de delegação de usuário para maximizar a segurança ao conceder acesso temporário. É o único SAS que usa credenciais do Microsoft Entra ID e não requer uma chave de conta de armazenamento permanente.

  • Impor autorização no Azure. Use o RBAC do Azure para atribuir privilégios mínimos às identidades dos usuários. O RBAC do Azure determina quais identidades de recursos do Azure podem acessar, o que elas podem fazer com esses recursos e a quais áreas elas têm acesso.

  • Evite permissões permanentes elevadas. Use o Microsoft Entra Privileged Identity Management para conceder acesso just-in-time para operações privilegiadas. Por exemplo, os desenvolvedores geralmente precisam de acesso em nível de administrador para criar/excluir bancos de dados, modificar esquemas de tabela e alterar permissões de usuário. Com o acesso just-in-time, as identidades dos usuários recebem permissões temporárias para executar tarefas privilegiadas.

Implementar identidades gerenciadas

Use Identidades Gerenciadas para todos os serviços do Azure que oferecem suporte a identidades gerenciadas. Uma identidade gerenciada permite que os recursos do Azure (identidades de carga de trabalho) se autentiquem e interajam com outros serviços do Azure sem gerenciar credenciais. Os sistemas híbridos e herdados podem manter soluções de autenticação local para simplificar a migração, mas devem fazer a transição para identidades gerenciadas o mais rápido possível. Para implementar identidades gerenciadas, siga estas recomendações:

  • Escolha o tipo certo de identidade gerenciada. Prefira identidades gerenciadas atribuídas pelo usuário quando você tiver dois ou mais recursos do Azure que precisam do mesmo conjunto de permissões. Essa configuração é mais eficiente do que criar identidades gerenciadas atribuídas ao sistema para cada um desses recursos e atribuir as mesmas permissões a todos eles. Caso contrário, use identidades gerenciadas atribuídas ao sistema.

  • Configure privilégios mínimos. Use o RBAC do Azure para conceder apenas as permissões que são críticas para as operações, como ações CRUD em bancos de dados ou acesso a segredos. As permissões de identidade de carga de trabalho são persistentes, portanto, você não pode fornecer permissões just-in-time ou de curto prazo para identidades de carga de trabalho. Se o RBAC do Azure não cobrir um cenário específico, complemente o RBAC do Azure com políticas de acesso de nível de serviço do Azure.

  • Proteja os segredos restantes. Armazene todos os segredos restantes no Cofre da Chave do Azure. Carregue segredos do Cofre da Chave na inicialização do aplicativo em vez de durante cada solicitação HTTP. O acesso de alta frequência em solicitações HTTP pode exceder os limites de transação do Cofre da Chave. Armazene configurações de aplicativos na Configuração de Aplicativo do Azure.

Por exemplo, a implementação de referência usa o Authentication argumento na cadeia de conexão do banco de dados SQL para que o Serviço de Aplicativo possa se conectar ao banco de dados SQL com uma identidade gerenciada: Server=tcp:my-sql-server.database.windows.net,1433;Initial Catalog=my-sql-database;Authentication=Active Directory Default. Ele usa o DefaultAzureCredential para permitir que a API da Web se conecte ao Cofre de Chaves usando uma identidade gerenciada (consulte o código a seguir).

    builder.Configuration.AddAzureAppConfiguration(options =>
    {
         options
            .Connect(new Uri(builder.Configuration["Api:AppConfig:Uri"]), new DefaultAzureCredential())
            .ConfigureKeyVault(kv =>
            {
                // Some of the values coming from Azure App Configuration
                // are stored in Key Vault. Use the managed identity
                // of this host for the authentication.
                kv.SetCredential(new DefaultAzureCredential());
            });
    });

Ambientes de tamanho certo

Use as camadas de desempenho (SKUs) dos serviços do Azure que atendem às necessidades de cada ambiente sem excesso. Para dimensionar corretamente seus ambientes, siga estas recomendações:

  • Estimativa de custos. Use a calculadora de preços do Azure para estimar o custo de cada ambiente.

  • Ambientes de produção otimizados em termos de custos. Os ambientes de produção precisam de SKUs que atendam aos contratos de nível de serviço (SLA), aos recursos e à escala necessários para a produção. Monitore continuamente o uso de recursos e ajuste as SKUs para alinhá-las com as necessidades reais de desempenho.

  • Otimize os custos dos ambientes de pré-produção. Os ambientes de pré-produção devem usar recursos de baixo custo, desabilitar serviços desnecessários e aplicar descontos, como preços de Desenvolvimento/Teste do Azure. Garantir que os ambientes de pré-produção sejam suficientemente semelhantes aos da produção para evitar a introdução de riscos. Esse equilíbrio garante que os testes permaneçam eficazes sem incorrer em custos desnecessários.

  • Defina SKUs usando infraestrutura como código (IaC). Implemente o IaC para selecionar e implantar dinamicamente as SKUs corretas com base no ambiente. Essa abordagem aumenta a consistência e simplifica o gerenciamento.

Por exemplo, a implementação de referência usa parâmetros Bicep para implantar camadas mais caras (SKUs) no ambiente de produção.

    var redisCacheSkuName = isProd ? 'Standard' : 'Basic'
    var redisCacheFamilyName = isProd ? 'C' : 'C'
    var redisCacheCapacity = isProd ? 1 : 0

Implementar dimensionamento automático

O dimensionamento automático garante que um aplicativo Web permaneça resiliente, responsivo e capaz de lidar com cargas de trabalho dinâmicas de forma eficiente. Para implementar o dimensionamento automático, siga estas recomendações:

  • Automatize o dimensionamento. Use o dimensionamento automático do Azure para automatizar o dimensionamento horizontal em ambientes de produção. Configure regras de dimensionamento automático para dimensionamento com base nas principais métricas de desempenho, para que seu aplicativo possa lidar com cargas variáveis.

  • Refine os gatilhos de dimensionamento. Comece com a utilização da CPU como seu gatilho de dimensionamento inicial se você não estiver familiarizado com os requisitos de dimensionamento do seu aplicativo. Refine seus gatilhos de dimensionamento para incluir outras métricas, como RAM, taxa de transferência de rede e E/S de disco. O objetivo é corresponder ao comportamento do seu aplicativo Web para um melhor desempenho.

  • Forneça um buffer de expansão. Defina seus limites de dimensionamento para acionar antes de atingir a capacidade máxima. Por exemplo, configure o dimensionamento para ocorrer com 85% de utilização da CPU em vez de esperar até atingir 100%. Essa abordagem proativa ajuda a manter o desempenho e a evitar possíveis gargalos.

Automatizar a implementação de recursos

Use a automação para implantar e atualizar recursos e código do Azure em todos os ambientes. Siga estas recomendações:

  • Use a infraestrutura como código. Implante a infraestrutura como código por meio de pipelines de integração contínua e entrega contínua (CI/CD). O Azure tem modelos pré-fabricados de Bicep, ARM (JSON) e Terraform para cada recurso do Azure.

  • Use um pipeline de integração contínua/implantação contínua (CI/CD). Use um pipeline de CI/CD para implantar o código do controle do código-fonte em seus vários ambientes, como teste, preparo e produção. Utilize o Azure Pipelines se estiver trabalhando com o Azure DevOps ou GitHub Actions para projetos do GitHub.

  • Integre testes de unidade. Priorize a execução e a aprovação de todos os testes de unidade em seu pipeline antes de qualquer implantação nos Serviços de Aplicativo. Incorpore ferramentas de qualidade e cobertura de código como o SonarQube para obter uma cobertura de teste abrangente.

  • Adote uma estrutura zombeteira. Para testes envolvendo endpoints externos, utilize estruturas simuladas. Essas estruturas permitem que você crie pontos de extremidade simulados. Eles eliminam a necessidade de configurar pontos de extremidade externos reais e garantem condições de teste uniformes em todos os ambientes.

  • Execute verificações de segurança. Utilize testes estáticos de segurança de aplicativos (SAST) para encontrar falhas de segurança e erros de codificação em seu código-fonte. Além disso, conduza a análise de composição de software (SCA) para examinar bibliotecas e componentes de terceiros quanto a riscos de segurança. As ferramentas para essas análises são prontamente integradas ao GitHub e ao Azure DevOps.

Implementar monitorização

Implemente o monitoramento de aplicativos e plataformas para melhorar a excelência operacional e a eficiência de desempenho de seu aplicativo Web. Para implementar o monitoramento, siga estas recomendações:

  • Colete telemetria de aplicativos. Use a autoinstrumentação no Azure Application Insights para coletar telemetria de aplicativos, como taxa de transferência de solicitação, duração média de solicitação, erros e monitoramento de dependência, sem alterações de código.

    A implementação de referência usa AddApplicationInsightsTelemetry o pacote Microsoft.ApplicationInsights.AspNetCore NuGet para habilitar a coleta de telemetria (consulte o código a seguir).

    public void ConfigureServices(IServiceCollection services)
    {
       ...
       services.AddApplicationInsightsTelemetry(Configuration["App:Api:ApplicationInsights:ConnectionString"]);
       ...
    }
    
  • Crie métricas de aplicativos personalizadas. Use instrumentação baseada em código para telemetria de aplicativo personalizada. Adicione o SDK do Application Insights ao seu código e use a API do Application Insights.

    A implementação de referência reúne telemetria em eventos relacionados à atividade do carrinho. this.telemetryClient.TrackEvent Conta os bilhetes adicionados ao carrinho. Ele fornece o nome do evento (AddToCart) e especifica um dicionário que tem o concertId e count (consulte o código a seguir).

    this.telemetryClient.TrackEvent("AddToCart", new Dictionary<string, string> {
        { "ConcertId", concertId.ToString() },
        { "Count", count.ToString() }
    });
    
  • Monitore a plataforma. Habilite o diagnóstico para todos os serviços suportados e envie diagnósticos para o mesmo destino que os logs do aplicativo para correlação. Os serviços do Azure criam logs de plataforma automaticamente, mas só os armazenam quando você habilita o diagnóstico. Habilite as configurações de diagnóstico para cada serviço que ofereça suporte a diagnósticos.

Implantar a implementação de referência

A implementação de referência orienta os desenvolvedores por meio de uma migração simulada de um aplicativo ASP.NET local para o Azure, destacando as alterações necessárias durante a fase inicial de adoção. Este exemplo usa um aplicativo de venda de ingressos para concertos para a empresa fictícia Relecloud, que vende ingressos por meio de seu aplicativo Web local. O Relecloud definiu as seguintes metas para sua aplicação web:

  • Implemente alterações de código de baixo custo e alto valor
  • Atingir um objetivo de nível de serviço (SLO) de 99,9%
  • Adote práticas de DevOps
  • Crie ambientes otimizados em termos de custos
  • Aumente a fiabilidade e a segurança

A Relecloud determinou que sua infraestrutura local não era uma solução econômica para atingir essas metas. Eles decidiram que migrar seu aplicativo Web CAMS para o Azure era a maneira mais econômica de alcançar seus objetivos imediatos e futuros. A arquitetura a seguir representa o estado final da implementação do padrão Reliable Web App do Relecloud.

Diagrama mostrando a arquitetura da implementação de referência.Figura 3. Arquitetura da implementação de referência. Baixe um arquivo Visio desta arquitetura.