私が構築しているWebサイトには、リアルタイムメッセージングコンポーネントがあります。バックエンドはFlaskで構築されており、ユーザーがメッセージングページにいるときにWebsocket接続を処理するFlask-SocketIOを統合しました。
私の現在のインフラストラクチャはかなりシンプルです。 Flaskは、HTTPリクエストとWebsocketイベントの両方を処理します。ユーザーが[メッセージ]ページに到達すると、クライアントはGET /message_history
リクエストし、ソケット接続を開きます。
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」イベントを受信しているようです...
PSQLデータベースはまだ必要ですか? Redisストアを使用して履歴メッセージを取得できますか? Redisインスタンスが停止するとどうなりますか?
これをロードバランサーの下で実行し、スティッキーセッションを構成した場合、Redis(またはFlask?)はメッセージを正しいノードに配信する方法を自動的に知っていますか?
おおまかな設計では、PostgreSQLデータベースがRedisキャッシュまたはメッセージングシステム、あるいはその両方に代わっています。
これは機能させることができますが、スケーラビリティの問題に遭遇する可能性があります。データベースをメッセージングシステムとして使用する場合、メッセージの状態の管理が問題になります。たとえば、送信する新しいメッセージを作成する場合、1つのハンドラのみがそのメッセージを取得して配信することを確認する必要があります。この調整は、DBがデフォルトで提供する傾向があるものではありません。使用できるスキームはさまざまですが、メッセージングプラットフォームを使用する場合、それは固有の機能です。