web-dev-qa-db-ja.com

インスタンス間で状態を転送する必要があるWebアプリの複数のインスタンスを実行する最良の方法は何ですか?

ユーザーが「部屋」に入るWebアプリに取り組んでいます。これらの部屋の状態は常にサーバーのメモリに読み込まれ、WebSocketを介してクライアントと同期されます。 Webアプリのインスタンスが複数ある場合に部屋を処理する最良の方法は何ですか?

したほうがいい...

A.どのインスタンスがどの部屋を処理しているかに応じて接続を指示する、ある種のロードバランサーがありますか?

B.ルームに接続されたクライアントを持つすべてのインスタンスが同期されるように、Webアプリインスタンスは内部で互いに通信しますか?

C.他に何かありますか?

1
Carson McManus

これらの部屋の状態は常にサーバーのメモリに読み込まれます

状態をサーバーのメモリに保存すると、実際の運用環境ではこの状態が時々失われます。これは受け入れられますか? (通常はそうではありません):

状態を失うことが許容され、サーバーごとの部屋のパーティションを管理して各サーバーの負荷を管理できる場合は、ソリューションAを使用できます。ただし、方法によっては負荷を管理するのが簡単ではない場合があることに注意してください。システムが動作します。たとえば、部屋1〜10をサーバーAに配置しても、部屋4の負荷が大きいため、部屋4を別のサーバーに移動する必要があります。管理が非常に複雑になる可能性があります。

一方、状態を失うことが許容できない場合は、部屋の状態に対して何らかの安全な永続化が必要になります。いくつかのオプションがあります:

  1. データベース:これは効率が悪いと述べましたが、うまくいくかもしれない方法を忘れてしまった場合に備えて、この点を再確認します。

  2. Hans-Martinが述べたREDIS。

  3. ある種のメモリデータベースに複製されたもの(つまり、Service Fabric Reliable Collections)。メモリーに格納するのと同じくらい高速ですが、複数のレプリカに複製されるため、サーバーがダウンしても、データは失われず、クラスターは自己回復します。ところで、Rooms状態更新の同時実行モデルに応じて、Actorモデルを使用できます。

オプション1と2は最も単純なアプローチです。サーバーはステートレスであるため、データ/ロードのパーティション化を気にすることなく、ソリューションを非常に簡単にスケーリングして負荷を管理できます。また、ソリューション1と2を組み合わせて、データベースで非常に信頼性の高い長期的なデータ永続性を実現し、Redisで高速読み取りを実現することもできます。

オプション3は実装がはるかに複雑です(パーティショニングの管理も必要になります)が、おそらく信頼性が高く、最高のパフォーマンスが得られるものでしょう。

0

「最善」であるかどうかはわかりませんが、「可能」です。共有REDISを使用してください。もちろん、部屋の状態と操作をREDISでサポートされている状態と操作にマッピングする必要があります。

サーバーが地理的に分散している場合は、これをどのように処理するかを決定する必要があります。いくつかのオプションは次のとおりです。

  • 単一のREDISインスタンスを使用し、ネットワーク遅延に対応

  • 複製REDISインスタンスを使用して読み取りパフォーマンスを向上させます。書き込みでは、引き続きマスターインスタンスをアドレス指定する必要があります。

  • 各サーバークラスタに、部屋のサブセットを処理する独自のREDISインスタンスを持たせ、クライアントを適切なサーバークラスタにリダイレクトする

0