Serwer WebSocket działający w pojedynczym procesie to nic trudnego. W chwili, gdy umieścisz dwie lub więcej instancji serwera za load balancerem, coś po cichu się psuje: każdy klient łączy się z dokładnie jednym węzłem, więc wiadomość opublikowana na węźle A nigdy nie dociera do subskrybentów znajdujących się na węźle B. Kanały, rozgłaszanie i Presence zaczynają działać połowicznie. To najczęstszy powód, dla którego zespoły wyrastają z biblioteki WebSocket i migrują gdzie indziej.
Nowy komponent TsgcWSCluster zamyka tę lukę. Umieść go obok swojego serwera, skieruj węzły na siebie nawzajem, a zdarzenie publikacji lub Presence na dowolnym węźle dotrze do subskrybentów połączonych z każdym węzłem, przy czym Twój istniejący kod Publish / kanałów / Presence pozostaje bez zmian. Ten wpis omawia dwa silniki backplane, konfigurację oraz gotowe do wklejenia przykłady dla Delphi i .NET.
Dwa silniki backplane
Klastrowanie działa poprzez backplane, z którym łączy się każdy węzeł. Gdy klient publikuje na węźle, ten węzeł dostarcza wiadomość swoim lokalnym subskrybentom i przekazuje ją do backplane; każdy inny węzeł ją otrzymuje i rozsyła do swoich lokalnych subskrybentów. Pętle są eliminowane poprzez oznaczanie każdej wiadomości identyfikatorem węzła pochodzenia.
Backplane wybierasz za pomocą właściwości EngineType:
- Mesh (
clusterMesh) — zero zewnętrznej infrastruktury. Każdy węzeł nasłuchuje na porcie klastra i łączy się bezpośrednio ze swoimi peerami. Idealne dla małych klastrów, które mają po prostu działać, bez instalowania niczego dodatkowego. - Redis (
clusterRedis) — wykorzystuje serwer Redis, który już uruchamiasz, jako backplane Pub/Sub, dla większych wdrożeń.
Backplane typu mesh (zero infrastruktury)
Silnik mesh to najszybszy sposób na utworzenie klastra. Nadaj każdemu węzłowi ClusterPort do nasłuchiwania oraz host:port jego peerów, a następnie wykonaj Attach protokołu sgc, aby jego pub/sub kanałów (oraz Presence) został objęty klastrowaniem:
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;
To cała zmiana. Klient połączony z tym węzłem może wykonać Publish na kanał, a klienci na pozostałych dwóch węzłach otrzymają wiadomość, dokładnie tak, jakby wszyscy byli na jednym serwerze. Sesje sticky nie są wymagane.
Backplane Redis
Dla większych wdrożeń przełącz silnik na clusterRedis i skieruj go na swój serwer Redis. Wszystko powyżej backplane — kanały, Presence, Twój kod aplikacji — pozostaje takie samo:
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
Zarządzana edycja sgcWebSockets udostępnia ten sam komponent. Dołącz klaster do protokołu sgc serwera i uruchom go — publikacja na jednym węźle dociera do subskrybentów na pozostałych:
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;
W tej wersji edycja .NET dostarcza silnik mesh; backplane Redis jest dostępny w edycji Delphi / C++Builder.
Presence w skali całego klastra
Presence — „kto jest online w tym kanale” — to funkcja, która najbardziej cierpi, gdy serwer się skaluje, ponieważ każdy węzeł widzi tylko swoich własnych członków. TsgcWSCluster to naprawia: wykonaj Attach protokołu Presence w taki sam sposób, w jaki dołączasz protokół sgc, a lista członków staje się sumą ze wszystkich węzłów. Zdarzenia dołączenia / opuszczenia propagują się w skali całego klastra, a węzeł, który ulega awarii, ma swoich członków automatycznie usuwanych, więc nigdy nie pokazujesz członków-duchów.
oCluster.Attach(oPresenceProtocol); // TsgcWSPServer_Presence
// GetMembers now returns the cluster-wide roster, not just this node's.
Wiedza o tym, kiedy klaster jest gotowy
Każdy klaster udostępnia informacje o swojej łączności, dzięki czemu możesz poczekać na backplane, zanim zaczniesz publikować, lub pokazać kondycję węzłów na pulpicie:
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
W .NET te same sygnały to OnPeerConnected / OnPeerDisconnected, właściwość ConnectedPeerCount oraz IsReady.
Jak to współgra z resztą biblioteki
Klastrowanie znajduje się poniżej kodu Twojego protokołu, więc nic innego się nie zmienia. Te same API Publish, subskrypcje kanałów, potwierdzenia QoS i Presence, których już używasz, działają dalej, teraz na wszystkich węzłach. Silnik mesh nie potrzebuje żadnej zewnętrznej usługi, co sprawia, że wdrożenie dwu- lub trzywęzłowe jest trywialne; Redis jest dostępny, gdy skalujesz większe. Z biblioteką dostarczane jest demo dwuwęzłowe (02.WebSocket_Protocols\14.MultiNode_Clustering w Delphi, samples\ClusterDemo w .NET), dzięki czemu możesz zobaczyć, jak wiadomość przechodzi między węzłami na Twojej własnej maszynie.
Dostępność
Klastrowanie wielowęzłowe to funkcja edycji Enterprise i kompiluje się od Delphi 7 do 13 (Win32/Win64, Linux64, macOS, Android oraz iOS) oraz w zarządzanej edycji .NET.
Klienci z aktywną subskrypcją mogą pobrać nową kompilację ze strefy klienta. Użytkownicy wersji próbnej mogą pobrać zaktualizowany instalator pod adresem esegece.com/products/websockets/download.
Pytania, opinie lub pomoc w podłączeniu tego do Twojego wdrożenia? Skontaktuj się z nami — otrzymasz odpowiedź od ludzi, którzy napisali ten kod.
