Компания IBM
Опубликован: 14.12.2004 | Доступ: свободный | Студентов: 1533 / 139 | Оценка: 4.36 / 3.98 | Длительность: 16:32:00
ISBN: 978-5-9556-0031-4
Специальности: Системный архитектор
Лекция 12:

Дополнительные особенности программирования для WebSphere MQ

< Лекция 11 || Лекция 12: 1234 || Лекция 13 >

Работа с MsgId и CorrelId

Теперь полезно изучить способы контроля доставки сообщений, тем более что для этого существуют специальные поля в дескрипторе сообщений: MsgId и CorrelId . Например, некоторое приложение отправляет запросы на обработку в очередь Queue1 и ожидает уведомления о доставке в очереди ReplyToQ = Queue2. Совершенно очевидно, что уведомления о доставке не обязаны появиться в очереди Queue2 в той же последовательности, в какой отправлялись запросы в очередь Queue1. Как же в таком случае отслеживать доставку сообщений?

Другой пример, приложение отправляет запросы в разные системы, в частности, по банковским счетам клиента и по проверке его кредитной истории и ожидает получить ответ от запрашиваемых систем в одну и ту же очередь для всех клиентов. Как же идентифицировать поступающие ответы? Самое простое - использовать идентификаторы MsgId и CorrelId , которые являются уникальными для каждого сообщения и создаются на основе времени выполнения команды MQPUT. Идентификаторы MsgId и CorrelId создаются менеджером, если они установлены в NULL, либо заданы опции MQPMO_NEW_MSG_ID и/или MQPMO_NEW_CORREL_ID ; в противном случае, MsgId и CorrelId создаются приложением.

Таким образом, задавая значения MsgId и CorrelId при выполнении MQPUT, появляется возможность автоматически получать значения MsgId и CorrelId при чтении командой MQGET. При этом не надо забывать, что в цикле считывания перед командой MQGET следует ставить обнуление этих переменных ( MsgId=MQMI_NONE и CorrelId=MQCI_NONE ), иначе можно получить ошибку считывания сообщений из очереди MQRC_NO_MSG_AVAILABLE, несмотря на то, что сообщения в очереди имеются.

Рассмотрим на примере, как работает MQGET с MsgId и CorrelId на практике. Пусть в некоторую очередь поступили сообщения в определенном порядке, как указано в таблице ниже.

Номер сообщения MSGID CORRELID
1 1 1
2 1 2
3 1 3
4 2 1
5 2 2
6 3 1

Теперь варьируя MsgId и CorrelId , можно читать самые разные сообщения.

MQGET (MSGID= MQMI_NONE, CORRELID= MQCI_NONE) читает первое доступное сообщение независимо от MsgId и CorrelId , то есть сообщение 1.

MQGET (MSGID= MQMI_NONE, CORRELID= 3) может прочитать только одно сообщение, имеющее значение CorrelId = 3, это сообщение 3.

MQGET (MSGID= 2, CORRELID= MQCI_NONE) читает первое сообщение со значением MsgId = 2, это сообщение 4.

MQGET (MSGID= 2, CORRELID= 2) может прочитать только одно сообщение, имеющее уникальное сочетание MsgId = 2 и CorrelId = 2, это сообщение 5.

Таким образом, если никакие другие сообщения не поступят в очередь, то в очереди после четырех MQGET останутся 2 сообщения. Здесь уместен вопрос о производительности работы менеджера очередей при таком поиске сообщений. Если число сообщений в очереди не превышает 100, то время поиска будет незначительным, оно практически не зависит от числа сообщений. Но если число сообщений в очереди превысит 1000, то менеджер будет сканировать очередь и время поиска будет заметным. На OS/390 MQSeries администратор может определить MsgId или CorrelId (но не одновременно) как индекс и это существенно ускорит поиск нужного сообщения в очереди. Следует также отметить, что на других платформах (AS/400, HP_UX, AIX, Sun Solaris, Windows) в версии 5.3 WebSphere MQ можно использовать опции соответствия MatchOption: MQMO_MATCH_MSG_ID и MQMO_MATCH_CORREL_ID. Если эти опции соответствия не будут определены, то MsgId и CorrelId будут игнорироваться, как если бы использовались опции MQMI_NONE и MQCI_NONE и будет извлекаться очередное сообщение.

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

INPUT_MSG_DESC.MsgId = MQMI_NONE;
INPUT_MSG_DESC.CorrelId  = MQCI_NONE;
MQGET (..........);
    /* Обработка входного сообщения  */        
OUT_MSG_DESC.MsgId = MQMI_NONE;
OUT_MSG_DESC.CorrelId = INPUT_MSG_DESC.MsgId;
MQPUT  (..........);

Разрабатывая логику в цепи программ-обработчиков сообщений на разных платформах следует стремиться к тому, чтобы CorrelId содержал MsgId исходного запроса, а MsgId выходного сообщения содержал уникальный идентификатор, полученный наиболее важной в функциональном смысле выходной программой. На основе такой логики легко получить подтверждение на выходе, что исходный запрос был отработан, и промежуточные программы проставили свой MsgId в выходном сообщении. Это позволяет осуществить контроль времени прохождения запроса и получения сообщения-отчета.

В завершение раздела, уж если речь пошла о контроле доставки сообщений, необходимо отметить возможность использования полей context (контекст) в дескрипторе сообщения для контроля авторизации пользователя и обеспечения безопасности. Группа полей context состоит из 8 полей, их значения по умолчанию приводятся в таблице ниже.

Поле Размер Значение Поле Размер Значение
UserIdentifier CHAR12 Имя пользователя PutAppName CHAR28 Имя приложения
AccountingToken BYTE32 Учетный номер приложения-отправителя PutDate CHAR8 YYYYMMDD
AppIdentityData CHAR32 Пробелы PutTime CHAR8 HHMMSSTH
PutApplType LONG UNIX и т.п. AppOriginData CHAR4 пробелы

Используя UserIdentifier и AccountingToken, а также опции для работы с полями context такими как MQPMO_DEFAULT_CONTEXT, MQPMO_PASS_IDENTITY_CONTEXT, MQPMO_PASS_ALL_CONTEXT, MQPMO_SET_IDENTITY_CONTEXT, MQPMO_SET_ALL_CONTEXT, а также MQOO_ALTERNATE_USER_AUTHORITY [ 14 ] для альтернативной авторизации, позволяющей одному пользователю посылать сообщения от имени другого, можно контролировать авторизацию пользователей, запускающих задачи. Эти права устанавливает MQSeries - администратор с помощью команды setmqaut. Об этом не следует забывать при разработке приложений.

< Лекция 11 || Лекция 12: 1234 || Лекция 13 >