3

Clojure でスケーラブルなチャット サーバーを構築しようとしています。http-kit、compojure、および redis pub/sub を使用して、異なるノード間で通信しています (ファンアウト アプローチ)。サーバーは、長いポーリングへのフォールバックを使用して、クライアントとサーバー間の接続に websocket を使用します。1 人のユーザーは、ブラウザのタブごとに 1 つの接続でチャットするために複数の接続を持つことができ、メッセージはすべての接続に配信される必要があります。

基本的に、ユーザーが接続すると、ランダムな uuid を持つアトムにチャネルを保存します。

{:userid1 [{:socketuuid "random uuid#1 for uerid1" :socket "channel#1 for userid1"}
          {:socketuuid "random uuid#2" :socket "channel#2"}]
:userid2 [{:socketuuid "random uuid#1 for userid2" :socket "channel#1 for userid2}]}

メッセージは Websocket とロング ポーリング チャネルの両方の共通ルートに POST されます。メッセージ構造は次のようになります。

{:from "userid1" :to "userid2" :message "message content"}

サーバーは、:from および :to ユーザー ID のアトム内のすべてのチャネルを見つけ、それぞれのユーザーの接続されたチャネルにメッセージを送信します。また、接続されたノードが格納されているチャネルを探す redis サーバーを介してメッセージを発行します。自分のアトムを作成し、それぞれのユーザーにメッセージを配信します。

したがって、私が直面している問題は、プレゼンスを適切に実装する方法です。基本的にhttp-kitは、チャネルが切断されたときにステータスを送信します。ステータスは「server-close」または「client-close」にすることができますが、サーバーの切断を処理できます(クライアントは自動的に再接続します)が、切断時に問題が発生していますたとえば、クライアント側から発生します。ユーザーは別のページに移動し、数秒後に接続します。クライアントが切断されたときに、ユーザーがオフラインになったことをどのように判断しますか? また、ロング ポーリング モードでのメッセージ到着の双方向再接続についても懸念しています (ロング ポーリング タイムアウトは 30 秒です)。

また、上記のアーキテクチャに適したプレゼンス メカニズムを提案してください。ありがとう。

さらに情報が必要な場合はコメントしてください。ありがとう

編集#1:

チャット サーバーにプレゼンスを実装するための優れたチュートリアル/資料をお勧めできますか?

私の現在の解決策 - >現在、特定のユーザーIDの接続チャネルのグローバルカウントと最後に接続されたタイムスタンプを維持しており、ユーザーが切断するとカウントが減少し、ユーザーが持っているかどうかを確認する10秒間のタイムアウトが実装されています再接続された場合 (つまり、最後に接続されたスタンプは 10 秒前で、カウントはまだゼロです)、そうでない場合、ユーザーはオフラインになったと言われます。この解決策をお勧めしますか。また、http-kit で timer/scheduled-task を使用していることに注意してください。これらのタイムアウトはパフォーマンスに大きな影響を与えますか?

4

1 に答える 1