ОБЗОРЫ
Проблема связывания отдельных частей распределенных приложений существует почти столько же лет, сколько и сама вычислительная техника. Соответственно и поколения технологий для решения этой задачи сменяются одно за другим - от общих областей памяти до современных систем MOM и средств интеграции на базе сквозных деловых процессов. О платформах интеграции задач PC Week/RE часто писал на протяжении последнего года (см. PC Week/RE, N 12/2004, с. 25)*1, но разговоры с ИТ-менеджерами показывают, что очень часто предприятие не имеет материальных и временных ресурсов и просто желания, чтобы подойти к проблеме фундаментальным образом, и предпочитает создать точечные мосты между двумя-тремя модулями распределенной системы. В данном обзоре мы рассмотрим, какие программные альтернативы имеются на сегодняшний день у разработчиков. Исключение будет сделано лишь для Web-сервисов, подробно рассмотренных в PCWeek ранее см. обзор в PC Week/RE N 27-35/2004).
_____
*1 Подробную информацию по ним можно прочитать также в отчете RC Group "Методы и средства интеграции корпоративных приложений", 2003-2004 гг.
Удаленный вызов процедур (RPC)
Remote Procedure Call (RPC) остается важной технологией, используемой для "ручного" связывания компонентов распределенных приложений. Она опирается на синхронный режим взаимодействия между двумя прикладными модулями (клиентом и сервером), т. е. работа клиента блокируется до окончания обработки задания на сервере.
Для установки связи, передачи вызова и возврата результата клиент и сервер используют специальные программные "заглушки" (client stub и server stub). Эти процедуры не реализуют никакой прикладной логики, а лишь изолируют прикладные модули от уровня сетевых коммуникаций. Обычно описания этих stub-процедур генерируются средой разработки. И клиентская, и серверная программа могут вызывать их как обычные локально-исполняемые функции. Правда, для установления соединения необходимо проделать ряд дополнительных операций как со стороны клиента, так и со стороны оболочки исполнения. Эти операции довольно типичны для всех подобных технологий, и о них будет сказано ниже.
В общем случае механизм RPC создает статические отношения между компонентами распределенного приложения: привязка клиентского процесса к конкретным серверным суррогатам происходит на этапе компиляции и сборки и не может быть изменена во время выполнения. Этим RPC невыгодно отличается от систем, ориентированных на обмен сообщениями (МОМ), позволяющих динамически выбирать сервер, или некоторых мониторов транзакций, поддерживающих возможности оптимального распределения нагрузки на серверы и средства восстановления при сбоях.
RPC очень широко используется в разных других технологиях. Например, на RPC базируется коммуникационный слой модели Windows COM/DCOM. Основной недостаток RPC-систем заключается как раз в синхронности взаимодействия, из которого вытекает необходимость установления стабильного соединения между взаимодействующими приложениями (в принципе есть надстройки над RPC, эмулирующие асинхронность, но они не дают и десятой доли преимуществ МОМ). В итоге распределенные системы оказываются чувствительны к надежности и доступности каналов связи.
Объектная модель COM/DCOM
Компонентная модель COM (Component Object Model) является наследником средств динамического связывания приложений DDE (Dynamic Data Exchange), имевшихся еще в самых первых версиях Microsoft Windows. Она позволяет разбить приложение, работающее на отдельном ПК, на компоненты, характеризуемые четко описанными интерфейсами. Так как в таком компоненте пользователю доступен только интерфейс, то при его сохранении, сохраняется и связанность компонентного приложения, даже если отдельные компоненты заменяются на другие или, скажем, переписываются на другой язык программирования. Конечно, для сохранения работоспособности приложения в целом необходимо, чтобы каждый такой компонент вел себя в точности, как его предшественник.
Вариантом COM, позволяющим строить распределенные приложения, - является DCOM (Distributed Component Object Model). Она распространяет принципы вызова удаленных процедур на объектные приложения COM. В DCOM взаимодействие удаленных объектов базируется на спецификации Distributed Computing Environment Remote Procedure Call (DCE RPC). Среда скрывает от клиента детали сетевого взаимодействия.
DCOM в отличие от RPC позволяет динамически связывать удаленные объекты: клиент может обратиться к серверу-объекту на фазе исполнения, даже если не располагает на этапе компиляции информацией об его свойствах. В частности, имеется возможность нахождения объектов на сервере.
Информацию об объектах, доступных на сервере на этапе исполнения, клиент получает из специального хранилища метаданных об объектах (Type Library), используя механизм OLE Automation. За счет этого можно менять функциональность серверов, не внося существенных изменений в код клиентских компонентов программы.
В модели DCOM допускается использовать созданную Microsoft модификацию языка описания интерфейсов IDL (Interface Definition Language) - DCE IDL, но он не играет важной роли и служит в основном для удобства описания объектов. Реальная интеграция объектов в DCOM происходит не на уровне абстрактных интерфейсов, а на уровне двоичного кода.
В Windows есть возможность группировать объекты DCOM в рамках транзакций. За это отвечает служба ОС Microsoft Transaction Server (MTS). Он предлагает все стандартные функции монитора транзакций. Важным свойством MTS является то, что свойства транзакционности задаются на уровне контейнера COM. (Кроме того, в Windows входит служба Distributed Transaction Service, отвечающая за координацию распределенных транзакций в базах данных.) MTS был одной из первых коммерческих систем, комбинировавших поддержку транзакций и компонентов. MTS лучше всего описать как контейнер для транзакционных компонентов или сервер приложений. Приложения, управляемые MTS, представляют из себя наборы COM-компонентов, оформленных в виде динамически подключаемых DLL-библиотек (Dynamic Link Libraries). С технической точки зрения есть несколько сервисов ОС, контролирующих работу инициированных компонентов COM и отвечающих на исходящие от этих компонентов вызовы. Данные сервисы и обеспечивают автоматическую поддержку транзакций, обеспечение безопасности, образование пулов соединений к БД, поддержку потоков выполнения и управление состоянием объектов.
Среда DCOM/MTS удобна для создания распределенных приложений, но она намертво привязана к платформе Windows, что не всегда приемлемо для корпоративных решений. Важные проблемы, возникающие при построении Windows-приложений, - проблемы надежности, производительности и контроля версий используемых библиотек компонентов (и связанных с ними библиотек DLL).
Стоит заметить, что в связи с переходом на платформу Microsoft .Net для построения решений корпоративного класса технологию DCOM стоит рассматривать как унаследованную и учитывать лишь с точки зрения интеграции в новые КИС большого числа написанных на ней приложений.
CORBA
В середине 90-х годов прошлого столетия для построения распределенных приложений стала применяться технология CORBA (Common Object Request Broker Architecture - общая архитектура брокера объектных запросов). Она разделяет много идей, заложенных в COM и RPC, но использует их особым образом.
Рис 1. Архитектура CORBA
Ключевым компонентом архитектуры CORBA является язык IDL, на котором описываются интерфейсы вызываемых серверных компонентов. На его базе компиляторами генерируются классы-"заглушки" (stubs) и "посредники" (proxy). Они задействуются соответственно программами на клиенте и сервере как локальные объекты, но на самом деле отвечают за посредничество в передаче обращений к удаленной системе. С их помощью обеспечивается также независимость от конкретного объектно-ориентированного языка.
Для управления серверными объектами применяется брокер запросов (Object Request Broker, ORB). В числе прочего он позволяет клиенту получать сведения о доступных объектах и их свойствах. В отличие от DCE IDL язык CORBA IDL поддерживает основные понятия объектно-ориентированной парадигмы (инкапсуляцию, полиморфизм и наследование). Есть также возможность динамического связывания удаленных объектов - ее реализует интерфейс динамического вызова DII (Dynamic Invocation Interface). Однако поддержка этого интерфейса - опциональна и зависит от реализации ORB.
Для CORBA-взаимодействий используется специальный протокол IIOP (Internet InterORB Protocol). Вся механика сетевых и объектных коммуникаций от клиента скрывается - брокер автоматизирует процессы передачи свойств объектов (marshaling/unmarshaling), технические сложности установления соединения и т. п. Однако использование специального протокола требует некоторых усилий по организации его транспорта через брандмауэры на границе корпоративной сети.
CORBA изначально нацелена на кросс-платформную поддержку. Ее реализации имеются для всех разновидностей Unix, Windows и многих других важных ОС. В этом - ее главное преимущество перед объектной моделью Microsoft. Но часто эти реализации сильно различаются, т. е. они не до конца интероперабельны. Стандарт определяет почти два десятка служб брокера запросов, из которых часто реализуется в брокерах лишь 3-4 ключевых. Наиболее известные на сегодня продукты: VisiBroker и Enterprise Server компании Borland, BEA Tuxedo и IONA Orbix (подробно познакомиться со списком доступных на рынке брокеров и поддерживаемыми ими сервисами можно на сайте www.puder.org/corba/matrix/).
Механизм динамического вызова CORBA сложен в реализации. А ввиду недостаточной интегрированности с традиционными средствами разработки он долго не мог получить широкого признания, на которое претендовали его создатели. Кроме того, ORB-системы, как и RPC, ориентированы на синхронную связь. На сегодня CORBA имеет большое унаследованное значение, но новые распределенные приложения чаще разрабатываются на J2EE и Microsoft .Net. Заметна и тенденция конвергенции CORBA в Java-платформу (см. следующий раздел).
RMI: синхронное взаимодействие в Java
В языке программирования и платформе Java изначально встраивались средства для синхронного удаленного вызова методов RMI (Remote Method Invocation), по сути своей очень похожие на CORBA. Как и в CORBA, в RMI используются свои "заглушки" и "каркасы" (описания интерфейсов объектов), брокер запросов RMI.
Упрощенная последовательность шагов для связывания модулей программы выглядит примерно следующим образом. Необходимо определить интерфейс дистанционно вызываемого объекта как производный от стандартного Java-интерфейса java.rmi.RemoteException, а затем реализовать (т. е. написать логику работы) методы этого интерфейса в нужном объекте. Затем на основе интерфейса удаленного доступа сгенерировать (при помощи утилиты rmic) RMI-заглушку для клиента*1. Во время запуска серверного приложения необходимо зарегистрировать класс на сервере имен.
_____
*1 В ранних версиях RMI использовался еще и специальный "каркас" для сервера, но в последних версиях он больше не требуется
Клиент с помощью службы имен JNDI получает ссылку на экземпляр удаленного объекта и преобразует ее к типу интерфейса удаленного объекта. Затем клиент обращается с полученным интерфейсным объектом как с локальным. Класс-посредник должен при этом присутствовать в пакете клиентского приложения - он отвечает за преобразование вызовов и отсылку пакетов на удаленный сервер.
В роли параметров вызываемых на клиенте методов могут выступать Java-объекты. Поддерживается передача как по ссылке, так и по значению. Посредник и RMI-сервер скрывают от программиста сложности сериализации и десериализации объектов-параметров. В этом смысле RMI аналогичен Microsoft .Net Remoting. (В принципе CORBA 2.3 также поддерживает данные механизмы, но использовать функционал CORBA гораздо сложнее.) Еще одно сходство RMI и .Net Remoting состоит в возможности активизации по запросу клиента объекта, уже давно существующего на сервере.
Для связи RMI использует собственный коммуникационный протокол JRMP. Обычно он работает поверх транспортного протокола TCP, но могут быть исключения, например сервер BEA WebLogic применяет фирменный протокол T3.
Важно отметить конвергенцию CORBA и RMI. Брокер, удовлетворяющий стандарту CORBA 2.3.1, является частью Java 2 Platform, Standard Edition, v1.3, причем он тоже написан на Java и потому является переносимым. Он может также взаимодействовать с другими CORBA 2.3.1-совместимыми брокерами. Но главное, брокер поддерживает одновременно и вызовы компонентов по протоколу IIOP, и вызовы по RMI. При этом можно организовать взаимодействие между двумя Java/RMI-платформами через IIOP, что часто предпочтительно с точки зрения туннелирования трафика через брандмауэр. Пользователь Java также избавлен от необходимости делать какие-либо дополнительные лицензионные платежи для использования CORBA.
Поддержка CORBA есть и в J2EE, а стало быть, в серверах Web-приложений корпоративного класса, например WebLogic 8.1. Используя функцию RMI-IIOP, программист может при помощи RMI API обратиться к CORBA-северу. Это позволяет вызывать из компонента Enterprise Java Beans (EJB) удаленные объекты, написанные как на Java, так и на других CORBA-совместимых языках. Можно также вызывать объекты EJB из сторонних программ, воспользовавшись сервисами CORBA. Для этого необходимо сгенерировать их IDL-интерфейсы и интерфейсы-посредники при помощи утилиты rmic.
BEA WebLogic предлагает еще одну новую технологию - динамические объекты-посредники, которые позволяют устранить необходимость генерации классов посредников на этапе разработки приложения. Они представляют собой сериализуемые классы, передаваемые через сеть клиенту, когда тот находит нужный объект путем запроса к RMI-реестру. Как и в случае со статическими proxy, клиент работает с ними, как с обычными локальными объектами. Посредники же сериализуют запросы клиента и переправляют их в WebLogic Server.
Остается проблема, когда и как генерировать подобные динамические прокси-классы. Сервер Weblogic позволяет делать это во время исполнения, когда происходит регистрация удаленного объекта. Компилятор weblogic.rmic "на лету" выявляет реализованные классом интерфейсы, определенные как производные от интерфейса дистанционного доступа, и продуцирует весь необходимый дополнительный байт-код. Он также создает вспомогательный серверный байт-код, отвечающий за десериализацию запросов клиента и передачу их на исполнение методам реального объекта, а также сериализацию результатов и возврат их обратно посреднику клиента.
Иначе говоря, все, что нужно для создания приложения, - это просто зарегистрировать в реестре объект, реализующий дистанционно доступный интерфейс.
Надо сказать, что несмотря на подобные ухищрения, технология RMI оказалась слишком низкоуровневой и сложной для непосредственного построения на ее базе распределенных приложений и де-факто была скрыта Java-технологией корпоративных объектов Enterprise Java Beans (EJB), а именно их контейнерами.
JMS: асинхронное взаимодействие в Java
Вторая важная технология связывания Java-приложений называется Java Messaging Service (JMS). Она предлагает обобщенную модель и набор интерфейсов для средств гарантированной доставки сообщений.
Рис. 3. JMS: архитектура программных объектов
JMS позволяет связать компоненты, работающие под управлением разных Java-машин асинхронным образом. Как правило, в качестве провайдера функций JMS служат какие-либо из существующих платформ MOM, например WebSphere MQ корпорации IBM или JES Message Queue Enterprise корпорации Sun Microsystems. Фактически она является модификацией технологии MOM, о которой речь пойдет ниже, в применении к платформе Java.
Спецификация JMS обеспечивает универсальный Java API, позволяющий разработчикам писать приложения, не заботясь о том, какое конкретно транспортное ПО будет использоваться. JMS позволяет передать Java-объект целиком, не думая об его преобразовании в подходящий для передачи формат (средства сериализации). Но при этом она только определяет порядок доступа к корпоративной системе обмена сообщениями, а каждый производитель JMS-ПО самостоятельно разрабатывает инструменты для администрирования среды подобного обмена.
Благодаря асинхронности JMS обеспечивает существенно большую независимость от обрывов канала связи, а также масштабируемость системы. В последних спецификациях появились требования к реализациям по распределению нагрузки, отказоустойчивости, обработки ошибок. JMS включен в J2EE как стандартный компонент начиная с версии 1.3.
Современные реализации JMS опираются на понятие фабрик соединений и конечных адресатов. Имеющиеся средства администрирования позволяют привязать эти объекты к системе имен Java Naming Directory Interface (JNDI). Клиент может сделать запрос к серверу JNDI и получить по осмысленным для человека именам ссылки на фабрику соединений и пункт назначения сообщения. С помощью этих ссылок он создает сначала соединение, а затем и сессию связи с конкретным адресатом и начинает отправлять ему сообщения. Поддерживаются также и неявные схемы доставки - публикации - подписки, которые характерны для брокеров сообщений.
Спецификация требует от провайдеров обеспечения поддержки многих функций, включая гарантированную доставку, временное хранение сообщений на постоянном носителе, отсылки групп сообщений (локальная транзакционность) и пр. И эти их качества становятся типовыми. Однако большой люфт в методах реализации спецификации остается - например, приоритет обслуживания лишь предлагается учитывать и он может и не поддерживаться менеджером очередей. Аналогичным образом указание времени жизни сообщения, указываемое при его отправке, не является командой для менеджера очередей, и клиенту не запрещается принять устаревшее сообщение.
В заключение стоит сказать, что основной трудностью при работе с Java-ориентированными продуктами естественно является требование использования языка Java и связанной с ним платформы исполнения байт-кода (виртуальной машины), что не всегда желательно ввиду возможного повышения гетерогенности КИС в целом и необходимости приема на работу сотрудников с дополнительными трудовыми навыками.
Microsoft .NET Remoting
.Net Remoting - новейшая технология связывания распределенных приложений, предложенная корпорацией Microsoft. Она обеспечивает вызов методов удаленных объектов, находящихся под управлением среды Microsoft .Net. Поддерживается множество услуг, таких, как активация удаленных объектов, контроль времени их существования, взаимодействие между удаленными объектами через различные транспортные каналы.
Рис. 2. Архитектура .Net Remoting
Во многом .Net опирается на тот опыт, что был накоплен за много лет создания распределенных приложений на базе RPC, CORBA, DCOM и EJB. В архитектуре .Net Remoting также выделяют клиентскую и серверную машину. Сервером является хост, отвечающий на запрос, а клиентом - хост, его отправляющий. Однако в отличие, скажем, от EJB это разделение относительно условно - в любой момент роли могут быть изменены. В этом смысле она похожа на технологию Web-сервисов.
Как и в RPC и CORBA, клиент локально работает только с классом-посредником (proxy). Этот класс генерируется средой одним из трех способов: либо на основе экземпляра кода удаленного класса, либо на основе класса, содержащего описания интерфейсов удаленного класса (но не код его логики), либо специальным инструментом на основе получаемого с дистанционного сервера описания Web-сервиса.
Вкратце схема взаимодействия выглядит следующим образом: в сообщении, отсылаемом клиентом серверу, классы-посредники кодируют название вызываемого метода удаленного объекта и все входящие переменные. На сервере сообщение раскодируется (т. е. определяется название метода и все входящие параметры) и выполняется реальный метод. Чтобы передать какие-либо данные на сервер, достаточно вызвать метод класса-посредника в качестве аргументов метода, взяв эти данные. Например, можно передавать любые двоичные данные или строки текста. Сервер, в свою очередь, аналогичным образом может передать клиенту возвращаемое значение метода - оно будет раскодировано на клиенте через класс-посредник. В этом отношении .Net Remoting напоминает сериализацию Java-объектов, применяемую, в частности, в JMS.
Отличительной особенностью .Net Remoting является наличие нескольких четко разделенных слоев, отвечающих за сокрытие от пользователя сложностей дистанционного взаимодействия с объектом. Первым из них является слой "прозрачных" посредников (Transpa-rentProxy), отвечающих за упаковку всех параметров удаленного вызова в объект-посылку IMessage*1. Сформированная посылка передается в "настоящий" посредник (RealProxy), который уже и передает ее на удаленный сервер. Все эти классы заранее заданы средой .Net, но пользователь может расширять класс RealProxy, например, для подключения своих средств безопасности.
_____
*1 Для того чтобы параметр мог быть упакован подобным образом, его класс должен реализовывать интерфейс ISerializable.
Для взаимодействия с коммуникационным слоем RealProxy опирается на каналы. В канале важны два элемента - формовщик (formatters) и транспортировщик (transport sink). Формовщик отвечает за преобразование сообщения IMessage в пакеты данных протокола высокого уровня. В стандартном варианте .Net содержится два формовщика: двоичный и SOAP. Транспортировщик решает проблему доставки этих пакетов на более низком сетевом уровне - для стандартной редакции .Net это TCP и SOAP.
Таким образом, доступны два стандартных вида взаимодействия (пользователем могут быть описаны и иные): для взаимодействия по двоичному каналу через TCP и пересылки запросов к удаленным объектам в виде сообщений SOAP поверх HTTP. В первом случае достигается наибольшая производительность, но ценой утраты значительной части кросс-платформенности. Он подходит для построения приложений в локальных сетях. Во втором случае методы удаленного объекта видны как Web-сервисы, обращение к которым может происходить через Интернет и границу, определенную брандмауэром. При этом может использоваться любой транспортный протокол третьего уровня модели OSI, а не только IP, как в первом случае. Однако для его реализации требуются большие вычислительные и сетевые ресурсы, нежели для случая двоичной связью.
Протокол, который обращается к серверному приложению для доступа к своим объектам, настраивается при его запуске. Сначала регистрируется канал связи, затем как подключенные к нему регистрируются доступные дистанционные объекты. При регистрации канала указывается транспортный протокол (TCP, HTTP и пр.), протокол доступа (двоичный, SOAP и др.) и номер порта, по которому сервер будет принимать запросы.
В .Net различаются два типа объектов - активизируемые сервером и клиентом. Объекты, активизируемые клиентом, находятся под управлением менеджера контроля жизненного цикла, гарантирующего, что по истечении определенного срока действия объекта (срока аренды, в терминологии Microsoft) будет произведена необходимая очистка памяти. Среда предоставляет развитые средства для контроля за этой арендой, в том числе и со стороны самого объекта. Объекты, активизируемые сервером, делятся на объекты для однократного обращения (Single call) и "единичные" (Singleton). Экземпляры однократных объектов создаются в момент обращения к их методам, "единичные" объекты могут существовать долго и сохранять состояние между вызовами их методов.
Все настройки свойств объектов (типы объектов, каналы, номера портов) можно сохранить в конфигурационном XML-файле, благодаря чему перестройка приложения становится совсем простой.
Число типов объектов в .Net Remo-ting существенно меньше, чем в EJB. Например, отсутствуют Persistent-объекты, связанные с записями в базах данных. Но для модели вычислений, принятой в .Net, это не нужно. Нет также средств обеспечения транзакционности на уровне контейнера, наличествующих в серверах приложений EJB. Но часто подобные расширения создают лишь дополнительные сложности, не давая программистам никакой экономии сил. Например, создание и регистрация объекта EJB - очень трудоемкая вещь, а все, что нужно для создания дистанционно доступного класса .Net Remoting, - это определить его как класс, производный от класса MarshalByRefObject.
В заключение стоит отметить, что .Net Remoting совместим с иными технологиями удаленного доступа, например COM/DCOM (через средства самой Microsoft), а благодаря поддержке открытых стандартов, наподобие XML и SOAP, можно теоретически организовать взаимодействие приложениями на других платформах, в первую очередь Java.
Важной особенностью .Net Remoting является то, что она не ориентируется исключительно на синхронное взаимодействие, а при применении SOAP-транспорта настраивается и на асинхронный режим работы. Это означает, что она может быть применена в сочетании со средствами гарантированной доставки сообщений для обеспечения максимальной надежности системы в целом. Microsoft обещает в будущей платформе Indigo совместить средства транзакционности, гарантированной доставки и удаленного вызова под одной "крышей".