Технология Клиент-Сервер 2002'4 |
|||||||
|
Александр Цимбал
Интерсепторы (interceptors), по сути, являются callback-методами, зарегистрированными программистом в ORB. Эти методы автоматически вызываются ORB'ом при выполнении тех или иных действий.
Интерсепторы являются очень важной частью CORBA, хотя обычный, "прикладной" программист имеет дело с ними нечасто. Возможно, причиной является еще и то, что спецификация интерсепторов появилась в CORBA недавно. До этого интерсепторы использовались разработчиками реализаций CORBA, так сказать, в инициативном порядке. Спецификация интерсепторов в версиях 2.3 и 2.4 выглядит достаточно бледно. Только в CORBA 3 появилась подробная и хорошо продуманная спецификация (так называемые "Переносимые интерсепторы" – Portable Interceptors).
Для чего могут потребоваться интерсепторы? Для ответа на этот вопрос нужно сначала рассмотреть некоторые аспекты взаимодействия ORB, сервисов CORBA, клиентских и серверных приложений.
Для возможности обращения к удаленному объекту с помощью технологии CORBA прежде всего необходимо создать на стороне сервера CORBA-объект. За создание объекта отвечает объектный адаптер. В настоящий момент существует единственная современная спецификация объектного адаптера – POA (Portable Object Adapter). Прежде, чем приступить к созданию CORBA-объектов, нужно создать должным образом настроенный POA. Делается это с помощью набора опций или "политик" (policies). Настройки POA влияют на вид создаваемых CORBA-объектов.
Реальным результатом создания CORBA-объекта является создание объектной ссылки на этот объект. Объектная ссылка - это совокупность информации, которая нужна для получения доступа к нужному серверному объекту. Давайте рассмотрим структуру объектной ссылки CORBA. Для краткости мы будем говорить о формате объектной ссылки при использовании протокола GIOP 1.2. Под "объектной ссылкой" мы везде будем понимать объектную ссылку в формате IOR - Interoperable Object Reference. Воообще-то объектная ссылка в тех случаях, когда она не выходит за пределы одной реализации ORB, может существовать в различных форматах – так, как это удобно авторам данной реализации. Но если возникает потенциальная возможность передачи объектной ссылки другому ORB'у, объектная ссылка из "внутреннего" произвольного формата должна быть преобразована к формату IOR.
Удобнее всего описать ссылку на языке IDL. Главной ее особенностью является то, что с помощью одной объектной ссылки можно получить доступ к серверному объекту с использованием различных транспортных протоколов, "поверх" которых реализован протокол GIOP. Естественно, параметры для различных транспортов должны быть различными (например, для TCP/IP естественно ожидать задания IP-адреса и номера порта, которые характеризуют серверное приложение). Совокупность параметров, характерных для того или иного транспортного протокола, называется "профилем" (profile). Объектная ссылка может содержать от одного до нескольких профилей.
module IOP { // IDL typedef unsigned long ProfileId; struct TaggedProfile { ProfileId tag; sequence <octet> profile_data; }; // Interoperable Object Reference является последовательностью // (sequence) профилей для различных протоколов; кроме того, она // содержит строковый идентификатор типа (type ID) - Репозитарный // Идентификатор реализуемого интерфейса. struct IOR { string type_id; sequence <TaggedProfile> profiles; }; // В свою очередь, профиль может содержать несколько элементов // (компонентов). typedef unsigned long ComponentId; struct TaggedComponent { ComponentId tag; sequence <octet> component_data; }; typedef sequence<TaggedComponent> TaggedComponentSeq; };
Спецификация оговаривает некоторые стандартные значения тегов профилей (ProfileId) и компонентов (ComponentId), например...
Взаимодействие клиентов и серверов в CORBA осуществляется, естественно, с помощью отправки запросов в соответсвие с требованиями протокола GIOP. Протокол предусматривает восемь различных типов сообщений, основными из которых являются два: Request (посылка запроса) и Reply (ответ на него). Их мы рассмотрим ниже подробнее...
Главное назначение интерсепторов – обеспечение возможность перехвата и обработки выполняемого с помощью ORB'а удаленного вызова в интересах того или иного сервиса CORBA (в том числе вашего собственного). Основные программные модели, для которых используются интерсепторы, оговорены в спецификации. Это:
Добавление специфических для того или иного сервиса CORBA компонентов (Tagged components) в объектную ссылку. Для этой цели используются интерсепторы типа IORInterceptor;
Создание необходимых политик для нужд того или иного сервиса. Для этого используются объекты типа PolicyFactory, оговоренные с спецификации интерсепторов;
Перехват посылаемого запроса, анализ информации в нем и передача информации из контекста клиентского запроса в контекст того или иного сервиса CORBA. Ранее было сказано, что контексты сервисов (IOP::ServiceContext) кодируются в виде структуры, содержащей целочисленный признак и массив байтов. Следовательно, нужен механизм извлечения нужной информации из контекста запроса и посещения ее (в преобразованном к массиву байтов виде – в так называемом CDR-формате) – в контекст сервиса (если это необходимо). Для этого используются Request-интерсепторы, интерфейс PortableInterceptor::Current и интерфейс кодирования/декодирования IDL-типов данных в CDR-представление и обратно (интерфейс IOP::Codec);
Перехват обработки запроса на стороне сервера. Здесь выполняются действия, обратные тем, что характерны для отправки запроса на клиенте, а именно, извлечение информации из контекста сервиса CORBA и передача ее контексту обработки запроса в серверном приложении.
Перехват отправки отклика на запрос клиенту.
Даже если вы не собираетесь создавать свой специфический сервис CORBA, изменять объектные ссылки, оговаривать, передавать и обрабатывать свои сервисные контексты, интерсепторы все же могут быть полезны, например, для:
создания мониторов анализа трафика в сети и определения уровня загрузки CORBA-серверов, а также сбора статистики о выполняемых в системе вызовах;
для реализации своих собственных механизмов перераспределения нагрузки между серверами и обеспечения устойчивости к сбоям.
Интерсепторы вызываются в случае передачи запроса по ORB. Если запрос передается локально (клиентский и серверный объект находятся в одном приложении, и выход на уровень ORB не выполняется), то интерсепторы вызваны не будут.
Интерсептор, перехватывающий запрос, может вызвать исключение, воспрепятствовав, тем самым, доставке запроса на сторону сервера (или ответа на запрос на сторону клиента).
Интерсептор может перенаправить перехваченный запрос другому серверному объекту.
Интерсептор, "перехватывающий" запрос, не может изменять ни значения параметров, заданных клиентом (т.е. in-аргументов), ни значения out-параметров запроса или возвращаемого результата.
Интерсепторы, "перехватывающие" запрос, не связаны друг с другом и не должны знать о существовании друг друга.
Интерсептор, "перехватывающий" запрос, может перед тем, как позволить выполниться текущему запросу, выполнить свой собственный запрос к тому же или другому объекту.
Ни клиентское, ни серверное приложение не обязаны знать о существовании интерсепторов.
Спецификация Переносимых Интерсепторов оговаривает два вида интерсепторов: Request-интерсепторы и IOR-интерсепторы.
Request-интерсепторы служат для "вмешательства" в процесс передачи информации по ORB в интересах некоторого сервиса CORBA (стандартного или написанного вами). Это вмешательство необходимо для того, чтобы передавать специфическую для сервиса информацию (в виде IOP::ServiceContextList) между клиентами и серверами. Такие интерсепторы используются, например, сервисами Транзакций (OTS) и Безопасности CORBA. Клиент вызывает удаленный метод. Если вызов выполняется в контексте глобальной транзакции и/или с использованием системы обеспечения безопасности, то наряду с параметрами, заданными клиентом, нужно передать в виде контекста(ов) соответствующего сервиса дополнительную информацию – например, контекст текущей транзакции. Для этого необходимо перехватить клиентский запрос, чтобы добавить в заголовок GIOP-запроса соответствующую информацию. На стороне сервера нужно перехватить поступивший запрос (вместе с контекстом транзакции) и передать ее серверу (контексту сервера), чтобы обработчик запроса мог получить запрос к этому контексту транзакции – например, чтобы вызвать для него метод rollback_only.
IOR-интерсепторы предназначены, в первую очередь, для внесения необходимых для некоторого сервиса изменений в структуру объектных ссылок. Более конкретно, они работают с TaggedComponents – элементами профилей, описывающих те или иные аспекты организации взаимодействия, формализованные в виде данных, находящихся в самой объектной ссылке. Для работы с IOR-интерсепторами необходимо очень глубокое понимание деталей "внутренней" механики CORBA.
Существуют два вида request-интерсепторов – на стороне клиента и на стороне сервера.
Для каждого из видов определены так называемые "точки срабатывания" – этапы выполнения удаленных запросов, на которых происходит вызов ORB'ом зарегистрированных интерсепторов. Точки срабатывания делятся на три группы:
начальные (starting). Только одна из начальных точек может быть задействована в процессе выполнения конкретного удаленного вызова.
конечные (ending). Как и в случае с начальной точкой, только в одной конечной точке может произойти вызов интерсептора для данного удаленного вызова.
промежуточные (intermediate). Для текущего запроса может произойти любое число вызовов интерсепторов в промежуточных точках срабатывания.
Для request-интерсепторов определено по 5 точек срабатывания на стороне сервера и клиента (рисунок 1)
Рисунок 1.
Рассмотрим сначала точки срабатывания для клиента...
ORB на стороне сервера вызывает зарегистрированные IOR-интерсепторы в трех случаях:
при формировании списка компонентов (TaggedComponents), которые будут включены в профиль (или профили) для объектной ссылки. Для POA это обычно выполняется при вызове метода POA::create_POA;
при изменении состояния менеджера объектных адаптеров;
при изменении состояния объектных адаптеров.
В этом разделе будут рассмотрены основные интерфейсы спецификации Переносимых интерсепторов...
Спецификация переносимых интерсепторов позволяет контролировать процессы, протекающие на уровне ORB при выполнении удаленных вызовов, а также создавать свои собственные сервисы. Регистрация request-интерсепторов как на стороне клиента, так и на стороне сервера может быть выполнена так, что не требуется вносить никаких изменений в код клиентских или серверных приложений.
Copyright © 1994-2016 ООО "К-Пресс"