web-dev-qa-db-ja.com

負荷分散Webソケット

Webソケットの負荷を分散する方法について質問があります。

Webソケットをサポートするサーバーがあります。ブラウザが私のサイトに接続し、それぞれがwww.mydomain.comへのウェブソケットを開きます。そうすれば、私のソーシャルネットワークアプリはクライアントにメッセージをプッシュできます。

従来は、HTTPリクエストのみを使用して、2台のWebサーバーの前に2台目のサーバーとロードバランサーを追加してスケールアップしていました。

Webソケットの場合、接続はロードバランサーではなくWebサーバーと直接接続する必要があります。マシンの物理的な制限が64kのオープンポートなどで、クライアントがロードバランサーに接続している場合、サポートできなかったためです64k以上の同時ユーザー。

どうすればいいですか-

  1. ページがロードされたときに、クライアントが(ロードバランサーではなく)Webサーバーに直接接続するようにしますか?ノードからJavaScriptをロードするだけで、ページが最初にリクエストされるたびに、ロードバランサー(または何でも)がスクリプトのURLをランダムに変更しますか?

  2. リップルスタートを処理しますか?ブラウザは、Webサーバーがシャットダウンすると接続が閉じられたことを認識します。 JavaScriptコードを記述して接続を再度開くことはできますが、ノードはしばらく消えます。だから私はロードバランサーに戻って使用する次のノードのアドレスを照会する必要があると思いますか?

  3. ブラウザが最初にwww.mydomain.comを要求し、www34.mydomain.comにリダイレクトされるように、最初のリクエストでロードバランサーがリダイレクトを送信することについて疑問に思いました。ノードがダウンするまで、それは非常にうまく機能します-Facebookのようなサイトはそうしません。どうやってやっているの?

88
John Smith

ソースIPポートハッシュに基づいてIPパケットをWebSocketサーバーファームに配布するL3ロードバランサーを配置します。 L3バランサーは状態を維持しないため(ハッシュされたソースIPポートを使用)、ローエンドハードウェア(たとえば10GbE)のワイヤ速度に合わせてスケーリングします。 (ハッシュされたソースIPポートを使用して)配布は決定的であるため、TCP(したがってWebSocket)で動作します。

また、64kのハード制限は、特定の(ソース)IPアドレスのoutgoingTCP/IPにのみ適用されることに注意してください。着信TCP/IPには適用されません。 Autobahn (高性能WebSocketサーバー)、2コア、4GB RAM VM。

また、最初のWebSocketハンドシェイク中に通知されたHTTPパスでL7ロードバランシングを実行できることに注意してください。その場合、ロードバランサーは状態(どのソースIPポートペアがどのバックエンドノードに行くか)を維持する必要があります。それにも関わらず、適切なセットアップで数百万の接続に拡張されるでしょう。

免責事項:私はアウトバーンの原著者であり、タベンドで働いています。

75
oberstet

Websocketサーバーロジックがsocket.ioを使用してnodejsで実行される場合、socket.ioに同期のために共有redisキー/値ストアを使用するように指示できることに注意してください。この方法では、ロードバランサーを気にする必要さえありません。イベントはサーバーインスタンス間で伝播します。

var io = require('socket.io')(3000);
var redis = require('socket.io-redis'); 
io.adapter(redis({ Host: 'localhost', port: 6379 }));

参照: http://socket.io/docs/using-multiple-nodes/

しかし、ある時点でredisがボトルネックになる可能性があると思います...

3
Convolver

検査と「ルーティング機能」を使用して、レイヤー7の負荷分散を実現することもできます。

「Stingray Traffic Managerを使用してWebSocketトラフィックを検査および負荷分散する方法、および必要に応じて、同じIPアドレスとポートで受信されるWebSocketおよびHTTPトラフィックを管理する方法」を参照してください。 https://splash.riverbed.com/docs/DOC-1451

2
David