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