web-dev-qa-db-ja.com

リアルタイムアプリケーションのアーキテクチャ、アクティブなコンシューマーのないキューの重複メッセージを回避

私は、典型的なバックエンドコンポーネントとフロントエンドコンポーネントを持つアプリケーションのアーキテクチャを設計しています。フロントエンドアプリケーションは準リアルタイムである必要があります。この要件では、バックエンドがキューにメッセージをプッシュし、フロントエンドがそのキューを消費しています。ほとんどの場合、これにはRabbitMQを使用します。説明させてください。

ユーザーがフロントエンドアプリケーションにログインすると、バックエンドでセッションが作成されます。このセッションが有効である限り、フロントエンドアプリケーションは動作を許可されます。通常、ログイン後、フロントエンドは最初にREST API(彼のセッションを認証資格情報として)から)からすべてのデータをロードし、その後のすべての更新はメッセージキューを介して受信されます。

現在の設計では、各フロントエンドセッションに独自のキューがあります。そのため、バックエンドで何かが変更されるたびに、関連するすべてのセッションキューにメッセージが送信されます。言ったように、フロントエンドはこのキューを消費しています。

問題は、フロントエンドがキューから切断されている場合です。たとえば、ユーザーが勤務時間の終わりにラップトップを休止状態にしたとき。それ以降、メッセージが蓄積され始めます。実際の問題は、キューに重複したメッセージが入力されることです。クライアントがキューから切断されている時間が長いほど、この問題は大きくなります。

小さな付記、duplicate messages付き実際はsemantically identical messagesを意味します。たとえば、証券取引所のアプリケーションを見てみましょう。 2つのprice of stock xyz has been changedメッセージは、意味的に同一です。それらは異なるイベント/トランザクションからのものですが、同じ変更を定義します。そのため、以前のメッセージは新しいメッセージによって古くなっています。詳細についてはコメントを参照してください。

これを解決するためのアーキテクチャを探しています。私の考えを振り返ってみましょう:

  • session queueの代わりに、session exchangeを作成することもできます。ログイン後、専用の自動削除専用キューが作成され、その交換にバインドされます。切断/タイムアウト後、このキューはブローカーによって削除されます。次に、フロントエンドアプリケーションが戻ってくると、新しいキューが作成されます。つまり、フロントエンドアプリケーションは空のキューで戻ります。

    • ただし、これにより、クライアントは再接続後にすべてのデータを更新する必要があります。すべてが変更されている可能性があります。
    • クライアントを可能な限りシンプル/シンプルにしたいと思います。
    • したがって、これは最適なソリューションではないと思います。
  • したがって、これをバックエンドで解決することは理にかなっています。つまり、セッションキューでメッセージが重複しないようにする方法が必要です。特定のメッセージがすでにキューにある場合、同じメッセージを再度キューに入れることはありません。

    • ここに私のオプションは何ですか?特定のメッセージがすでにキューに入っていることを確認するにはどうすればよいですか?これはAMQPで直接サポートされていないことを完全に理解しています。したがって、これを自分で実装するには、メッセージの配信と理想的にはメッセージの確認も追跡できる必要があることを意味します。これは可能ですか?
    • (Rabit)MQブローカーのTTL、配信不能、...機能を利用することもできます。しかし、本当にうまくいくものを思いつきませんでした。

私の質問はこれに要約されます:切断後にクライアントを最新の状態にするにはどうすればよいですか?

どんなアイデアや洞察も大歓迎です。

3
TheMQJuggler

ここにキューの値が表示されるかどうかはわかりませんが、直接双方向通信の方が優れており、現在の問題を解決します。ユーザーがコンピューターを休止状態から復帰したとき、ページを完全に更新して双方向通信をトリガーする必要がありますコミュニケーション。

Webアプリケーションを使用している場合は、STOMP/Webソケットを探します。そうでない場合でも、STOMPとWebソケットを使用できますが、単純なTCP接続で作業を行うこともできます。

これらは非常に信頼できるライブラリを提供していることに注意してくださいTCP自動再接続を使用した接続など、ネットワークの問題を処理するために、再度コーディングする方法はありません。そのようなことは本当に苦痛です適切に開発およびテストします。

その他の方法:

  • メッセージを1つずつクライアントに配信する代わりに、メッセージが複数ある場合はすべてを配信し、メッセージをアクションのセット(一意のオブジェクトのコレクション)に変換して、すべてのアクションを実行します。
  • ユーザーのセッションが30分間の非アクティブ状態の後に有効期限が切れないのはなぜですか?期限切れになると、キューをクリーンアップします。
  • RabbitMQはJMS仕様を実装していないため、永続サブスクリプションを備えたJMSトピックに相当するものがない可能性があり、これはシステムよりも適しているようです。
1
Walfrat