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

Sie lesen gerade die Apigee Edge-Dokumentation.
Zur Apigee X-Dokumentation.
info

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-Richtlinie ist der HTTP-Client. Der HTTP-Client (oder das Objekt httpClient) kann für einen oder mehrere Aufrufe an Back-End- oder externe Dienste verwendet werden. Der HTTP-Client ist besonders dann nützlich, wenn mehrere externe Dienste aufgerufen werden müssen und die Antworten in einer einzigen API zusammengefasst werden müssen.

Beispiel für JavaScript-Code, der einen Back-End mit dem HTTP-Objekt „Client“ ausführt

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 get und send (send wird im obigen Beispielcode verwendet) zum Senden von HTTP-Anfragen bereit. Beide Methoden sind asynchron und geben ein exchange-Objekt zurück, bevor die tatsächliche HTTP-Anfrage abgeschlossen wird.

Die HTTP-Anfragen können einige Sekunden bis zu einigen Minuten dauern. Nachdem eine HTTP-Anfrage gesendet wurde, ist es wichtig zu wissen, wann sie abgeschlossen ist, damit die Antwort auf die Anfrage verarbeitet werden kann. Eine der häufigsten Möglichkeiten, zu ermitteln, wann die HTTP-Anfrage abgeschlossen ist, ist der Aufruf der waitForComplete() Methode des exchange Objekts.

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.

Beispiel für JavaScript-Code 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, der waitForComplete() nach dem Senden einer HTTP-Anfrage aufruft.

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, in dem der JavaScript-Code ausgeführt wird, blockiert wird, bis das Back-End die Verarbeitung der Anfrage abgeschlossen hat und antwortet.

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

Im Allgemeinen kann dieses Szenario auftreten, wenn die Verarbeitung von Anfragen durch das Back-End lange dauert oder der Traffic hoch 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, die Leistung zu verbessern und die Verwendung von waitForComplete() im JavaScript-Code zu vermeiden. Diese Methode stellt sicher, dass die Ausführung von JavaScript durch den Thread 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 zum Pool zurück. Da der Thread nicht mehr blockiert wird, kann er andere Anfragen verarbeiten. Sobald 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-Codebeispiel 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