Многопоточный код JMS: CLIENT_ACKNOWLEDGE или транзакционный сеанс - PullRequest
0 голосов
/ 01 октября 2010

Отредактированный вопрос: я работаю над многопоточным кодом приемника и издателя JMS (автономное многопоточное Java-приложение). Мама MQSonic. XML-сообщение получено из очереди, вызываются хранимые процедуры (70 секунд), а ответ отправляется в раздел в течение 90 секунд. Мне нужно обработать условие, когда брокер не работает или приложение находится на запланированном завершении работы. то есть состояние, при котором сообщения принимаются из очереди и обрабатываются в java, в то время как очередь и тема будут недоступны. Затем для обработки тех сообщений, которые не находятся в очереди и не отправляются в тему, но находятся в памяти Java, у меня есть следующие параметры:

(1) Чтобы создать сеанс CLIENT_ACKNOWLEDGE как: connection.createSession (false, javax.jms.Session.CLIENT_ACKNOWLEDGE) Здесь я буду подтверждать сообщение только после успешного завершения транзакций (хранимых процедур)

(2) Использовать транзакционный сеанс, т.е. connection.createSession (true, -1). В этом подходе из-за некоторого исключения в транзакции (хранимой процедуре) сообщение откатывается и доставляется. Они откатываются снова и снова и продолжаются, пока я не убью программу. Можно ли ограничить количество повторных доставок сообщений jms из очереди?

Также в вышеприведенных двух подходах какой из них лучше?

Ответы [ 4 ]

3 голосов
/ 06 октября 2010

В интерфейсе progress.message.jclient.ConnectionFactory есть метод setMaxDeliveryCount(java.lang.Integer value), в котором вы можете установить максимальное количество раз, которое сообщение будет доставлено на ваш MessageConsumer. Когда это количество раз увеличится, оно будет перемещено в очередь SonicMQ.deadMessage.

Вы можете проверить это в книге "Руководство по программированию приложений Sonic MQ" на стр. 210 (в версии 7.6).

Что касается вашего вопроса о том, что лучше ... это зависит от того, будет ли хранимая процедура выполняться несколько раз. Если это проблема, вы должны использовать транзакцию, которая охватывает очередь JMS и базу данных (Sonic поддерживает транзакции XA). Если вы не возражаете выполнить несколько раз, то я бы не стал подтверждать сообщение и прерывать обработку, когда вы замечаете, что брокер не работает (при попытке подтверждения сообщения, скорее всего). Таким образом, другой процессор может обработать сообщение, если первый не сможет сделать это после сбоя соединения.

Если сообщения обрабатываются с переменным временем, вы также можете посмотреть режим SINGLE_MESSAGE_ACKNOWLEDGE сеанса Sonic JMS. Обычно вызов acknowledge() для сообщения также подтверждает все сообщения, которые были до него. Если вы обрабатываете их не по порядку, это не то, чего вы хотите. В режиме подтверждения одного сообщения (которого нет в стандарте JMS), acknowledge() подтверждает только сообщение, для которого оно вызывается.

0 голосов
/ 01 октября 2010

Если вы беспокоитесь о связи с очередью сообщений / посредником / сервером / и т. Д., Которая может быть недоступна, и о том, как это прерывает общий поток более крупного процесса, который вы пытаетесь создать, то вам, вероятно, следует заглянуть в очередь JMS поддерживает кластеризацию серверов, поэтому вы можете надежно генерировать / потреблять сообщения, когда отдельные серверы в кластере отключаются.

0 голосов
/ 01 октября 2010

Ваш вопрос не ясен на 100%, но, похоже, проблема в том, что вы генерируете исключение при обработке сообщения, когда вам действительно не нужно.

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

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

0 голосов
/ 01 октября 2010

Не зная, каким провайдером сообщений вы пользуетесь, я не знаю, поможет ли это вам.

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

// get/receive message from queue

if ( backout counter > n ) {
   move_message_to_app_dead_letter_queue();
   return;
}
process_message();

Поля заголовка серии MQ доступны в виде свойств JMS.

Использование вышеуказанного подхода также поможет, если вы сможете использовать транзакции XA для отката или фиксации базы данных и администратора очередей одновременно.
Однако транзакции XA влекут за собой значительное снижение производительности, и с сохраненными процедурами это, вероятно, невозможно.

Альтернативным подходом было бы немедленно записать сообщение в message_table в виде большого двоичного объекта, а затем зафиксировать сообщение из очереди.
Поместите триггер в message_table, чтобы вызвать сохраненный процесс, а затем добавьте механизм ответа JMS в сохраненный процесс.

...