私は、OTP Genserver を使用して Elixir で 1 つのチャットルーム [all to all] アプリケーションに取り組んでおり、ユーザーが最初のフェーズとして自分の名前で登録されると、js クライアントからメッセージを取得しています。さて、これらの名前をどうにかしてエリクサーサーバーに保存し、オンラインのユーザーのリストまたはデータベースストレージを使用してクライアントに定期的な更新を送信するための最良の方法は何かわかりません。最善のアプローチを提案してください。
2 に答える
ETS が適しているという bitwalker の意見に同意します。
ここでは、私が制作で行ったことの簡単な要約を示します。これはチャット サーバーではなく、数千人のユーザーがロング ポーリングを介して接続するサーバー プッシュでした。プッシュされたデータは約 50 のカテゴリに分類され、ユーザーは必要なものを選択できました。ピーク時には、サーバーは 2 秒ごとに新しいメッセージをプッシュし、1 秒あたり 2000 件以上の要求を処理しました。
基本的に、gen_server
保留中のメッセージとユーザーの構成 (基本的には選択されたチャネルのリスト) を保持するユーザーごとに保持しました。ユーザーのデータはユーザーの要求から切り離され、要求が一時的な間もデータが残るため、これは長いポーリングで有益でした。ただし、このアプローチは、websocket などの永続的な接続にも適していると思います。これは、時々切断される可能性があり、より安定したユーザーのデータを維持することで、再接続後に再開する可能性があるためです。
明らかに、リクエストが到着したら、ユーザー固有のプロセスを見つける必要があります。これには、プロセスのボトルネックが 1 つもない ETS が適しています。ETS を手動で操作する代わりに、タプルと組み合わせてgprocvia
を使用することをお勧めします。基本的に、ユーザーの gen_server を起動するときに、内部ユーザーの id に基づいて作成したカスタム キー (任意の用語) を指定できます (name: {:via, :gproc, {:n, :l, key}}
ローカルノードで一意の名前を示します) 。その後、呼び出し/キャストを発行するときに同じタプルを使用でき、対応するプロセスを見つけるために使用します。key
:n
:l
via
gen_server
gproc
最後に、ユーザー プロセスをクリーンアップするためのタイムアウト/切断ロジックが必要です。私の場合、Web レイヤーからのアクティビティがなければ (しばらくエンド ユーザーがデータを取りに来なかった場合)、単純にユーザーのプロセスを終了しました。Gproc は、終了したプロセスのエントリを内部 ETS テーブルから自動的に削除します。temporary
戦略に基づいてユーザー プロセスを監視するのがおそらく最善です。
これはまだ少し漠然としていますが、ある程度の意味があることを願っています。これは究極のパターンではないことに注意してください (もちろんそんなことはありません) が、妥当な最初の試みだと思います。
また、興味深い pub-sub 機能を備えたPhoenix Web フレームワークTopics
も参照してください。私はまだこれを自分で試していませんが、興味深いようで、上で説明したことのいくつかを簡素化するか、少なくともチャットルームからすべてのユーザーに通知をプッシュするのに役立つかもしれません.
ETSの良いユースケースのように思えます。
より簡単な方法は、エージェントを使用してオンライン ユーザー情報を保存することかもしれませんが、選択したストレージ メカニズムから何が必要かによって大きく異なります。