Um servidor WebSocket rodando em um único processo é fácil. No momento em que você coloca duas ou mais instâncias do servidor atrás de um balanceador de carga, algo quebra silenciosamente: cada cliente conecta-se a exatamente um nó, então uma mensagem publicada no nó A nunca alcança os assinantes que estão no nó B. Canais, broadcasts e Presence ficam todos meio cegos. Esse é o motivo isolado mais comum pelo qual equipes superam uma biblioteca WebSocket e migram para outra.
O novo componente TsgcWSCluster elimina essa lacuna. Coloque-o ao lado do seu servidor, aponte os nós uns para os outros, e um evento de publicação ou de Presence em qualquer nó alcança os assinantes conectados a cada nó, com seu código existente de Publish / canal / Presence inalterado. Este post percorre os dois motores de backplane, a configuração e exemplos prontos para colar em Delphi e .NET.
Dois motores de backplane
O clustering funciona por meio de um backplane ao qual cada nó se conecta. Quando um cliente publica em um nó, esse nó entrega a mensagem aos seus próprios assinantes locais e a encaminha para o backplane; cada outro nó a recebe e a distribui para seus assinantes locais. Os loops são evitados marcando cada mensagem com o id do nó de origem.
Você escolhe o backplane com a propriedade EngineType:
- Mesh (
clusterMesh) — zero infraestrutura externa. Cada nó escuta em uma porta de cluster e conecta-se diretamente aos seus peers. Perfeito para clusters pequenos que devem "simplesmente funcionar" sem nada extra a instalar. - Redis (
clusterRedis) — usa um servidor Redis que você já mantém em execução como backplane Pub/Sub, para implantações maiores.
Backplane mesh (sem infraestrutura)
O motor mesh é a maneira mais rápida de fazer clustering. Dê a cada nó uma ClusterPort para escutar e o host:port de seus peers, depois faça Attach do protocolo sgc para que seu pub/sub de canal (e o Presence) seja agrupado em cluster:
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;
Essa é toda a mudança. Um cliente conectado a este nó pode fazer Publish em um canal e os clientes nos outros dois nós a recebem, exatamente como se estivessem todos em um único servidor. Sem necessidade de sticky sessions.
Backplane Redis
Para implantações maiores, troque o motor para clusterRedis e aponte-o para o seu servidor Redis. Tudo acima do backplane — canais, Presence, o código da sua aplicação — permanece igual:
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
A edição gerenciada do sgcWebSockets expõe o mesmo componente. Faça o Attach do cluster ao protocolo sgc do servidor e inicie-o — uma publicação em um nó alcança os assinantes nos outros:
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;
Nesta versão, a edição .NET inclui o motor mesh; o backplane Redis está disponível na edição Delphi / C++Builder.
Presence em todo o cluster
O Presence — "quem está online neste canal" — é o recurso que mais sofre quando um servidor escala horizontalmente, porque cada nó vê apenas seus próprios membros. O TsgcWSCluster corrige isso: faça Attach do protocolo Presence da mesma forma que você faz Attach do protocolo sgc, e a lista de membros torna-se a união entre todos os nós. Os eventos de entrada / saída se propagam por todo o cluster, e um nó que cai tem seus membros removidos automaticamente, de modo que você nunca exibe membros fantasmas.
oCluster.Attach(oPresenceProtocol); // TsgcWSPServer_Presence
// GetMembers now returns the cluster-wide roster, not just this node's.
Saber quando o cluster está pronto
Cada cluster expõe sua conectividade para que você possa aguardar o backplane antes de começar a publicar, ou exibir a saúde dos nós em um dashboard:
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
No .NET os mesmos sinais são OnPeerConnected / OnPeerDisconnected, a propriedade ConnectedPeerCount e IsReady.
Como ele se compõe com o restante da biblioteca
O clustering fica abaixo do código do seu protocolo, então nada mais muda. As mesmas APIs de Publish, assinaturas de canal, confirmações de QoS e Presence que você já usa continuam funcionando, agora em todos os nós. O motor mesh não precisa de nenhum serviço externo, o que torna trivial uma implantação de dois ou três nós; o Redis está lá para quando você escalar para algo maior. Uma demo de dois nós acompanha a biblioteca (02.WebSocket_Protocols\14.MultiNode_Clustering no Delphi, samples\ClusterDemo no .NET) para que você possa ver uma mensagem atravessar os nós na sua própria máquina.
Disponibilidade
O clustering de múltiplos nós é um recurso da edição Enterprise e compila do Delphi 7 ao 13 (Win32/Win64, Linux64, macOS, Android e iOS) e na edição gerenciada .NET.
Os clientes com uma assinatura ativa podem baixar a nova build na área do cliente. Os usuários de avaliação podem obter o instalador atualizado em esegece.com/products/websockets/download.
Dúvidas, feedback ou ajuda para integrar isso à sua implantação? Entre em contato — você receberá uma resposta das pessoas que escreveram o código.
