web-dev-qa-db-ja.com

RabbitMQチャネルが閉じ続けるのはなぜですか?

Apache POIを使用してMicrosoft OfficeドキュメントからデータをプルするJavaコードをデバッグしています。時折、大きなドキュメントに遭遇し、メモリ不足になるとPOIがクラッシュします。その時点で、他のコンポーネントがこのステップが失敗したことを認識し、適切なアクションを実行できるように、エラーをRabbitMQに公開しようとします。ただし、キューにパブリッシュしようとすると、com.rabbitmq.client.AlreadyClosedException (clean connection shutdown; reason: Attempt to use closed channel)を取得します。

エラーハンドラコードは次のとおりです。

try {
    //Extraction and indexing code
}
catch(Throwable t) {
    // Something went wrong! We'll publish the error and then move on with
    // our lives
    System.out.println("Error received when indexing message: ");
    t.printStackTrace();
    System.out.println();
    String error = PrintExc.format(t);
    message.put("error", error);

    if(mime == null) {
        mime = "application/vnd.unknown";
    }

    message.put("mime", mime);
    publish("IndexFailure", "", MessageProperties.PERSISTENT_BASIC, message);
}

完全を期すために、公開方法は次のとおりです。

private void publish(String exch, String route, 
    AMQP.BasicProperties props, Map<String, Object> message) throws Exception{
    chan.basicPublish(exch, route, props, 
        JSONValue.toJSONString(message).getBytes());  
}

Tryブロック内でRabbitMQチャネルを閉じるように見えるコードが見つかりません。チャネルが暗黙的に閉じられる状況はありますか?

[〜#〜] edit [〜#〜]:publish内のbasicPublish呼び出しによってAlreadyClosedExceptionがスローされることに注意してください。

26
quanticle

AMQPチャネルは、チャネルエラーが発生すると閉じられます。チャネルエラーを引き起こす可能性のある2つの一般的なこと:

  • 存在しない取引所にメッセージを公開しようとしています
  • アクティブなコンシューマーセットを持つキューがない即時フラグセットを持つメッセージを発行しようとしています

addShutdownListener() を使用してメッセージをパブリッシュするために使用しようとしているチャネルでShutdownListenerを設定して、シャットダウンイベントをキャッチし、その原因を調べます。

39
alanxz

私の場合のもう1つの理由は、誤ってメッセージを2回確認したことです。これにより、2回目の確認後にログにRabbitMQエラーが発生します。

=ERROR REPORT==== 11-Dec-2012::09:48:29 ===
connection <0.6792.0>, channel 1 - error:
{amqp_error,precondition_failed,"unknown delivery tag 1",'basic.ack'}

重複した確認応答を削除すると、エラーがなくなり、チャネルが閉じなくなり、AlreadyClosedExceptionもなくなりました。

11
Christoph

このトピックを検索する他のユーザーにこの情報を追加したい

チャネルクローズ例外を受信する別の考えられる理由は、パブリッシャーとコンシューマーが異なるキュー宣言/設定でチャネル/キューにアクセスしている場合です。

出版社

channel.queueDeclare("task_queue", durable, false, false, null);

ワーカー

channel.queueDeclare("task_queue", false, false, false, null);

RabbitMQサイトから

RabbitMQ doesn't allow you to redefine an existing queue with different parameters and will return an error to any program that tries to do that
5
denil

消費チャネルが閉じている理由がわからない場合は、配信を2回以上確認するか、確認するかを確認してください。

Rabbitmqログには、次のようなメッセージが表示されます。

操作basic.ackにより、チャネル例外precondition_failedが発生しました:不明な配信タグ...

1
la0rg

私もこの問題を抱えていました。私のケースの理由は、最初に永続= falseでキューを構築し、ログファイルに永続をtrueに切り替えたときにこのエラーメッセージがあったからです。

「vhost '/'のキュー 'logsQueue'の等価な引数 'durable': 'true'を受信しましたが、現在は 'false'です」

その後、キューの名前を変更しました。 RabbitMQサーバーは構築されたキューの記録をどこかに保持しており、ステータスを永続から非永続に、またはその逆に変更できないと想定しました。

繰り返しますが、私は新しいキューに対して耐久性=偽を作成しましたが、今回はこのエラーが発生しました

「vhost '/'のキュー 'logsQueue1'の等価な引数 'durable': 'false'を受信しましたが、currentは 'true'です」

私の仮定は真実でした。 rabbitMQサーバーのキューを次のようにリストしたとき:

rabbitmqctl list_queues 

サーバーで両方のキューを見ました。

要約すると、2つの解決策は次のとおりです。1.良い解決策ではないキューの名前を変更する2.次の方法でrabbitMQをリセットする

rabbitmqctl stop_app
rabbitmqctl reset
rabbitmqctl start_app
0
M. Mashaye