Regrouper les requêtes API avec NGINX Plus et le module JavaScript NGINX

NGINX | 24 mai 2018

La version du module JavaScript NGINX publiée avec NGINX Plus R15 peut désormais émettre des sous-requêtes, ce qui signifie que des requêtes peuvent être lancées dans du code JavaScript. Cela permet de répondre à un tout nouvel ensemble de cas d’utilisation.

L’un de ces cas d’utilisation consiste à regrouper les requêtes API afin qu’une seule requête API provenant d’un client puisse être transformée en plusieurs requêtes API adressées à un ensemble de serveurs backend, puis que les réponses soient agrégées en une réponse unique envoyée au client. Dans cet article, nous prenons l’exemple d’un site d’e-commerce : lorsque le client demande des informations sur un produit donné, des sous-requêtes sont envoyées à trois services backend : catalogue, stock et avis clients.

Cet article s’appuie sur l’exemple de sous-requête présenté dans l’annonce de NGINX Plus R15, qui montre comment utiliser des sous-requêtes pour envoyer la même requête à deux serveurs backend et ne renvoyer au client que la première réponse.

[Note de la rédaction – Cet article fait partie d’une série consacrée aux cas d’utilisation du module JavaScript de NGINX. Pour consulter la liste complète, voir Cas d’utilisation du module JavaScript de NGINX.

L’article a été mis à jour pour utiliser la directive js_import, qui remplace la directive js_include dans NGINX Plus R23 et les versions ultérieures. Pour plus d’informations, consultez la documentation de référence du module JavaScript NGINX : la section « Exemple de configuration » présente la syntaxe correcte pour les fichiers de configuration NGINX et les fichiers JavaScript.]

Introduction

L’objectif de cet article est de fournir des exemples fonctionnels, simples et faciles à comprendre, de regroupement de requêtes API. Ces exemples répondent à toutes les exigences suivantes :

  • La méthode HTTP « GET » est utilisée pour toutes les requêtes.
  • Toutes les réponses sont au format JSON.
  • Deux types de requêtes API sont pris en charge. Notez que, dans les deux cas, des arguments supplémentaires peuvent être ajoutés à la chaîne de requête.
    • L’argument transmis au programme d’API est le dernier élément de l’URI. Nous appelons cela le « style de requête par élément final ». Dans notre exemple, une requête client adressée à /batch-api/product/14286 génère des requêtes vers /myapi/catalog/14286, /myapi/inventory/14286 et /myapi/review/14286.
    • L’argument est indiqué dans la chaîne de requête de l’URI. Nous appelons cela le « style de requête par chaîne de requête ». Dans cet exemple, une requête adressée à /batch-api2/product?item=14286 génère des requêtes vers /myapi/catalog.php?item=14286, /myapi/inventory.php?item=14286 et /myapi/review.php?item=14286.
  • L’ensemble des sous-requêtes déclenchées par une requête client est configurable de manière dynamique, ce qui signifie que nous pouvons le modifier sans avoir à éditer manuellement la configuration de NGINX Plus ni à la recharger.
  • Les requêtes API adressées aux serveurs backend sont indépendantes les unes des autres.

Présentation de la solution

En plus d’utiliser la nouvelle fonctionnalité de sous-requête de NGINX JavaScript, cette solution exploite la fonctionnalité de stockage clé-valeur de NGINX Plus, ce qui permet de modifier dynamiquement la configuration à l’aide de l’API NGINX Plus.

Les schémas suivants illustrent les deux types de requêtes pris en charge.

Style de requête de l’élément final :

Le client envoie des requêtes de type « élément final » à une API

Style de requête avec paramètres dans l’URL :

Le client envoie des requêtes à une API sous forme de chaînes de requête

Dans les deux exemples, le client doit obtenir des informations sur un produit auprès des services de catalogue, de gestion des stocks et d’avis. Il envoie une requête à NGINX Plus, en transmettant le numéro de l’article soit dans l’URI, soit dans la chaîne de requête. Les requêtes sont ensuite envoyées aux trois services, et leurs réponses sont regroupées en une seule réponse adressée au client.

Deux composants sont nécessaires pour que cela fonctionne avec NGINX Plus : un programme JavaScript et la configuration de NGINX Plus.

Le programme JavaScript

La fonction JavaScript batchAPI() est appelée pour chaque requête client. Elle récupère dans le magasin clé-valeur la liste des URI d’API séparées par des virgules et les parcourt, en effectuant une sous-requête pour chacune et en spécifiant la fonction de rappel done() pour traiter chaque réponse. Pour les requêtes où le paramètre correspond au dernier élément, le dernier élément de l’URI, stocké dans la variable NGINX $uri_suffix, est transmis comme chaîne de requête à chaque sous-requête, avec tous les autres arguments de chaîne de requête présents dans l’URI client d’origine. Pour les requêtes où les paramètres figurent dans la chaîne de requête, la chaîne de requête des requêtes client est transmise comme chaîne de requête à chaque sous-requête.

Les appels sont effectués dans l’ordre où ils figurent dans le magasin clé-valeur, mais ils sont asynchrones ; les réponses peuvent donc arriver dans n’importe quel ordre. Elles sont regroupées en une seule réponse envoyée au client, dans leur ordre de réception. Voici une version minimale du programme JavaScript :

Chargement de l’exemple de code…

Une version du programme JavaScript intégrant une gestion des erreurs, une journalisation et des commentaires plus détaillés est disponible dans le dépôt GitHub Gist sous le nom de « batch-api.js ».

Configuration minimale de NGINX Plus

La configuration NGINX Plus suivante met en œuvre les deux styles de requête décrits ci-dessus à l’aide d’un groupe de serveurs en amont. Par souci de simplicité, cette configuration suppose que les serveurs en amont sont capables de convertir un appel de la forme /myapi/service/item# (style avec élément final) en /myapi/service.php/?item=item# (style avec chaîne de requête), qui correspond au format d’URI « natif » de PHP, le langage utilisé pour nos exemples de services de catalogue, de gestion des stocks et d’avis.

Pour une configuration NGINX Plus plus complète qui effectue elle-même la conversion, consultez la section « Extension de la configuration NGINX pour convertir les URI » ci-dessous.

Examinons le fichier de configuration section par section et expliquons le rôle de chacune d’elles :

  • Importez le fichier JavaScript:

    Chargement de l’exemple de code…

  • Définissez un magasin clé-valeur pour contenir la liste des requêtes d’API dans lesquelles le dernier élément de l’URI identifie l’argument du programme d’API. La clé utilise la variable $uri_prefix pour capturer la partie de l’URI située avant le dernier /:

    Chargement de l’exemple de code…

    Dans NGINX Plus R16 et les versions ultérieures, vous pouvez tirer parti de deux fonctionnalités clé-valeur supplémentaires. Pour savoir comment configurer la synchronisation des magasins clé-valeur, consultez le Guide d’administration de NGINX Plus.
    • Définissez un délai d’expiration pour les entrées d’un magasin clé-valeur en ajoutant le paramètre « timeout » à la directive « keyval_zone ». Par exemple, pour que chaque URI regroupé expire quotidiennement, ajoutez « timeout=1d ».
    • Synchronisez le magasin clé-valeur sur l’ensemble d’un cluster d’instances NGINX Plus en ajoutant le paramètre sync à la directive keyval_zone. Dans ce cas, vous devez également inclure le paramètre timeout.
  • Définissez un autre magasin clé-valeur pour les API où l’argument est identifié dans la chaîne de requête. Ici, la clé ($uri) capture l’URI complète, sans inclure la chaîne de requête :

    Chargement de l’exemple de code…

  • Définissez deux mappages pour scinder l’URI en deux parties pour les API qui acceptent les requêtes dont l’argument est le dernier élément de l’URI. La variable $uri_prefix capture les éléments de l’URI situés avant le dernier /, tandis que $uri_suffix capture le dernier élément :

    Chargement de l’exemple de code…

  • Définissez le groupe en amont de serveurs d’API (ici, ils s’exécutent sur localhost avec NGINX Plus) :

    Chargement de l’exemple de code…

  • Définissez le serveur virtuel qui traite les requêtes et les sous-requêtes des clients :

    Chargement de l’exemple de code…

  • Définissez un emplacement pour traiter les requêtes clientes qui utilisent le style avec élément final, signalé à la fonction batchAPI en définissant la variable $batch_api_arg_in_uri sur on:

    Chargement de l’exemple de code…

  • Définissez un emplacement pour traiter les requêtes clientes utilisant le format avec chaîne de requête, ce qui est indiqué à la fonction batchAPI en définissant la variable $batch_api_arg_in_uri sur off:

    Chargement de l’exemple de code…

  • Définissez l’emplacement qui traite les sous-requêtes :

    Chargement de l’exemple de code…

  • Activez l’API NGINX Plus afin de pouvoir gérer les données dans le magasin clé-valeur :

    Chargement de l’exemple de code…

Voici la configuration complète :

Chargement de l’exemple de code…

Configuration des requêtes API par lots

Nous utilisons la fonctionnalité de stockage clé-valeur de NGINX Plus pour associer les requêtes clientes entrantes à un ensemble de requêtes d’API à exécuter. La configuration de la section précédente définit des stockages clé-valeur distincts pour les deux types de requêtes :

  • Le magasin clé-valeur correspondant au style avec élément final est nommé « batch_api » et sa clé est la variable « $uri_prefix », qui capture les éléments précédant le dernier « / » de l’URI de la requête.
  • Le magasin clé-valeur utilisé pour le format avec chaîne de requête est nommé « batch_api2 » et sa clé est la variable « $uri », qui contient l’URI complète de la requête sans la chaîne de requête.

Dans les deux magasins clé-valeur, la valeur associée à chaque clé est une liste d’URI séparées par des virgules, mise à disposition lors de l’exécution dans les variables « $batch_api » ou « $batch_api2 ».

Pour les requêtes de type « élément final », nous souhaitons faire correspondre une requête client adressée à /batch-api/product à des requêtes adressées aux trois services /myapi/catalog, /myapi/inventory et /myapi/review, de sorte qu’une requête adressée à /batch-api/product/14286 génère des requêtes adressées à /myapi/catalog/14286, /myapi/product/14286 et /myapi/review/14286.

Pour ajouter ces mappages au magasin clé-valeur batch_api, nous envoyons la requête suivante à l’instance NGINX Plus exécutée sur la machine locale :

$ curl -iX POST -d '{"/batch-api/product":"/myapi/catalog,/myapi/inventory,/myapi/review"}' http://localhost/api/3/http/keyvals/batch_api

Pour les requêtes utilisant des paramètres de chaîne de requête, nous souhaitons faire correspondre une requête client adressée à /batch-api2/product à des requêtes adressées aux trois services /myapi/catalog.php, /myapi/inventory.php et /myapi/review.php, de sorte qu’une requête adressée à /batch-api2/product?item=14286 génère des requêtes adressées à /myapi/catalog?item=14286, /myapi/product?item=14286 et /myapi/review?item=14286.

Pour ajouter ces correspondances au magasin clé-valeur batch_api2, nous envoyons la requête suivante :

$ curl -iX POST -d '{"/batch-api2/product":"/myapi/catalog.php,/myapi/inventory.php,/myapi/review.php"}' http://localhost/api/3/http/keyvals/batch_api2

Exécution des exemples

Les mêmes pages PHP traitent les requêtes effectuées selon les deux styles. Par souci de simplicité, nous supposons que les serveurs back-end sont capables de convertir les URI de type « élément final » (/myapi/service/item#) en URI de type « chaîne de requête » (/myapi/service.php?item=item#). Il n’est pas nécessaire de convertir les URI de type « chaîne de requête », car il s’agit du format d’URI « natif » des programmes PHP.

Tous les services renvoient une réponse au format JSON qui inclut le nom du service et l’argument item. Par exemple, une requête adressée à /myapi/catalog.php?item=14286 entraîne la réponse suivante de la part de catalog.php :

{"service":"Catalog","item":"14286"}

Bien que les programmes PHP utilisés dans ces exemples incluent le nom du service dans la réponse, ce n’est pas nécessairement le cas pour tous les services. Afin de faciliter l’association des réponses aux services qui les ont générées, le programme JavaScript inclut l’URI dans la réponse agrégée.

Par exemple, la réponse agrégée à une requête portant sur /batch-api/product/14286 se présente comme suit (bien que l’ordre des trois réponses qui la composent puisse varier) :

[["/myapi/review/14286",{"service":"Review","item":"14286"}],["/myapi/inventory/14286",{"service":"Inventory","item":"14286"}],["/myapi/catalog/14286",{"service":"Catalog","item":"14286"}]]

Extension de la configuration NGINX Plus pour traduire les URI

Comme indiqué précédemment, la configuration minimale de NGINX Plus présentée ci-dessus suppose que les serveurs d’API sont capables de convertir les URI au format /myapi/service/numéro d’élément en /myapi/service.php/?item=numéro d’élément. Nous pouvons également effectuer cette conversion dans la configuration de NGINX Plus en apportant les modifications suivantes.

  • Ajoutez un nouveau groupe upstream pour recevoir les sous-requêtes :

    Chargement de l’exemple de code…

  • Ajoutez un nouveau serveur virtuel pour écouter les requêtes reçues par le groupe en amont services. Lorsque des requêtes utilisant des paramètres de chaîne de requête sont reçues, elles sont simplement transmises par proxy au groupe en amont api_servers, car l’URI possède déjà l’extension .php. Lorsque des requêtes utilisant le dernier élément de l’URI sont reçues, l’URI est réécrite afin que son dernier élément soit supprimé et converti en paramètre de chaîne de requête :

    Chargement de l’exemple de code…

  • Modifiez l’/myapi emplacement pour transmettre les requêtes au nouveau groupe en amont :

    Chargement de l’exemple de code…

Voici la configuration complète :

Chargement de l’exemple de code…

Composants supplémentaires

Les exemples de programmes JavaScript et les configurations NGINX Plus peuvent être adaptés à d’autres styles d’API. Toutefois, si vous souhaitez effectuer des tests avec tous les composants utilisés pour créer cet article de blog, ceux-ci sont disponibles dans notre dépôt Gist sur GitHub, notamment la configuration NGINX Unit permettant de servir les pages PHP :

batch-api.js
catalog.php
inventory.php
review.php
unit.config

Conclusion

Ces exemples montrent comment regrouper des requêtes d’API et fournir une réponse agrégée au client. Le magasin clé-valeur de NGINX Plus permet de configurer dynamiquement les requêtes d’API à l’aide de l’API NGINX Plus. Le fonctionnement précis des systèmes d’API varie considérablement. Cet exemple peut donc être amélioré de nombreuses façons afin de répondre aux besoins d’une API particulière.

Vous pouvez commencer à tester les sous-requêtes JavaScript de NGINX avec NGINX Open Source, mais si vous souhaitez essayer les exemples de regroupement de requêtes API ou tester d’autres cas d’utilisation tirant parti des fonctionnalités de NGINX Plus, telles que le magasin clé-valeur et l’API NGINX Plus, demandez un essai gratuit de 30 jours et commencez vos expérimentations.


Partager

À propos de l’auteur

Rick Nelson
Rick NelsonVice-président régional, ingénierie des solutions

Autres articles de Rick Nelson

Articles de blog associés

Tendances actuelles des technologies cloud natives, de l’ingénierie de plateforme et de l’IA
NGINX | 13/10/2025

Tendances actuelles des technologies cloud natives, de l’ingénierie de plateforme et de l’IA

Découvrez les principaux enseignements tirés des réponses à l’enquête annuelle F5 NGINX sur les dernières tendances en matière de technologies cloud natives, de sécurité, d’ingénierie de plateforme et d’IA.

Quels contrôleurs Ingress NGINX sont affectés par les vulnérabilités CVE-2022-4886, CVE-2023-5043 et CVE-2023-5044 ?
NGINX | 03/11/2023

Quels contrôleurs Ingress NGINX sont affectés par les vulnérabilités CVE-2022-4886, CVE-2023-5043 et CVE-2023-5044 ?

Lorsque de nouvelles CVE sont signalées, il est facile de ne plus savoir si elles concernent un outil de contrôleur Ingress NGINX particulier, car il existe plusieurs projets. Cet article présente les CVE et explique comment distinguer les différents projets de contrôleurs Ingress afin de dissiper toute confusion.

Votre API est-elle en temps réel ? Testez sa latence avec l’outil rtapi de NGINX
NGINX | 11/03/2020

Votre API est-elle en temps réel ? Testez sa latence avec l’outil rtapi de NGINX

Votre API répond-elle aux requêtes en moins de 30 ms ? Si ce n’est pas le cas, il ne s’agit pas d’une API en temps réel offrant la faible latence exigée par la grande majorité des organisations. Mesurez la latence de votre API avec l’outil rtapi de NGINX et découvrez comment NGINX peut l’aider à offrir une réactivité en temps réel.

Un testeur d’expressions régulières pour NGINX et NGINX Plus
NGINX | 11/06/2019

Un testeur d’expressions régulières pour NGINX et NGINX Plus

Le testeur d’expressions régulières (regex) pour NGINX et NGINX Plus vous évite de tâtonner en vous indiquant si une expression régulière utilisée dans un bloc location ou map correspond aux valeurs comme prévu. Il génère la configuration appropriée et affiche les valeurs des groupes de capture.

Caches partagés avec les clusters de cache NGINX Plus, partie 1
NGINX | 24/01/2017

Caches partagés avec les clusters de cache NGINX Plus, partie 1

Optimisez la capacité de votre cache web en le répartissant entre plusieurs serveurs de cache web NGINX ou NGINX Plus. Découvrez comment procéder dans cet article.

Introduction aux microservices
NGINX | 19/05/2015

Introduction aux microservices

Les microservices suscitent actuellement beaucoup d’intérêt. Cet article de blog est le premier d’une série de sept consacrée à la conception, au développement et au déploiement de microservices.