Интернет-журнал "Домашняя лаборатория", 2007 №6
Шрифт:
• Recorder
Во многом роль Recoder ясна из вышеизложенного. Это специальный прокси, который принимает все вызовы методов данного интерфейса данного асинхронного компонента и записывает их все в одно MSMQ сообщение. В это же сообщение записывается CLSID асинхронного компонента, который должен обработать вызовы на получающей стороне.
Только после того, как все вызовы данного интерфейса со стороны клиента выполнены (клиент освобождает ссылку на интерфейс асинхронного компонента и подтверждает завершение транзакции), во время своей деактивации Recoder отправляет (через MSMQ) построенное сообщение в очередь назначения принимающего приложения. Именно это приложение содержит данный асинхронный компонент, а имя
Выше уже обсуждались вопросы безопасности в MSMQ. В случае асинхронных компонент все проще. Как правило, Recoder выполняется в процессе клиента и имеет одинаковый с клиентом SID. SID клиента записывается Recorder в сообщение. MSMQ при отправке этого сообщения приписывает к нему дополнительно SID отправителя, т. е.
Recorder. Клиент потенциально может сфабриковать сообщение с чужим SID, однако, он не может изменить SID отправителя. На принимающей стороне эти два SID сравниваются и при их равенстве аутентификация считается успешной.
• Listener
Запускается при запуске приложения на принимающей стороне. Извлекает сообщение из очереди, анализирует переданный в нем CLSID асинхронного компонента и запускает соответствующий Player, которому и передается данное сообщение для последующей обработки.
• Player
Аутентифицирует сообщение как описано выше. В случае успеха активирует нужный асинхронный компонент и вызывает его методы.
В некоторых случаях некоторый вызов может завершиться ошибкой. Причиной может являться просто ошибка в параметрах данного вызова. А может быть, через некоторое время этот же вызов завершится успехом. Player пытается повторить вызов несколько раз, передавая в случае неудачи этот вызов в некоторую локальную очередь с меньшим приоритетом. Из низшей по приоритету очереди вызов может извлечь только администратор.
• Экземпляр асинхронного компонента
Очередь (транзакционная) создается автоматически при создании приложения с атрибутом queued. Имя очереди совпадает с именем приложения.
Приложение запускается либо администратором либо программно. Если в приложении одновременно имеются обычные (синхронные) и асинхронные компоненты, то при вызове любого синхронного компонента приложение запустится, запустится Listener и станут возможными вызовы асинхронных компонент. Рекомендуется не смешивать в одном приложение компоненты этих двух типов. В этом случае запуск приложения с асинхронными компонентами будет находиться под контролем администратора, что и соответствует духу технологии асинхронных компонент — доступ к асинхронным компонентам открывается в удобное для них время.
Асинхронный компонент должен содержать интерфейсы помеченные как QUEUEABLE. Все методы таких интерфейсов должны иметь только входные ([in]) параметры и не должны возвращать ничего специфического для данного метода. При вызове такого метода клиенту возвращается значение типа HRESULT не сервером, a Recoder. Это значение только уведомляет об успехе либо неудаче записи вызова в буфер. Параметры передаются по значению, либо это может быть указатель на СОМ объект, поддерживающий интерфейс IPersistStream, либо указатель на асинхронный компонент. Последняя опция позволяет клиенту отправить серверу свой объект, который поможет серверу возвратить ответ клиенту (например, через электронную почту).
В асинхронных компонентах можно использовать основанную на ролях систему контроля доступа к его функциональности. Однако, не поддерживается имперсонализация. Аутентификация уже обсуждалась ранее.
Модель событий
Необходимость использования механизма событий часто возникает при разработке распределенных приложений. Классический пример — отслеживание курса акций определенного предприятия. Один компонент (издатель), имеющий доступ к информации с биржи, публикует эту информацию, а другой компонент (подписчик), представляющий интересы некоторого пользователя, получает уведомление о событии, состоящем в том, что курс акций некоторого конкретного предприятия превысил заданный порог.
Рассмотрим прежде всего две ранее использовавшиеся модели событий, недостатки которых устранены в более совершенной модели событий СОМ+:
• Регулярный опрос издателя
Издатель имеет интерфейс, через который подписчик может обратиться к издателю с вопросом — произошло ли заданное событие (курс акций некоторого предприятия превысил некоторый порог). Вопрос реализуется путем вызова некоторого метода, входные параметры которого описывают само событие, а выходные представляют ответ издателя.
Данная модель имеет следующие основные недостатки:
? Огромная доля запросов подписчиков к издателю завершается отрицательным ответом (ожидаемое событие еще не произошло), и ресурсы и подписчика и издателя тратятся впустую,
? От момента реального возникновения события до того момента, как об этом событии узнает подписчик, проходит определенное время (в среднем — половина длины временного интервала между двумя последовательными опросами издателя данным подписчиком).
• Тесно-связанные события
В рамках этой модели издатель выставляет интерфейс, используя который подписчик подписывается на получение уведомлений об интересующем его событии, передавая издателю указатель на собственный интерфейс (реализованный подписчиком, но описанный издателем), через который издатель и будет уведомлять подписчика о появлении данного события.
Модель тесно связанных событий устраняет упомянутые недостатки предыдущей модели, но не все. Остаются следующие вопросы:
? Реализация
Организация подписки, рассылка уведомлений большому числу подписчиков, контроль ошибок и т. п. — сложная задача, которую следует решать не разработчику приложения. Он должен сконцентрироваться на бизнес-логике, а не на построении инфраструктуры, общей для многих приложений. В рамках СОМ была выполнена стандартизация данной модели — описаны интерфейс IConnectionPoint и некоторые другие, но их реализация остается за разработчиком,
? Фильтрация уведомлений
Подписчик получает все предназначенные ему уведомления и не может отказаться от получения некоторых из них, не отказываясь от подписки полностью,
? Активация подписчика
Издатель получает только указатель на интерфейс подписчика, но не знает его CLSID. Это означает, что подписчик все время должен находиться в активном состоянии. Издатель не сможет создать подписчика при появлении интересующего данного подписчика события.
В СОМ+ предлагается новая модель свободно-связанных событий. Идея состоит в разделении издателя и подписчика посредником, хранящим описание события и подписку на это событие. В роли посредника выступает подсистема событий (сервис операционной системы), все данные о событиях и подписках на них хранятся в СОМ+ каталоге. Подписчик подписывается на интересующие его события независимо от издателя. Издатель, при возникновении некоторого события, по умолчанию инициирует рассылку уведомлений всем подписчикам (собственно рассылка выполняется подсистемой событий). Однако он имеет возможность просмотреть подписку на данное событие и инициировать отправку уведомлений только тем подписчикам, которым пожелает. В свою очередь, подписчик может установить фильтр, ограничивающий приходящие к нему уведомления.