
Websocket を使用した pub/sub サービスの設定を検討しています。私の知る限り、スケーラビリティのボトルネックは主にメモリにあり、一度に開くことができるソケットの数に影響するため、API などのサービスを実行している他のサーバーからこれを分離するのが賢明だと思います。これは正しいでしょうか? ホスティングに関しては、メモリはコンピューティング能力よりも高価だと思いますが、このタイプのサーバーをスケーラビリティとコストの面で最適化するベスト プラクティスはありますか?
目標は、バックエンドを定期的にポーリングすることなく、現場のシステムが新しいデータをチェックインするときに、この Web アプリケーションのユーザーにリアルタイムの更新を提供することです。ただし、サーバーのコストを 2 倍にすることは望ましくありません。そうすると、価値がなくなる可能性があります。現在の API サーバーには、負荷分散と自動スケーリングを備えた AWS EC2 を使用しています。
答え1
1 つのソケットの実際のメモリ使用量はそれほど多くありません。
メモリを消費するのは、どのクライアントがどの更新に関心があるか、どのクライアントがすでに特定の更新を受信しているかに関連する状態です。
原始的な実装 (つまり、OS ネットワーク スタックを使用) では、後者の状態は送信バッファーの形式で保持されます。つまり、更新が 10,000 台のクライアントに送信された場合、データは 10,000 回コピーされ、各コピーは送信キューに追加され、そこで必要なヘッダー (接続ごとの状態を含む) が追加され、次に、ヘッダーとペイロードを連結したパケットを送信するようにハードウェアに指示する記述子が作成されます。
ペイロードのクライアントごとのコピーは、クライアントによって確認されるまでメモリ内に保持され、メモリ要件はそこから発生します。このメモリはページ アウトできないため、他のアプリケーションにメモリとキャッシュの負荷がかかります。
サーバー プログラム自体の中にネットワーク スタックの一部を実装する実装があり、参照カウントやオンデマンドのペイロードの再作成によってコピーを回避できます。これにより、メモリ使用量を大幅に削減できますが、真にスケーラブルにするには多くのトリッキーなコーディングが必要になります。特にマルチソケット サーバーでは、OS ネットワーク スタックが既に回避方法を知っている興味深い問題がいくつか発生します。
選択肢
- アプリと同じサーバー上でpub/subサービスを実行する
- OSネットワークを備えた専用サーバー上でpub/subサービスを実行する
- カスタムネットワークを備えた専用サーバー上でpub/subサービスを実行する
- 複数の専用サーバーでpub/subサービスを実行する
サービスが拡大するにつれて、エスカレーション戦略を立てる必要があります。共有から専用への移行には多くの計画は必要なく、必要に応じて実行できます。移行が完了したら、次の段階を準備します。
複数のサーバーにスケールアップすると、クライアントが異なる順序で更新を受け取る可能性があるため、システムに非決定性が導入されます。そのため、このスケーリング手順を成功させるには、クライアントがこれを認識し、一貫したビューを提示できる必要があります。これが簡単か難しいかは、実際のアプリケーションによって異なります。
要約:時期尚早に最適化する必要はありません。サービスを分割して、スケーリングの最初のステップが単純な構成変更になるようにし、変更が完了したらすぐに最適化を開始します。