Hinweise zum Anwendungsdesign für Asynchronous Request Dispatcher (ARD)
Asynchronous Request Dispatcher (ARD) ist keine immer und überall passende Lösung für die Servletprogrammierung. Sie müssen die Anforderungen Ihrer Anwendung auswerten und mögliche Vorbehalt gegen die Verwendung von ARD in Betracht ziehen. Die Umstellung aller Include-Aufrufe auf asynchronen Start ist nicht für alle Szenarien die geeignete Lösung, aber bei einem wohl überlegten Einsatz kann ARD zu einer Verbesserung der Antwortzeiten führen.
Clientseitige Implementierung von Asynchronous Request Dispatcher
- In die Antwortausgabe wird dynamisch JavaScript geschrieben.
- Die Verwendung von JavaScript führt dazu, dass Ajax-Anforderungen an einen serverseitigen Ergebnisprovider gesendet werden.
- Wegen der AIO-Features (Asynchronous Input/Output, asynchrone Ein-/Ausgabe) des Kanals wird die Ajax-Anforderung nicht an einen Thread gebunden. Stattdessen erfolgt eine Benachrichtigung über die Ausführung über einen Include-Callback.
- Der Client setzt jeweils nur eine einzige Anforderung für die asynchronen Includes ab, weil die Anzahl der Verbindungen im Browser beschränkt ist.
- Die ursprüngliche Verbindung muss für die Laufzeit de Includes gültig sein. Sie kann nicht für Ajax-Anforderungen wiederverwendet werden.
- In das Browserobjektmodell werden Kommentarknoten wie
eingefügt, da Kommentarknoten keine Auswirkung auf das Seitenlayout haben.<!--eindeutigePlatzhalterID--><!--1-->
- Sobald ein vollständiges Fragment vorhanden ist, kann eine Antwort an den Client gesendet werden und der Kommentarknoten mit derselben ID wird ersetzt. Es werden so lange Anforderungen abgesetzt, bis alle Fragmente abgerufen wurden.
- Es werden alle Anwendungen in allen unterstützten Browsern geprüft, wenn die clientseitige Aggregation verwendet wird. Es werden objektorientierte JavaScript-Prinzipien angewendet, so dass Anwendungen nur vermeiden müssen, die Methode "getDynamicDataIBMARD" zu verwenden. Alle bereits angegebenen Methoden "window.onload" werden vor der ARD-Methode "onload" gestartet.
ARD-Kanal als Ergebnisservice
Anforderungen für Include-Daten aus dem asynchronen JavaScript-Code werden an bekannte Uniform Resource Identifier (URIs, auch als URLs bezeichnet) gesendet, die der ARD-Kanal abfangen kann, um zu verhindern, dass sie die Anforderungsbearbeitung des Web-Containers durchlaufen. Diese URIs sind für jeden Serverneustart eindeutig.
Beispielsweise ist /IBMARD01234567/asyncInclude.js der URI für den JavaScript-Code, der den Abruf der Ergebnisse erzwingt, und /IBMARD01234567/IBMARDQueryStringEntries?=12000 der URI, der verwendet wird, um die Ergebnisse für den Eintrag mit der ID 12000 abzurufen.
Zur Verhinderung unbefugter Zugriffe auf die Ergebnisse werden eindeutige IDs für den Service-URI und für die ARD-Einträge generiert. Sitzung und ARD verwenden einen gemeinsamen ID-Generator, so dass die Eindeutigkeit über die Sitzungskonfiguration konfiguriert werden kann. Sitzungs-IDs werden als sicher eingestuft, aber sie sind nicht so sicher wie die Verwendung von LTPA-Token (Lightweight Third-Party Authentication).
Angepasste clientseitige Aggregation
<!--eindeutigePlatzhalterID--><!--x-->
geschrieben,
wobei x die Reihenfolge der Includes angibt.
Der Endpunkt für den Abruf der Ergebnisse wird dem Anforderungsattribut
"com.ibm.websphere.webcontainer.ard.endpointURI" entnommen.<div id="2"><BR>Servlet 3--dispatcher3 requesting Servlet3 to sleep for 0 seconds at: 1187967704265
<BR> Servlet 3--Okay, all done! This should print pop up: third at: 1187967704281 </div>
Weitere Informationen zu den Schnittstellen "AsyncRequestDispatcherConfig" und "AsyncRequestDispatcher" finden Sie in den Informationen zum Paket "com.ibm.websphere.webcontainer.async" in der API-Dokumentation. Sie finden die generierte API-Dokumentation im Inhaltsverzeichnis der Dokumentation unter
.Serverseitige Aggregation
Wie bei der clientseitigen Aggregation wird bei der serverseitigen Aggregation der ARD-Kanal als Ergebnisservice verwendet. Der ARD-Kanal weiß, welche asynchronen Includes für bestimmte Puffer stattgefunden haben. Diese Puffer können dann nach einem Include-Platzhalter durchsucht werden. Wegen der Probleme mit der Pufferung von JSPs ist der Platzhalter für den Include möglicherweise nicht in den durchsuchten Puffern enthalten. In diesem Fall muss auch die nächste Gruppe von Puffern nach Include-Platzhaltern durchsucht werden, die in der vorherigen Gruppe nicht gefunden wurden. ARD versucht, die Includes iterativ zusammenzufassen, wenn diese zurückgegeben werden, so dass der Antwortinhalt sobald wie möglich an den Client gesendet werden kann.
Parallelität
Zum Starten der Includes wird ein Arbeitsmanager verwendet. Wenn die Anzahl gleichzeitig angeforderter Includes die maximale Thread-Poolgröße des Arbeitsmanagers übersteigt und der Thread-Pool nicht vergrößert werden kann, wird die Arbeit im aktuellen Thread gestartet und das Schreiben der Platzhalter wird übersprungen. Bei der Verwendung von Concurrency Utilities for Java™ EE wird die Weitergabe des Java EE-Kontextes des ursprünglichen Threads unterstützt, einschließlich der Kontexte für den Arbeitsbereich, die Internationalisierung, das Anwendungsprofil, das Workload-Management des z/OS-Betriebssystems, die Sicherheit, die Transaktion und die Verbindung.
Zeitgeber
Es wird ein einziger Zeitgeber für ARD verwendet und es werden Zeitgebertasks für alle Zeitlimittypen von ARD-Anforderungen erstellt. Tasks, die beim Zeitgeber registriert werden, werden möglicherweise nicht genau zur angegebenen Zeit ausgeführt, weil der Zeitgeber in einem einzigen Thread ausgeführt wird. Deshalb muss ein Zeitlimit möglicherweise auf den Abschluss anderer Zeitlimitaktionen warten. Der Zeitgeber wird als letzte Abhilfemaßnahme verwendet.
Remote Request Dispatcher
Optional kann ARD zusammen mit Remote Request Dispatcher verwendet werden. Remote Request Dispatcher führt das Include in einem anderem Anwendungsserver in einer Stammgruppe aus, indem er den Anforderungskontext in eine SOAP-Nachricht serialisiert und Web-Services für den Aufruf des fernen Servers verwendet. Dies ist hilfreich, wenn die Kosten für das lokale Absetzen der Anforderung höher sind als die für das Erstellen und Senden einer SOAP-Nachricht über Web-Services.
Ausnahmen
Wenn eine Ausnahme in einem eingeschlossenen Servlet auftritt, arbeitet der Web-Container die Fehlerseitendefinitionen durch, die den Ausnahmetypen zugeordnet sind. Es wird also eine im Implementierungsdeskriptor definierte Fehlerseite als Teil der aggregierten Seite angezeigt. Fügen Sie der Fehlerseite selbst Logik hinzu, wenn das Verhalten für ein Include anders ist. Da der Include asynchron ausgeführt wird, wird das Servlet der Ausgangsebene möglicherweise nicht mehr ausgeführt. Deshalb wird die Ausnahme vom asynchronen Include nicht an dieses Servlet weitergegeben, wie es bei normalen Includes der Fall ist. Die anderen Includes werden abgeschlossen, so dass Teilseiten angezeigt werden können.
Wenn der ARD-Work-Manager keine weiteren Worker-Threads zu bearbeiten hat, wird der Include wie ein synchroner Include verarbeitet. Dies ist die Standardeinstellung, aber die Arbeit des Arbeitsmanagers kann auch zunehmen, so dass diese Bedingung nicht eintritt. Diese Änderung bei der Verarbeitung ist für den Benutzer zur Laufzeit nicht sichtbar, aber sie wird in den Systemprotokollen und ansonsten in den Traceprotokollen aufgezeichnet, sofern diese aktiviert sind. Andere Bedingungen, die eine synchrone Verarbeitung des Includes auslösen können, sind das Erreichen der maximalen Anzahl verfallener Anforderungen in einem bestimmten Zeitintervall und das Erreichen der maximalen Größe des Ergebnisspeichers.
Es können Ausnahmen außerhalb des Geltungsbereichs der normalen Fehlerseitenbehandlung eintreten. Beispielsweise kann Arbeit vom Arbeitsmanager zurückgewiesen werden. Ein Zeitgeber kann ablaufen, während auf die Rückgabe einer Include-Antwort gewartet wird. Der ARD-Kanal, der als generischer Service für den Abruf der Ergebnisse eingesetzt wird, kann eine ID empfangen, die nicht gültig ist. In diesen Fällen gibt es keinen Pfad zur Fehlerseitenbehandlung, weil der Kontext fehlt, z. B. eine ServletRequest, eine ServletResponse oder ein ServletContext, damit die Anforderung funktioniert. Um diese Probleme in Grenzen zu halten, können Sie die Schnittstelle "AsyncRequestDispatcherConfig" verwenden, um angepasste Fehlernachrichten bereitzustellen. Es werden Standardfehlernachrichten bereitgestellt und bei bedarf international verwendbar gemacht.
Es können auch Ausnahmen außerhalb des Geltungsbereichs der Anforderung, in der die angepasste Konfiguration definiert wurde, eintreten, z. B. wie in den nachfolgenden clientseitigen XMLHttpRequests. In diesem Fall muss die globale Konfiguration geändert werden. Diese kann über die Methode "com.ibm.wsspi.ard.AsyncRequestDispatcherConfigImpl.getRef()" abgerufen werden.
- Include-Start
- Der Arbeitsmanager bietet ein Zeitlimit, mit dem festgelegt wird, wie lange auf den Start eines Includes gewartet wird. Da Includes normalerweise sofort gestartet werden, gibt es keine programmgesteuerte Methode, diese Einstellung zu aktivieren. Diese Einstellung kann jedoch im Arbeitsmanager konfiguriert werden. Standardmäßig stellt sich dieses Problem nicht, weil die maximale Anzahl der Threads geprüft wird, bevor die Arbeit geplant wird. Arbeit kann abgerufen werden, wenn die Methode "setRetriable(true)" in der aktiven AsyncRequestDispatcherConfig aufgerufen wird.
- Include-Ende
- Das festgelegte Zeitlimit beginnt mit der Annahme der Arbeit. Es kann über die Konsole oder über das Programm mit der Methode "AsyncRequestDispatcherConfig.setExecutionTimeoutOverride" konfiguriert werden. Der Standardwert ist 60000 ms bzw. eine Minute. Anstelle der Include-Ergebnisse wird die Nachricht von AsyncRequestDispatcherConfig.setExecutionTimeoutMessage gesendet. Wenn das festgelegte Zeitlimit abgelaufen ist, aber die eigentlichen Include-Ergebnisse bereit sind, wenn die Daten in einer Flush-Operation geschrieben werden können, wird den eigentlichen Ergebnissen der Vorzug gegeben. Außerdem gilt diese Einstellung nicht für insertFragmentBlocking-Aufrufe, die immer warten, bis der Include abgeschlossen ist.
- Verfall von Ergebnissen
- Da die Clientseite die Ergebnisse für die Ajax-Anforderung in einem Service verwalten muss, wird eine Methode benötigt, die Ergebnisse verfallen lassen zu können, falls der Client abstürzt und den Eintrag nicht abruft. Der Standardwert von einer Minute ist für eine typische Anforderung ausreichend, weil die Ajax-Anforderung direkt nach dem Senden der Antwort eingehen würde. Der Zeitgeber kann über das Programm mit der Methode "setExpirationTimeoutOverride" von AsyncRequestDispatcherConfig konfiguriert werden. Die Nachricht der Methode "getOutputRetrievalFailureMessage" von AsyncRequestDispatcherConfig wird angezeigt, wenn jemand versucht, auf einen Eintrag zuzugreifen, der verfallen ist und aus dem Cache entfernt wurde. Diese Nachricht ist dieselbe, die an jemanden gesendet wird, der ein Ergebnis mit einer nicht vorhandenen ID anfordert.
Includes oder Fragmente
Überlegen Sie, welche Operationen asynchron ausgeführt und wann sie gestartet werden können. Idealerweise sind alle Includes abgeschlossen, wenn die getFragment-Aufrufe beim Start der Anforderung abgesetzt werden, so dass die Includes mehr Zeit zur Ausführung haben und beim Einfügen der Fragmente nicht so viel zusätzlicher Pufferungs- und Aggregationsaufwand entsteht. Einen asynchronen Include aufzurufen, ist jedoch einfacher, weil hierfür dasselbe Muster verwendet wird wie bei einem normalen Anforderungs-Dispatcher-Include.
Web-Container
- ServletContext
- Bei der Ausführung kontextübergreifender Includes muss ARD auch im Zielkontext des Includes aktiviert sein, weil die Webanwendung für ARD initialisiert sein muss, damit der zugehörige Servletkontext gültige Methoden für den Abruf eines AsyncRequestDispatcher besitzt. Der Aggregationstyp wird durch die Konfiguration des ursprünglichen Kontextes bestimmt, da Aggregationstypen nicht gemischt werden können.
- ServletRequest
- Sie müssen die Anforderung für jeden Include klonen. Andernfalls können Konflikte zwischen Threads auftreten. Da Anwendungen die Standardanforderungsobjekte einschließen können (Wrapping), müssen Ihre Wrapper die Schnittstelle "com.ibm.wsspi.webcontainer.servlet.IServletRequest" implementieren, die eine einzige Methode, die Methode "public Object clone" enthält, die die Ausnahme des Typs "CloneNotSupportedException" erstellt.
- Die Aufhebung des Wrappings findet erst statt, wenn ein Anforderungswrapper gefunden wird, der diese Schnittstelle implementiert. Wrapper, die diese Schnittstelle nicht implementieren, sind verloren. Ein für den Include konfigurierter Servletfilter kann die Antwort jedoch erneut einschließen.
- An der ServletRequest vorgenommene Änderungen werden nur an das Servlet der Ausgangsebene zurückgegeben, wenn "transferState" in AsyncRequestDispatcherConfig aktiviert und "insertFragmentBlocking" aufgrufen wird.
- ServletResponse
- Eine eingeschlossene Antwort, die die Schnittstelle "com.ibm.websphere.servlet.response.StoredResponse" erweitert, wird von ARD erstellt und an die Includes gesendet, weil die Antwortausgabe über den Lebenszyklus der ursprünglichen Antwort hinaus abrufbar sein muss.
- In asynchronen Includes definierte interne Header werden aufgrund der Lebenszykluseinschränkungen nur unterstützt, wenn "transferState" in der AsyncRequestDispatcher-Konfiguration aktiviert und "insertFragmentBlocking" aufgerufen wird. Normale Header werden gemäß der Servlet-Spezifikation in einem synchronen Include nicht unterstützt.
- Include-Filter können die neue Antwort erneut einschließen und müssen nach Abschluss des Includes eine Flush-Operation ausführen.
- ServletInputStream
- Eine Anwendung, die Parameter mit "getParameter" liest, ist nicht problematisch. Die Syntaxanalyse der Parameter wird vor dem ersten asynchronen Include erzwungen, um so den gleichzeitigen Zugriff auf den Eingabedatenstrom zu verhindern.
- HttpSession
- Das Servlet der Ausgangsebene muss zuerst getSession-Aufrufe, die einen Set-Cookie-Header liefern, absetzen, weil es nicht unvorhersehbar ist, wann die Includes gestartet werden und ob die Header bereits in einer Flush-Operation geschrieben wurden. Die Ausnahme tritt ein, wenn "transferState" in "AsyncRequestDispatcherConfig" aktiviert ist und "insertFragmentBlocking" aufgerufen wird. In diesem Fall wird normalerweise eine Ausnahme erstellt, wenn Sie den Header hinzufügen.
- Filter
- Wenn ein Filter für einen Include vorhanden ist, wird der Filter im asynchronen Thread abgesetzt.
- Verschachtelte asynchrone Includes
- Verschachtelte asynchrone Includes werden nicht unterstützt, weil sie die Aggregation komplizieren. Ein asynchroner Include kann jedoch verschachtelte synchrone Includes enthalten. Jeder Versuch, einen verschachtelten asynchronen Include durchzuführen, führt dazu, dass auf einen synchronen Include zurückgegriffen wird.
Transaktionen
Jede an den Arbeitsmanager übergebene Task wird mit einer eigenen Transaktion aufgerufen, ähnlich wie containergesteuerte Transaktionen in einer typischen Enterprise-Bean. Die Laufzeitumgebung startet eine lokale Transaktion, bevor sie die Methode startet. Die Task kann eine eigene globale Transaktion starten, wenn diese Transaktion für die aufrufende Java EE-Komponente möglich ist.
Wird von der Task eine Ausnahme zurückgegeben, werden alle lokalen Transaktionen rückgängig gemacht. Falls die Methode normal zurückkehrt, werden unvollständige lokale Transaktionen gemäß der für die Bean konfigurierten Richtlinie für nicht aufgelöste Aktionen beendet. Falls die Task ihre eigene globale Transaktion startet und diese globale Transaktion nicht festschreibt (Commit), dann wird die Transaktion rückgängig gemacht (Rollback), wenn die Methode zurückgegeben wird.
Verbindungsverwaltung
- Der JNDI-Name ist fest in der Anwendung codiert, z. B. als Eigenschaft oder als Zeichenfolgeliteral.
- Die Verbindungsfactorys werden nicht gemeinsam benutzt, weil es nicht möglich ist, einen gemeinsamen Bereich zu definieren.
Leistung
Da Includes asynchron ausgeführt werden, muss in den Gesamtleistungsdaten für eine Anforderung die Leistung der asynchronen Includes berücksichtigt werden. Die Gesamtdauer der Anforderung konnte zuvor als die Zeit verstanden werden, die das Servlet der Ausgangsebene für seine Ausführung benötigt, aber jetzt wird dieses Servlet beendet, bevor die Includes abgeschlossen sind. Das Servlet der Ausgangsebene trägt weiterhin wesentlich zu der für die für jeden Include erforderlichen zusätzlichen Konfigurationszeit bei.
Deshalb wurde Performance Monitoring Infrastructure (PMI) eine neue ARD-Leistungsmetrik hinzugefügt, die die Zeit für die Ausführung einer Anforderung über den ARD-Kanal misst. Die Differenzierung dieser Metrik findet auf der Ebene der Anforderungs-URIs statt.
Da ARD ein optionales Feature ist, das aktiviert werden muss, wird kein Leistungsabfall erkannt, wenn ARD nicht verwendet wird. Anwendungen, die ARD nicht nutzen und sich in einem Anwendungsserver befinden, in dem ARD aktiviert ist, würden jedoch durch die zusätzliche Schicht mit dem ARD-Kanal beeinträchtigt werden. Die Kanalschicht erkennt nicht, welche Anwendung sie zugeteilt wird, d. h., sie ist für alle Anwendungen in einer Kanalkette entweder aktiviert oder inaktiviert. Die Definition erfolgt für jeden virtuellen Host.
Sicherheit
Die Sicherheit wird gemäß Servlet-Spezifikation in synchronen Include-Zuteilungen nicht aufgerufen. Der Sicherheitskontext wird zur Unterstützung der programmgesteuerten Verwendung der Methoden "isUserInRole" und "getUserPrincipal" in ServletRequest jedoch über Concurrency Utilities for Java EE übergeben. Dieser Sicherheitskontext kann auch an einen Dispatcher für ferne Anforderungen weitergegeben werden, der Web Services Security verwendet.