Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Java EE (J2EE) и Spring > Доступ к внешним системам и механизм глобальных


Автор: ekr 20.8.2007, 17:41
Disclaimer
Цель этой статьи - дать общее представление и систематизировать знания о процессах взаимодействия с внешними ресурсами и управления глобальными транзакциями из j2ee-приложений. Статья ориентирована на начинающих j2ee-разработчиков.
Более подробно эта и другие темы раскрываются в курсах по направлениям java и j2ee, проводимых на площадке Люксофта. Презентации курсов я выкладываю по адресу http://courses.4shared.com в разделе courses. В данной статье используются материалы курса по JDBC API.

Введение
В статье речь пойдет об одном из наиболее востребованных сервисов платформы j2ee - сервисе JTA (Java Transaction API). Сервисы платформы j2ee - это уже реализованный функционал, являющийся частью j2ee-контейнера. Задача j2ee-сервисов - снять с разработчика приложений инфраструктурные задачи с тем, чтобы он концентрировался только на реализации бизнес-логики.

Процесс взаимодействия с внешними ресурсами из j2ee-приложений
Большинство приложений так или иначе взаимодействуют с внешними системами для получения, обработки и сохранения данных. Наиболее распространенные типы внешних систем: СУБД, JMS, внешние корпоративные системы (КИС/EIS). Соответственно, для каждого из типов предусмотрен свой API доступа:
  • для СУБД - JDBC API (Java Database Connectivity)
  • для JMS - JMS API (Java Messaging Service)
  • для EIS - J2CA API (Java2 Connector Architecture), циферка 2 добавлена, чтобы не было путаницы с JCA - Java Cryptography Architecture ;-)
Взаимодействовать с внешними системами из приложения можно напрямую или с использованием соответствующего сервиса.
Взаимодействие напрямую с внешней системой подразумевает работу с ней с использованием двухзвенной схемы клиент-сервер (приложение-клиент взаимодействует с внешней системой-сервером). при этом используется соответствующий API, в клиенте инкапсулируется информация о местоположении системы и учетная запись доступа.
Но есть более удобный способ - воспользоваться j2ee-сервисом доступа. Этот сервис - промежуточное звено между клиентом и внешней системой. Что же такого полезного реализует этот пресловутый сервис?
  • Сервис сам по себе доступен клиенту через тот же API, что и скрываемая за ним внешняя система.
  • Сервис настраивается администратором j2ee-сервера. Такое разделение ролей админа и разработчика позволит резко повысить поддерживаемость приложения: админ может изменять расположение внешней системы и учетную запись доступа к ней без модификации приложения.
  • Сервис обеспечивает пулирование соединений с внешней системой. Это значит, что сервис заранее открывает кучу соединений (т.н. пул соединений) с внешней системой. Теперь при использовании сервиса когда приложению понадобится соединение, то оно попросит соединение у нашего сервиса и получит уже открытое соединение, т.е. не будет тратить время на его установку.
    Почему это так важно и когда следует пользоваться сервисом в обязательном порядке: дело в том, что для stand-alone клиентов (которые на рабочих местах пользователей) время получение соединения не так критично. Тетя-бухгалтер щелкает кнопочку в своем fat-клиенте, при обработке нажатия она подождет пол-секунды и не расстроится ;-) Одна тетя - одно приложение.
    А вот если приложение работает на сервере, т.е. на него приходится множество жаждущих клиентов (много теть - один сервлет), то эти пол-секунды установки соединений выливаются в большие проблемы с нагрузочной масштабируемостью.
Резюмируя возможные комбинации вида "тип клиента - сервис доступа", можно нарисовать следующую картинку для любых технологий:
user posted image
Небольшое терминологическое отступление: в общем случае промежуточные системы, через которые производится доступ к СУБД, называются DB middleware. Но т.к. мы говорим о платформе j2ee, то эту роль у нас будет играть jdbc-сервис.
Таким образом, предыдущая картинка с учетом специфики платформы j2ee будет выглядеть так:
user posted image
В дальнейшем мы будем подразумевать работу с внешними системами именно через сервисы. В описаниях будет подразумеваться JDBC, если не указано иное.

Реализация сервисов доступа к внешним системам.
Как же устроены эти сервисы и как разработчику приложений работать с ними?
Технически сервис представляет из себя совокупность Resource Managers (RM) - менеджеров ресурсов. Настраивает эти менеджеры, как правило, администратор j2ee-сервера (есть еще вариант автоматической настройки при развертывании приложения, но это детали). RM представляет из себя совокупность следующих компонентов: пула соединений (connection pool) и фабрики соединений (connection factory).
Давайте рассмотрим роль и механизм настройки этих компонентов:
  • Пул соединений.
    Задача пула - минимизировать время получения соединения с внешней системой из приложений.
    Для этого контейнер заранее открывает несколько соединений (пул) и по требования приложения отдает уже открытое соединение. Приложение не тратит время на получение соединения.
    При этом пул, отдав соединение клиенту, помечает его как используемое и не будет выдавать его другим клиентам. Когда клиент закрывает соединение, оно не закрывается физически, а всего лишь помечается как вновь свободное.Вопрос 1: как этого можно добиться? Как можно перехватить метод закрытия соединения, чтобы оно не закрывалось, а помечалось как свободное?
    Какие настройки необходимы? Пул выступает непосредственным клиентом для СУБД, поэтому его необходимые настройки аналогичны настройке простого клиента для СУБД: местоположение СУБД (т.н. JDBC-URL или DB-URL) и учетная запись, под которой пул аутентифицируется перед СУБД (так же есть возможность указывать учетную запись непосредственно при получении соединения из приложения).
    Так же необходимо указать используемый класс jdbc-драйвера, тем самым, по сути, определив тип используемой СУБД.
    Какие настройки достаточны?
    Помимо необходимых настроек, различные производители контейнеров или разработчики классов пулов предлагают так же возможность тонкого тюнинга пула: начальный и максимальный размер пула; таймауты на получение и удержание соединения; connection leak detection и многое другое.
    user posted image
  • Фабрика соединений.
    Клиент не работает с пулом напрямую. Для получения соединений он использует фабрику.
    Фабрика (Factory) - очень популярный шаблон проектирования (design pattern). Используется в тех случаях, когда необходимо инкапсулировать логику создания/получения некоторого объекта или их группы.
    Задача фабрики - скрыть сложность и обеспечить клиентам единую точку получения соединений. Классы пула и фабрики являются частью контейнера (или внешним продуктом, что реже). Поэтому администратору при создании RM достаточно только настроить пул и фабрику.
    Т.к. одной из задач фабрики является обеспечение единой точки получения соединений, возникает вопрос: где клиент найдет фабрику? Специально для этих целей j2ee-контейнер предлагает сервис именования, доступный через JNDI API.
    Сервис именования - один из предоставляемых j2ee-контейнером сервисов. Он предназначен для хранения объектов, необходимых приложениям. К этим объектам можно отнести фабрики соединений и EJB. Хранение объектов в сервисе именования организовано в виде дерева, поэтому приложению необходимо знать путь (aka jndi-name) нужного объекта в дереве. Так же сервис именования часто называют jndi-сервисом, jndi-деревом.
    Поэтому клиенту необходимо сначала получить фабрику из сервиса именования, а затем получить у неё соединение с внешним ресурсом.
    user posted image
    Какие настройки необходимы? Администратор, настраивая фабрику, дожен указать пул, поверх которого устанавливается фабрика, и jndi-имя этой фабрики, по которому её будут искать приложения.
    Еще одна важная задача фабрики - обеспечить измененное поведение соединений.
    На самом деле фабрика выдает не native jdbc connection, класс которых настраивается в пуле, а класс-обертку. Так сделано, чтобы изолировать клиента от типа СУБД и модифицировать поведение соединений. Например, клиентский вызов метода закрытия соединения не должен приводить к закрытию, а только к пометке соединения как вновь свободного (см. Вопрос 1). Еще один пример необходимости модифицированного поведения будет рассмотрен позже при обсуждении эмуляции интерфейса XA в драйверах, его не поддерживающих.
    Приняты следующие названия фабрик соединений для различных типов ресурсов:
    • JDBC - DataSource
    • JMS - JMS Connection Factory
    • J2CA - J2CA Connection Factory
    Резюме
    Резюмируя, можно нарисовать следующие схемы работы приложения с RM:
    user posted image
    user posted image

    Что дальше?
    Во второй части статьи будут рассмотрены: механизм глобальных транзакций, интерфейс XA, JTA API.

Вторая часть выложена на http://ekrs.blogspot.com/2007/10/j2ee-2.html.

Автор: YuG 21.8.2007, 11:15
ekr, очень интересно, жду 2-ю часть... )

Автор: COVD 22.8.2007, 17:26
Полезное начинание и оформлено красиво. Стал читать именно с целью получить "общее представление". Но сразу возникло много вопросов. 

В начале вводится понятие сервиса на примере пула соединений к базе данных (а применяют ли пулы соединений кроме как для базы данных?). Эта стандартная вещь наверное входит в состав EJB сервера. Какая польза от выделения этого компонента в отдельный сервис? EJB сервер тоже кто-то настраивает. Может быть, этих серверов несколько, и тогда они будут использовать общий сервис? Или серверов приложений нет вообще и пользователи напрямую в базу лезли (своими jtable  smile ), а тут им предлагается пул. И в предположении, что это все очевидно, дальше сразу фабрики, настройки, транзакции,...   

Автор: ekr 22.8.2007, 17:57
Цитата(COVD @  22.8.2007,  17:26 Найти цитируемый пост)
а применяют ли пулы соединений кроме как для базы данных?

да, конечно, для описанных типов ресурсов: jms-соединения и соединения с внешними КИС и других.

Цитата(COVD @  22.8.2007,  17:26 Найти цитируемый пост)
Эта стандартная вещь наверное входит в состав EJB сервера

если быть точным, то или в состав j2ee-сервера, или как отдельная библиотека.
отступление: j2ee-сервер структурно состоит из 1. реализаций сервисов, 2. web- и 3. ejb-контейнера.

Цитата(COVD @  22.8.2007,  17:26 Найти цитируемый пост)
Какая польза от выделения этого компонента в отдельный сервис?

тут, в j2ee,  так принято ;-) (С)старый анекдот
а если серьезно, то как по-другому?

Цитата(COVD @  22.8.2007,  17:26 Найти цитируемый пост)
Может быть, этих серверов несколько, и тогда они будут использовать общий сервис?

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

Цитата(COVD @  22.8.2007,  17:26 Найти цитируемый пост)
Или серверов приложений нет вообще и пользователи напрямую в базу лезли (своими jtable  smile ), а тут им предлагается пул

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

Цитата(COVD @  22.8.2007,  17:26 Найти цитируемый пост)
И в предположении, что это все очевидно, дальше сразу фабрики, настройки, транзакции,...

невозможно удовлетворить сразу всех и учесть их текущий уровень))
поэтому удовлетворяю тех, кто спрашивает ))

COVD, спасибо за вопросы. 
значит затеяно все не зря )))
буду рад ответить на вновь возникающие вопросы

Автор: AntonSaburov 22.8.2007, 18:39
Думаю, что тема достойна повисеть в вверхней части форума - спасибо большое за полезное начинание.

Автор: ekr 22.8.2007, 21:12
будем стараццо )))

Автор: COVD 23.8.2007, 15:38
Цитата

отступление: j2ee-сервер структурно состоит из 1. реализаций сервисов, 2. web- и 3. ejb-контейнера.


Теперь понятно - вы рассматриваете один (или несколько) сервисов, входящих в типовой j2ee сервер. Спасибо.

Цитата

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


Как я предполагаю, напрямую - это уже не j2ee технология (или все еще j2ee ?), а так , вообще (тут на форуме регулярно вопросы задают, как соединить апплет с базой данных). 

Цитата

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


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


Автор: ekr 23.8.2007, 22:43
Цитата(COVD @  23.8.2007,  15:38 Найти цитируемый пост)
Цитата
Как я предполагаю, напрямую - это уже не j2ee технология (или все еще j2ee ?), а так , вообще (тут на форуме регулярно вопросы задают, как соединить апплет с базой данных). 

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

Цитата(COVD @  23.8.2007,  15:38 Найти цитируемый пост)
т.е. напрямую - это когда клиент работает с сервером (СУБД - прим. науч. ред ;-), но при этом клиенту зачем-то  нужно знать о существовании внешних систем и иметь учетные записи. 

при двухвенной схеме все это надо знать клиенту.
представим разработку тяжелого (fat) клиента для СУБД. ведь этой программе надо знать, где располгается СУБД и логин/пароль к ней?

Автор: COVD 23.8.2007, 23:50
Понятно. В данном контексте сервер - это СУБД. 

Cпасибо.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)