Добавить в цитаты Настройки чтения

Страница 203 из 372

• Очередь

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

♦ Очереди, создаваемые приложением

При создании новой очереди необходимо определить, будет ли создаваемая очередь публичной (public) или личной (private), и будет ли она транзакционной (transactional) или нетранзакционной (non-transactional):

— Публичная очередь

Регистрируется в Active Directory и, следовательно, может быть обнаружена любым приложением. Интересно отметить, что среди параметров, приписываемых очереди при ее создании, имеется параметр, задающий тип очереди в виде GUID. Это позволяет приложениям искать публичные очереди нужного типа (например, очередь печати).

— Личная очередь

Регистрируется только на локальной машине. Другие приложения могут узнать об этой очереди от создавшего ее приложения (например, через свойство Response Queue полученного сообщения).

— Транзакционная очередь и нетранзакционная очередь

Важная роль распределенных транзакций уже обсуждалась ранее. Напомним, что основными игроками в распределенной транзакции являются прикладные объекты, менеджеры ресурсов и менеджер транзакций. Транзакционная очередь является менеджером транзакций. Сообщения из контекста транзакции посылаютя только в транзакционную очередь. Сообщения, посылаемые извне контекста транзакции могут посылаться только в нетранзакционную очередь.

Если необходимо гарантировать доставку сообщения от отправителя до получателя, причем только одной копии такого сообщения, следует использовать транзакционную очередь назначения на машине получателя, отправлять сообщение из контекста транзакции и получать сообщение из контекста транзакции.

♦ Очереди приложения делятся на

— Очередь назначения

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

— Административная очередь

В этом качестве можно использовать любую нетранзакционную очередь, обычно локальную. Именно в эту очередь MSMQ отправляет положительные и отрицательные подтверждения относительно доставки сообщений, отправляемых данным приложением другим приложениям.

— Очередь ответов

В эту очередь приложения-получатели сообщений, отправляемых данным приложением, отправляют свои ответы,

♦ Системные очереди

Среди системных очередей, создаваемых MSMQ, отметим

— Журнал

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

— Dead-letter

Сообщения, которые не удалось отправить.

Завершая краткий обзор MSMQ, осталось рассмотреть типы MSMQ приложений:

• MSMQ сервер

Поддерживаются и используются очереди, менеджер очередей, MSMQ API, маршрутизация сообщений между очередями. Хотя бы один такой сервер должен иметься в любом распределенном приложении, поддерживающем обмен сообщениями.

• Независимый клиент





Поддерживаются и используются очереди, менеджер очередей, MSMQ API. Благодаря наличию собственных очередей независимый клиент может отправлять сообщения даже будучи отключенным от сети. Отправляемые сообщения накапливаются в некоторой очереди и передаются в очередь назначения автоматически при подключении к сети.

• Зависимый клиент

Поддерживается и используется только MSMQ API. Такой клиент может работать только при подключении к сети.

Архитектура асинхронных компонент

Вновь обратимся к рассмотрению технологии асинхронных компонент. Основными элементами ее архитектуры являются:

• Клиент

Интересно отметить, что клиент может вызывать экземпляр асинхронного компонента либо обычным, синхронным образом, либо асинхронно. Все зависит от способа активации объекта.

При явном использовании стандартного для СОМ способа (функции CoGetClassObject или CoCreateInstance [Ex]) будет создан экземпляр асинхронного компонента, пригодный только для обычных синхронных вызовов. Точнее, на стороне клиента будет сформирован обычный прокси, а на стороне сервера — стаб, которые и обеспечат вызовы методов экземпляра асинхронного компонента в реальном времени.

Для использования возможностей технологии асинхронных компонент клиент должен инициировать формирование экземпляра асинхронного компонента посредством использования моникеров ТИПОВ queue, new И функции CoGetObject. Например,

hr = CoGetObject(L" queue:/new: My_App.My_Class",

            NULL, IID_My_interface, (void**)&ppv);

Моникер иногда называют интеллектуальным именем. Моникер — это объект, который знает как найти, активировать, инициализировать другой СОМ объект. Моникеры бывают как встроенные (нескольких типов), так и пользовательские. Используя встроенные моникеры и их композицию можно получить бесконечно много новых моникеров, что практически позволяет обойтись без разработки и реализации пользовательских моникеров, которые могут понадобиться только в весьма частных случаях.

Указанные выше моникеры типов queue и new являются встроенными, т. е. мы можем использовать их не заботясь о их реализации. Моникер освобождает клиента от участия в процессе активации объекта. Этот процесс зависит от типа объекта, и без использования моникеров клиент должен входить во все детали (например, как активировать объект, состояние которого хранится в заданном файле). Каждый моникер реализует интерфейс IMoniker, скрывающий за стандартным фасадом все детали конкретного алгоритма активации.

Функция CoGetObject в нашем случае делает следующее:

1. Создает контекст связывания.

Связывание — процесс получения указателя на интерфейс некоторого объекта, что и является основной задачей любого моникера. Вызывается функция CreateBindContext, которая создает специальный объект — контекст связывания, который будет использоваться различными функциями, связанными с построением и использованием моникеров. Контекст связывания будет хранить данные, нужные в течение всего процесса связывания (например, ссылки на объекты, использующиеся в процессе связывания). Освобождается этот объект по завершении связывания, что значительно сокращает время связывания, т. к. каждая новая функция, вызывающаяся в процессе связывания, будет повторно использовать этот же контекст связывания и все хранящиеся в нем данные.

2. Создает моникер по его строке инициализации (текстовое представление моникера, display name).

Технология моникеров позволяет построить единое иерархическое пространство имен для объектов различных типов. Строка инициализации моникера, связанного с данным объектом, и может рассматриваться как его имя.

Вызывается функция MkParseDispiayName, которая получает на входе

— Указатель на контекст связывания (полученный в предыдущем пункте)

— Строку инициализации формируемого моникера

Выходными параметрами являются

— Длина начальной части строки инициализации, распознанная данной функцией

— Указатель на построенный моникер

В нашем случае строкой инициализации моникера является строка "queue: /new: Mу_Арр. My_Class". Слева от первого разделителя "стоит префикс — тип моникера (в нашем случае queue), который должен быть зарегистрирован как ProgID в реестре. Справа от этого разделителя стоит специфичное для данного типа моникера строка, которая хранит некоторую информацию об объекте, с которым должен быть связан этот моникер. В нашем случае эта строка является строкой инициализации еще одного моникера, тип которого new. Таким образом, в данном случае мы имеем композицию двух моникеров.

Алгоритм работы функции MkParseDispiayName: