Каков наилучший способ непрерывной обработки асинхронной очереди в Java?

Мне трудно понять, как спроектировать последнюю часть моей системы. В настоящее время я использую сервер Tomcat с сервлетом, который отвечает на запросы клиентов. Каждый запрос, в свою очередь, добавляет сообщение обработки в асинхронную очередь (вероятно, я буду использовать JMS через Spring или, что более вероятно, Amazon SQS).

Последовательность событий такова:

Отправляющая сторона:
1. Принять запрос клиента
2. Добавить в БД некоторые данные, связанные с этим запросом, с уникальным идентификатором
3. Добавить объект сообщения, представляющий этот запрос, в очередь сообщений

Принимающая сторона:
1. Извлечь новый объект сообщения из очереди
2. Развернуть объект и получить некоторую информацию с веб-сайта на основе информации, содержащейся в объекте msg.
3. Отправить оповещение по электронной почте
4. обновить строку моей БД (тот же уникальный идентификатор) с информацией о том, что операция была завершена для этого запроса.

Мне трудно понять, как правильно обращаться с принимающей стороной. С одной стороны, я, вероятно, могу создать простую программу Java, которую я запускаю из командной строки, которая выбирает каждый элемент в очереди и обрабатывает его. Это безопасно? Имеет ли смысл запускать эту программу как отдельный поток внутри контейнера Tomcat? Я не хочу делать это последовательно, а это означает, что принимающая сторона должна иметь возможность обрабатывать несколько объектов одновременно, используя несколько потоков. Я хочу, чтобы это работало всегда, 24 часа в сутки.

Какие есть варианты построения принимающей стороны?


person Ish    schedule 05.02.2009    source источник
comment
В случае, если кому-то интересно, что я в итоге сделал. Я использовал Amazon SQS и у меня есть java-клиент (использующий Spring Framework), который опрашивает очередь. Когда он находит сообщение, он обрабатывает его и возвращается в состояние ожидания. Я мог бы добавить многопоточность Quartz, а пока я просто запускаю несколько процессов.   -  person Ish    schedule 24.03.2009
comment
Я столкнулся с аналогичной проблемой. Я хотел бы знать, как реализован Java-клиент. Я надеюсь, что это не работает в бесконечном цикле while и пулах для сообщения?   -  person TheMonkWhoSoldHisCode    schedule 28.10.2014


Ответы (4)


«С одной стороны, я, вероятно, могу создать простую Java-программу, которую я запускаю из командной строки, которая выбирает каждый элемент в очереди и обрабатывает его. Это безопасно?»

Что в этом небезопасного? Это прекрасно работает.

«Имеет ли смысл запускать эту программу как отдельный поток внутри контейнера Tomcat?»

Только если у Tomcat есть много свободного времени для фоновой обработки. Часто это так и есть — у вас есть свободное время для такой обработки.

Однако потоки не оптимальны. Потоки совместно используют общие ресурсы ввода-вывода, и ваш фоновый поток может замедлить внешний интерфейс.

Лучше иметь очередь JMS между внешним интерфейсом «порт 80» и отдельным внутренним процессом. Внутренний процесс запускается, подключается к очереди, получает и выполняет запросы. Бэкенд-процесс может (при необходимости) быть многопоточным.

person S.Lott    schedule 05.02.2009

Если вы используете JMS, почему вы помещаете задачи в БД?

Вы можете использовать устойчивую очередь в JMS. Это сохранит задачи, даже если брокер JMS умрет, до тех пор, пока они не будут подтверждены. У вас могут быть резервные брокеры, так что если один брокер умрет, второй автоматически вступит во владение. Это может быть более надежным, чем использование одной БД.

person Peter Lawrey    schedule 05.02.2009
comment
Потому что я получу некоторую информацию с целевого веб-сайта и размещу ее рядом со строкой в ​​БД. Затем эта информация должна быть получена клиентом в какой-то более поздний момент времени. На самом деле я использую db не столько для резервирования, сколько для хранения данных для последующего поиска. - person Ish; 05.02.2009

Если вы уже используете Spring, проверьте DefaultMessageListenerContainer. Это позволяет вам создать bean-компонент, управляемый сообщениями POJO. Это можно использовать из существующего контейнера приложения (ваш файл WAR) или как отдельный процесс.

person John Meagher    schedule 05.02.2009
comment
В этом случае потребитель постоянно опрашивает очередь или он как-то уведомляется? - person Ish; 06.02.2009
comment
Я почти уверен, что опросы DefaultMessageListenerContainer. Самое приятное в этом то, что он скрывает от вас проблему с опросом/уведомлением. Вы просто реализуете jms MessageListener и выполняете всю необходимую работу. - person John Meagher; 07.02.2009

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

Я использую различные решения JMS, включая tibco, activemq (до того, как apache включил его) и joram. Joram был более надежным решением с открытым исходным кодом, но теперь, когда он стал частью Apache, это могло измениться.

person Don Branson    schedule 05.02.2009
comment
Можете ли вы объяснить, как реализовать событийную модель? - person TheMonkWhoSoldHisCode; 28.10.2014
comment
Взгляните на docs.oracle.com/cd/ E13222_01/wls/docs90/jms/, раздел "Асинхронный прием сообщений". - person Don Branson; 29.10.2014