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

Sie sehen die Dokumentation zu Apigee Edge.
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-Flows 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
  • Backend-Ziel-URL dynamisch bearbeiten
  • Header einer Anfrage oder Antwort dynamisch hinzuzufügen oder zu entfernen
  • Eine JSON-Antwort zu parsen

HTTP-Client

Eine leistungsstarke Funktion der JavaScript-Richtlinie ist der HTTP-Client. Mit dem HTTP-Client (oder dem httpClient-Objekt) können ein oder mehrere Aufrufe an Back-End- oder externe Dienste gesendet werden. Der HTTP-Client ist besonders nützlich, wenn mehrere externe Dienste aufgerufen und die Antworten in einer einzigen API zusammengefasst werden müssen.

JavaScript-Beispielcode zum Aufrufen 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 die beiden Methoden get und send (im obigen Beispielcode wird send verwendet) für HTTP-Anfragen bereit. 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. Es ist wichtig zu wissen, wann eine HTTP-Anfrage abgeschlossen ist, damit die Antwort der Anfrage verarbeitet werden kann. Um festzustellen, ob die HTTP-Anfrage abgeschlossen ist, rufen Sie am häufigsten die Methode waitForComplete() des exchange-Objekts auf.

waitForComplete()

Die Methode waitForComplete() pausiert den Thread, bis die HTTP-Anfrage abgeschlossen 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.

Betrachten Sie den folgenden JavaScript-Code, mit dem waitForComplete() nach dem Senden einer HTTP-Anfrage aufgerufen wird.

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 sorgt dafür, dass der Thread, der den JavaScript-Code ausführt, blockiert wird, bis das Back-End die Verarbeitung der Anfrage abgeschlossen 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. Nach Erreichen dieses Limits sind keine Threads mehr verfügbar, um den JavaScript-Code auszuführen. Wenn also zu viele Anfragen gleichzeitig die waitForComplete() API im JavaScript-Code ausführen, schlagen nachfolgende Anfragen fehl und es werden 500 Interner Serverfehler und eine Fehlermeldung wegen Zeitüberschreitung ausgegeben, noch bevor die JavaScript-Richtlinie das Zeitlimit überschreitet.

Dieses Szenario kann im Allgemeinen auftreten, wenn die Verarbeitung von Anfragen durch das Back-End lange dauert oder es hohen Traffic gibt.

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. Es kann schwierig sein, die Ursache des Problems zu diagnostizieren, da das JavaScript mit dem Fehler „Zeitüberschreitung“ fehlschlägt, obwohl das Zeitlimit für die spezifische JavaScript-Richtlinie noch nicht abgelaufen ist.

Best Practice

Verwende Callbacks im HTTP-Client, um den Callout-Code zu optimieren und die Leistung zu verbessern. Vermeiden Sie die Verwendung von waitForComplete() im JavaScript-Code. Mit dieser Methode wird sichergestellt, dass der Thread, der JavaScript ausführt, nicht blockiert wird, bis die HTTP-Anfrage abgeschlossen ist.

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

JavaScript-Beispielcode mit 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