Почему мои каналы RabbitMQ продолжают закрываться?

Я отлаживаю код Java, который использует Apache POI для извлечения данных из документов Microsoft Office. Иногда он сталкивается с большим документом, и 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: я должен отметить, что AlreadyClosedException вызывается вызовом basicPublish внутри публикации.

Канал AMQP закрывается по ошибке канала. Две распространенные вещи, которые могут вызвать ошибку канала:

  • Попытка опубликовать сообщение для обмена, который не существует
  • Попытка опубликовать сообщение с немедленным набором флагов, который не имеет очереди с активным набором пользователей

Я бы посмотрел на настройку ShutdownListener на канале, который вы пытаетесь опубликовать, используя addShutdownListener(), чтобы поймать событие выключения и посмотреть при чем это вызвало.

35
ответ дан 12 янв. '12 в 20:23
источник

Другая причина в моем случае заключалась в том, что по ошибке я дважды признал сообщение. Это приводит к ошибкам 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
ответ дан 11 дек. '12 в 12:41
источник

Я хотел бы добавить эту информацию для других пользователей, которые будут искать эту тему

Еще одна возможная причина для получения закрытого канала - это когда издатели и потребители обращаются к каналу/очереди с разными объявлениями/настройками очереди

Издатель

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
4
ответ дан 25 июня '14 в 12:23
источник

Для тех, кто интересуется, почему их потребительские каналы закрываются, проверьте, не пытаетесь ли вы подтвердить или отменить доставку более одного раза.

В журнале rabbitmq вы увидите такие сообщения:

операция basic.ack вызвала исключение канала precondition_failed: неизвестный тег доставки...

0
ответ дан 22 янв. '19 в 12:59
источник

У меня также была эта проблема. Причиной моего случая было то, что сначала я построил очередь с durable = false, и в файле журнала у меня появилось это сообщение об ошибке, когда я переключил durable на true:

"неэквивалентный arg 'durable' для очереди 'logsQueue' в vhost '/': получил" true ", но текущий -" false".

Затем я изменил имя очереди, и это сработало для меня. Я предположил, что сервер RabbitMQ хранит запись построенных очередей где-то, и он не может изменить статус от долговременного до недолговечного и наоборот.

Снова я сделал durable = false для новой очереди, и на этот раз я получил эту ошибку

"неэквивалентный arg 'durable' для очереди 'logsQueue1' в vhost '/': получил" false ", но текущий -" true".

Мое предположение было правдой. Когда я перечислил очереди на сервере rabbitMQ, выполните следующие действия:

rabbitmqctl list_queues 

Я видел обе очереди на сервере.

Подводя итог, 2 решения: 1. переименование имени очереди, которое не является хорошим решением 2. сброс rabbitMQ с помощью:

rabbitmqctl stop_app
rabbitmqctl reset
rabbitmqctl start_app
0
ответ дан 06 нояб. '15 в 0:01
источник