Exercício – Refatorar um serviço dentro do monolito como um microsserviço

Concluído

Agora que terminou de analisar o aplicativo, a Fabrikam está pronta para iniciar o processo de refatoração e migrar serviços de sua arquitetura monolítica para microsserviços. Vamos modificar o aplicativo para mover o serviço de processamento de pacotes para um microsserviço.

Visualization of the resources for the Drone Delivery application.

Refatorar o aplicativo

Antes de implantar o aplicativo atualizado, vamos ver como essa atualização foi feita. O aplicativo monolítico tem um serviço para processar pacotes, o PackageProcessor.cs. Após analisar o desempenho do aplicativo, esse serviço foi identificado como um gargalo no desempenho. Conforme a demanda dos clientes aumenta, esse serviço fica muito carregado ao manipular o agendamento e a logística das entregas por drones. Uma equipe dedicada gerencia totalmente esse serviço e, portanto, migrá-lo para um microsserviço ajuda com o desempenho e fornece maior agilidade de desenvolvimento.

Vamos examinar mais de perto as alterações que foram feitas.

Entrega por drone antes

A classe PackageProcessor se encarrega da funcionalidade básica do processamento de pacotes no arquivo PackageProcessor.cs. Neste exemplo, é realizado um trabalho com uso intensivo de recursos. Um cenário de mundo real pode incluir cálculo de tempos de entrega, rotas de entrega e atualização de fontes de dados com essas informações.

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 });
        }
    }

Conforme as solicitações por esse serviço aumentam, também aumenta o uso de recursos e o limite são os recursos físicos alocados ao aplicativo monolítico. Se esse serviço for implantado no Serviço de Aplicativo do Azure, poderemos escalá-lo vertical e horizontalmente. O ideal é que você queira que esse recurso seja amplamente utilizado para escalar de modo independente, a fim de otimizar o desempenho e os custos. Neste cenário, usaremos o Azure Functions para fazer exatamente isso.

Entrega por drone depois

Vamos examinar o código do aplicativo DroneDelivery-after antes de implantá-lo. Você pode ver que a classe PackageProcessor foi alterada para uma classe PackageServiceCaller. A interface IPackageProcessor ainda é implementada, mas, em vez disso, faz uma chamada HTTP para o microsserviço.

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 };
        }
    }

O microsserviço será implantado em uma função do Azure. O código dele pode ser encontrado em PackageServiceFunction.cs e contém o código a seguir.

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));
        }
    }

Quando você coloca esse código no Azure Functions, esse serviço pode ser dimensionado de forma independente, à medida que a carga do usuário aumenta. Você pode manter os serviços para o código de aplicativo restante otimizados para o restante do aplicativo. O serviço de pacote é dimensionado conforme mais solicitações para entregas de drone entram no sistema.

Agora, vamos reimplantar o aplicativo. Primeiro, implantamos nosso serviço refatorado no Azure Functions. Em seguida, implantamos o aplicativo refatorado no Serviço de Aplicativo e o apontamos para a função.

Implantar o aplicativo de funções

  1. Execute o comando a seguir para configurar as variáveis de ambiente apontadas para nossos serviços.

    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. Vamos criar e compactar o código do aplicativo para a o aplicativo de funções.

    cd ~/mslearn-microservices-architecture/src/after
    dotnet build ./PackageService/PackageService.csproj -c Release
    cd PackageService/bin/Release/netcoreapp2.2
    zip -r PackageService.zip .
    
  3. Execute o comando a seguir para efetuar push do código para o aplicativo de funções.

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

Implantar o aplicativo Entrega por Drone atualizado

Agora que o serviço está em execução no Azure Functions, é necessário apontar o aplicativo do drone para esse aplicativo de funções.

  1. Primeiro, é preciso obter o código de acesso do aplicativo de funções, para que possamos chamá-la do aplicativo com êxito. Execute os comandos a seguir para recuperar esse código. Você exibe o nome e o código do aplicativo de funções para usar nas próximas etapas.

    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. No Azure Cloud Shell, execute os comandos a seguir para abrir appsettings.json no editor de código.

    cd ~/mslearn-microservices-architecture/src/after
    code ./DroneDelivery-after/appsettings.json
    
  3. No editor de código, substitua os valores PackageServiceUri e PackageServiceFunctionCode. Em PackageServiceUri, substitua <FunctionName> pelo nome do aplicativo de funções.

    Em PackageServiceFunctionCode, substitua <FunctionCode> pelo código da função recuperada. O arquivo appsettings.json deverá se parecer com o seguinte exemplo:

    {
        "Logging": {
        "LogLevel": {
            "Default": "Warning"
        }
        },
        "AllowedHosts": "*",
        "PackageServiceUri": "https://packageservicefunction-abc.azurewebsites.net/api/packages/",
        "PackageServiceFunctionCode": "SvrbiyhjXJUdTPXrkcUtY6bQaUf7OXQjWvnM0Gq63hFUhbH2vn6qYA=="
    }
    
  4. Selecione Ctrl+S para salvar o arquivo e, em seguida, pressione Ctrl+Q para fechar o editor de código.

  5. Execute o comando a seguir para implantar o aplicativo atualizado no seu Serviço de Aplicativo.

    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. Após o site ter sido reimplantado, atualize sua página. Agora ele deve estar atualizado.

    Screenshot of the redeployed Drone Delivery website.

Testar o desempenho da nova arquitetura

Agora que o serviço com restrição de recursos foi migrado para um microsserviço que é executado no Azure Functions, vamos ver como essa alteração afetou o desempenho do aplicativo.

  1. Na página inicial do site, clique em Enviar Solicitações. Essa ação envia solicitações do aplicativo monolítico para o microsserviço em execução em uma função do Azure.

  2. A primeira tentativa pode fornecer resultados semelhantes ao aplicativo monolítico. Atualize a página e reenvie a solicitação, se solicitado. Execute essa etapa várias vezes e você deverá ver 100 mensagens enviadas em um segundo.

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

A tentativa inicial foi mais lenta enquanto o aplicativo de funções foi iniciado. Após estar ativo e em uso, o tempo de resposta do aplicativo ficou melhor do que quando o código estava sendo executado na arquitetura monolítica.

Agora, essa parte da arquitetura pode ser expandida quase infinitamente e ainda ter o mesmo desempenho. Com a migração desse código do aplicativo para um microsserviço, aprimoramos o desempenho de 5 a 10 vezes. Como a Fabrikam tem uma equipe de desenvolvimento dedicada a isso, a empresa também pode iterar nesse microsserviço e usufruir dos benefícios de uma maior agilidade e dos lançamentos de recursos.