web-dev-qa-db-ja.com

実際にメッセージブローカーが必要ですか、それともWebSocketで十分ですか?

私が構築しているWebサイトには、リアルタイムメッセージングコンポーネントがあります。バックエンドはFlaskで構築されており、ユーザーがメッセージングページにいるときにWebsocket接続を処理するFlask-SocketIOを統合しました。

私の現在のインフラストラクチャはかなりシンプルです。 Flaskは、HTTPリクエストとWebsocketイベントの両方を処理します。ユーザーが[メッセージ]ページに到達すると、クライアントはGET /message_historyリクエストし、ソケット接続を開きます。

enter image description here

AliceがメッセージをBobに送信すると、サーバーはイベントを処理し、AliceがログインしていてBobとの会話が許可されていることを確認してから、メッセージをデータベースに格納し、最終的にメッセージをAliceとBobの両方に返します。サーバーからイベントをリッスンします。

これは開発では問題なく機能しますが、本番環境では変更を加える必要があります。

主に、これはロードバランサーでは機能しません。 Flask-SocketIO docs に従って:

複数のFlask-SocketIOワーカーを使用するには、2つの要件があります。

  • ロードバランサーは、特定のクライアントからのすべてのHTTPリクエストを常に同じワーカーに転送するように構成する必要があります。これは「スティッキーセッション」と呼ばれることもあります。

  • 各サーバーはクライアント接続のサブセットのみを所有しているため、RedisやRabbitMQなどのメッセージキューは、ブロードキャストやルームなどの複雑な操作を調整するためにサーバーによって使用されます。

ただし、クライアントがRedis/RabbitMQに直接接続しないため、現在のイベントハンドラーの一部としてRedisまたはRabbitMQを実装する方法がよくわかりません。 Flaskサーバーは、チェックを実行してメッセージをデータベースに格納する必要があるため、常に仲介者である必要があります。

SOで この答え を見てください:

Redis pub/subは、すべてのクライアントがredisに直接アクセスできる場合に最適です。複数のノードサーバーがある場合、1つは他にメッセージをプッシュできます。

ただし、ブラウザにクライアントもある場合は、サーバーからクライアントにデータをプッシュするために別のものが必要です。この場合、socket.ioが最適です。

これで、redisストアでsocket.ioを使用すると、socket.ioは内部でRedis pub/subを使用してサーバー間でメッセージを伝達し、サーバーはメッセージをクライアントに伝達します。


編集

私はドキュメントに従いました:私はRedisをローカルで実行していて、依存関係とサルがパッチを当てたイベントレットをインストールしました。私はすべてを実行し、それは動作します...? Redisが「SUBSCRIBE」イベントと「PUBLISH」イベントを受信して​​いるようです...

  1. PSQLデータベースはまだ必要ですか? Redisストアを使用して履歴メッセージを取得できますか? Redisインスタンスが停止するとどうなりますか?

  2. これをロードバランサーの下で実行し、スティッキーセッションを構成した場合、Redis(またはFlask?)はメッセージを正しいノードに配信する方法を自動的に知っていますか?

3
turnip

おおまかな設計では、PostgreSQLデータベースがRedisキャッシュまたはメッセージングシステム、あるいはその両方に代わっています。

これは機能させることができますが、スケーラビリティの問題に遭遇する可能性があります。データベースをメッセージングシステムとして使用する場合、メッセージの状態の管理が問題になります。たとえば、送信する新しいメッセージを作成する場合、1つのハンドラのみがそのメッセージを取得して配信することを確認する必要があります。この調整は、DBがデフォルトで提供する傾向があるものではありません。使用できるスキームはさまざまですが、メッセージングプラットフォームを使用する場合、それは固有の機能です。

2
JimmyJames