web-dev-qa-db-ja.com

RabbitMQ:メッセージが「未確認」のまま

私のJavaアプリケーションはメッセージをRabbitMQ交換に送信し、交換はメッセージをバインドされたキューにリダイレクトします。SpringframeworkAMQP Java RabbitMQプラグインを使用します。

問題:メッセージはキューに入りますが、「未確認」状態のままで、「準備完了」になることはありません。

その理由は何でしょうか?

19
sunny

Unacknowledgedメッセージは、コンシューマーによって読み取られたことを意味しますが、コンシューマーは、RabbitMQブローカーにACKを送り返して、処理が完了したことを伝えたことはありません。

私はSpring Frameworkプラグインに過度に精通していませんが、どこか(コンシューマーにとって)キューを宣言します。キューは次のようになります( http://www.rabbitmq.com/tutorialsから取得) /tutorial-two-Java.html ):

channel.queueDeclare(queueName, ....)

次に、コンシューマーをセットアップします

bool ackMode = false;
QueueingConsumer consumer = new QueueingConsumer(channel);
channel.basicConsume(queueName, ackMode, consumer);

上記のackModeはブール値であり、falseに設定することで、指定された各メッセージをコンシューマーが確認することをRabbitMQに明示的に伝えています。このフラグがtrueに設定されている場合、コンシューマーがメッセージを読み取った直後(つまり、メッセージがコンシューマーに配信され、キューから削除されます)になると、RabbitMQにUnacknowledgedカウントは表示されません。

メッセージを確認するには、次のようにします。

QueueingConsumer.Delivery delivery = consumer.nextDelivery();
//...do something with the message...
channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false); //the false flag is to do with multiple message acknowledgement

いくつかのコンシューマーコードを投稿できる場合は、さらにお役に立てるかもしれませんが、当面は BlockingQueueConsumer を見てください。具体的には、コンストラクターで設定できることがわかります- AcknowledgeMode と、nextMessage()も見てください。これにより、getDeliveryTag()というメソッドを含むMessageオブジェクトが返されます。これにより、basicAckで送信するIDであるLongが返されます。

18
kzhen

消費者が確実にbasicAckメソッドを使用しているにもかかわらず、メッセージが未確認の状態のままになる別の理由のために2セントを追加するだけです。

RabbitMQ接続が開いているプロセスの複数のインスタンスが実行中のままになる場合があります。その1つが原因でメッセージが未確認の状態でスタックし、コンシューマーの別のインスタンスがこのメッセージを再フェッチできない場合があります。

RabbitMQ管理コンソール(ローカルマシンの場合、localhost:15672で利用可能である必要があります)にアクセスして、複数のインスタンスがチャネルを取得しているかどうか、または単一のインスタンスのみが現在アクティブかどうかを確認できます。

RabbitMQ Connections

冗長な実行中のタスク(この場合はJava)を見つけて終了します。不正なプロセスを削除した後、メッセージが再びReady状態にジャンプするのを確認してください。

11
Shlomi Uziel