Anti-Pattern: waitForComplete() im JavaScript-Code verwenden

Sie sehen die Dokumentation zu Apigee Edge.
Gehen Sie zur Apigee X-Dokumentation.
Weitere Informationen

Mit der JavaScript-Richtlinie in Apigee Edge können Sie benutzerdefinierten Code hinzufügen, der im Kontext eines API-Proxy-Ablaufs ausgeführt wird. Der benutzerdefinierte Code in der JavaScript-Richtlinie kann beispielsweise für Folgendes verwendet werden:

  • Flussvariablen abzurufen und festzulegen
  • Benutzerdefinierte Logik auszuführen und Fehlerbehandlung durchzuführen
  • Daten aus Anfragen oder Antworten zu extrahieren
  • Back-End-Ziel-URL dynamisch zu bearbeiten
  • Header einer Anfrage oder Antwort dynamisch hinzuzufügen oder zu entfernen
  • Eine JSON-Antwort zu parsen

HTTP-Client

Eine leistungsstarke Funktion der JavaScript-Richtlinien ist der HTTP-Client. Der HTTP-Client (oder das httpClient-Objekt) kann verwendet werden, um einen oder mehrere Aufrufe an Back-End- oder externe Dienste zu senden. Der HTTP-Client ist besonders nützlich, wenn Sie mehrere externe Dienste aufrufen und die Antworten in einer einzigen API zusammenfassen müssen.

JavaScript-Beispielcode für einen Aufruf des Back-Ends mit dem httpClient-Objekt

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

Das httpClient-Objekt stellt zwei Methoden zur Verfügung, get und send (im obigen Beispielcode wird send verwendet), um HTTP-Anfragen zu senden. Beide Methoden sind asynchron und geben ein exchange-Objekt zurück, bevor die eigentliche HTTP-Anfrage abgeschlossen ist.

Die HTTP-Anfragen können einige Sekunden bis zu einigen Minuten dauern. Nach einer HTTP-Anfrage ist es wichtig zu wissen, wann sie abgeschlossen ist, damit die Antwort der Anfrage verarbeitet werden kann. Eine der häufigsten Methoden, um festzustellen, wann die HTTP-Anfrage abgeschlossen ist, besteht darin, die waitForComplete()-Methode des exchange-Objekts aufzurufen.

waitForComplete()

Die Methode waitForComplete() pausiert den Thread, bis die HTTP-Anfrage abgeschlossen ist und eine Antwort (Erfolg/Fehler) zurückgegeben wird. Anschließend kann die Antwort von einem Back-End oder externen Dienst verarbeitet werden.

JavaScript-Beispielcode mit waitForComplete()

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

Anti-Pattern

Die Verwendung von waitForComplete() nach dem Senden einer HTTP-Anfrage in JavaScript-Code wirkt sich auf die Leistung aus.

Sehen Sie sich den folgenden JavaScript-Code an, mit dem waitForComplete() aufgerufen wird, nachdem eine HTTP-Anfrage gesendet wurde.

Code für 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);
}

In diesem Beispiel:

  1. Der JavaScript-Code sendet eine HTTP-Anfrage an eine Back-End-API.
  2. Anschließend wird waitForComplete() aufgerufen, um die Ausführung anzuhalten, bis die Anfrage abgeschlossen ist.

    Die waitForComplete() API bewirkt, dass der Thread, der den JavaScript-Code ausführt, blockiert wird, bis das Back-End die Verarbeitung der Anfrage abgeschlossen hat und eine Antwort zurückgibt.

Es gibt eine Obergrenze für die Anzahl der Threads (30%), die jederzeit JavaScript-Code auf einem Message Processor ausführen können. Nachdem dieses Limit erreicht ist, sind keine Threads zum Ausführen des JavaScript-Codes mehr verfügbar. Wenn also zu viele gleichzeitige Anfragen die waitForComplete() API im JavaScript-Code ausführen, schlagen nachfolgende Anfragen mit der Fehlermeldung 500 Interner Serverfehler und „Zeitüberschreitung“ fehl, bevor das Zeitlimit der JavaScript-Richtlinie überschritten wird.

Im Allgemeinen kann dieses Szenario eintreten, wenn die Verarbeitung von Anfragen durch das Back-End sehr lange dauert oder wenn ein hoher Traffic vorhanden ist.

Auswirkungen

  1. Die API-Anfragen schlagen mit 500 Interner Serverfehler und mit der Fehlermeldung "Zeitüberschreitung" fehl, wenn die Anzahl der gleichzeitigen Anfragen, die waitForComplete() im JavaScript-Code ausführen, das vordefinierte Limit überschreitet.
  2. Die Fehlerdiagnose und -behandlung kann schwierig sein, da das JavaScript mit dem Fehler "Zeitüberschreitung" fehlschlägt, obwohl das Zeitlimit für die jeweilige JavaScript-Richtlinie nicht abgelaufen ist.

Best Practice

Verwenden Sie Callbacks im HTTP-Client, um den Callout-Code zu optimieren und die Leistung zu verbessern. Vermeiden Sie die Verwendung von waitForComplete() im JavaScript-Code. Diese Methode stellt sicher, dass der Thread, der JavaScript ausführt, erst blockiert wird, wenn die HTTP-Anfrage abgeschlossen ist.

Wenn ein Callback verwendet wird, sendet der Thread die HTTP-Anfragen im JavaScript-Code und kehrt an den Pool zurück. Da der Thread nicht mehr blockiert wird, kann er andere Anfragen verarbeiten. Wenn die HTTP-Anfrage abgeschlossen ist und der Callback ausgeführt werden kann, wird eine Aufgabe erstellt und der Aufgabenwarteschlange hinzugefügt. In einem der Threads aus dem Pool wird der Callback abhängig von der Priorität der Aufgabe ausgeführt.

JavaScript-Beispielcode für Callbacks in 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);

Weitere Informationen