sgcWebSockets クラスタリング — WebSocket サーバーを複数ノードにスケール | eSeGeCe ブログ

sgcWebSockets クラスタリング — WebSocket サーバーを複数ノードにスケール

· コンポーネント

単一プロセスで動く WebSocket サーバーは簡単です。しかし、ロードバランサーの背後に 2 つ以上のサーバーインスタンスを置いた瞬間、何かが静かに壊れます。各クライアントはちょうど1 つのノードにしか接続しないため、ノード A で publish されたメッセージはノード B にいるサブスクライバーには決して届きません。チャネル、ブロードキャスト、そして Presence のすべてが半分見えなくなります。これは、チームが WebSocket ライブラリの限界に達して別の手段へ移行する、最も一般的な理由です。

新しい TsgcWSCluster コンポーネントは、そのギャップを埋めます。サーバーの隣に配置し、ノード同士を互いに向け合わせるだけで、いずれかのノードでの publish や Presence イベントがすべてのノードに接続しているサブスクライバーに届き、既存の Publish / チャネル / Presence のコードはそのまま変更不要です。この記事では、2 つのバックプレーンエンジン、設定方法、そしてそのまま貼り付けて使える Delphi と .NET のサンプルを順に見ていきます。

2 つのバックプレーンエンジン

クラスタリングは、すべてのノードが接続するバックプレーンを介して機能します。クライアントがあるノードで publish すると、そのノードはメッセージを自身のローカルサブスクライバーに配信し、バックプレーンへ転送します。他のすべてのノードがそれを受け取り、自身のローカルサブスクライバーへファンアウトします。各メッセージに送信元ノード ID をタグ付けすることで、ループは防止されます。

バックプレーンは EngineType プロパティで選択します。

メッシュバックプレーン(ゼロインフラ)

メッシュエンジンは、最も手早くクラスタ化できる方法です。各ノードにリッスンする ClusterPort とピアの host:port を与え、sgc プロトコルを Attach すれば、そのチャネルの pub/sub(と Presence)がクラスタ化されます。

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;

変更はこれだけです。このノードに接続したクライアントはチャネルに Publish でき、他の 2 つのノードのクライアントは、まるで全員が 1 台のサーバー上にいるかのようにそれを受け取ります。スティッキーセッションは不要です。

Redis バックプレーン

より大規模なデプロイでは、エンジンを clusterRedis に切り替えて Redis サーバーを指定します。バックプレーンの上にあるすべて — チャネル、Presence、アプリケーションコード — はそのままです。

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

マネージド版の sgcWebSockets は、同じコンポーネントを公開しています。クラスタをサーバーの sgc プロトコルに Attach して開始すれば — あるノードでの publish が他のノードのサブスクライバーに届きます。

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;

このリリースでは、.NET 版はメッシュエンジンを提供します。Redis バックプレーンは Delphi / C++Builder 版で利用できます。

クラスタ全体の Presence

Presence —「このチャネルに誰がオンラインか」— は、各ノードが自分自身のメンバーしか見えないため、サーバーをスケールアウトしたときに最も影響を受ける機能です。TsgcWSCluster はそれを修正します。sgc プロトコルを Attach するのと同じように Presence プロトコルを Attach すると、メンバーの名簿はすべてのノードにまたがる和集合になります。Join / Leave イベントはクラスタ全体に伝播し、ダウンしたノードのメンバーは自動的に削除されるため、ゴーストメンバーが表示されることはありません。

oCluster.Attach(oPresenceProtocol);   // TsgcWSPServer_Presence
// GetMembers now returns the cluster-wide roster, not just this node's.

クラスタの準備完了を知る

各クラスタは自身の接続状態を公開しているため、publish を開始する前にバックプレーンを待ったり、ダッシュボードでノードの健全性を表示したりできます。

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

.NET では、同じシグナルは OnPeerConnected / OnPeerDisconnectedConnectedPeerCount プロパティ、そして IsReady です。

ライブラリの他の機能との組み合わせ方

クラスタリングはプロトコルコードのに位置するため、それ以外は何も変わりません。すでに使っている同じ Publish、チャネルサブスクリプション、QoS の確認応答、そして Presence の API は、今やすべてのノードにまたがってそのまま動作し続けます。メッシュエンジンは外部サービスを必要としないため、2 ノードや 3 ノードのデプロイが簡単になります。より大きくスケールするときのために Redis が用意されています。2 ノードのデモがライブラリに同梱されており(Delphi では 02.WebSocket_Protocols\14.MultiNode_Clustering、.NET では samples\ClusterDemo)、自分のマシン上でメッセージがノードをまたぐ様子を見ることができます。

提供状況

マルチノードクラスタリングは Enterprise エディションの機能で、Delphi 7 から 13(Win32/Win64、Linux64、macOS、Android、iOS)およびマネージド .NET 版でコンパイルできます。

有効なサブスクリプションをお持ちのお客様は、カスタマーエリアから新しいビルドをダウンロードできます。トライアルユーザーの方は、更新されたインストーラーを esegece.com/products/websockets/download から入手できます。

ご質問、フィードバック、またはデプロイへの組み込みのお手伝いが必要ですか? お問い合わせください — コードを書いた本人から返信が届きます。