Про то, как можно использовать компоненты управляемые сообщениями (Message Driven Beans) на практике.

В статье рассматривается пример использования MDB в реальном коммерческом приложении. От постановки задачи до описания реализации программы. Статья включает в себя фрагменты исходного кода. Тестовое приложение и все необходимые настройки и библиотеки доступны для скачивания.

Постановка задачи

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

К сожалению компания, заказавшая нам сайт, сама не производит этот полезный продукт, а являемся филиалом четырех иностранных компаний — производителей. Некоторые из них, как мы догадываемся, тоже пытаются подзаработать и перепродают запчасти сторонних разработчиков. Все эти иностранные компании(для упрощения изложения мы будем называть их далее контент-провайдерами) — контент-провайдеры — предоставляют полный доступ к своим базам данных запчастей посредством веб-сервисов, основанных на XML (и XML-RPC), что значительно упрощает получение информации. Т е в самом простом случае я могу зайти на сайт компании, зарегистрироваться и сделать запрос с различными параметрами. В ответ мы получим XML файл с информацией о запчастях. Более того, используя их интерфейс, мы можем продавать их запчасти на своем сайте. Нам не требуется подключать платежную систему к нашему сайту. Мы просто пересылаем информацию о выбранном товаре и данные о кредитной карте пользователя и получаем результат о статусе операции - покупка прошла удачно или код ошибки, допустим, неверный номер карточки. После удачной продажи товара с нашего веб сайта компания контент провайдер переводит на наш банковский счет определенный процент.

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

Мы имеем Linux и сервер приложений Orion версии 2.0.7. Это дадено свыше и обсуждению не подлежит. Необходимо всего лишь создать Java приложение для загрузки данных от провайдеров в нашу базу.

Подводные камни

Каждый контент-провайдер ведет успешный бизнес и число всевозможных модификаций автомобильных запчастей достигает десятков тысяч. Время работы одного запроса и добавления в базу пусть будет 30 секунд. При наличии четырех провайдеров со списком из 50000 позиций у каждого получаем примерно 70 дней на все. Это невозможно! Такие сроки даже упоминать при заказчике смертельно опасно.

Одно из решений

Для того, чтобы уменьшить время загрузки обновленной информации от контент-провайдера, необходимо распараллелить процесс. У нас уже написаны пакеты для работы с каждым провайдером. Они же работают на сервере приложений на живом сайте. Эти пакеты умеют общаться с провайдером через веб сервисы. Делать запросы в реальном времени на предмет наличия товара на текущий момент по параметрам, которые ввел пользователь в форме запроса — цвет, форма, размер, обьем и многим другим параметрам. Они могут бронировать товар, непосредственно перед покупкой и полностью обслуживают процесс покупки. Ну и конечно же, в этих классах есть методы для получения дополнительной информации о товарах. Из-за этого мы не можем придумывать что-то другое и вынужден использовать данный сервер приложений.

Как это сделали мы: Рассмотрим случай с одним контент-провайдером. Создаем сервлет, который в цикле начинает проходить по всем уникальным идентификаторам товара. В теле цикла сервлет считает и посылает 50(это зависит от сети, можно и больше) сообщений для компонентов управляемых сообщениями MDB(будем называть их дальше работниками) - работников. Работник, получив сообщение с уникальным идентификаторам товара и кодом контент-провайдера, берет пакет этого провайдера и получает все данные. Он заполняет таблицы в базе данных. После этого он увеличивает на 1 системную переменную, в которой хранится число завершивших работу работников и умирает. Сервлет, считывает в цикле системную переменную в которой хранится число активных работников и обнаружив, что число занятых работников стало меньше 50 тут же создает нового работника и посылает ему задание. Таким образом, сервлет следит только за количеством запущенных MDB. 70 дней изнурительной работы трансформировались от силы в полтора.

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

  • The JMS server is not clusterable.
  • J2EE applications using message driven beans can not be clustered.

Еще больше расстроило следующее заявление: The JMS spec/api itself has no mention or support for clustering. Вселило надежду лишь возможность перехода на сервер приложений JBoss, создатели которого бьют себя ногой в грудь: In the current production release of JBoss AS, the HA-JMS service is implemented as a clustered singleton fail-over service. Но мы не можем перейти на JBoss немедленно в силу ограничений, даденых свыше и поэтому попытаемся выкрутиться количеством машин. К нашему счастью, совершенно случайно под рукой оказалось 4 машины. 2 линуксовые и две под winxp. Оптимизировав приложение на каждой машине под одного провайдера получили новое ускорение.

Что делать не нужно.

Не нужно использовать системные переменные для передачи параметров между MDB и вызывающим приложением — в нашем случае между сервлетом и работником. Для этого надо использовать базу данных(persistent layer). Работники будут писать свое состояние — сервлет читать и считать количество. В нашем случае, когда создание кластера не грозило, для упрощения процесса и в силу природной лени мы использовали системную переменную.

Страница: