Modèle de passerelle API et communication directe de client à microservice

Conseil

Ce contenu est un extrait du livre électronique, de l’architecture des microservices .NET pour les applications .NET conteneurisées, disponibles sur .NET Docs ou en tant que PDF téléchargeable gratuitement qui peut être lu hors connexion.

.NET Microservices Architecture for Containerized .NET Applications eBook cover thumbnail.

Dans une architecture de microservices, chaque microservice expose un ensemble de points de terminaison (généralement) très ciblés. Ceci peut impacter la communication de client à microservice, comme cette section l’explique.

Communication directe de client à microservice

Une approche possible consiste à utiliser une architecture de communication directe de client à microservice. Dans cette approche, une application cliente peut envoyer des demandes directement à certains des microservices, comme le montre la figure 4-12.

Diagram showing client-to-microservice communication architecture.

Figure 4-12. Utilisation d’une architecture de communication directe de client à microservice

Avec cette approche, chaque microservice a un point de terminaison public, parfois avec un port TCP différent pour chaque microservice. Voici un exemple d’URL pour un service particulier dans Azure :

http://eshoponcontainers.westus.cloudapp.azure.com:88/

Dans un environnement de production basé sur un cluster, cette URL serait mappée à l’équilibreur de charge utilisé dans le cluster, qui à son tour distribue les demandes entre les microservices. Dans les environnements de production, vous pouvez avoir un contrôleur de livraison d’application comme Azure Application Gateway entre vos microservices et Internet. Cette couche agit comme un niveau transparent qui effectue non seulement l’équilibrage de charge, mais sécurise vos services en offrant une terminaison SSL. Cette approche améliore la charge de vos hôtes en déchargeant la terminaison SSL intensive du processeur et d’autres tâches de routage vers le Azure Application Gateway. Dans tous les cas, un équilibreur de charge et un contrôleur de livraison d’application sont transparents du point de vue de l’architecture logique d’une application.

Une architecture de communication directe de client à microservice peut être suffisante pour une petite application basée sur des microservices, surtout si l’application cliente est une application web côté serveur, comme une application ASP.NET MVC. Cependant, quand vous créez des applications basées sur les microservices de grande taille et complexes (par exemple quand vous gérez des dizaines de types de microservice), et en particulier quand les applications clientes sont des applications mobiles distantes ou des applications web SPA, cette approche doit faire face à quelques problèmes.

Quand vous développez une application de grande taille basée sur les microservices, considérez les questions suivantes :

  • Comment les applications clientes peuvent-elles minimiser le nombre de requêtes envoyées au back-end et réduire le volume important des communications avec plusieurs microservices ?

Interagir avec plusieurs microservices pour créer un seul écran de l’interface utilisateur augmente le nombre d’allers-retours sur Internet. Cette approche augmente la latence et la complexité côté interface utilisateur. Dans l’idéal, les réponses doivent être agrégées de façon efficace côté serveur. Cette approche réduit la latence, car plusieurs éléments de données reviennent en parallèle et certaines interface utilisateur peuvent afficher des données dès qu’elles sont prêtes.

  • Comment pouvez-vous gérer des problèmes transversaux comme l’autorisation, les transformations de données et la distribution des requêtes dynamiques ?

L’implémentation de la sécurité et de problèmes transversaux, comme la sécurité et l’autorisation, sur chaque microservice peut nécessiter un travail de développement considérable. Une approche possible consiste à avoir ces services au sein de l’hôte Docker ou du cluster interne, de façon à limiter leur l’accès direct depuis l’extérieur et à implémenter ces problèmes transversaux à un emplacement centralisé, comme une passerelle API.

  • Comment les applications clientes peuvent-elles communiquer avec des services qui utilisent des protocoles non internet ?

Les protocoles utilisés côté serveur (comme les protocoles AMQP ou binaires) ne sont pas pris en charge dans les applications clientes. Ainsi, les requêtes doivent être exécutées via des protocoles comme HTTP/HTTPS et être traduites après cela pour les autres protocoles. Une approche par intercepteur peut aider dans cette situation.

  • Comment pouvez-vous mettre en forme une façade spécialement conçue pour les applications mobiles ?

L’API de plusieurs microservices peut ne pas être bien conçue pour les besoins de différentes applications clientes. Par exemple, les besoins d’une application mobile peuvent être différents de ceux d’une application web. Pour les applications mobiles, une optimisation supplémentaire peut être nécessaire pour rendre les réponses des données plus efficaces. Vous pouvez effectuer cette fonctionnalité en agrégeant des données à partir de plusieurs microservices et en retournant un seul ensemble de données, et parfois en éliminant toutes les données de la réponse qui n’est pas nécessaire par l’application mobile. Bien sûr, vous pouvez aussi compresser les données. Là encore, une façade ou une API entre l’application mobile et les microservices peut être utile dans ce scénario.

Pourquoi utiliser des passerelles d’API plutôt qu’une communication directe de client à microservice

Dans une architecture microservices, les applications clientes doivent généralement consommer la fonctionnalité de plusieurs microservices. Si cette consommation est effectuée directement, le client doit gérer plusieurs appels à des points de terminaison de microservices. Que se passe-t-il lorsque l’application évolue et que de nouveaux microservices sont introduits ou que des microservices existants sont mis à jour ? Si votre application comporte de nombreux microservices, la gestion d’autant de points de terminaison à partir des applications clientes peut être un cauchemar. Étant donné que l’application cliente est associée à ces points de terminaison internes, le futur développement des microservices peut avoir un fort impact sur les applications clientes.

Par conséquent, avoir un niveau intermédiaire ou un niveau d’indirection (passerelle) peut être pratique pour les applications basées sur des microservice. Si vous n’avez pas de passerelles d’API, les applications clientes doivent envoyer des requêtes directement aux microservices, ce qui entraîne les problèmes suivants :

  • Couplage : sans le modèle de passerelle d’API, les applications clientes sont couplées aux microservices internes. Les applications clientes doivent savoir comment les différentes zones de l’application sont décomposées en microservices. Lors de l’évolution et de la refactorisation des microservices internes, ces actions affectent la maintenance, car elles provoquent des modifications cassantes aux applications clientes en raison de la référence directe aux microservices internes des applications clientes. Les applications clientes doivent être fréquemment mises à jour, ce qui perturbe le développement de la solution.

  • Trop d’allers-retours: un seul écran ou une seule page dans l’application cliente peut nécessiter plusieurs appels à différents services. Cette approche peut entraîner plusieurs allers-retours réseau entre le client et le serveur, ajoutant une latence significative. L’agrégation gérée dans un niveau intermédiaire peut améliorer les performances et l’expérience utilisateur pour l’application cliente.

  • Problèmes de sécurité : sans passerelle, tous les microservices doivent être exposés au « monde externe », augmentant ainsi la surface d’attaque même si vous masquez les microservices internes qui ne sont pas directement utilisés par les applications clientes. Plus la surface d’attaque est réduite, plus votre application peut être sécurisée.

  • Préoccupations croisées : chaque microservice publié publiquement doit gérer les préoccupations telles que l’autorisation et SSL. Dans de nombreux cas, ces problèmes pourraient être traités dans un même niveau afin de simplifier les microservices internes.

Présentation du modèle Passerelle d’API

Quand vous concevez et que vous créez des applications de grande taille ou complexes basées sur des microservices avec plusieurs applications clientes, une passerelle d’API peut être une bonne approche à considérer. Ce modèle est un service qui fournit un point d’entrée unique pour certains groupes de microservices. Il est similaire au modèle Façade de la conception orientée objet, mais dans ce cas, il fait partie d’un système distribué. Le modèle Passerelle API est également parfois appelé « backend for frontend » (BFF), car vous le créez en prenant en compte les besoins de l’application cliente.

Par conséquent, la passerelle d’API se place entre les applications clientes et le microservices. Elle agit comme un proxy inverse, en acheminant les requêtes des clients vers les services. Il peut également fournir d’autres fonctionnalités croisées telles que l’authentification, l’arrêt SSL et le cache.

La figure 4-13 montre comment une passerelle d’API personnalisée peut s’intégrer dans une architecture simplifiée basée sur quelques microservices.

Diagram showing an API Gateway implemented as a custom service.

Figure 4-13. Utilisation d’une passerelle d’API implémentée comme service personnalisé

Les applications se connectent à un point de terminaison unique, la passerelle API, configurée pour transférer des requêtes à des microservices individuels. Dans cet exemple, la passerelle d’API doit être implémentée comme un service ASP.NET Core WebHost personnalisé s’exécutant en tant que conteneur.

Il est important de souligner que dans ce diagramme, vous utilisez un seul service de passerelle API personnalisée faisant face à plusieurs applications clientes différentes. Ceci peut présenter un risque important, car votre service de passerelle d’API va croître et évoluer en fonction des nombreuses exigences différentes des applications clientes. Finalement, elle sera gonflée en raison de ces différents besoins et peut être similaire à une application monolithique ou à un service monolithique. C’est pourquoi il est vivement recommandé de diviser la passerelle API en plusieurs services ou en plusieurs passerelles API plus petites, par exemple, une par type de facteur de forme dans une application cliente.

Soyez prudent lors de l’implémentation du modèle Passerelle API. Il n’est en général pas judicieux d’avoir une seule passerelle d’API agrégeant tous les microservices internes de votre application. Dans ce cas, elle se comporte comme un agrégateur ou un orchestrateur monolithique, et contrevient au principe d’autonomie des microservices en couplant tous les microservices.

Par conséquent, les passerelles d’API doivent être séparées en fonction des limites métier et des applications clientes et ne pas agir comme un agrégateur pour tous les microservices internes.

Quand vous divisez le niveau de la passerelle API en plusieurs passerelles API, si votre application a plusieurs applications clientes, cela peut être un pivot essentiel pour identifier les différents types de passerelles API, et pouvoir ainsi utiliser une façade différente selon les besoins de chaque application cliente. Ce cas est un modèle intitulé « Backend for Frontend » (BFF), dans lequel chaque passerelle API peut fournir une API différente adaptée à chaque type d’application cliente, ou même personnalisée en fonction du facteur de forme de l’application cliente en implémentant un code d’adaptateur spécifique qui appelle plusieurs microservices internes de façon sous-jacente, comme le montre l’image suivante :

Diagram showing multiple custom API Gateways.

Figure 4-13.1. Utilisation de plusieurs passerelles d’API personnalisées

La figure 4-13.1 montre les passerelles API séparées par type de client; un pour les clients mobiles et un pour les clients web. Une application web traditionnelle se connecte à un microservice MVC qui utilise la passerelle API web. L’exemple illustre une architecture simplifiée avec plusieurs passerelles API affinées. Dans ce cas, les limites identifiées pour chaque passerelle API reposant uniquement sur le modèle « Backend for Frontend » (BFF), elles sont basées uniquement sur l’API nécessaire à l’application cliente. Toutefois, dans les applications plus volumineuses, vous devez également aller plus loin et créer d’autres passerelles d’API basées sur des limites métier en tant que deuxième pivot de conception.

Principales fonctionnalités du modèle Passerelle d’API

Une passerelle d’API peut offrir plusieurs fonctionnalités. Selon le produit, elle peut proposer des fonctionnalités plus ou moins complètes, mais les fonctionnalités de bases les plus importantes pour toute passerelle d’API sont les modèles de conception suivants :

Proxy inversé ou routage de passerelle. La passerelle d’API offre un proxy inversé pour rediriger ou acheminer les requêtes (routage de couche 7, généralement les requêtes HTTP) vers les points de terminaison des microservices internes. La passerelle fournit un point de terminaison ou une URL unique pour les applications clientes puis mappe en interne les requêtes à un groupe de microservices internes. Cette fonctionnalité de routage permet de dissocier les applications clientes des microservices, mais elle est également pratique lors de la modernisation d’une API monolithique en plaçant la passerelle API entre l’API monolithique et les applications clientes, puis vous pouvez ajouter de nouvelles API en tant que nouvelles microservices tout en utilisant l’API monolithique héritée jusqu’à ce qu’elle soit divisée en plusieurs microservices à l’avenir. Avec la passerelle API, les applications clientes ne sauront pas si les API utilisées sont implémentées comme des microservices internes ou comme une API monolithique et, plus important encore, lors du développement et de la refactorisation de l’API monolithique en microservices, grâce au routage de la passerelle API, les applications clientes ne seront pas impactées par les modifications d’URI.

Pour plus d’informations, consultez le modèle de routage de passerelle.

Agrégation de requêtes. Dans le cadre du modèle de passerelle, vous pouvez agréger plusieurs requêtes de client (généralement des requêtes HTTP) ciblant plusieurs microservices internes dans une requête de client unique. Ce modèle est particulièrement pratique lorsqu’une page ou un écran d’un client a besoin d’informations provenant de plusieurs microservices. Avec cette approche, l’application cliente envoie une demande unique à la passerelle d’API qui répartit plusieurs requêtes aux microservices internes, puis agrège les résultats et envoie le tout à l’application cliente. Le principal avantage et l’objectif de ce modèle de conception est de réduire les conversations entre les applications clientes et l’API back-end, ce qui est particulièrement important pour les applications distantes hors du centre de données où les microservices vivent, comme les applications mobiles ou les demandes provenant d’applications SPA provenant d’applications JavaScript dans les navigateurs distants clients. Pour les applications web normales effectuant les requêtes dans l’environnement du serveur (par exemple, une application web ASP.NET Core MVC), ce modèle n’est pas si important car la latence est bien plus faible que pour les applications clientes à distance.

Selon le produit Passerelle d’API que vous utilisez, il sera en mesure d’effectuer cette agrégation. Toutefois, dans de nombreux cas, il est plus simple de créer des microservices d’agrégation dans le cadre de la passerelle API. Vous définissez alors l’agrégation directement dans le code (code C#) :

Pour plus d’informations, consultez Modèle d’agrégation de passerelle.

Problèmes transversaux ou déchargement de passerelle. Selon les fonctionnalités offertes par chaque produit Passerelle d’API, vous pouvez décharger des fonctionnalités de microservices individuels vers la passerelle, ce qui simplifie l’implémentation de chaque microservice en consolidant les problèmes transversaux dans un seul niveau. Cette approche est particulièrement pratique pour les fonctionnalités spécialisées qui peuvent être complexes à implémenter correctement dans chaque microservice interne, comme les fonctionnalités suivantes :

  • Authentification et autorisation
  • Intégration de la découverte de service
  • Mise en cache des réponses
  • Stratégies de nouvelle tentative, disjoncteur et qualité de service (QoS)
  • Limitation du débit
  • Équilibrage de la charge
  • Journalisation, suivi, corrélation
  • Transformation des en-têtes, chaînes de requête et revendications
  • Liste verte IP

Pour plus d’informations, consultez Modèle de déchargement de passerelle.

Utilisation de produits avec les fonctionnalités de la Passerelle d’API

Il peut y avoir plusieurs problèmes transversaux générés par les produits de la passerelle d’API en fonction de chaque implémentation. Nous aborderons ici les points suivants :

Gestion des API Azure

En plus de répondre à vos besoins de passerelle API, le service Gestion des API Azure (comme illustré à la figure 4-14) offre plusieurs fonctionnalités, telles que la collecte d’insights à partir de vos API. Si vous utilisez une solution de gestion des API globale, une passerelle API est simplement un composant de cette solution.

Diagram showing how to use Azure API Management as your API gateway.

Figure 4-14. Utilisation de Gestion des API Azure pour votre passerelle d’API

Azure Gestion des API résout à la fois vos besoins en matière de passerelle d’API et de gestion, comme la journalisation, la sécurité, le contrôle, etc. Dans ce cas, lorsque vous utilisez un produit comme Azure Gestion des API, le fait que vous avez peut-être une passerelle API unique n’est pas si risqué, car ces types de passerelles d’API sont « plus minces », ce qui signifie que vous n’implémentez pas de code C# personnalisé qui pourrait évoluer vers un composant monolithique.

Les produits Passerelle d’API agissent généralement comme un proxy inversé pour la communication en entrée, où vous pouvez aussi filtrer les API des microservices internes et appliquer une autorisation aux API publiées dans ce niveau unique.

Les informations disponibles provenant d’un système de gestion des API vous aident à comprendre comment vos API sont utilisées et comment elles fonctionnent. Ils effectuent cette activité en vous permettant d’afficher des rapports d’analyse en quasi temps réel et d’identifier les tendances susceptibles d’avoir un impact sur votre entreprise. De plus, vous pouvez avoir des journaux sur l’activité des demandes et des réponses, que vous pouvez alors analyser de façon plus approfondie en ligne et hors connexion.

Avec Gestion des API Azure, vous pouvez sécuriser vos API avec une clé, un jeton et un filtrage des adresses IP. Ces fonctionnalités vous permettent d’appliquer des quotas et des limites de débit de façon souple et précise, de modifier la forme et le comportement de vos API avec des stratégies, et d’améliorer les performances avec la mise en cache des réponses.

Dans ce guide et dans l’exemple d’application de référence (eShopOnContainers), l’architecture est limitée à une architecture en conteneurs plus simple et personnalisée, de façon à mettre l’accent sur des conteneurs ordinaires sans utiliser de produits PaaS comme Gestion des API Azure. Cependant, pour les applications de grande taille basées sur des microservices et déployées sur Microsoft Azure, nous vous encourageons à évaluer Gestion des API Azure comme base pour vos passerelles d’API en production.

Ocelot

Ocelot est une passerelle API légère qui est recommandée pour les approches plus simples. Ocelot est une passerelle d’API open source .NET Core spécialement conçue pour les architectures de microservices qui nécessitent des points d’entrée unifiés dans leurs systèmes. Il est léger, rapide et évolutif et fournit le routage et l’authentification parmi de nombreuses autres fonctionnalités.

La principale raison de choisir Ocelot pour l’application de référence eShopOnContainers 2.0 est que Ocelot est une passerelle d’API légère .NET Core que vous pouvez déployer dans le même environnement de déploiement d’application que celui où vous déployez vos microservices/conteneurs, tels qu’un hôte Docker, Kubernetes, etc. Et comme il est basé sur .NET Core, il est multiplateforme vous permettant de déployer sur Linux ou Windows.

Les diagrammes précédents montrant des passerelles d’API personnalisée en cours d’exécution dans les conteneurs expliquent précisément comment vous pouvez également exécuter Ocelot dans un conteneur et dans une application basée sur un microservice.

En outre, il existe plusieurs autres produits sur le marché qui offrent des fonctionnalités de passerelles d’API, par exemple Apigee, Kong, MuleSoft, WSO2, et d’autres produits comme Linkerd et Istio pour les fonctionnalités de contrôleur d’ingestion de maille de services.

Après les sections consacrées à l’architecture initiale et à la présentation des modèles, les sections suivantes expliquent comment implémenter des passerelles d’API avec Ocelot.

Inconvénients du modèle Passerelle d’API

  • L’inconvénient plus important est que, quand vous implémentez une passerelle d’API, vous couplez ce niveau avec les microservices internes. Un tel couplage peut introduire de graves difficultés pour votre application. Clemens Vaster, architecte de l’équipe Azure Service Bus, parlait de cette difficulté potentielle comme de « la nouvelle ESB » dans la session « Messaging and Microservices » à la conférence GOTO 2016.

  • L’utilisation d’une passerelle d’API de microservices crée un possible point de défaillance unique supplémentaire.

  • Une passerelle d’API peut introduire des temps de réponse accrus en raison de l’appel réseau supplémentaire. Cependant, cet appel supplémentaire a généralement moins d’impact qu’un client de l’interface qui émet trop de communications en appelant directement les microservices internes.

  • Si elle n’est pas montée pas en charge correctement, la passerelle d’API peut devenir un goulot d’étranglement.

  • Une passerelle d’API nécessite des coûts de développement supplémentaires et une maintenance ultérieure si elle inclut une logique personnalisée et effectue une agrégation des données. Les développeurs doivent mettre à jour la passerelle API pour pouvoir exposer les points de terminaison de chaque microservice. En outre, les changements d’implémentation dans les microservices internes peuvent entraîner des modifications du code au niveau de la passerelle d’API. Cependant, si la passerelle d’API applique simplement la sécurité, la journalisation et la gestion des versions (comme quand vous utilisez Gestion des API Azure), ces coûts de développement supplémentaires peuvent ne pas s’appliquer.

  • Si la passerelle d’API est développée par une même équipe, il peut y avoir un goulot d’étranglement en matière de développement. Cet aspect est une autre raison pour laquelle une meilleure approche consiste à avoir plusieurs passerelles API affinées qui répondent à différents besoins clients. Vous pouvez aussi diviser la passerelle d’API en interne en plusieurs parties ou couches, affectées chacune aux différentes équipes travaillant sur les microservices internes.

Ressources supplémentaires