7

コンシステント ハッシュによってコンシューマー間で一貫して作業を分散したいプロデューサーがいます。たとえば、コンシューマ ノード X と Y では、タスク A、B、C は常にコンシューマ X に、D、E、F はコンシューマ Y に移動する必要があります。ただし、Z がコンシューマのプールに参加すると、少しシフトする可能性があります。

コンシューマー ノードに接続するための独自のロジックを記述したくありませんでした。特に、ノードのプールへの参加と退出を管理する必要はありませんでした。そのため、RabbitMQ と、コンシューマー ノードごとの専用キューを使用する道をたどりました。 .

私が直面している問題の 1 つは、これらのキューを一覧表示することです。プロデューサーは、作業が分散される前に、使用可能なすべてのキューを知る必要があるためです。AMQP はキューの一覧表示さえサポートしていないため、私のアプローチ全体が不確かになります。ただし、 RabbitMQ と Alice (現時点では壊れています) はその機能を追加しています: RabbitMQ でキューと交換を一覧表示するための API はありますか?

これはRabbitの賢い使い方ですか?メッセージキューを使用する必要がありますか? キューが自分の作業をコンシューマ間で一貫して分割できるようにするためのより良い設計はありますか?

4

2 に答える 2

6

あなたが説明したことは、RabbitMQ で実行できます。

セットアップは次のようになります。

  • プロデューサはメッセージをトピック交換に発行します。これに、consistent_divider という名前を付けましょう。
  • コンシューマーがプールに参加すると、ブローカーに接続し、その名前で排他キューを作成しますが、それを何にもバインドしません
  • プロデューサーは定期的にブローカーをポーリングし (おそらく rabbitmqctl list_consumers を使用)、コンシューマーが変更されたかどうかを確認します。存在する場合は、既存のバインディングをすべて削除し、必要に応じてキューを再バインドします。
  • プロデューサがパブリッシュすると、タスク タイプに一致するルーティング キーがメッセージに割り当てられます。

したがって、A、B、C、D、E、F の 6 つのタスク タイプがあり、C1 と C2 の 2 つのコンシューマーしかない場合、バインディングは次のようになります。C2 は、ルーティング キー D、E、および F を使用して c_d に 3 回バインドしました。

C3 がプールに参加すると、プロデューサーはこれを確認し、それに応じてキューを再バインドします。

プロデューサがパブリッシュすると、routing_keys A、B、C、D、E、および/または F を持つメッセージが送信され、メッセージは正しいキューにルーティングされます。

これには 2 つの潜在的な問題があります。

  1. コンシューマーがプールに参加してからメッセージがルーティングされるまでには、わずかな時間差があります。また、すでにメッセージがキューにある場合、コンシューマーが別のコンシューマー向けのメッセージを取得する可能性があります (たとえば、C3 が参加し、プロデューサーが再バインドしますが、C2 は E および F メッセージが既にキューにあるため、いくつかの E および F メッセージを取得します)。
  2. コンシューマーが何らかの理由で停止した場合、そのキュー内 (およびそのキューに向かう途中) のメッセージは失われます。これは、メッセージをそれぞれ再発行および配信不能にすることで解決できます。

最後の質問に答えるために、おそらくキューイングを使用したいと考えており、RabbitMQ は優れた選択肢ですが、要件 (より正確には「一貫して作業を分割する」ビット) は AMQP に完全には適合しません。

于 2010-09-03T11:39:28.827 に答える