Кто-нибудь точно знает, какие сообщения JMS будут доставляться в режиме CLIENT_ACKNOWLEDGE, если клиент падает? - PullRequest
3 голосов
/ 07 июня 2010

В спецификации сказано: «Подтверждение потребленного сообщения автоматически подтверждает получение всех сообщений, которые были доставлены его сеансом», - но мне нужно знать, что означает «доставлено».

Например, если я вызываю customer.receive () 6 раз, а затем вызываю .acknowledge для 3-го сообщения - это (а) только первые 3 сообщения, которые были подтверждены, или (б) все 6?

Я действительно надеюсь, что это вариант a, то есть сообщения после того, что вы назвали квитировать на, БУДУТ доставлены, иначе трудно понять, как вы могли бы предотвратить потерю сообщения в случае сбоя процесса моего получателя, прежде чем у меня шанс сохранить и подтвердить сообщения. Но спецификация сформулирована так, что не понятно. У меня сложилось впечатление, что авторы спецификации JMS рассматривали сбой брокера, но не слишком долго думали о том, как защитить его от сбоев клиента: o (

Спасибо Ben

1 Ответ

4 голосов
/ 08 июня 2010

Согласно спецификации, опция (b) является правильным поведением.Если вы получаете опцию (а) и полагаетесь на нее, приложение не будет переносимым.

В приведенном ниже объяснении я имею в виду конкретно спецификацию JMS Версия 1.1 12 апреля 2002 года .

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

Что действительно происходит, хотя это то, что подтверждение сообщения управляет вызовами фиксации в сеансеуровень.Поскольку сеанс может иметь только одну активную транзакцию за раз, каждое подтверждение ограничивает не точку в потоке сообщений, а точку во времени .Ack фиксирует существующую единицу работы и запускает следующую.Сообщения, доставленные до подтверждения , должны быть включены в единицу работы, подтвержденную подтверждением .

Термин «доставлено» обычно считается завершением вызова API, удаляющегосообщение из очереди и приводит к заполнению объекта в памяти программы.В действительности, сообщение считается доставленным, когда оно удаляется из очереди, независимо от того, попадает ли оно в программу.Например, рассмотрим следующую последовательность событий:

  1. Приложение запрашивает сообщение.
  2. Запрос передается через сокет TCP процессу на сервере, который действует как проксидля приложения.
  3. Прокси-сервер выдает GET для очереди.
  4. Сообщение заблокировано в единице работы и передано процессу прокси.
  5. Процесс проксипытается доставить сообщение через сокет TCP вызывающему приложению.Если в этот момент соединение разорвано, приложение никогда не увидит сообщение, но провайдер JMS считает, что оно доставлено.При обнаружении разорванного соединения единица работы отменяется, сообщение откатывается в очередь и счетчик повторных поставок увеличивается.
  6. Приложение получает сообщение.
  7. Приложение подтверждаетсообщение.
  8. Процесс прокси получает вызов коммита и выполняет его.

Между 6 и 8 имеется окно, в течение которого сокет TCP может быть отключен.Со стороны провайдера JMS, он не может действительно отличить это от сбоя на шаге 5. В любом случае, сообщение откатывается и доставляется позже.Однако в этом случае приложение увидит сообщение дважды.Спецификация ожидает эту ситуацию в 4.4.13, где говорится:

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

Это дело JMS-приложения, чтобы справиться с этой неоднозначностью.В некоторых случаях это может привести к тому, что клиент будет создавать функционально дублирующиеся сообщения.

Сообщение, которое доставляется в результате восстановления сеанса, не считается дублирующим сообщением.

В вашем примере, гдевы «вызываете customer.receive () 6 раз, а затем вызываете .acknowledge для 3-го сообщения» и наблюдаете, что сообщения с 4 по 6 доставляются, возможные объяснения состоят в том, что а) шесть сообщений не все из одного сеанса,или б) поведение не соответствует спецификации.

...