Ich arbeite an einem Projekt, in dem wir einen Authentifizierungsmechanismus haben. Wir befolgen die folgenden Schritte im Authentifizierungsmechanismus.
wait()
-Methode warten. notify()
für den zuvor wartenden Thread auf und senden Erfolg als Antwort, und der Benutzer wird in unser System eingegeben. notify()
-Methode für den zuvor wartenden Thread auf und senden failed als Antwort und zeigen dem Benutzer eine ungültige Anmeldeinformation an. Alles funktioniert gut, aber kürzlich sind wir in eine Clusterumgebung gewechselt. Wir haben festgestellt, dass einige Threads auch nach einer Antwort des Benutzers und einer unbegrenzten Wartezeit nicht benachrichtigt werden.
Für den Server verwenden wir Tomcat 5.5, und wir folgen The Apache Tomcat 5.5 Servlet / JSP Container für die Tomcat Cluster-Umgebung.
Antwort :: Mögliches Problem und Lösung
Das mögliche Problem sind die mehreren JVMs in einer Clusterumgebung. Jetzt senden wir auch die gruppierte Tomcat-URL zusammen mit der generierten Zeichenfolge an die Android-Anwendung des Benutzers.
Und wenn der Benutzer auf die Antwortschaltfläche klickt, senden wir die generierte Zeichenfolge zusammen mit der gruppierten Tomcat-URL. In diesem Fall werden beide Anfragen an dieselbe JVM gesendet, und es funktioniert einwandfrei.
Aber ich frage mich, ob es eine einzige Lösung für das oben genannte Problem gibt.
Es gibt ein Problem in dieser Lösung. Was passiert, wenn der Clustered-Tomcat abstürzt? Der Load-Balancer sendet eine Anfrage an den zweiten Cluster-Tomcat, und wieder tritt das gleiche Problem auf.
Der Grund für Ihre Probleme liegt darin, dass Java EE so konzipiert wurde, dass es auf eine andere Art und Weise funktioniert. Der Versuch, einen Dienst-Thread zu blockieren / zu warten, ist einer der wichtigen No-No-Punkte. Ich werde den Grund dafür zuerst nennen und danach das Problem lösen.
Java EE (sowohl die Web- als auch die EJB-Ebene) wurde so entworfen, dass es auf sehr große Größen skaliert werden kann (Hunderte von Computern in einem Cluster). Um dies zu tun, mussten die Designer jedoch die folgenden Annahmen treffen, die spezifische Einschränkungen bei der Codierung darstellen:
Transaktionen sind:
Der gesamte Benutzerstatus wird in bestimmten Datenspeichercontainern beibehalten, einschließlich:
Websitzung Dies ist ein Schlüssel-Wert-Speicher (etwa wie eine NoSQL-Datenbank, aber ohne die Skalierungs- oder Suchfunktionen), die Daten für einen bestimmten Benutzer über ihre Sitzung hinweg festhält. Es wird vom Java EE-Container verwaltet und hat die folgenden Eigenschaften:
Wenn wir diesen Regeln folgen, kann der Java EE-Container erfolgreich einen Cluster verwalten, einschließlich dem Herunterfahren von Knoten, dem Starten neuer Knoten und dem Migrieren von Benutzersitzungen, ohne einen bestimmten Entwicklercode . Entwickler schreiben die grafische Benutzeroberfläche und die Geschäftslogik - alle "Installationen" werden durch konfigurierbare Containerfunktionen verwaltet.
Außerdem kann der Java EE-Container zur Laufzeit von einer ziemlich ausgeklügelten Software überwacht und verwaltet werden, die Anwendungsleistung und Verhaltensprobleme in einem Live-System nachverfolgen kann.
& lt; snark & gt; Nun, das war die Theorie. Die Praxis legt nahe, dass es ziemlich wichtige Einschränkungen gibt, die übersehen wurden, die zu AOSP- und Code-Injektionstechniken führen, aber das ist eine andere Geschichte & lt; / snark & gt;
[Es gibt viele Diskussionen rund um das Internet dazu. Eine, die sich auf EJBs konzentriert, ist hier: Warum Laich-Threads in Java EE-Container wird abgeraten? Genau das gleiche gilt für Webcontainer wie Tomcat]
Entschuldigung für den Aufsatz - aber das ist wichtig für Ihr Problem. Aufgrund der Beschränkungen für Threads sollten Sie die Webanforderung, die auf eine spätere Anforderung wartet, nicht blockieren.
Ein weiteres Problem mit dem aktuellen Design ist, was passiert, wenn der Benutzer vom Netzwerk getrennt wird, keine Stromversorgung mehr hat oder sich einfach entscheidet aufzugeben? Vermutlich wirst du aussteigen, aber nach wie lange? Gerade zu früh für einige Kunden, vielleicht, was Zufriedenheitsprobleme verursachen wird. Wenn das Zeitlimit zu lang ist, können Sie in Tomcat die alle Worker-Threads blockieren und der Server wird einfrieren. Dies öffnet Ihre Organisation für einen Denial-of-Service-Angriff.
BEARBEITEN: Verbesserte Vorschläge, nachdem eine detailliertere Beschreibung des Algorithmus veröffentlicht wurde.
Ungeachtet der obigen Diskussion über die schlechte Praxis des Blockierens eines Web-Worker-Threads und der möglichen Dienstverweigerung ist es klar, dass dem Benutzer ein kleines Zeitfenster angezeigt wird, in dem er auf die Benachrichtigung auf dem Android-Telefon reagieren kann. und das kann relativ klein gehalten werden, um die Sicherheit zu erhöhen. Dieses Zeitfenster kann auch unterhalb von Tomcat's Timeout für Antworten gehalten werden. So könnte der Thread-Blocking-Ansatz verwendet werden.
Es gibt zwei Möglichkeiten, wie dieses Problem gelöst werden kann:
Bei Ansatz 1 fragt der Browser den Server über Javascript mit einem AJAX-Aufruf an einen Web-Service auf Tomcat ab; Der AJAX-Aufruf gibt True
zurück, wenn die Android-App authentifiziert wurde.Vorteil: Client-Seite, minimale Implementierung auf dem Server, keine Thread-Blockierung auf dem Server. Nachteile: Während der Wartezeit müssen Sie häufig telefonieren (vielleicht eine Sekunde - der Benutzer wird diese Latenz nicht bemerken), was zu vielen Anrufen und zusätzlicher Belastung des Servers führt.
Für Ansatz 2 gibt es wieder die Wahl:
Blockieren Sie den Thread mit einem Object.wait()
, der optional die Knoten-ID, IP oder eine andere Kennung in einem freigegebenen Datenspeicher speichert: Wenn dies der Fall ist, muss der Knoten, der die Android-App-Autorisierung erhält:
Senden Sie für jeden Knoten in 1. oben eine Nachricht, die angibt, welche Benutzersitzung entsperrt werden soll. Die Nachricht könnte gesendet werden über:
Object.notify
im korrekten Thread Object.notify()
im richtigen Thread aufruft. Beantworten Sie einen Datenspeicher, bis der Thread zum Fortfahren berechtigt ist: In diesem Fall muss die gesamte Android-App den Status in einer SQL-Datenbank speichern
Die Verwendung von wait / notify kann schwierig sein. Denken Sie daran, dass jeder Thread jederzeit unterbrochen werden kann. Es ist also möglich, dass notify vor dem Warten angerufen wird. In diesem Fall wird wait für immer blockiert.
Ich würde dies in Ihrem Fall nicht erwarten, da Sie Benutzerinteraktion beteiligt sind. Aber für die Art der Synchronisation, die Sie gerade tun, versuchen Sie es mit einem Semaphor. Erstellen Sie einen Semaphor mit 0 (Null) Menge. Der wartende Thread ruft acquire () auf und blockiert, bis ein anderer Thread release () aufruft.
Semaphore auf diese Weise zu verwenden, ist wesentlich robuster als Warten / Benachrichtigen für die Aufgabe, die Sie beschrieben haben.
Ziehen Sie die Verwendung eines speicherinternen Gitters in Betracht, damit die Instanzen im Cluster den Status gemeinsam nutzen können. Wir haben Hazelcast verwendet, um Daten zwischen Instanzen zu teilen. Falls eine Antwort eine andere Instanz erreicht, kann sie damit umgehen.
z. Sie können den verteilten Countdown-Latch mit dem Wert 1 verwenden, um den nach dem Senden der Nachricht wartenden Thread festzulegen. Wenn die Antwort vom Client auf eine separate Instanz ankommt, kann diese Instanz den Latch auf 0 reduzieren und den ersten Thread ausführen .
Ihre Cluster-Bereitstellung bedeutet, dass jeder Knoten im Cluster eine Antwort erhalten kann.
Die Verwendung von wait / notify mit Threads für eine Webanwendung birgt das Risiko, dass viele Threads angehäuft werden, die möglicherweise nicht benachrichtigt werden und Speicher oder viele blockierte Threads verursachen könnten. Dies könnte die Zuverlässigkeit Ihres Servers beeinträchtigen.
Eine robustere Lösung wäre, die Anfrage an die Android-App zu senden und den aktuellen Status der Benutzeranforderung für die spätere Verarbeitung zu speichern und die HTTP-Anfrage abzuschließen. Um den Zustand zu speichern, den Sie in Erwägung ziehen könnten:
Dieser Status ist für alle Knoten in Ihrem Tomcat-Cluster sichtbar.
Wenn die Antwort der Android App auf einem anderen Knoten eintrifft, stellen Sie den Zustand des Threads wieder her und fahren Sie mit der Verarbeitung auf diesem Knoten fort.
Wenn die Benutzeroberfläche der Anwendung auf eine Antwort vom Server wartet, können Sie eine ajax Anfrage zur Abfrage des Antwortstatus vom Server. Der Knoten, der die Android-App-Antwort verarbeitet, muss nicht mit den UI-Anforderungen identisch sein.
Die Verwendung von Thread.wait
in einer Web-Service-Umgebung ist ein kolossaler Fehler. Pflegen Sie stattdessen eine Datenbank mit Benutzer- / Token-Paaren, und führen Sie sie in Intervallen aus.
Wenn Sie einen Cluster möchten, verwenden Sie eine Datenbank, die gruppierbar ist. Ich würde etwas wie memcached empfehlen, da es in-memory (und schnell) und wenig Aufwand (Schlüssel / Wert-Paare sind tot einfach, so dass Sie nicht brauchen RDBMS, etc.). memcached behandelt den Ablauf von Token für Sie bereits, so dass es wie eine perfekte Passform scheint.
Ich denke der Benutzername - & gt; Token - & gt; Die Passwortstrategie ist unnötig, insbesondere weil zwei verschiedene Komponenten die gleiche 2-Faktor-Authentifizierungsverantwortung teilen. Ich denke, dass Sie Ihre Komplexität weiter reduzieren, Verwirrung für Ihre Benutzer reduzieren und sich etwas Geld in SMS-Sendegebühren sparen können.
Die Interaktion mit Ihrem Webservice ist einfach:
userid
= token
in memcached Es gibt keine Threading-Probleme mit der obigen Lösung und es werden so viele JVMs skaliert, wie Sie benötigen, um Ihre eigene Software zu unterstützen.
Nachdem ich Ihre Frage analysiert hatte, kam ich zu dem Schluss, dass das genaue Problem mehrere JVMs in einer Clusterumgebung sind.
Das genaue Problem liegt an der Cluster-Umgebung. Beide Anfragen gehen nicht zur selben JVM. Aber wir wissen, dass eine normale / einfache Benachrichtigung auf der gleichen JVM funktioniert, wenn der vorherige Thread wartet.
Sie sollten versuchen, beide Anfragen auszuführen (erste Anfrage, zweite Anfrage, wenn der Benutzer aus einer Android-Anwendung antwortet).
Ziehen Sie die Verwendung eines speicherinternen Gitters in Betracht, damit die Instanzen im Cluster den Status gemeinsam nutzen können. Wir haben Hazelcast verwendet, um Daten zwischen Instanzen zu teilen. Falls eine Antwort eine andere Instanz erreicht, kann sie damit umgehen.
z. Sie können den verteilten Countdown-Latch mit dem Wert 1 verwenden, um den nach dem Senden der Nachricht wartenden Thread festzulegen. Wenn die Antwort vom Client auf eine separate Instanz ankommt, kann diese Instanz den Latch auf 0 reduzieren und den ersten Thread ausführen .
Die Verwendung von wait / notify kann schwierig sein. Denken Sie daran, dass jeder Thread jederzeit unterbrochen werden kann. Es ist also möglich, dass notify vor dem Warten angerufen wird. In diesem Fall wird wait für immer blockiert.
Ich würde dies in Ihrem Fall nicht erwarten, da Sie Benutzerinteraktion beteiligt sind. Aber für die Art der Synchronisation, die Sie gerade tun, versuchen Sie es mit einem Semaphor. Erstellen Sie einen Semaphor mit 0 (Null) Menge. Der wartende Thread ruft acquire () auf und blockiert, bis ein anderer Thread release () aufruft.
Semaphore auf diese Weise zu verwenden, ist wesentlich robuster als Warten / Benachrichtigen für die Aufgabe, die Sie beschrieben haben.
Der Grund für Ihre Probleme liegt darin, dass Java EE so konzipiert wurde, dass es auf eine andere Art und Weise funktioniert. Der Versuch, einen Dienst-Thread zu blockieren / zu warten, ist einer der wichtigen No-No-Punkte. Ich werde den Grund dafür zuerst nennen und danach das Problem lösen.
Java EE (sowohl die Web- als auch die EJB-Ebene) wurde so entworfen, dass es auf sehr große Größen skaliert werden kann (Hunderte von Computern in einem Cluster). Um dies zu tun, mussten die Designer jedoch die folgenden Annahmen treffen, die spezifische Einschränkungen bei der Codierung darstellen:
Transaktionen sind:
Der gesamte Benutzerstatus wird in bestimmten Datenspeichercontainern beibehalten, einschließlich:
Websitzung Dies ist ein Schlüssel-Wert-Speicher (etwa wie eine NoSQL-Datenbank, aber ohne die Skalierungs- oder Suchfunktionen), die Daten für einen bestimmten Benutzer über ihre Sitzung hinweg festhält. Es wird vom Java EE-Container verwaltet und hat die folgenden Eigenschaften:
Wenn wir diesen Regeln folgen, kann der Java EE-Container erfolgreich einen Cluster verwalten, einschließlich dem Herunterfahren von Knoten, dem Starten neuer Knoten und dem Migrieren von Benutzersitzungen, ohne einen bestimmten Entwicklercode . Entwickler schreiben die grafische Benutzeroberfläche und die Geschäftslogik - alle "Installationen" werden durch konfigurierbare Containerfunktionen verwaltet.
Außerdem kann der Java EE-Container zur Laufzeit von einer ziemlich ausgeklügelten Software überwacht und verwaltet werden, die Anwendungsleistung und Verhaltensprobleme in einem Live-System nachverfolgen kann.
& lt; snark & gt; Nun, das war die Theorie. Die Praxis legt nahe, dass es ziemlich wichtige Einschränkungen gibt, die übersehen wurden, die zu AOSP- und Code-Injektionstechniken führen, aber das ist eine andere Geschichte & lt; / snark & gt;
[Es gibt viele Diskussionen rund um das Internet dazu. Eine, die sich auf EJBs konzentriert, ist hier: Warum Laich-Threads in Java EE-Container wird abgeraten? Genau das gleiche gilt für Webcontainer wie Tomcat]
Entschuldigung für den Aufsatz - aber das ist wichtig für Ihr Problem. Aufgrund der Beschränkungen für Threads sollten Sie die Webanforderung, die auf eine spätere Anforderung wartet, nicht blockieren.
Ein weiteres Problem mit dem aktuellen Design ist, was passiert, wenn der Benutzer vom Netzwerk getrennt wird, keine Stromversorgung mehr hat oder sich einfach entscheidet aufzugeben? Vermutlich wirst du aussteigen, aber nach wie lange? Gerade zu früh für einige Kunden, vielleicht, was Zufriedenheitsprobleme verursachen wird. Wenn das Zeitlimit zu lang ist, können Sie in Tomcat die alle Worker-Threads blockieren und der Server wird einfrieren. Dies öffnet Ihre Organisation für einen Denial-of-Service-Angriff.
BEARBEITEN: Verbesserte Vorschläge, nachdem eine detailliertere Beschreibung des Algorithmus veröffentlicht wurde.
Ungeachtet der obigen Diskussion über die schlechte Praxis des Blockierens eines Web-Worker-Threads und der möglichen Dienstverweigerung ist es klar, dass dem Benutzer ein kleines Zeitfenster angezeigt wird, in dem er auf die Benachrichtigung auf dem Android-Telefon reagieren kann. und das kann relativ klein gehalten werden, um die Sicherheit zu erhöhen. Dieses Zeitfenster kann auch unterhalb von Tomcat's Timeout für Antworten gehalten werden. So könnte der Thread-Blocking-Ansatz verwendet werden.
Es gibt zwei Möglichkeiten, wie dieses Problem gelöst werden kann:
Bei Ansatz 1 fragt der Browser den Server über Javascript mit einem AJAX-Aufruf an einen Web-Service auf Tomcat ab; Der AJAX-Aufruf gibt %code% zurück, wenn die Android-App authentifiziert wurde.Vorteil: Client-Seite, minimale Implementierung auf dem Server, keine Thread-Blockierung auf dem Server. Nachteile: Während der Wartezeit müssen Sie häufig telefonieren (vielleicht eine Sekunde - der Benutzer wird diese Latenz nicht bemerken), was zu vielen Anrufen und zusätzlicher Belastung des Servers führt.
Für Ansatz 2 gibt es wieder die Wahl:
Blockieren Sie den Thread mit einem %code% , der optional die Knoten-ID, IP oder eine andere Kennung in einem freigegebenen Datenspeicher speichert: Wenn dies der Fall ist, muss der Knoten, der die Android-App-Autorisierung erhält:
Senden Sie für jeden Knoten in 1. oben eine Nachricht, die angibt, welche Benutzersitzung entsperrt werden soll. Die Nachricht könnte gesendet werden über:
Beantworten Sie einen Datenspeicher, bis der Thread zum Fortfahren berechtigt ist: In diesem Fall muss die gesamte Android-App den Status in einer SQL-Datenbank speichern
Die Verwendung von %code% in einer Web-Service-Umgebung ist ein kolossaler Fehler. Pflegen Sie stattdessen eine Datenbank mit Benutzer- / Token-Paaren, und führen Sie sie in Intervallen aus.
Wenn Sie einen Cluster möchten, verwenden Sie eine Datenbank, die gruppierbar ist. Ich würde etwas wie memcached empfehlen, da es in-memory (und schnell) und wenig Aufwand (Schlüssel / Wert-Paare sind tot einfach, so dass Sie nicht brauchen RDBMS, etc.). memcached behandelt den Ablauf von Token für Sie bereits, so dass es wie eine perfekte Passform scheint.
Ich denke der Benutzername - & gt; Token - & gt; Die Passwortstrategie ist unnötig, insbesondere weil zwei verschiedene Komponenten die gleiche 2-Faktor-Authentifizierungsverantwortung teilen. Ich denke, dass Sie Ihre Komplexität weiter reduzieren, Verwirrung für Ihre Benutzer reduzieren und sich etwas Geld in SMS-Sendegebühren sparen können.
Die Interaktion mit Ihrem Webservice ist einfach:
Es gibt keine Threading-Probleme mit der obigen Lösung und es werden so viele JVMs skaliert, wie Sie benötigen, um Ihre eigene Software zu unterstützen.
Ihre Cluster-Bereitstellung bedeutet, dass jeder Knoten im Cluster eine Antwort erhalten kann.
Die Verwendung von wait / notify mit Threads für eine Webanwendung birgt das Risiko, dass viele Threads angehäuft werden, die möglicherweise nicht benachrichtigt werden und Speicher oder viele blockierte Threads verursachen könnten. Dies könnte die Zuverlässigkeit Ihres Servers beeinträchtigen.
Eine robustere Lösung wäre, die Anfrage an die Android-App zu senden und den aktuellen Status der Benutzeranforderung für die spätere Verarbeitung zu speichern und die HTTP-Anfrage abzuschließen. Um den Zustand zu speichern, den Sie in Erwägung ziehen könnten:
Dieser Status ist für alle Knoten in Ihrem Tomcat-Cluster sichtbar.
Wenn die Antwort der Android App auf einem anderen Knoten eintrifft, stellen Sie den Zustand des Threads wieder her und fahren Sie mit der Verarbeitung auf diesem Knoten fort.
Wenn die Benutzeroberfläche der Anwendung auf eine Antwort vom Server wartet, können Sie eine ajax Anfrage zur Abfrage des Antwortstatus vom Server. Der Knoten, der die Android-App-Antwort verarbeitet, muss nicht mit den UI-Anforderungen identisch sein.
Nachdem ich Ihre Frage analysiert hatte, kam ich zu dem Schluss, dass das genaue Problem mehrere JVMs in einer Clusterumgebung sind.
Das genaue Problem liegt an der Cluster-Umgebung. Beide Anfragen gehen nicht zur selben JVM. Aber wir wissen, dass eine normale / einfache Benachrichtigung auf der gleichen JVM funktioniert, wenn der vorherige Thread wartet.
Sie sollten versuchen, beide Anfragen auszuführen (erste Anfrage, zweite Anfrage, wenn der Benutzer aus einer Android-Anwendung antwortet).
Ich fürchte, aber Threads können nicht über klassische Java EE Cluster migrieren.
Sie müssen Ihre Architektur überdenken, um das Warten / Benachrichtigen anders (verbindungslos) zu implementieren.
Oder Sie versuchen es mit terracotta.org . Es sieht so aus, als ob damit ein gesamter JVM Prozess über mehrere Rechner hinweg geclustert werden kann. Vielleicht ist es deine einzige Lösung.
Lesen Sie eine kurze Einführung in Einführung in OpenTerracotta .
>Ich schätze, das Problem ist, dass Ihr erster Thread eine Benachrichtigung an die Android-Anwendung des Benutzers in JVM 1 sendet und wenn der Benutzer antwortet, geht das Steuerelement an JVM 2. Und das ist das Hauptproblem.
Irgendwie können beide Threads auf dieselbe JVM zugreifen, um die Warte- und Benachrichtigungslogik anzuwenden.
Lösung:
Erstellen Sie einen einzigen Kontaktpunkt für alle wartenden Threads. Daher werden in einer Clusterumgebung alle Threads auf eine dritte JVM (Single Point of Contact) warten, so dass auf diese Weise alle Anfragen (alle Clustered Tomcat ) wird dieselbe JVM kontaktieren, um auf die Logik zu warten und sie zu benachrichtigen. Daher wird kein Thread für eine unbegrenzte Zeit warten. Wenn es eine Antwort gibt, wird der Thread benachrichtigt, wenn das gleiche Objekt gewartet hat und das zweite Mal benachrichtigt wird.
Ich arbeite an einem Projekt, in dem wir einen Authentifizierungsmechanismus haben. Wir befolgen die folgenden Schritte im Authentifizierungsmechanismus.
Alles funktioniert gut, aber kürzlich sind wir in eine Clusterumgebung gewechselt. Wir haben festgestellt, dass einige Threads auch nach einer Antwort des Benutzers und einer unbegrenzten Wartezeit nicht benachrichtigt werden.
Für den Server verwenden wir Tomcat 5.5, und wir folgen The Apache Tomcat 5.5 Servlet / JSP Container für die Tomcat Cluster-Umgebung.
Antwort :: Mögliches Problem und Lösung
Das mögliche Problem sind die mehreren JVMs in einer Clusterumgebung. Jetzt senden wir auch die gruppierte Tomcat-URL zusammen mit der generierten Zeichenfolge an die Android-Anwendung des Benutzers.
Und wenn der Benutzer auf die Antwortschaltfläche klickt, senden wir die generierte Zeichenfolge zusammen mit der gruppierten Tomcat-URL. In diesem Fall werden beide Anfragen an dieselbe JVM gesendet, und es funktioniert einwandfrei.
Aber ich frage mich, ob es eine einzige Lösung für das oben genannte Problem gibt.
Es gibt ein Problem in dieser Lösung. Was passiert, wenn der Clustered-Tomcat abstürzt? Der Load-Balancer sendet eine Anfrage an den zweiten Cluster-Tomcat, und wieder tritt das gleiche Problem auf.
Ich schätze, das Problem ist, dass Ihr erster Thread eine Benachrichtigung an die Android-Anwendung des Benutzers in JVM 1 sendet und wenn der Benutzer antwortet, geht das Steuerelement an JVM 2. Und das ist das Hauptproblem.
Irgendwie können beide Threads auf dieselbe JVM zugreifen, um die Warte- und Benachrichtigungslogik anzuwenden.
Lösung:
Erstellen Sie einen einzigen Kontaktpunkt für alle wartenden Threads. Daher werden in einer Clusterumgebung alle Threads auf eine dritte JVM (Single Point of Contact) warten, so dass auf diese Weise alle Anfragen (alle Clustered Tomcat ) wird dieselbe JVM kontaktieren, um auf die Logik zu warten und sie zu benachrichtigen. Daher wird kein Thread für eine unbegrenzte Zeit warten. Wenn es eine Antwort gibt, wird der Thread benachrichtigt, wenn das gleiche Objekt gewartet hat und das zweite Mal benachrichtigt wird.
Tags und Links java web-applications architecture tomcat cluster-computing