Ejercicio: Refactorización de un servicio como microservicio dentro de la aplicación monolítica

Completado

Ahora que Fabrikam ha terminado de analizar su aplicación, están listos para iniciar el proceso de refactorización con el fin de trasladar los servicios de su arquitectura monolítica a los microservicios. Se modificará la aplicación para pasar el servicio de procesamiento de paquetes a un microservicio.

Visualization of the resources for the Drone Delivery application.

Refactorización de la aplicación

Antes de implementar la aplicación actualizada, se describirá cómo se ha actualizado. La aplicación monolítica tiene un servicio para procesar los paquetes, PackageProcessor.cs. Después de analizar el rendimiento de la aplicación, este servicio se ha identificado como un cuello de botella de rendimiento. A medida que los clientes aumentan la demanda de entregas mediante drones, la carga de este servicio se incrementa de forma intensiva mientras controla la programación y la logística de las entregas. Un equipo dedicado administra por completo este servicio, por lo que moverlo a un microservicio ayuda con el rendimiento y proporciona una mayor agilidad de desarrollo.

Se analizarán con más detalle los cambios que se han realizado.

Drone Delivery antes

La clase PackageProcessor controla la funcionalidad principal del procesamiento de paquetes en el archivo PackageProcessor.cs. En este ejemplo, realiza un trabajo que consume muchos recursos. Es posible que en un escenario real se incluyera el cálculo de los tiempos de entrega, las rutas de entrega y la actualización de los orígenes de datos con esta información.

public class PackageProcessor : IPackageProcessor
    {
        public Task<PackageGen> CreatePackageAsync(PackageInfo packageInfo)
        {
            //Uses common data store e.g. SQL Azure tables
            Utility.DoWork(100);
            return Task.FromResult(new PackageGen { Id = packageInfo.PackageId });
        }
    }

A medida que aumentan las solicitudes de este servicio, se incrementa el uso de recursos y se limita a los recursos físicos asignados a la aplicación monolítica. Si este servicio se implementa en Azure App Service, se puede escalar vertical y horizontalmente. Lo ideal es que este recurso de uso intensivo se escale de forma independiente para optimizar el rendimiento y los costos. En este escenario, se usa Azure Functions para hacerlo.

Drone Delivery después

Echemos un vistazo al código de aplicación DroneDelivery-after antes de implementarlo. Puede ver que la clase PackageProcessor se cambió a una clase PackageServiceCaller. Todavía implementa la interfaz IPackageProcessor, pero en su lugar realiza una llamada HTTP al microservicio.

public class PackageServiceCaller : IPackageProcessor
    {
        private readonly HttpClient httpClient;

        public static string FunctionCode { get; set; }

        public PackageServiceCaller(HttpClient httpClient)
        {
            this.httpClient = httpClient;
        }

        public async Task<PackageGen> CreatePackageAsync(PackageInfo packageInfo)
        {
            var result = await httpClient.PutAsJsonAsync($"{packageInfo.PackageId}?code={FunctionCode}", packageInfo);
            result.EnsureSuccessStatusCode();

            return new PackageGen { Id = packageInfo.PackageId };
        }
    }

El microservicio se implementa en una función de Azure. Su código se puede encontrar en PackageServiceFunction.cs y contiene el código siguiente.

public static class PackageServiceFunction
    {
        [FunctionName("PackageServiceFunction")]
        public static Task<IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Function, "put", Route = "packages/{id}")] HttpRequest req,
            string id, ILogger log)
        {
            log.LogInformation("C# HTTP trigger function processed a request.");

            //Uses common data store e.g. SQL Azure tables
            Utility.DoWork(100);
            return Task.FromResult((IActionResult)new CreatedResult("http://example.com", null));
        }
    }

Al colocar este código en Azure Functions, este servicio se puede escalar de forma independiente a medida que aumente la carga de usuarios. Puede mantener los servicios del código de aplicación restante optimizados para el resto de la aplicación. El servicio de paquetes se escala horizontalmente a medida que el sistema de entregas mediante drones recibe más solicitudes.

Ahora se volverá a implementar la aplicación. En primer lugar, se implementa el servicio refactorizado en Azure Functions. Después, se implementa la aplicación refactorizada en App Service y se apunta a la función.

Implementación de la aplicación de funciones

  1. Ejecute el siguiente comando para configurar las variables de entorno que apuntan a los servicios.

    APPSERVICENAME="$(az webapp list \
                        --resource-group "<rgn>[sandbox resource group]</rgn>" \
                        --query '[].name' \
                        --output tsv)"
    FUNCTIONAPPNAME="$(az functionapp list \
                        --resource-group "<rgn>[sandbox resource group]</rgn>" \
                        --query '[].name' \
                        --output tsv)"
    
  2. A continuación, se compilará y comprimirá el código de aplicación de la aplicación de funciones.

    cd ~/mslearn-microservices-architecture/src/after
    dotnet build ./PackageService/PackageService.csproj -c Release
    cd PackageService/bin/Release/netcoreapp2.2
    zip -r PackageService.zip .
    
  3. Ejecute el siguiente comando para enviar el código a la aplicación de funciones.

    az functionapp deployment source config-zip \
        --resource-group "<rgn>[sandbox resource group]</rgn>" \
        --name $FUNCTIONAPPNAME \
        --src PackageService.zip
    

Implementación de la aplicación Drone Delivery actualizada

Ahora que el servicio se ejecuta en Azure Functions, es necesario apuntar la aplicación de drones a esa aplicación de funciones.

  1. En primer lugar, es necesario obtener el código de acceso de la aplicación de funciones, para poder llamarlo correctamente desde la aplicación. Ejecute los comandos siguientes para recuperar este código. Se mostrará el código y el nombre de la aplicación de funciones para usarlos en los pasos siguientes.

    RESOURCEGROUPID=$(az group show \
                        --resource-group "<rgn>[sandbox resource group]</rgn>" \
                        --query id \
                        --output tsv)
    FUNCTIONCODE=$(az rest \
                        --method post \
                        --query default \
                        --output tsv \
                        --uri "https://management.azure.com$RESOURCEGROUPID/providers/Microsoft.Web/sites/$FUNCTIONAPPNAME/functions/PackageServiceFunction/listKeys?api-version=2018-02-01")
    echo "FunctionName - $FUNCTIONAPPNAME"
    echo "FunctionCode - $FUNCTIONCODE"
    
  2. En Azure Cloud Shell, ejecute los siguientes comandos para abrir appsettings.json en el editor de código.

    cd ~/mslearn-microservices-architecture/src/after
    code ./DroneDelivery-after/appsettings.json
    
  3. En el editor de código, reemplace los valores PackageServiceUri y PackageServiceFunctionCode. En PackageServiceUri, reemplace <FunctionName> por el nombre de la aplicación de funciones.

    En PackageServiceFunctionCode, reemplace <FunctionCode> por el código de función que ha recuperado. El archivo appsettings.json debe tener un aspecto similar al de este ejemplo:

    {
        "Logging": {
        "LogLevel": {
            "Default": "Warning"
        }
        },
        "AllowedHosts": "*",
        "PackageServiceUri": "https://packageservicefunction-abc.azurewebsites.net/api/packages/",
        "PackageServiceFunctionCode": "SvrbiyhjXJUdTPXrkcUtY6bQaUf7OXQjWvnM0Gq63hFUhbH2vn6qYA=="
    }
    
  4. Presione Ctrl+S para guardar el archivo y, después, Ctr+Q para cerrar el editor de código.

  5. Ejecute el siguiente comando para implementar la aplicación actualizada en App Service.

    zip -r DroneDelivery-after.zip . -x \*/obj/\* \*/bin/\*
    az webapp deploy \
        --resource-group "<rgn>[sandbox resource group]</rgn>" \
        --name $APPSERVICENAME \
        --src-path DroneDelivery-after.zip
    
  6. Con el sitio implementado, actualice la página. Ahora debería actualizarse.

    Screenshot of the redeployed Drone Delivery website.

Comprobación del rendimiento de la nueva arquitectura

Ahora que el servicio restringido de recursos se mueve a un microservicio que se ejecuta en Azure Functions, se verá cómo ha afectado este cambio al rendimiento de la aplicación.

  1. En la página principal del sitio web, seleccione Send Requests (Enviar solicitudes). Esta acción envía solicitudes desde la aplicación monolítica al microservicio que se ejecuta en una función de Azure.

  2. Es posible que el primer intento genere resultados similares a los de la aplicación monolítica. Actualice la página y vuelva a enviar la solicitud si se le pide. Repita este paso varias veces; debería ver 100 messages sent in 1 second (100 mensajes enviados en 1 segundo).

    Screenshot of performance of the Drone Delivery site after moving to a microservices architecture.

El intento inicial ha sido más lento mientras se iniciaba la aplicación de funciones. Una vez en ejecución, el tiempo de respuesta fue mejor que cuando este código se ejecutaba en la arquitectura monolítica.

Ahora este fragmento de la arquitectura se puede escalar horizontalmente casi de forma infinita, al tiempo que proporciona el mismo rendimiento. Al cambiar este código de aplicación a un microservicio, mejoramos el rendimiento de cinco a diez veces. Como Fabrikam tiene un equipo de desarrollo dedicado para este servicio, también pueden iterar en este microservicio y obtener las ventajas de una mayor agilidad y versiones de características.