Exercício - Implementar resiliência de aplicativos
O projeto 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 atuais disponíveis para compra.
A versão atual do aplicativo não tem manipulação de resiliência. Se o serviço Product não estiver disponível, o serviço Store 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 serviço Store 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 , utilize este link de criação para criar um Codespace do GitHub pré-configurado com .
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 Visual Studio Code, clone o repositório https://github.com/MicrosoftDocs/mslearn-dotnet-cloudnative para sua máquina local. Em seguida:
- Instale qualquer 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: >Dev Containers: Reconstruir e Reabrir no Contêiner
- Selecione eShopLite - dotnet-resiliency na lista suspensa. O Visual Studio Code cria seu contêiner de desenvolvimento localmente.
Criar e executar o aplicativo
No painel inferior, selecione o separador TERMINAL e execute o seguinte comando para aceder à raiz do código:
cd dotnet-resiliencyExecute o seguinte comando para criar as imagens do aplicativo eShop:
dotnet publish /p:PublishProfile=DefaultContainerQuando a compilação for concluída, execute o seguinte comando para iniciar o aplicativo:
docker compose upNo 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 estiver a executar a aplicação localmente, abra uma janela do browser para ver
http://localhost:32000/products.A aplicação eShop deve estar em execução. Selecione o Produtos item de menu, você verá a lista de produtos.
Testar a resiliência atual
Pare o serviço do produto para ver o que acontece com a aplicação.
Volte ao seu espaço de código 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 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 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 6ba80f3c7ab0Volte 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 codespace e, no TERMINAL selecione o docker terminal e pressione Ctrl+C para parar o aplicativo. Você deve 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 pacote NuGet Microsoft.Extensions.Http.Resilience 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 StoreExecute o seguinte comando para adicionar o pacote NuGet de resiliência:
dotnet add package Microsoft.Extensions.Http.ResilienceA execução deste comando a partir do terminal na pasta do projeto de apps adiciona a referência do pacote ao arquivo de projeto Store.csproj.
Na barra lateral do EXPLORER, selecione Program.cs.
No topo do ficheiro, adicione a seguinte instrução using:
using Microsoft.Extensions.Http.Resilience;
Adicionar uma estratégia de resiliência padrão
Na Linha 13, antes ;, adicione este código:
.AddStandardResilienceHandler()Seu código deve ter esta aparência:
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=DefaultContainerQuando a compilação for concluída, execute o seguinte comando para iniciar o aplicativo:
docker compose upVolte 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, na guia TERMINAL, selecione o segundo terminal bash. Copie o ID do CONTAINER para o contentor 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 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 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 nova tentativa. 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=DefaultContainerQuando a compilação for concluída, execute o seguinte comando para iniciar o aplicativo:
docker compose upPare 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=DefaultContainerQuando 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 Docker.
No painel DOCKER, em CONTAINERS, clique com o botão direito do rato no contentor 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 para o seu codespace e, na guia TERMINAL, selecione o docker terminal. A estratégia de resiliência está a funcionar.
No painel DOCKER, em CONTÊINERS, clique com o botão direito do mouse no contêiner 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.