Wir entwickeln eine Anwendung, die einige rudimentäre Chat / Message-Passing-Funktionen beinhaltet. Die Webanwendung wird auf Wildfly 8.x bereitgestellt und verwendet Standard-JavaEE 7-Bibliotheken (im Gegensatz zu einem zusätzlichen Anwendungsframework wie Spring). Wir nutzen WebSockets, um dies zu erreichen, da wir die Push-to-Browser-Funktionalität benötigen bietet. Wir stellen diese Webanwendung jedoch in einer Cluster- / HA-Konfiguration bereit. Wenn UserA mit NodeA verbunden ist und eine Nachricht an UserB weiterleitet, die mit NodeB verbunden ist, wie machen wir dann den Transport dieser Nachricht?
In einer Konfiguration mit einem einzelnen Knoten würde die einfache Antwort darin bestehen, eine statische Map
oder List
mit allen Websockets und Sitzungen beizubehalten und auf der Grundlage des Nachrichtenziels zum entsprechenden Websocket zu routen. Aber mit mehr als einem Knoten, der offensichtlich nicht funktioniert, weil die statische Map
/ List
pro-JVM ist.
Wie würden wir dieses Ziel erreichen? Wäre es möglich, JMS zu verwenden und jeden Websocket als JMS-Listener zu verwenden? Welchen Einfluss hätte dies auf die Ressourcennutzung, Skalierbarkeit und Leistung?
Wir haben ein wenig verloren, um dieses Problem zu lösen, und würden uns über jeden Rat freuen, den Sie geben können.
Sie können dies auf zwei Arten tun
1) Sie können einen separaten Push-Dienst auf einem anderen Webserver erstellen, damit der Publisher und der Abonnent diesen Dienst abhören können. Verwenden Sie diesen Push-Service als Broker, das heißt, wann immer der Publisher mit den Daten fertig ist, um sie zu pushen, werden sie ihn an diesen Service senden, dann erhält der Broker die Datensendungen an alle Abonnenten.
2) Sie können eine JMS-Warteschlange in einer separaten JVM erstellen und den Publisher und Abonnenten auf diesen Dienst aufmerksam machen. Verwenden Sie diesen JVM-Dienst als Broker.
Sie können diesen Dienst auch für andere Zwecke verwenden, z. B. zum Sichern der Nachrichten, zum Verwalten von Sitzungen und zum Speichern von Nachrichten für die zukünftige Zustellung, wenn der beabsichtigte Empfänger nicht zum Empfang der Nachrichten verfügbar ist.
Der Nachteil bei der Verwendung des Modells ist jedoch, dass es zu einem zusätzlichen Wartungsaufwand für Ihre Anwendungskonfiguration führt.
Ich schlage vor, eine Datenbank als Synchronisationspunkt zu verwenden.
Stellen Sie sich eine einzelne DB-Tabelle mit ausstehenden Nachrichten vor, jeder Knoten fragt sie periodisch ab und wählt nur Nachrichten für seine aktiven Clients aus, liefert sie und aktualisiert die Tabelle (und fügt neu empfangene Nachrichten ein).
Vorteile:
Die einzige Komplikation besteht darin, dass Sie eine gute Strategie entwickeln müssen, um zu entscheiden, wann Sie eine Abfrage durchführen müssen, um die Datenbank nicht zu überlasten. zum Beispiel können Sie ein einzelnes JMS-Thema verwenden, um anderen Knoten zu signalisieren, dass eine neue Nachricht angekommen ist.
Ich weiß, es scheint nicht so schick zu sein, wie es nur mit asynchronem Messaging zu tun, aber denke darüber nach!
Der einfachste Weg ist wahrscheinlich, das integrierte Cluster-Kommunikationssystem zu verwenden. Auf diese Weise bleiben Sie horizontal skalierbar:
Wenn Sie die Nachrichtenzielverbindung auf dem aktuellen Knoten nicht haben, leiten Sie sie einfach an alle anderen Knoten des Clusters weiter. Derjenige, der die gute Verbindung verwaltet, wird ihn drücken, andere ignorieren ihn.
Ich habe diese Art von Features sowieso nie benutzt, ich nehme an, dass Multicast vom Netzwerk unterstützt werden muss.
Tags und Links java-ee websocket jboss wildfly cluster-computing