Каков наилучший способ безопасного завершения Java-приложения с запущенными пользователями RabbitMQ - PullRequest
8 голосов
/ 15 июля 2011

У нас есть отдельное Java-приложение, выполняющее некоторую фоновую обработку на компьютере Debian.Задания, которые он должен обрабатывать, отправляются через сообщения RabbitMQ.

Когда необходимо обновить java-приложение, мы должны остановить его (убить).Но мы должны быть уверены, что ни один из потребителей в настоящее время не обрабатывает сообщение.Какой, по вашему опыту, лучший способ добиться этого?

Мы пытались отправить сообщение «ВЫКЛЮЧЕНИЕ» потребителю, но мы не можем закрыть очередь или канал ?!Это замораживает приложение!Или есть другое решение, где мы могли бы, например, автоматически завершить работу приложения, не выполняя команду kill в linux?

Thx, чтобы поделиться своим опытом.

Привет

Ответы [ 2 ]

3 голосов
/ 15 июля 2011

Библиотеки Java RabbitMQ не предоставляют (AFAIK) ничего, что автоматически откладывало бы завершение процесса потребителя, пока некоторые сообщения еще обрабатываются. Поэтому вам придется сделать это самостоятельно.

Если ваше приложение может это терпеть, просто выключите его. Любое сообщение, которое не было подтверждено в этот момент, останется в очереди в брокере и будет повторно доставлено, когда потребитель вернется.

Если вы не можете с этим смириться, и вам абсолютно необходимо убедиться, что вся текущая обработка сообщений завершается, вам необходимо следовать советам, аналогичным приведенным в в этом ответе , и выполнить следующее при выключении обработчик:

  1. Установить флаг "все потоки должны выйти" в значение true
  2. Присоединиться к каждому из потоков в вашем пуле потоков
  3. Выход изящно

Это означает, что каждый из ваших потоков обработки сообщений (при условии, что у вас есть несколько потоков, обрабатывающих сообщения одновременно) должен следовать этой общей схеме:

  1. Извлечь сообщение из очереди и обработать его
  2. Подтвердить только что обработанное сообщение
  3. Если флаг «все потоки должны выйти» равен true, выйти из функции потока
  4. Промыть, повторить

Надеюсь, это поможет.

0 голосов
/ 04 апреля 2014

Вот мое мнение.

Я создал свой подкласс DefaultConsumer (BasicConsumer), который предоставляет isCancelled () и реализует handleCancelOk (), который устанавливает "отмененный флаг" в true.

Последовательность запуска:

consumers = new ArrayList<BasicConsumer>();
consumers.add(...)

Последовательность останова:

// Cancel all consumers
for (BasicConsumer consumer : consumers) {
  try {
    consumer.getChannel().basicCancel(consumer.getConsumerTag());
  } catch (Exception e) {
    // report
  }
}

// Wait for all consumers to be cancelled
Timeout timeout = ...;
while (!consumers.isEmpty() && !timeout.isElapsed()) {
  // Remove cancelled consumers
  for (Iterator<BasicConsumer> iterator = consumers.iterator(); iterator.hasNext();) {
    if (iterator.next().isCancelled())
      iterator.remove();
  }
}

// Here we could force-close the remaining timed-out consumers if we
// used our own ExecutorService by shutting down all of its threads.
connection.close();

Соответствующий поток RabbitMQ ML: Как выполнить чистое завершение работы приложения Java с помощью потребителей?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...