Exercício – Implementar resiliência do aplicativo
O projeto do eShop tem dois serviços que se comunicam entre si usando solicitações HTTP. O serviço Store chama o serviço Product para obter a lista de todos os produtos disponíveis para compra.
A versão atual do aplicativo não tem nenhum tratamento de resiliência. Se o Product serviço não estiver disponível, o Store serviço retornará um erro aos clientes e solicitará que eles tentem 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 realizar a chamada ao serviço de backend, caso ela falhe.
Neste exercício, você adiciona resiliência a um aplicativo nativo de nuvem existente e testa sua correção.
Abrir o ambiente de desenvolvimento
Você pode optar por usar um codespace do GitHub que hospeda o exercício ou concluí-lo localmente no Visual Studio Code.
Para usar um codespace, crie um Codespace do GitHub pré-configurado com este link de criação de codespace.
O GitHub leva vários minutos para criar e configurar o codespace. Quando o processo for concluído, você verá os arquivos de código do 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 repositório https://github.com/MicrosoftDocs/mslearn-dotnet-cloudnative em seu computador local. Em seguida:
- Instale todos os requisitos do sistema para executar o Contêiner de Desenvolvimento no Visual Studio Code.
- Confira 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 o aplicativo
No painel inferior, vá para a guia TERMINAL e execute o seguinte comando para ir à raiz do código:
cd dotnet-resiliencyExecute o seguinte comando para criar as imagens do aplicativo eShop:
dotnet publish /p:PublishProfile=DefaultContainerDepois que o build for concluído, execute o seguinte comando para iniciar o aplicativo:
docker compose upNo painel inferior, selecione para a guia PORTAS e, 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 aplicativo eShop deve estar em execução. Selecione o item de menu Produtos , você deverá ver a lista de produtos.
Testar a resiliência atual
Pare o serviço de produto para ver o que acontece com o aplicativo.
Volte para o seu codespace e, na guia TERMINAL , selecione + para abrir um novo terminal bash.
Execute o seguinte comando do Docker para listar os contêineres em execução:
docker psVocê 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 minutesProcure o ID do container para o productservice. No exemplo acima, a ID é 6ba80f3c7ab0.
Interrompa o serviço de produto com este comando docker:
docker stop <CONTAINER ID>Onde
<CONTAINER ID>é a ID que você encontrou na etapa anterior. Por exemplo:docker stop 6ba80f3c7ab0Volte para a aba do navegador onde o aplicativo está sendo executado e atualize a página. Você deverá ver uma mensagem de erro:
Há um problema ao carregar nossos produtos. Tente novamente mais tarde.
Volte para o seu codespace e, no TERMINAL , selecione o terminal do docker e pressione Ctrl+C para interromper o aplicativo. Você 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. Em seguida, você pode usá-lo em Program.cs.
Adicionar o pacote Microsoft.Extensions.Http.Resilience
No seu codespace, na guia TERMINAL, navegue até a pasta do projeto Store:
cd StoreExecute o seguinte comando para adicionar o pacote NuGet de resiliência:
dotnet add package Microsoft.Extensions.Http.ResilienceExecutar esse comando do terminal na pasta de projeto de aplicativos adiciona a referência de 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()Seu código deve ficar assim:
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 recompilar o aplicativo eShop:
cd .. dotnet publish /p:PublishProfile=DefaultContainerQuando o build for concluído, execute o seguinte comando para iniciar o aplicativo:
docker compose upVolte para a guia do navegador que está executando o aplicativo e atualize a página do produto. Você deve ver a lista de produtos.
Volte para o seu codespace e, na guia TERMINAL , selecione o segundo terminal bash. Copie a ID do CONTÊINER referente ao contêiner productservice.
Execute novamente o comando docker stop:
docker stop <CONTAINER ID>Volte para a guia do navegador que está executando o aplicativo e atualize a página do produto. Desta vez, deve demorar um pouco mais até que você veja a mensagem de erro dos aplicativos:
Há um problema ao carregar nossos produtos. Tente novamente mais tarde.
Vamos verificar os logs para ver se nossa estratégia de resiliência está funcionando.
Volte para o seu codespace e, na guia TERMINAL , selecione o terminal do Docker .
No terminal, pressione Ctrl+C para interromper a execução do aplicativo.
Nas mensagens de log, role para cima até encontrar referências ao 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ê deverá encontrar muitas mensagens como esta, cada uma representando uma nova tentativa de execução. A mensagem acima mostra a segunda tentativa e o tempo necessário para executar.
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 suas necessidades de negócios.
Neste exemplo, você gostaria que o serviço da loja esperasse um pouco mais, para dar ao serviço a chance de se recuperar.
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 novas tentativas para ter um número máximo de sete tentativas. Lembre-se de que a estratégia é uma retirada exponencial, portanto, o tempo total é de cerca de 5 minutos.
Pare o Docker com Ctrl+C. Em seguida, execute o seguinte comando para recompilar o aplicativo eShop:
dotnet publish /p:PublishProfile=DefaultContainerQuando o build for concluído, execute o seguinte comando para iniciar o aplicativo:
docker compose upInterrompa o contêiner de serviço de back-end no terminal bash e atualize o eShop. Observe que leva mais tempo para ver a mensagem de erro. Se você verificar os logs, 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 a solicitação excedeu o tempo limite total, impedindo que o número máximo de tentativas seja atingido. Você pode corrigir o problema aumentando o tempo limite total da solicitação.
No terminal, pressione Ctrl+C para interromper 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 é maior do que a estratégia de repetição.
Com essas alterações, você deve ter tempo suficiente para executar o aplicativo, interromper o serviço de produto, verificar os logs de terminal para tentar novamente, atualizar o eShop para ver a mensagem de carregamento e, por fim, reiniciar o serviço de produto para ver com êxito a lista de produtos.
Execute o seguinte comando para recompilar o aplicativo eShop:
dotnet publish /p:PublishProfile=DefaultContainerQuando o build for concluído, 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 do Docker. A extensão fornece uma GUI para exibir e controlar o estado dos contêineres.
No menu à esquerda, selecione o ícone do Docker .
No painel do 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 está executando o aplicativo e atualize a página do produto. Você deve ver a mensagem Carregando...
Volte para o seu codespace e, na guia TERMINAL , selecione o terminal do Docker . A estratégia de resiliência está funcionando.
No painel do DOCKER , em CONTÊINERES, clique com o botão direito do mouse no contêiner de produtos e selecione Iniciar.
Volte para a guia navegador que executa o aplicativo. Aguarde e o aplicativo deve se recuperar mostrando a lista dos produtos.
No Terminal, interrompa o Docker com Ctrl+C.
