Exercício - Implementar resiliência de aplicativos
O projeto eShop tem dois serviços que se comunicam entre si usando solicitações HTTP. O Store
serviço chama o Product
serviço para obter a lista de todos os produtos atuais disponíveis para compra.
A versão atual do aplicativo não tem manipulação de resiliência. Se o Product
serviço não estiver disponível, o Store
serviço devolve um erro aos clientes e pede-lhes para tentarem novamente mais tarde. Esse comportamento não é uma boa experiência do usuário.
Seu gerente solicita que você adicione resiliência ao aplicativo, para que o Store
serviço tente novamente a chamada de serviço de back-end se ela falhar.
Neste exercício, você adiciona resiliência a um aplicativo nativo da nuvem existente e testa sua correção.
Abra o ambiente de desenvolvimento
Você pode optar por usar um espaço de código GitHub que hospeda o exercício ou concluí-lo localmente no Visual Studio Code.
Para usar um codespace, crie um Codespace GitHub pré-configurado com este link de criação do Codespace.
O GitHub leva vários minutos para criar e configurar o espaço de código. Quando o processo for concluído, você verá os arquivos de código para o exercício. O código a ser usado para o restante deste módulo está no diretório /dotnet-resiliency .
Para usar o Visual Studio Code, clone o https://github.com/MicrosoftDocs/mslearn-dotnet-cloudnative repositório para sua máquina local. Em seguida:
- Instale quaisquer requisitos do sistema para executar o Dev Container no Visual Studio Code.
- Verifique se o Docker está em execução.
- Em uma nova janela do Visual Studio Code, abra a pasta do repositório clonado
- Pressione Ctrl+Shift+P para abrir a paleta de comandos.
- Pesquisa: >Contêineres de desenvolvimento: reconstruir e reabrir no contêiner
- Selecione eShopLite - dotnet-resiliency na lista suspensa. O Visual Studio Code cria seu contêiner de desenvolvimento localmente.
Compilar e executar a aplicação
No painel inferior, selecione a guia TERMINAL e execute o seguinte comando vá para a raiz do código:
cd dotnet-resiliency
Execute o seguinte comando para criar as imagens do aplicativo eShop:
dotnet publish /p:PublishProfile=DefaultContainer
Quando a compilação for concluída, execute o seguinte comando para iniciar o aplicativo:
docker compose up
No painel inferior, selecione a guia PORTAS e, em seguida, na coluna Endereço Encaminhado da tabela, selecione o ícone Abrir no navegador para a porta Front-End (32000).
Se você estiver executando o aplicativo localmente, abra uma janela do navegador para exibir
http://localhost:32000/products
o .A aplicação eShop deve estar em execução. Selecione o item de menu Produtos , você verá a lista de produtos.
Testar a resiliência atual
Pare o serviço do produto para ver o que acontece com o aplicativo.
Volte ao seu codespace e, na guia TERMINAL , selecione + para abrir um novo terminal bash.
Execute o seguinte comando docker para listar os contêineres em execução:
docker ps
Você deve ver a lista de contêineres em execução no momento, por exemplo:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES c08285e8aaa4 storeimage "dotnet Store.dll" 8 minutes ago Up 8 minutes 80/tcp, 443/tcp, 0.0.0.0:5902->8080/tcp, :::5902->8080/tcp eshoplite-frontend-1 6ba80f3c7ab0 productservice "dotnet Products.dll" 8 minutes ago Up 8 minutes 80/tcp, 443/tcp, 0.0.0.0:5200->8080/tcp, :::5200->8080/tcp eshoplite-backend-1 cd0c822a5222 vsc-eshoplite-958868d22c9851dd911b2423199bfc782861d1a8f7afac48e5096a1b7516082f "/bin/sh -c 'echo Co…" 27 minutes ago Up 27 minutes
Procure o ID do CONTAINER para o contêiner productservice . No exemplo acima, o ID é 6ba80f3c7ab0.
Pare o serviço do produto com este comando docker:
docker stop <CONTAINER ID>
Onde o
<CONTAINER ID>
é o ID que você encontrou na etapa anterior. Por exemplo:docker stop 6ba80f3c7ab0
Volte para a guia do navegador que executa o aplicativo e atualize a página. Deverá ver uma mensagem de erro:
Existe um problema ao carregar os nossos produtos. Tente novamente mais tarde.
Volte para o seu espaço de código e, no TERMINAL , selecione o terminal docker e pressione Ctrl+C para parar o aplicativo. Deverá ver:
Gracefully stopping... (press Ctrl+C again to force) Aborting on container exit... [+] Stopping 2/1 ✔ Container eshoplite-frontend-1 Stopped 0.3s ✔ Container eshoplite-backend-1 Stopped 0.0s canceled
Adicionar resiliência ao aplicativo
As primeiras etapas para tornar seu aplicativo mais resiliente são adicionar o Microsoft.Extensions.Http.Resilience
pacote NuGet ao projeto. Você pode usá-lo em Program.cs.
Adicione o pacote Microsoft.Extensions.Http.Resilience
No seu espaço de código, na guia TERMINAL , navegue até a pasta do projeto Store :
cd Store
Execute o seguinte comando para adicionar o pacote NuGet de resiliência:
dotnet add package Microsoft.Extensions.Http.Resilience
A execução deste comando a partir do terminal na pasta do projeto apps adiciona a referência do pacote ao arquivo de projeto Store.csproj .
Na barra lateral do EXPLORER, selecione Program.cs.
Na parte superior do arquivo, adicione a seguinte instrução using:
using Microsoft.Extensions.Http.Resilience;
Adicionar uma estratégia de resiliência padrão
Na Linha 13, antes de ;, adicione este código:
.AddStandardResilienceHandler()
O código deverá ser semelhante a:
builder.Services.AddHttpClient<ProductService>(c => { var url = builder.Configuration["ProductEndpoint"] ?? throw new InvalidOperationException("ProductEndpoint is not set"); c.BaseAddress = new(url); }).AddStandardResilienceHandler();
O código acima adiciona um manipulador de resiliência padrão ao HTTPClient. O manipulador usa todas as configurações padrão para a estratégia de resiliência padrão.
Nenhuma outra alteração de código é necessária para seu aplicativo. Vamos executar o aplicativo e testar a resiliência.
Execute os seguintes comandos para reconstruir o aplicativo eShop:
cd .. dotnet publish /p:PublishProfile=DefaultContainer
Quando a compilação for concluída, execute o seguinte comando para iniciar o aplicativo:
docker compose up
Volte para a guia do navegador que executa o aplicativo e atualize a página do produto. Você deve ver a lista de produtos.
Volte ao seu codespace e, no separador TERMINAL , selecione o segundo terminal bash. Copie o ID do CONTAINER para o contêiner productservice .
Execute novamente o comando docker stop:
docker stop <CONTAINER ID>
Volte para a guia do navegador que executa o aplicativo e atualize a página do produto. Desta vez, deve demorar um pouco mais até ver a mensagem de erro das aplicações:
Há um problema ao carregar os nossos produtos. Tente novamente mais tarde.
Vamos verificar os logs para ver se nossa estratégia de resiliência está funcionando.
Volte ao seu codespace e, na guia TERMINAL, selecione o terminal docker.
No terminal, pressione Ctrl+C para interromper a execução do aplicativo.
Nas mensagens de registo, desloque-se para cima até encontrar referências a Polly.
eshoplite-frontend-1 | warn: Polly[3] eshoplite-frontend-1 | Execution attempt. Source: 'ProductService-standard//Standard-Retry', Operation Key: '', Result: 'Name or service not known (backend:8080)', Handled: 'True', Attempt: '2', Execution Time: '27.2703'
Você deve ver muitas mensagens como esta; cada uma é uma tentativa de repetição. A mensagem acima mostra a segunda tentativa e o tempo que levou para ser executada.
Configurar uma estratégia de resiliência
Ao adicionar resiliência ao seu aplicativo, você está equilibrando a necessidade de responder rapidamente aos usuários com a necessidade de não sobrecarregar nenhum serviço de back-end. Somente você pode decidir se as opções padrão atendem às necessidades da sua empresa.
Neste exemplo, você gostaria que o serviço da loja esperasse um pouco mais, para dar ao serviço da loja uma chance de recuperação.
Na janela de código para Program.cs, altere o código na linha 13 para:
.AddStandardResilienceHandler(options => { options.Retry.MaxRetryAttempts = 7; });
O código acima altera o padrão da estratégia de repetição para ter um número máximo de aposentados para sete. Lembre-se que a estratégia é um recuo exponencial, então o tempo total é de cerca de 5 minutos.
Pare o docker com Ctrl+C. Em seguida, execute o seguinte comando para reconstruir o aplicativo eShop:
dotnet publish /p:PublishProfile=DefaultContainer
Quando a compilação for concluída, execute o seguinte comando para iniciar o aplicativo:
docker compose up
Pare o contêiner de serviço de back-end no terminal bash e atualize a eShop. Observe que leva mais tempo para ver a mensagem de erro. Se você verificar os registros, porém, poderá ver que a estratégia de repetição só foi repetida cinco vezes. A última mensagem de Polly é:
Polly.Timeout.TimeoutRejectedException: The operation didn't complete within the allowed timeout of '00:00:30'.
A mensagem acima informa que o tempo limite total da solicitação impede que o número máximo de novas tentativas seja atingido. Você pode corrigir o problema aumentando o tempo limite total da solicitação.
No terminal, pressione Ctrl+C para parar o aplicativo.
Na janela de código para Program.cs, altere o código na linha 13 para:
.AddStandardResilienceHandler(options => { options.Retry.RetryCount = 7; options.TotalRequestTimeout = new HttpTimeoutStrategyOptions { Timeout = TimeSpan.FromMinutes(5) }; });
O código acima altera o tempo limite total da solicitação para 260 segundos, que agora é mais longo do que a estratégia de repetição.
Com essas alterações, você deve ter tempo suficiente para executar o aplicativo, parar o serviço do produto, verificar os logs do terminal para tentativas de novas tentativas, atualizar a eShop para ver a mensagem de carregamento e, finalmente, reiniciar o serviço do produto para ver com êxito a lista de produtos.
Execute o seguinte comando para reconstruir o aplicativo eShop:
dotnet publish /p:PublishProfile=DefaultContainer
Quando a compilação for concluída, execute o seguinte comando para iniciar o aplicativo:
docker compose up
Testar as novas opções de resiliência
Para ajudar a testar o aplicativo em seu contêiner, use a extensão Docker. A extensão fornece uma GUI para visualizar e controlar o estado dos contêineres.
No menu à esquerda, selecione o ícone do Docker .
No painel DOCKER, em CONTÊINERES, clique com o botão direito do mouse no contêiner de produtos e selecione Parar.
Volte para a guia do navegador que executa o aplicativo e atualize a página do produto. Deverá ver a mensagem Carregando...
Volte ao seu codespace e, na guia TERMINAL , selecione o terminal docker . A estratégia de resiliência está a funcionar.
No painel DOCKER, em CONTÊINERES, clique com o botão direito do mouse no contêiner de produtos e selecione Iniciar.
Volte para a guia do navegador que executa o aplicativo. Aguarde e o aplicativo deve recuperar mostrando a lista dos produtos.
No Terminal, pare o docker com Ctrl+C.