10

耐久性のあるキューとそのバインディングを保持し、コンシューマーを一時停止する最良の方法は何ですか?

ユースケースは次のとおりです。「クラッシュさせて」、処理できないメッセージが大量に発生し続ける場合 (たとえば、データベースがダウンしている、またはスキーマの問題)、メッセージの処理を停止したいが、列。つまり、発行は許可されますが、消費は中断されます。

私は3つの解決策を考えることができます:

  1. キューにバインドされているすべてのコンシューマーに、メッセージを継続的に拒否して再キューイングさせることもできますが、これは、上記のロジックをプログラムで実行したことは言うまでもなく、一種の無駄なリソースです。
  2. すべての消費者を呼び出すことができますbasic.cancelConsumer(以下を参照)。
  3. またはに関しては、キューにバインドされているshutdownすべてのSimpleMessageListenerContainersを呼び出すことができると思います。

#1メッセージが拒否されているため、すでに行っています。問題は、これが失敗の無限 while ループのようになってしまい、その失敗をログに記録すると、さらに多くのリソースが無駄になることです。

#3理想的なようですが、すべてのメッセージリスナーについて知ってから、シャットダウンするように通知する必要があります。ファンアウト交換を使用して、キューを一時停止する必要があることを通知できると思います。このロジックには、RabbitMQ に何かが組み込まれている必要があるように感じます。もう 1 つの問題は、複数のキューをメッセージ コンテナーにバインドできることです (すべてのキューを一時停止する必要があるわけではありません)。

#2私はそれで消費者をキャンセルできることを知っていますconsumerTag、質問は(それが上記を行う正しい方法であると仮定して)どこでconsumerTags のリストをキューに取得するのですか?

4

2 に答える 2

3

コンシューマーを停止する必要がある場合は、基本的なキャンセルを呼び出すだけです。それがその方法です。

永続的なキューを持つことは、キューを宣言するときに解決する問題です: durable=true auto_delete=false.

永続的なメッセージを持つかどうかは、発行時に決定されます。delivery_mode=2.

各コンシューマには、独自のコンシューマ タグがあります。キューからメッセージを取得するときはいつでも、エンベロープにコンシューマ タグが必要であり、そのタグで基本キャンセルを呼び出す必要があります。

私の知る限り、 conn 1 にコンシューマー A を配置して、別の接続でそのコンシューマーの基本的なキャンセルを呼び出すことはできません。私はこれについて間違っているかもしれません。

于 2013-03-08T18:58:16.773 に答える
2

このソリューションは固有です。それは基本的#3に私の答えからです。

Map<String,CustomSimpleMessageListenerContainer>カスタム拡張されたキュー名を持つサービスを維持していますSimpleMessageListenerContainer

一定量の例外の後、「パニック」メッセージを送信します。このメッセージは、サービスが受信した特別なキューに送られ、コンシューマーをシャットダウンします。

于 2013-03-16T21:23:43.173 に答える