Problem

Viele benutzerdefinierte Anwendungen rufen Web-Services von AEM auf.  Diese Anwendungen verwenden Apache Commons HTTP Client oder andere Bibliotheken.  Wenn Leistungsprobleme bei den Back-End-Systemen auftreten, treten bei AEM nur geringe Antwortzeiten auf.  Wenn zu viele Threads hängen, kann dies außerdem zu langsamen JVM-Speicherbereinigungen, Fehlern im Arbeitsspeicher, Betriebssystemauslastung usw. führen.

Wenn Sie Thread-Dumps oder Heap-Dumps von AEM erfassen, beobachten Sie viele Threads, die auf die Web-Service-Aufrufe warten.

Beispielszenario:
Unter [1] befindet sich ein Beispiel für eine Stack-Ablaufverfolgung aus einem JVM-Thread-Dump.  Dieser wurde von einer AEM-Instanz erfasst, bei der eine Anwendung einen schlecht funktionierenden Back-End-Dienst aufweist.

Die Thread-Sicherheitskopie zeigte einige Probleme:

  • Der unten aufgeführte Anfrage-Thread war auf einem Web Service hängen geblieben, der nicht geantwortet hat.  Keine Socket-Lese-Zeitüberschreitung wurde gesetzt, so dass der Thread für immer warten musste.  Siehe hier für die Lösung.
  • Hunderte von Threads warten auf den einzelnen Anfrage-Thread.  Der Grund dafür war, dass der Threadpool als Single-Thread konfiguriert wurde, in einer als Erster rein, als Erster raus Warteschlange.  Die vielen ausstehenden vorhandenen Threads führten zu einer hohen Arbeitsspeicherauslastung.  Siehe hier für die Lösung.
  • Der Webdienst, der aufgerufen wurde, brauchte zu lange, um zu antworten.  Dies führte dazu, dass sich der oben erwähnte Thread anhäufte.

Beachten Sie die markierten Stapelzeilen:

  • In Gelb können Sie sehen, dass die benutzerdefinierte Anwendung die RestTemplate-Bibliothek vom Spring Framework verwendet, um einen Web-Service-Aufruf auszuführen.  
  • In Orange können Sie sehen, dass der Spring Framework einen Apache Commons HTTP Client für seine Web-Service-Aufrufe verwendet.  
  • In Rot können Sie sehen, dass der Thread in SocketInputStream.socketRead hängen geblieben ist, was bedeutet, dass er auf eine Antwort vom Web Service wartet.

[1]

capture

Ursache

Im Folgenden finden Sie einige häufige Ursachen:

  1. Der Web-Service-Host ist nicht erreichbar und das Socket „Verbindungs-Timeout“ ist nicht festgelegt oder zu lang eingestellt (z. B. 10 Minuten).
  2. Der Webdienst ist aktiv, reagiert jedoch mit einem Fehler, der von der Anwendung nicht bearbeitet wird.
  3. Der Webdienst ist aktiv, reagiert jedoch zu langsam oder hängt während der Antwort.  Der Socket „Lese-Timeout“ ist nicht gesetzt oder zu lang eingestellt.  Threads warten unbegrenzt auf eine Antwort.
  4. Der Threadpool ist so konfiguriert, dass jeweils nur eine Anfrage zulässig ist.  Dies führt dazu, dass gleichzeitige Anfrage-Threads warten.

Lösung

Lösungen für diese Probleme:

  1. Setzen Sie das „Verbindungs-Timeout“ auf einen angemessenen Wert, z. B. drei Sekunden.
  2. Setzen Sie das „Lese-Timeout“ auf einen vernünftigen Wert.  Dieser Wert hängt davon ab, wie lange Sie die Antworten erwarten.  Für die meisten kleinen Webdienste sind zehn Sekunden sinnvoll.  Einige Webdienste, die viel verarbeiten oder große Dateien senden und / oder empfangen, erfordern jedoch eine höhere Einstellung für das Zeitlimit.
  3. Informationen dazu, wie Sie Multithreading effizient verwalten, finden Sie in der Dokumentation zu Ihrem httpclient oder Ihrer Webservice-Clientbibliothek.  In Apache Commons Http Client 3.x können Sie beispielsweise auf diese Seite verweisen.
  4. Zwischenspeicher der Antworten von Serviceaufrufen.  Dies gilt, wenn Sie den Dienst mit den gleichen Parametern aufrufen und mehrmals dasselbe Ergebnis erhalten.
  5. Wenn die Daten freigegeben sind (nicht benutzerspezifisch), sollten Sie den Web-Service in einem Hintergrundthread vorzeitig aufrufen und das Ergebnis zur späteren Verwendung speichern.  Verwenden Sie zum Beispiel einen Sling-Auftrag, einen Sling-Scheduler oder AEM-Polling-Importer, um einen Hintergrund-Thread zu verwalten.
  6. Wenn Sie eine hohe Anzahl von ausgehenden Anrufen haben, implementieren Sie einen Back-Off-Algorithmus, um Fehler zu beheben.  Dies ist der Punkt, an dem die Anwendung den Dienst aufruft und X-mal fehlschlägt. Dann hören Sie auf, es für eine bestimmte Zeit zu versuchen und melden stattdessen sofort Fehler.  Dann versuchen Sie es x-mal und wenn es schief geht oder mal wieder ausgeht, warten Sie eine längere Zeit und so weiter.  Dies geschieht normalerweise mit einer exponentiellen Zunahme der Wartezeit mit einer maximalen Verkappungszeit (auch bekannt als „Truncated Exponential Back-Off Algorithm“).

Dieses Werk unterliegt den Bedingungen der Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported License.  Twitter™- und Facebook-Beiträge fallen nicht unter die Bedingungen der Creative Commons-Lizenz.

Rechtliche Hinweise   |   Online-Datenschutzrichtlinie