Exercice - Refactoriser un service dans le monolithe en tant que microservice

Effectué

Maintenant que Fabrikam a effectué l’analyse de son application, la société est maintenant prête à démarrer le processus de refactorisation pour extraire les services de leur architecture monolithique pour en faire des microservices. Nous allons modifier l’application pour déplacer le service de traitement des colis dans un microservice.

Visualization of the resources for the Drone Delivery application.

Refactoriser l’application

Avant de déployer l’application mise à jour, nous allons voir comment elle a été mise à jour. L’application monolithique dispose d’un service de traitement des colis, PackageProcessor.cs. Après l’analyse des performances de l’application, ce service a été identifié comme un goulot d’étranglement des performances. À mesure que la demande cliente de livraisons par drone augmente, la charge du service s’alourdit pendant qu’il gère la planification et la logistique des livraisons par drone. Une équipe dédiée gère entièrement ce service, de sorte que le déplacement de ce service vers un microservice favorise les performances et améliore l’agilité de développement.

Étudions les modifications apportées.

Drone Delivery avant

La classe PackageProcessor gère la fonctionnalité de base du traitement du package dans le fichier PackageProcessor.cs. Dans cet exemple, elle effectue un travail qui consomme beaucoup de ressources. Un scénario concret pourrait comprendre le calcul des délais de livraison et des itinéraires de livraison, ainsi que la mise à jour des sources de données avec ces informations.

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

Au fur et à mesure de l’augmentation du nombre de demandes pour ce service, l’utilisation des ressources augmente et elle est plafonnée aux ressources physiques allouées à l’application monolithique. Si ce service est déployé sur Azure App Service, nous pouvons le mettre à l’échelle. Dans l’idéal, vous souhaitez que cette ressource fortement utilisée soit mise à l’échelle indépendamment pour optimiser les performances et les coûts. Dans ce scénario, nous allons utiliser Azure Functions pour effectuer ces opérations.

Drone Delivery après

Examinons le code de l’application DroneDelivery-after avant son déploiement. Vous pouvez voir que la classe PackageProcessor a été changée en classe PackageServiceCaller. Il implémente toujours l’interface IPackageProcessor, mais effectue à la place un appel HTTP au microservice.

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

Le microservice est déployé sur une fonction Azure. Son code se trouve dans PackageServiceFunction.cs et contient le code suivant.

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

Lorsque vous placez ce code sur Azure Functions, ce service peut être mis à l’échelle indépendamment, à mesure que la charge utilisateur augmente. Vous pouvez vous assurer que les services du code d’application restant sont aussi optimisés pour le reste de l’application. Le service de package est mis à l’échelle au fur et à mesure que d’autres demandes de livraison par drone sont envoyées au système.

À présent, nous allons redéployer l’application. Tout d’abord, nous déployons notre service refactorisé sur Azure Functions. Ensuite, nous déployons l’application refactorisée sur App Service et nous la faisons pointer vers la fonction.

Déployer l’application de fonction

  1. Exécutez la commande suivante pour configurer les variables d’environnement afin qu’elles pointent vers nos services.

    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. Nous allons créer et compresser le code d’application pour l’application de fonction.

    cd ~/mslearn-microservices-architecture/src/after
    dotnet build ./PackageService/PackageService.csproj -c Release
    cd PackageService/bin/Release/netcoreapp2.2
    zip -r PackageService.zip .
    
  3. Exécutez la commande suivante pour envoyer (push) le code à l’application de fonction.

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

Déployer l’application Drone Delivery mise à jour

Maintenant que notre service est en cours d’exécution sur une fonction Azure, nous devons pointer notre application de drone vers cette application de fonction.

  1. Nous devons d’abord obtenir le code d’accès pour l’application de fonction, afin de pouvoir l’appeler avec succès à partir de l’application. Exécutez les commandes suivantes pour récupérer ce code. Vous afficherez le nom et le code de l’application de fonction, que vous utiliserez dans les étapes suivantes.

    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. Dans Azure Cloud Shell, exécutez les commandes suivantes pour ouvrir appsettings.json dans l’éditeur de code.

    cd ~/mslearn-microservices-architecture/src/after
    code ./DroneDelivery-after/appsettings.json
    
  3. Dans l’éditeur de code, remplacez les valeurs PackageServiceUri et PackageServiceFunctionCode. Dans PackageServiceUri, remplacez <FunctionName> par le nom de votre application de fonction.

    Dans PackageServiceFunctionCode, remplacez <FunctionCode> par le code de la fonction que vous avez récupéré. Votre fichier appsettings.json doit ressembler à cet exemple :

    {
        "Logging": {
        "LogLevel": {
            "Default": "Warning"
        }
        },
        "AllowedHosts": "*",
        "PackageServiceUri": "https://packageservicefunction-abc.azurewebsites.net/api/packages/",
        "PackageServiceFunctionCode": "SvrbiyhjXJUdTPXrkcUtY6bQaUf7OXQjWvnM0Gq63hFUhbH2vn6qYA=="
    }
    
  4. Appuyez sur Ctrl+S pour enregistrer le fichier, puis sur Ctrl+Q pour fermer l’éditeur de code.

  5. Exécutez la commande suivante pour déployer l’application mise à jour sur votre App Service.

    zip -r DroneDelivery-after.zip . -x \*/obj/\* \*/bin/\*
    az webapp deployment source config-zip \
        --resource-group "<rgn>[sandbox resource group]</rgn>" \
        --name $APPSERVICENAME \
        --src DroneDelivery-after.zip
    
  6. Une fois le site redéployé, actualisez votre page. Elle doit maintenant être mise à jour.

    Screenshot of the redeployed Drone Delivery website.

Tester les performances de la nouvelle architecture

Le service avec contraintes de ressources étant à présent déplacé vers un microservice exécuté sur Azure Functions, voyons comment cette modification a affecté les performances de l’application.

  1. Dans la page d’accueil de votre site web, sélectionnez Send Requests (Envoyer des demandes). Cette action envoie les demandes de votre application monolithique au microservice exécuté sur une fonction Azure.

  2. La première tentative peut fournir des résultats similaires à l’application monolithique. Actualisez la page et soumettez à nouveau la demande si vous y êtes invité. Effectuez cette étape plusieurs fois et vous devriez voir 100 messages envoyés en 1 seconde.

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

La tentative initiale était plus lente pendant le démarrage de l’application de fonction. Une fois opérationnel, le temps de réponse est meilleur que lorsque ce code s’exécutait dans l’architecture monolithique.

Cette partie de l’architecture peut maintenant faire l’objet d’un scale-out quasiment à l’infini tout en offrant les mêmes performances. En déplaçant ce code d’application vers un microservice, nous avons multiplié les performances par 5 à 10. Comme Fabrikam dispose d’une équipe de développement dédiée à ce service, elle peut également itérer sur ce microservice et tirer parti des avantages d’une agilité accrue et des fonctionnalités publiées.