Antimodèle : Utiliser waitForComplete() dans le code JavaScript

Vous consultez la documentation d'Apigee Edge.
Consultez la documentation Apigee X.
en savoir plus

La règle JavaScript dans Apigee Edge vous permet d'ajouter du code personnalisé qui s'exécute dans le contexte d'un flux de proxy d'API. Par exemple, le code personnalisé de la règle JavaScript peut être utilisé pour:

  • Obtenir et définir les variables de flux
  • Exécuter une logique personnalisée et procéder à la gestion des erreurs
  • Extraire des données de requêtes ou de réponses
  • Modifier dynamiquement l'URL cible du backend
  • Ajouter ou supprimer de manière dynamique des en-têtes dans une requête ou une réponse
  • Analyser une réponse JSON

Client HTTP

Le client HTTP constitue une fonctionnalité puissante de la règle JavaScript. Le client HTTP (ou l'objet httpClient) peut être utilisé pour effectuer un ou plusieurs appels à des services de backend ou des services externes. Le client HTTP est particulièrement utile lorsqu'il est nécessaire d'appeler plusieurs services externes et de combiner les réponses dans une seule API.

Exemple de code JavaScript effectuant un appel au backend avec l'objet httpClient

var headers = {'X-SOME-HEADER' : 'some value' };
var myRequest = new Request("http://www.example.com","GET",headers);
var exchange = httpClient.send(myRequest);

L'objet httpClient expose deux méthodes get et send (send est utilisé dans l'exemple de code ci-dessus) pour effectuer des requêtes HTTP. Ces deux méthodes sont asynchrones et renvoient un objet exchange avant la fin de la requête HTTP.

Les requêtes HTTP peuvent prendre de quelques secondes à quelques minutes. Une fois la requête HTTP effectuée, il est important de savoir quand la requête est terminée, afin que la réponse de la requête puisse être traitée. L'une des méthodes les plus courantes pour déterminer le moment où la requête HTTP est terminée consiste à appeler la méthode waitForComplete() de l'objet exchange.

waitForComplete()

La méthode waitForComplete() met le thread en pause jusqu'à ce que la requête HTTP soit terminée et qu'une réponse (succès/échec) soit renvoyée. Ensuite, la réponse d'un backend ou d'un service externe peut être traitée.

Exemple de code JavaScript avecwaitForComplete()

var headers = {'X-SOME-HEADER' : 'some value' };
var myRequest = new Request("http://www.example.com","GET",headers);
var exchange = httpClient.send(myRequest);
// Wait for the asynchronous GET request to finish
exchange.waitForComplete();

// Get and Process the response
if (exchange.isSuccess()) {
    var responseObj = exchange.getResponse().content.asJSON;
    return responseObj.access_token;
} else if (exchange.isError()) {
    throw new Error(exchange.getError());
}

Antimodèle

L'utilisation de waitForComplete() après l'envoi d'une requête HTTP dans le code JavaScript a des conséquences sur les performances.

Prenons l'exemple du code JavaScript suivant, qui appelle waitForComplete() après l'envoi d'une requête HTTP.

Code pour sample.js

// Send the HTTP request
var exchangeObj = httpClient.get("http://example.com");
// Wait until the request is completed
exchangeObj.waitForComplete();
// Check if the request was successful
if (exchangeObj.isSuccess())  {

    response = exchangeObj.getResponse();
    context.setVariable('example.status', response1.status);
} else {
   error = exchangeObj.getError();
   context.setVariable('example.error', 'Woops: ' + error);
}

Dans cet exemple :

  1. Le code JavaScript envoie une requête HTTP à une API backend.
  2. Il appelle ensuite waitForComplete() pour suspendre l'exécution jusqu'à ce que la requête soit terminée.

    L'API waitForComplete() bloque le thread qui exécute le code JavaScript jusqu'à ce que le backend ait terminé le traitement de la requête et y réponde.

Il existe une limite supérieure au nombre de threads (30 %) pouvant exécuter simultanément et à tout moment du code JavaScript sur un processeur de messages. Une fois cette limite atteinte, plus aucun thread n'est disponible pour exécuter le code JavaScript. Ainsi, si trop de requêtes simultanées exécutent l'API waitForComplete() dans le code JavaScript, les requêtes ultérieures échoueront avec un message d'erreur 500 Erreur interne au serveur et "Délai expiré" avant même que la règle JavaScript n'expire.

En général, ce scénario peut se produire si le backend prend beaucoup de temps pour traiter les requêtes ou si le trafic est important.

Impact

  1. Les requêtes API échouent avec le message d'erreur 500 Erreur interne au serveur et "Délai expiré" lorsque le nombre de requêtes simultanées exécutant waitForComplete() dans le code JavaScript dépasse la limite prédéfinie.
  2. Le diagnostic de l'origine du problème peut être complexe, car JavaScript échoue et renvoie une erreur "Expiration du délai", même si le délai pour la règle JavaScript spécifique n'est pas écoulé.

Bonne pratique

Utilisez des rappels dans le client HTTP pour simplifier le code de l'appel et améliorer les performances, et éviter d'utiliser waitForComplete() dans le code JavaScript. Cette méthode permet de s'assurer que le thread qui exécute JavaScript n'est pas bloqué tant que la requête HTTP n'est pas terminée.

Lorsqu'un rappel est utilisé, le thread envoie les requêtes HTTP dans le code JavaScript et revient au pool. Étant donné que le thread n'est plus bloqué, il est disponible pour gérer d'autres requêtes. Une fois la requête HTTP terminée et le rappel prêt à être exécuté, une tâche est créée et ajoutée à la file d'attente de tâches. L'un des threads du pool exécutera le rappel en fonction de la priorité de la tâche.

Exemple de code JavaScript utilisant des rappels dans httpClient

function onComplete(response,error) {
 // Check if the HTTP request was successful
    if (response) {
      context.setVariable('example.status', response.status);
     } else {
      context.setVariable('example.error', 'Woops: ' + error);
     }
}
// Specify the callback Function as an argument
httpClient.get("http://example.com", onComplete);

Complément d'informations