web-dev-qa-db-ja.com

オンラインステータスの保存方法

pubsub パターンを使用してリアルタイムWebチャットを開発しています。具体的には、pythonとバックエンドにトルネード-redis、フロントエンドにwebsockets(WS)(トルネード)を使用しています。WS接続のオープンイベントとクローズイベントがあるので、現在のオンラインユーザーリストを保存するのに最適なソリューションは何ですか。

ここにいくつかの論文があります

  • 複数のスレッドを実行して、オンラインユーザーに関するデータをすべての場所でアクセス可能な状態で保持する必要があります。 水平方向のスケーリング も同じです。
  • 1人のユーザーが複数の接続を開くことができます。同じユーザー名が複数の接続インスタンスに存在する可能性があることを意味します。

ソリューション

  • どこにも保管しないでください!現在のオンラインが必要なときの意味は、全員にメッセージをブロードキャストし、応答から誰がオンラインであるかを判断することです。 (+)私は知っていますrealuserlist everytime、(-)これにより、処理時間が長くなり、実装が複雑になります)。
  • 現在のオンラインを別のテーブルのデータベースに保存します。すべてのテーブル行は単一の接続と一致します。 (現在の実現では、redis hmapです。{"hash of current connection" : "username"}hset WSの開始時(ユーザーが接続する)hdel WSの終了時(ユーザーが切断する)(+)現在のオンラインを取得する必要がある場合は高速、(-)ユーザーが切断し、データベース接続が失われると同時にDB情報が誤っている場合。
  • Redisと私の現在の実現に固有です。 WS接続ごとに単一のredis接続があるため、ユーザー情報をトルネードに保存できます clientname 。 redisには既に接続ユーザーに関する情報があるので。 client-list を取得し、いくつかの基準(clientname)でフィルタリングして、オンラインにすることができます。 (+)オンラインでredisに委任します。 (-)複数のオンラインリストの保存は複雑になります。たとえば、webchatに複数の部屋(100とする)がある場合、1つの場所のすべての部屋をオンラインで保存すると、少し面倒に見えます。

どのソリューションが私の要件を最もよく満たしていますか、それともより優れたソリューションがありますか?

2
deathangel908

私はランダムにこの質問に出くわしましたが、これは私がそれを行う方法です:

usersテーブルで、lastActivityという列を作成し、DateTimeタイプにします。

WebSocket経由で接続する場合は、クライアントにソケット接続を認証してもらいます(authTokenを送信するなど)。認証時に、userのIDを接続のプロパティとして設定します。

認証後、クライアントにサーバーに定期的にメッセージを送信させます。

サーバーがメッセージを受信したら、ユーザーのlastActivityを更新し、接続に設定したIDを使用して、メッセージを送信しているユーザーを見つけます。

これで、アプリケーションでlastActivityフィールドを単に比較できます。たとえば、10秒より古く、10秒ごとにメッセージを送信するように設定している場合、ユーザーはオフラインと見なされます。

1
Sebastian Olsen