web-dev-qa-db-ja.com

AWSアプリケーションロードバランサーとsocket.io

1台のマシンで実行しているためトラフィックが増加しているsocket.ioチャットルームを実行しています。ソケットにwsライブラリを使用してベンチマークを実行しましたが、ハードウェアを利用することでパフォーマンスが向上します。ただし、アプリケーションを書き直す必要があります。

Socket.ioアプリケーションを使用すると、名前空間を使用して実装されるプライベートチャットルームを作成できます。例えば

localhost:8080/room/1
localhost:8080/room/2
localhost:8080/room/3

すべてが1つのインスタンスにある場合、それは非常に簡単ですが、現在、この容量を複数のノードに拡張することを検討しています。

このインスタンスはAmazonのクラウドで実行されます。以前は、WebSocketのスケーリングがELBの問題であるように見えました。 AmazonがWebソケットをサポートするアプリケーションロードバランサーをサポートするようになったことに気づきました。これは素晴らしいように聞こえますが、ドキュメントを読んだ後、私はそれが何を意味するのか本当にわからないことを認めなければなりません。何千もの名前空間でsocket.ioを使用している場合、インスタンスをこのALBの背後に置くだけですべてが機能しますか?私の主な質問は次のとおりです。

X人のユーザーが名前空間に参加した場合、ALBは適切なユーザーとの間でメッセージを自動的にリダイレクトしますか?したがって、ALBの背後で5つのVanilla socket.ioインスタンスが実行されているとしましょう。ユーザー1が名前空間を作成します。数時間後、ユーザー99999が来てこの名前空間に参加したい場合、これを行うために追加のコードを記述する必要がありますか、それとも、albはすべての宛先をリダイレクトする必要がありますか?メッセージの送受信にも同じことが言えますか?

12
user2924127

ALBはユーザーを正しく負荷分散しますが、特定の部屋に参加したユーザーはさまざまなサーバー全体に分散されるため、コードを少し調整する必要があります。

documentation でsocket.ioはこれを行う方法を提供します:

複数のSocket.IOノードが接続を受け入れるようになったので、イベントを全員(または特定の部屋の全員)にブロードキャストする場合は、プロセス間またはコンピューター間でメッセージを渡す何らかの方法が必要になります。

メッセージのルーティングを担当するインターフェースは、アダプターと呼ばれるものです。独自のsocket.io-adapterを(継承することで)実装することも、Redisの上に提供されているものを使用することもできます:socket.io-redis:

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

ALBセットアップ

ALBでスティッキーセッションを有効にすることをお勧めします。そうしないと、ロングポーリングなどの非WebSocketトランスポートを使用すると、socket.ioハンドシェイクが失敗します。このトランスポートを使用するハンドシェイクタスクには複数の要求が必要であり、それらすべての要求を同じサーバーに対して実行する必要があります。

enter image description hereenter image description here


Socket.ioアダプターなしでALBルーティングを使用する代替方法。

Redisデータベースを使用したくない場合。たとえば、私の部屋がユーザーによって作成された場合、userAがインスタンス4に部屋を作成した場合、別のユーザーがこの部屋に参加したい場合、どの部屋にあるかをどのようにして知ることができますか?ここにもアダプターが必要ですか?

この代替案の目的は、各部屋を特定のEC2インスタンスに割り当てることです。 ALB Routing を使用してこれを実現します

N部屋> 1インスタンス

ステップ1:

部屋のURLを次のように変更する必要があります。

/i1/room/550
/i1/room/20
/i2/room/5
/i5/room/492

であること:

/{instance-number}/room/{room-id}

これは、ALBが各部屋を特定のインスタンスにルーティングできるようにするために必要です。

ステップ2:

N個のターゲットグループを作成します(Nは現時点でのインスタンス数です)

Image

ステップ3:

各インスタンスを各ターゲットグループに登録する

ターゲットグループ>インスタンスXターゲットグループ>ターゲットタブ>編集>インスタンスXを選択>登録済みに追加

Target group X > EC2 Instance X
Target group Y > EC2 Instance Y

enter image description here

ステップ4:

ALBターゲットルールの編集

ロードバランサー> ALB>リスナー>ルールの表示/編集

enter image description here

ステップ5:

以下の設定で、ターゲットグループ/インスタンスごとに1つのルールを作成します。

  • IF>パス:/iX/room/*
  • 次に>転送先:instanceX

enter image description here


enter image description here

入力したときにこの設定が完了したら、次のようにします。

  • /i1/room/550 EC2インスタンス1を使用します。
  • /i2/room/200はEC2インスタンス2を使用します

等々。

ここで、インスタンス間で部屋のバランスをとるために、独自のロジックを作成する必要があります。 1つのインスタンスでほとんどすべてのグループをホストする必要はありません。

自動スケーリングが簡単なので、最初のアプローチをお勧めします。

22