Подтверждение сообщения JMS только до тех пор, пока сообщение не будет подтверждено

Как убедиться, что подтверждение сообщения удаляет только сообщения до сообщения, для которого подтверждение вызывается в брокере jms. В настоящее время у меня есть система, которая использует очередь jms и частично ее обрабатывает. Через некоторое время пакет этих сообщений сохраняется другим потоком. Мне нужно подтверждать сообщения сейчас. Но проблема в том, что я должен перестать потреблять сообщения, иначе подтверждение ранее полученного сообщения также подтвердит получение всех других последующих сообщений.

Другими словами, предположим, что у меня есть 10 сообщений в очереди. Я потребляю 7 из них, а затем подтверждаю 5-е сообщение. Это, в свою очередь, удаляет все 7 сообщений, полученных потребителем, из очереди. Есть ли способ подтверждать и удалять сообщения только из очереди до 5-го сообщения.

РЕДАКТИРОВАТЬ: я пытался создать два сеанса и использовать их из разных сеансов, но (по крайней мере, с apache qpid) это работает непоследовательно. Под непостоянством я подразумеваю, что иногда во время теста бывает так, что один потребитель может получать сообщения, а другой не получает вообще, сколько бы вы ни ждали. Это сработало бы для меня как решение, но из-за несоответствия я не могу использовать это как решение.


person Raks    schedule 06.12.2011    source источник
comment
Вы не указали, какой поставщик сообщений вы используете. Но, насколько я знаю, многие провайдеры обмена сообщениями не разрешают подтверждение случайного сообщения. Если вы подтвердите одно сообщение, все сообщения, полученные до этого момента, также будут подтверждены и удалены из очереди.   -  person Shashi    schedule 06.12.2011
comment
Я использую apache qpid, и я не делаю случайное подтверждение, а делаю подтверждение для определенного сообщения. Это нормально, если все сообщения до этого очищаются, но если были получены дальнейшие сообщения, они также удаляются.   -  person Raks    schedule 06.12.2011


Ответы (2)


Я понимаю, что этот пост устарел, но этот ответ должен принести пользу тем, кто наткнется на него позже.

Если вы хотите детально контролировать, какие сообщения вы хотите подтвердить, метод подтверждения individual должен вам помочь. Используя этот режим подтверждения, вы можете подтверждать отдельные сообщения в сеансе. Сообщения, которые не были подтверждены, будут доставлены повторно.

Это не является частью спецификации, но большинство поставщиков очередей поддерживают ее вне спецификации.

Oracle

Для большей гибкости очередь сообщений позволяет настроить режим подтверждения клиента JMS. В режиме клиентского подтверждения клиент явно подтверждает получение сообщения, вызывая метод accept() объекта сообщения.

Стандартное поведение этого метода заключается в том, что сеанс подтверждает все сообщения, которые были обработаны любым потребителем в сеансе с момента последнего вызова метода. (То есть сеанс подтверждает текущее сообщение и все ранее неподтвержденные сообщения, независимо от того, кто их использовал.)

В дополнение к стандартному поведению, заданному JMS, очередь сообщений позволяет вам использовать режим подтверждения клиента для подтверждения одного сообщения за раз.

public interface com.sun.messaging.jms.Message {
          void acknowledgeThisMessage() throws JMSException;
          void acknowledgeUpThroughThisMessage() throws JMSException;
}

ActiveMQ

Можно представить и другие режимы подтверждения, которые также были бы полезны, например: CONSUMER_ACKNOWLEDGE, где Message.acknowledge() будет подтверждать только сообщения, полученные от определенного MessageConsumer, или CONSUMER_CHECKPOINT_ACKNOWLEDGE, где Message.acknowledge() будет подтверждать только сообщения, полученные до включительно экземпляр Message, для которого был вызван метод.

Но, не прибегая ко всем этим различным возможностям, можно ли просто добавить режим INDIVIDUAL_ACKNOWLEDGE? Уже одно это позволило бы многопоточным приложениям добиться любого поведения, которое им нужно.

connection.createQueueSession(false, ActiveMQSession.INDIVIDUAL_ACKNOWLEDGE);

Я лично не использовал QPID, однако документация намекает на то, что возможны отдельные подтверждения сообщений.

Examples
  # acknowledge all received messages
  session.acknowledge

  # acknowledge a single message
  session.acknowledge :message => message

При обработке пакета вы можете подтвердить каждое полученное и обработанное сообщение. Если вы столкнулись с исключением, не подтверждайте сообщение.

person Deepak Bala    schedule 21.02.2014

Подтверждение сообщения заставит диспетчер очередей удалить это сообщение, а также все другие сообщения, полученные до этого сообщения. Он не должен удалять сообщения, которые еще не были получены приложением. Вы можете проверить свое приложение на то, как вы подтверждаете сообщение.

person Shashi    schedule 08.12.2011
comment
Проблема заключается в том, что все сообщения, полученные потребителем, удаляются, и это не зависит от сообщения, на которое вы нажимаете. Я хочу реализовать что-то, что удаляет только определенное сообщение, даже если после этого я получил больше сообщений. Это необходимо, потому что я обрабатываю сообщения в пакетном режиме, и всякий раз, когда пакетная обработка завершается, мне нужно подтвердить получение этого пакета. И эта пакетная обработка занимает много времени, поэтому я хочу продолжать получать сообщения параллельно. - person Raks; 08.12.2011
comment
Нет, это невозможно. Все полученные сообщения будут удалены, когда одно сообщение будет подтверждено. Возможно, вам придется рассмотреть альтернативы. - person Shashi; 12.12.2011