Ejercicio: Implementación de la resistencia de la aplicación

Completado

El proyecto de eShop tiene dos servicios que se comunican entre sí mediante solicitudes HTTP. El servicio Store llama al servicio Product para obtener la lista de todos los productos actuales disponibles para comprar.

La versión actual de la aplicación no tiene ningún control de resistencia. Si el Product servicio no está disponible, el Store servicio devuelve un error a los clientes y les pide que vuelvan a intentarlo más tarde. Este comportamiento no es una buena experiencia del usuario.

El administrador le pide que agregue resiliencia a la aplicación para que el Store servicio vuelva a intentar la llamada al servicio de backend si falla.

En este ejercicio, añades resiliencia a una aplicación nativa de la nube existente y pruebas tu corrección.

Abrir el entorno de desarrollo

Puede optar por usar un codespace de GitHub que hospede el ejercicio, o bien hacer el ejercicio localmente en Visual Studio Code.

Para usar un codespace, cree un codespace de GitHub preconfigurado con este vínculo de creación de Codespace.

GitHub tarda varios minutos en crear y configurar el espacio de código. Cuando se complete el proceso, verá los archivos de código del ejercicio. El código que se va a usar para el resto de este módulo está en el directorio /dotnet-resiliency .

Para usar Visual Studio Code, clone el repositorio https://github.com/MicrosoftDocs/mslearn-dotnet-cloudnative en la máquina local. A continuación:

  1. Instale cualquier requisito del sistema para ejecutar Dev Container en Visual Studio Code.
  2. Asegúrese de que Docker se está ejecutando.
  3. En una ventana nueva de Visual Studio Code, abra la carpeta del repositorio clonado
  4. Presione Ctrl+Mayús+P para abrir la paleta de comandos.
  5. Buscar: >Contenedores de desarrollo: Recompilar y volver a abrir en contenedor
  6. Seleccione eShopLite - dotnet-resiliency en la lista desplegable. Visual Studio Code crea el contenedor de desarrollo localmente.

Compilación y ejecución de la aplicación

  1. En el panel inferior, seleccione la pestaña TERMINAL y ejecute el siguiente comando ir a la raíz del código:

    cd dotnet-resiliency
    
  2. Ejecute el siguiente comando para compilar las imágenes de la aplicación eShop:

    dotnet publish /p:PublishProfile=DefaultContainer
    
  3. Una vez completada la compilación, ejecute el siguiente comando para iniciar la aplicación:

    docker compose up
    
  4. En el panel inferior, seleccione la pestaña PUERTOS y, a continuación, en la columna Dirección reenviada de la tabla, seleccione el icono Abrir en el explorador para el puerto front-end (32000).

    Si ejecuta la aplicación localmente, abra una ventana del explorador para ver http://localhost:32000/products.

  5. La aplicación eShop debería estar funcionando. Seleccione el elemento de menú Productos , debería ver la lista de productos.

    Captura de pantalla que muestra la aplicación eShop que se ejecuta en un explorador.

Prueba de la resistencia actual

Detenga el servicio de producto para ver lo que sucede con la aplicación.

  1. Vuelva al espacio de código y, en la pestaña TERMINAL , seleccione + para abrir un nuevo terminal de Bash.

  2. Ejecute el siguiente comando de Docker para enumerar los contenedores en ejecución:

    docker ps
    

    Deberías ver la lista de contenedores que se están ejecutando actualmente, por ejemplo:

    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     
    
  3. Busque el identificador de contenedor para el contenedor productservice . En el ejemplo anterior, el identificador es 6ba80f3c7ab0.

  4. Detenga el servicio de producto con este comando de Docker:

    docker stop <CONTAINER ID>
    

    Donde <CONTAINER ID> es el identificador que encontró en el paso anterior. Por ejemplo:

    docker stop 6ba80f3c7ab0
    
  5. Vuelva a la pestaña del explorador que ejecuta la aplicación y actualice la página. Debería ver un mensaje de error:

    Hay un problema al cargar nuestros productos. Inténtelo de nuevo más tarde.

  6. Vuelva al espacio de código y, en terminal, seleccione el terminal de Docker y presione Ctrl+C para detener la aplicación. Debería ver lo siguiente:

    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
    

Adición de resistencia a la aplicación

Los primeros pasos para que la aplicación sea más resistente son agregar el Microsoft.Extensions.Http.Resilience paquete NuGet al proyecto. Después, puede usarlo en Program.cs.

Adición del paquete Microsoft.Extensions.Http.Resilience

  1. En su espacio de código, en la pestaña TERMINAL, vaya a la carpeta del proyecto Store:

    cd Store
    
  2. Ejecute el siguiente comando para agregar el paquete NuGet de resistencia:

    dotnet add package Microsoft.Extensions.Http.Resilience
    

    Al ejecutar este comando desde el terminal de la carpeta del proyecto de aplicaciones, se agrega la referencia del paquete al archivo de proyecto Store.csproj .

  3. En la barra lateral EXPLORER , seleccione Program.cs.

  4. En la parte superior del archivo, agregue la siguiente instrucción using:

    using Microsoft.Extensions.Http.Resilience;
    

Adición de una estrategia de resistencia estándar

  1. En la línea 13, antes de ;, agregue este código:

    .AddStandardResilienceHandler()
    

    El código debe ser similar al siguiente:

    builder.Services.AddHttpClient<ProductService>(c =>
    {
        var url = builder.Configuration["ProductEndpoint"] ?? throw new InvalidOperationException("ProductEndpoint is not set");
    
        c.BaseAddress = new(url);
    }).AddStandardResilienceHandler();
    

    El código anterior agrega un controlador de resistencia estándar a HTTPClient. El controlador usa toda la configuración predeterminada para la estrategia de resistencia estándar.

    No se necesitan otros cambios de código en la aplicación. Vamos a ejecutar la aplicación y probar la resistencia.

  2. Ejecute los siguientes comandos para recompilar la aplicación eShop:

    cd ..
    dotnet publish /p:PublishProfile=DefaultContainer
    
  3. Cuando se complete la compilación, ejecute el siguiente comando para iniciar la aplicación:

    docker compose up
    
  4. Vuelva a la pestaña del explorador que ejecuta la aplicación y actualice la página del producto. Usted debería ver la lista de productos.

  5. Vuelva al espacio de código y, en la pestaña TERMINAL , seleccione el segundo terminal de Bash. Copie el ID del contenedor productservice.

  6. Vuelva a ejecutar el comando docker stop:

    docker stop <CONTAINER ID>
    
  7. Vuelva a la pestaña del explorador que ejecuta la aplicación y actualice la página del producto. Esta vez, debería tardar un poco más hasta que vea el mensaje de error de las aplicaciones:

    Hay un problema al cargar nuestros productos. Inténtelo de nuevo más tarde.

    Vamos a comprobar los registros para ver si nuestra estrategia de resistencia funciona.

  8. Vuelva al espacio de código y, en la pestaña TERMINAL , seleccione el terminal de Docker .

  9. En el terminal, presione Ctrl+C para detener la ejecución de la aplicación.

  10. En los mensajes de registro, desplácese hacia arriba hasta que encuentre referencias 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'
    

    Debería ver muchos mensajes como este; cada uno de ellos es un reintento. El mensaje anterior muestra el segundo intento y el tiempo que tardó en ejecutarse.

Configuración de una estrategia de resistencia

Al agregar resistencia a la aplicación, equilibra la necesidad de responder rápidamente a los usuarios, con la necesidad de no sobrecargar ningún servicio back-end. Solo puede decidir si las opciones predeterminadas satisfacen sus necesidades de negocio.

En este ejemplo, le gustaría que el servicio de la tienda espere un poco más, para dar al servicio de la tienda la oportunidad de recuperarse.

  1. En la ventana de código de Program.cs, cambie el código de la línea 13 a:

    .AddStandardResilienceHandler(options =>
    {
        options.Retry.MaxRetryAttempts = 7;
    });
    

    El código anterior cambia el valor predeterminado de la estrategia de reintento para tener un número máximo de retiros a siete. Recuerde que la estrategia es un retroceso exponencial, por lo que el tiempo total es de aproximadamente 5 minutos.

  2. Detenga Docker con Ctrl+C. A continuación, ejecute el siguiente comando para recompilar la aplicación eShop:

    dotnet publish /p:PublishProfile=DefaultContainer
    
  3. Cuando se complete la compilación, ejecute el siguiente comando para iniciar la aplicación:

    docker compose up
    

    Detenga el contenedor del servicio back-end en el terminal de Bash y actualice eShop. Tenga en cuenta que tarda más tiempo en ver el mensaje de error. Sin embargo, si comprueba los registros, puede ver que la estrategia de reintento solo se reintenta cinco veces. El último mensaje de Polly es:

    Polly.Timeout.TimeoutRejectedException: The operation didn't complete within the allowed timeout of '00:00:30'.
    

    El mensaje anterior indica que el tiempo de espera total de solicitudes impide que se alcance el número máximo de reintentos. Puede corregir el problema aumentando el tiempo de espera total de la solicitud.

  4. En el terminal, presione Ctrl+C para detener la aplicación.

  5. En la ventana de código de Program.cs, cambie el código de la línea 13 a:

    .AddStandardResilienceHandler(options =>
    {
        options.Retry.RetryCount = 7;
        options.TotalRequestTimeout = new HttpTimeoutStrategyOptions
        {
            Timeout = TimeSpan.FromMinutes(5)
        };
    });
    

    El código anterior cambia el tiempo de espera total de la solicitud a 260 segundos, que ahora es más largo que la estrategia de reintento.

    Con estos cambios debe tener tiempo suficiente para ejecutar la aplicación, detener el servicio de producto, comprobar los registros de terminal para los reintentos, actualizar eShop para ver el mensaje de carga y, por último, reiniciar el servicio de producto para ver correctamente la lista de productos.

  6. Ejecute el siguiente comando para recompilar la aplicación eShop:

    dotnet publish /p:PublishProfile=DefaultContainer
    
  7. Cuando se complete la compilación, ejecute el siguiente comando para iniciar la aplicación:

    docker compose up
    

Prueba de las nuevas opciones de resistencia

Para ayudar a probar la aplicación en el contenedor, use la extensión de Docker. La extensión proporciona una GUI para ver y controlar el estado de los contenedores.

  1. En el menú de la izquierda, seleccione el icono de Docker .

    Captura de pantalla de la extensión docker que muestra cómo detener el servicio de productos.

  2. En el panel DOCKER , en CONTENEDORES, haga clic con el botón derecho en el contenedor de productos y seleccione Detener.

  3. Vuelva a la pestaña del explorador que ejecuta la aplicación y actualice la página del producto. Debería ver el mensaje Loading... (Cargando...) .

  4. Vuelva al espacio de código y, en la pestaña TERMINAL , seleccione el terminal de Docker . La estrategia de resistencia funciona.

  5. En el panel DOCKER , en CONTENEDORES, haga clic con el botón derecho en el contenedor de productos y seleccione Iniciar.

  6. Vuelva a la pestaña del explorador que ejecuta la aplicación. Espere y la aplicación debe recuperarse mostrando la lista de los productos.

  7. En el terminal, detenga Docker con Ctrl+C.