Clustering no sgcWebSockets — Escale servidores WebSocket por múltiplos nós | Blog eSeGeCe

Clustering no sgcWebSockets — Escale servidores WebSocket por múltiplos nós

· Componentes

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:

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.