Ein WebSocket-Server, der in einem einzigen Prozess läuft, ist einfach. Sobald Sie jedoch zwei oder mehr Server-Instanzen hinter einen Load Balancer stellen, bricht still und leise etwas zusammen: Jeder Client verbindet sich mit genau einem Knoten, sodass eine auf Knoten A veröffentlichte Nachricht die Abonnenten auf Knoten B nie erreicht. Kanäle, Broadcasts und Presence werden allesamt halb blind. Das ist der mit Abstand häufigste Grund, warum Teams aus einer WebSocket-Bibliothek herauswachsen und zu etwas anderem migrieren.
Die neue Komponente TsgcWSCluster schließt diese Lücke. Platzieren Sie sie neben Ihrem Server, richten Sie die Knoten aufeinander aus, und ein Publish- oder Presence-Ereignis auf einem beliebigen Knoten erreicht Abonnenten, die mit jedem Knoten verbunden sind, ohne dass Ihr bestehender Publish-/Kanal-/Presence-Code geändert werden muss. Dieser Beitrag führt durch die beiden Backplane-Engines, die Konfiguration sowie direkt einfügbare Delphi- und .NET-Beispiele.
Zwei Backplane-Engines
Clustering funktioniert über ein Backplane, mit dem sich jeder Knoten verbindet. Wenn ein Client auf einem Knoten veröffentlicht, liefert dieser Knoten die Nachricht an seine eigenen lokalen Abonnenten aus und leitet sie an das Backplane weiter; jeder andere Knoten empfängt sie und verteilt sie an seine lokalen Abonnenten. Schleifen werden verhindert, indem jede Nachricht mit der ID des Ursprungsknotens gekennzeichnet wird.
Das Backplane wählen Sie über die Eigenschaft EngineType:
- Mesh (
clusterMesh) — keine externe Infrastruktur. Jeder Knoten lauscht auf einem Cluster-Port und verbindet sich direkt mit seinen Peers. Ideal für kleine Cluster, die einfach funktionieren sollen, ohne dass etwas zusätzlich installiert werden muss. - Redis (
clusterRedis) — verwendet einen bereits von Ihnen betriebenen Redis-Server als Pub/Sub-Backplane, für größere Deployments.
Mesh-Backplane (keine Infrastruktur)
Die Mesh-Engine ist der schnellste Weg zum Clustering. Geben Sie jedem Knoten einen ClusterPort, auf dem er lauscht, sowie das host:port seiner Peers, und Attach Sie dann das sgc-Protokoll, damit dessen Kanal-Pub/Sub (und Presence) geclustert wird:
uses
sgcWebSocket, sgcWebSocket_Protocols, sgcWebSocket_Cluster;
var
oServer: TsgcWebSocketServer;
oProtocol: TsgcWSPServer_sgc;
oCluster: TsgcWSCluster;
begin
oServer := TsgcWebSocketServer.Create(nil);
oServer.Port := 8080;
oProtocol := TsgcWSPServer_sgc.Create(nil);
oProtocol.Server := oServer;
oCluster := TsgcWSCluster.Create(nil);
oCluster.EngineType := clusterMesh; // zero-infrastructure backplane
oCluster.ClusterPort := 5410; // this node's mesh listener
oCluster.Peers.Add('192.168.1.101:5410'); // the other nodes
oCluster.Peers.Add('192.168.1.102:5410');
oCluster.Attach(oProtocol); // cluster this protocol's pub/sub
oCluster.Start;
oServer.Active := True;
end;
Das ist die gesamte Änderung. Ein mit diesem Knoten verbundener Client kann auf einem Kanal Publishen, und Clients auf den beiden anderen Knoten empfangen die Nachricht, genau so, als befänden sie sich alle auf einem einzigen Server. Es sind keine Sticky Sessions erforderlich.
Redis-Backplane
Für größere Deployments schalten Sie die Engine auf clusterRedis um und richten sie auf Ihren Redis-Server aus. Alles oberhalb des Backplanes — Kanäle, Presence, Ihr Anwendungscode — bleibt gleich:
oCluster.EngineType := clusterRedis;
oCluster.RedisHost := '127.0.0.1';
oCluster.RedisPort := 6379;
oCluster.RedisPassword := ''; // optional
oCluster.RedisChannel := 'sgccluster'; // the Pub/Sub channel
oCluster.Attach(oProtocol);
oCluster.Start;
.NET
Die verwaltete sgcWebSockets-Edition stellt dieselbe Komponente bereit. Hängen Sie das Cluster an das sgc-Protokoll des Servers an und starten Sie es — ein Publish auf einem Knoten erreicht Abonnenten auf den anderen:
var server = new TsgcWSServer { Port = 8080 };
var protocol = new TsgcWSPServer_sgc { Server = server };
var cluster = new TsgcWSCluster {
EngineType = ClusterEngineType.Mesh, // zero-infrastructure backplane
ClusterPort = 5414,
Protocol = protocol
};
cluster.Peers.Add("192.168.1.101:5414");
cluster.Peers.Add("192.168.1.102:5414");
cluster.Start();
server.Active = true;
In dieser Version liefert die .NET-Edition die Mesh-Engine; das Redis-Backplane ist in der Delphi-/C++Builder-Edition verfügbar.
Clusterweites Presence
Presence — "wer ist gerade in diesem Kanal online" — ist die Funktion, die am stärksten leidet, wenn ein Server horizontal skaliert wird, weil jeder Knoten nur seine eigenen Mitglieder sieht. TsgcWSCluster behebt das: Attach Sie das Presence-Protokoll auf die gleiche Weise, wie Sie das sgc-Protokoll anhängen, und die Mitgliederliste wird zur Vereinigung über alle Knoten hinweg. Join-/Leave-Ereignisse werden clusterweit propagiert, und bei einem ausfallenden Knoten werden dessen Mitglieder automatisch entfernt, sodass Sie nie Geistermitglieder anzeigen.
oCluster.Attach(oPresenceProtocol); // TsgcWSPServer_Presence
// GetMembers now returns the cluster-wide roster, not just this node's.
Erkennen, wann das Cluster bereit ist
Jedes Cluster gibt seine Konnektivität preis, sodass Sie auf das Backplane warten können, bevor Sie mit dem Veröffentlichen beginnen, oder den Knotenzustand in einem Dashboard sichtbar machen können:
oCluster.OnPeerConnected := procedure(Sender: TObject; const aPeer: string)
begin
// a peer link came up
end;
if oCluster.Ready then // at least one peer connected (or no peers configured)
// ConnectedPeerCount tells you how many links are up
In .NET lauten dieselben Signale OnPeerConnected / OnPeerDisconnected, die Eigenschaft ConnectedPeerCount sowie IsReady.
Wie es sich mit dem Rest der Bibliothek zusammensetzt
Clustering liegt unterhalb Ihres Protokollcodes, sodass sich sonst nichts ändert. Dieselben Publish-, Kanalabonnement-, QoS-Bestätigungs- und Presence-APIs, die Sie bereits verwenden, funktionieren weiterhin, jetzt über jeden Knoten hinweg. Die Mesh-Engine benötigt keinen externen Dienst, was ein Deployment mit zwei oder drei Knoten trivial macht; Redis steht bereit, wenn Sie größer skalieren. Eine Demo mit zwei Knoten wird mit der Bibliothek ausgeliefert (02.WebSocket_Protocols\14.MultiNode_Clustering bei Delphi, samples\ClusterDemo bei .NET), sodass Sie auf Ihrem eigenen Rechner beobachten können, wie eine Nachricht zwischen Knoten wechselt.
Verfügbarkeit
Multi-Node-Clustering ist eine Funktion der Enterprise-Edition und kompiliert über Delphi 7 bis 13 hinweg (Win32/Win64, Linux64, macOS, Android und iOS) sowie in der verwalteten .NET-Edition.
Kunden mit einem aktiven Abonnement können den neuen Build aus dem Kundenbereich herunterladen. Testbenutzer erhalten das aktualisierte Installationsprogramm unter esegece.com/products/websockets/download.
Fragen, Feedback oder Hilfe bei der Integration in Ihr Deployment? Nehmen Sie Kontakt auf — Sie erhalten eine Antwort von den Leuten, die den Code geschrieben haben.
