Замечания по выпуску


|20.5 Использование сценариев

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

|20.5.1 Базовая передача сообщений

|Базовый вариант передачи сообщений с использованием функций DB2 MQSeries |имеет место, когда все программы базы данных соединяются с одним сервером |DB2. Клиенты могут быть локальными по отношению к серверу баз данных |или распределенными в сетевой среде.

|В простом сценарии Клиент A вызывает функцию MQSEND, чтобы отправить |пользовательскую строку в местонахождение службы по умолчанию. Затем |функции MQSeries выполняются в DB2 на сервере баз данных. Через |некоторое время Клиент B вызывает функцию MQRECEIVE, чтобы принять сообщение, |стоящее первым в очереди, заданной службой по умолчанию, и возвратить его |клиенту. Для выполнения этой задачи DB2 снова вызывает функции |MQSeries.

|Клиенты баз данных могут пользоваться простой передачей сообщений рядом |способов. Наиболее обычные варианты применения передачи |сообщений: |

|Следующий сценарий по сравнению с простым сценарием, описанным выше, |дополнен удаленной передачей сообщений. Сообщение передается между |компьютером A и компьютером B. Последовательность шагов |следующая: |

  1. |Клиент DB2 вызывает MQSEND с указанием службы назначения, определенной для |представления удаленной очереди на компьютере B.
  2. |Функции DB2 MQSeries выполняют фактическую работу MQSeries, чтобы |отправить сообщение. Сервер MQSeries на компьютере A принимает |сообщение и гарантирует, что он доставит его его в место назначения, заданное |в определении точки службы и в текущей конфигурации компьютера A. |Сервер определяет, что это - очередь на компьютере B. Затем он пытается |отправить это сообщение серверу MQSeries на компьютере B, повторяя эти попытки |при необходимости.
  3. |Сервер MQSeries на компьютере B принимает сообщение от сервера на |компьютере A и помещает в очередь назначения на компьютере B.
  4. |Клиент MQSeries на компьютере B берет сообщение, стоящее первым в этой |очереди. |

|20.5.2 Отправка сообщений

|С помощью MQSEND пользователь или разработчик прикладных программ DB2 |выбирает, какие данные отправить, куда их отправить и когда они будут |отправлены. Такая ситуация обычно называется "отправить и забыть", то |есть отправитель просто посылает сообщение, полагаясь на гарантированные |протоколы доставки MQSeries, обеспечивающие, что сообщение достигнет своего |назначения. Это показано в следующих примерах.

|Пример 4: Чтобы отправить пользовательскую строку в точку службы |myPlace с правилами highPriority, введите:

|VALUES DB2MQ.MQSEND('myplace','highPriority','проверка')

|Здесь highPriority - это правила, определенные в Репозитории AMI, которые |задают для приоритета самый высокий уровень, а также могут настроить и другие |опции качества обслуживания, например, срок действия.

|В состав сообщения может входить любая разрешенная комбинация SQL и |пользовательских данных. Сюда входят вложенные функции, операторы и |преобразования типов. Например, если у нас есть таблица EMPLOYEE со |столбцами LASTNAME, FIRSTNAME и DEPARTMENT типа VARCHAR, чтобы отправить |сообщение, содержащее эту информацию для каждого сотрудника отдела 5LGA, нужно |ввести:

|Пример 5:

|SELECT DB2MQ.MQSEND(LASTNAME || ' ' || FIRSTNAME || ' ' || DEPARTMENT)
|   FROM EMPLOYEE
|   WHERE DEPARTMENT = '5LGA'

|Если в таблице присутствует также целочисленный столбец AGE, его можно |включить так:

|Пример 6:

|SELECT DB2MQ.MQSEND
|      (LASTNAME || ' ' || FIRSTNAME || ' ' || DEPARTMENT|| ' ' || char(AGE)) 
|   FROM EMPLOYEE
|   WHERE DEPARTMENT = '5LGA'

|Если в таблице EMPLOYEE вместо столбца AGE есть столбец RESUME типа CLOB, |сообщение с информацией о каждом сотруднике DEPARTMENT 5LGA можно послать |так:

|Пример 7:

|   SELECT DB2MQ.MQSEND
|      (clob(LASTNAME) || ' ' || clob(FIRSTNAME) || ' ' || clob(DEPARTMENT) || ' ' || RESUME))
|   FROM EMPLOYEE
|   WHERE DEPARTMENT = '5LGA'

|Пример 8:

|И наконец, в следующем примере показано, как можно создать содержимое |сообщения с использованием допустимого выражения SQL. Взяв вторую |таблицу DEPT со столбцами типа VARCHAR DEPT_NO и DEPT_NAME, можно отправить |сообщение, содержащее столбцы LASTNAME и DEPT_NAME:

|Пример 8:

|SELECT DB2MQ.MQSEND(e.LASTNAME || ' ' || d.DEPTNAME) FROM EMPLOYEE e, DEPT d
|   WHERE e.DEPARTMENT = d.DEPTNAME

|20.5.3 Прием сообщений

|Функции DB2 MQSeries позволяют либо получать, либо читать сообщения. |Чтение отличается от приема сообщения тем, что чтение возвращает головное |сообщение без удалении его из данной очереди, а при приеме сообщение удаляется |из очереди. С использованием операции приема сообщение можно получить |только один раз, а операция чтения позволяет получать одно и то же сообщение |многократно. Это показано в дальнейших примерах:

|Пример 8:

|VALUES DB2MQ.MQREAD()

|Этот пример возвращает строку VARCHAR, содержащую первое сообщение из |очереди, определенной службой по умолчанию с использованием правил качества |обслуживания по умолчанию. Важно отметить, что если сообщения, |доступные для чтения, отсутствуют, будет возвращено пустое значение. |При этой операции очередь не изменяется.

|Пример 9:

|VALUES DB2MQ.MQRECEIVE('Employee_Changes')

|В этом примере показано, как сообщение можно удалить из начала очереди, |заданной службой Employee_Changes, с использованием правил по |умолчанию.

|Полезная особенность DB2 - возможность сгенерировать таблицу при помощи |пользовательской функции (или функции, предоставляемой DB2). Эту |особенность табличных функций можно использовать, чтобы разрешить использовать |содержимое очереди как таблицу DB2. Простейший случай показан на |следующем примере:

|Пример 10:

|SELECT t.* FROM table ( DB2MQ.MQREADALL()) t 

|Это требование возвращает таблицу, включающую в себя все сообщения в |очереди, определенной службой по умолчанию, и метаданные об этих |сообщениях. Полное описание возвращенной структуры таблицы приведено в |Приложении, отметим лишь, что первый столбец отражает содержимое сообщения, а |остальные столбцы содержат метаданные. Чтобы требование возвращало |только сообщения, этот пример можно изменить так:

|Пример 11:

|SELECT t.MSG FROM table (DB2MQ.MQREADALL()) t

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

|Пример 12:

|SELECT t.MSG, e.LASTNAME
|   FROM table (DB2MQ.MQREADALL() ) t, EMPLOYEE e
|      WHERE t.MSG = e.LASTNAME

|Пример 13:

|SELECT COUNT(*) FROM table (DB2MQ.MQREADALL()) t

|Кроме того, можно скрыть факт, что источником таблицы является очередь, |если создать производную таблицу от табличной функции. Например, в |следующем примере на основании очереди, к которой служба обращается по имени |NEW_EMPLOYEES, создается производная таблица NEW_EMP:

|Пример 14:

|CREATE VIEW NEW_EMP (msg) AS
|   SELECT t.msg FROM table (DB2MQ.MQREADALL()) t

|Здесь производная таблица определяется только с одним столбцом, в котором |содержится все сообщение. Если структура сообщения простая, для |примера, содержащего два поля фиксированной длины, можно напрямую |воспользоваться встроенными функциями DB2, чтобы разбить данное сообщение на |два столбца. Например, если известно, что сообщения, отправляемые в |конкретную очередь, всегда содержат фамилию длиной не более 18 символов, за |которой следует максимум 18-символьное имя, вы можете опередить производную |таблицу, содержащую каждое поле как отдельный столбец, так:

|Пример 15:

|CREATE VIEW NEW_EMP2 AS
|   SELECT left(t.msg,18) AS LNAME, right(t.msg,18) AS FNAME
|   FROM table(DB2MQ.MQREADALL()) t

|Для создания новых табличных функций и производных таблиц DB2, которые |будут отображать в столбцы структуру сообщений с ограничителями можно |использовать новую возможность Построителя хранимых процедур DB2 - мастер |поддержки MQSeries.

|И наконец, как правило, полезно хранить содержимое одного или нескольких |сообщений в базе данных. Для этого можно использовать все возможности |SQL по управлению и хранению содержимого сообщений. Приведем простейший |пример:

|Пример 16:

|INSERT INTO MESSAGES 
|   SELECT t.msg FROM table (DB2MQ.MQRECEIVEALL()) t

|Этот оператор будет вставлять в таблицу MESSAGES, содержащую единственный |столбец VARCHAR(2000), сообщения из очереди службы по умолчанию. |Развивая эту технику, можно охватить широкий спектр самых разнообразных |обстоятельств.

|20.5.4 Возможности соединения программ друг с другом

|Интеграция программ - обычный элемент во многих решениях. Будь то |интеграция приобретенной программы в существующую инфраструктуру или всего |лишь интеграция только что разработанной программы в существующую среду, мы |часто сталкиваемся с задачей склеить вместе разнородное собрание подсистем, |чтобы сформировать работающее целое. MQSeries обычно рассматривается |как необходимый инструмент для интеграции программ. Доступная на |большей части аппаратных средств, программного обеспечения и языковых сред, |MQSeries обеспечивает средства для связи воедино самого разнородного собрания |программ.

|В этом разделе мы обсудим некоторые сценарии интеграции программ и |возможности их использования с DB2. Поскольку тема весьма широка, |всестороннее обсуждение интеграции программ выходит за рамки этой |работы. Поэтому остановимся на двух простых вопросах: |взаимодействие требование/ответ, а также интегратор MQSeries и |публикация/подписка.

|20.5.4.1 Взаимодействие требование/ответ

|Метод взаимодействия требование/ответ (R/R) - наиболее общая техника, когда |одна программа запрашивает службы другой программы. В одном из таких |способов реквестер отправляет сообщение провайдеру службы, требуя, чтобы была |выполнена некоторая работа. Как только работа выполнена, провайдер |может решить отправить результаты (или просто подтверждение о выполнении) |назад реквестеру. Но при использовании техники базовой отправки |сообщений, описанной выше, нет такого средства, которое соединило бы |требование отправителя с ответом провайдера службы. Если реквестер не |ожидает ответа перед тем, как продолжить работу, должен использоваться |какой-нибудь механизм, чтобы связать каждый ответ с соответствующим |требованием. От разработчика не требуется создания такого механизма, |так как MQSeries обеспечивает идентификатор корреляции, который позволяет |коррелировать сообщения при обмене.

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

|Пример 17:

|DB2MQ.MQSEND ('myRequester','myPolicy','SendStatus:cust1','Req1')

|Этот оператор добавляет заключительный параметр Req1 в вышеуказанный |оператор MQSEND, чтобы указать идентификатор корреляции для требования.

|Чтобы получить ответ на это конкретное требование, воспользуйтесь |оператором MQRECEIVE для выборочного получения первого сообщения, |определенного указанной службой, соответствующей данному идентификатору |корреляции, так:

|Пример 18:

|DB2MQ.MQRECEIVE('myReceiver','myPolicy','Req1')

|Если программа, обслуживающая требование, занята, а реквестер выдает |указанный выше оператор MQRECEIVE перед отправкой ответа, не будет найдено ни |одного сообщения, удовлетворяющего данному идентификатору корреляции.

|Чтобы получить и требование службы, и идентификатор корреляции, |используется примерно такой оператор:

|Пример 19:

|SELECT msg, correlid FROM table (DB2MQ.MQRECEIVEALL('aServiceProvider','myPolicy',1)) t

|Он возвращает от провайдера aServiceProvider сообщение и идентификатор |корреляции первого требования.

|После того, как служба выполнена, она отправляет сообщение-ответ в очередь |реквестера. В это время реквестер службы может заниматься другой |работой. Фактически нет никакой гарантии, что на начальное требование |службы будет дан ответ в установленное время. Сроками ожидания уровня |программы, подобными этому, должен управлять разработчик; за обнаружение |ответа ответственен реквестер.

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

|20.5.4.2 Публикация/подписка

|Простая публикация данных

|Другой обычный сценарий в интеграции программ состоит в том, что одна |программа уведомляет другие программы о представляющих интерес |событиях. Этого легко добиться, послав сообщение в очередь, которую |отслеживает другая программа. Содержание сообщения может быть заданной |пользователем строкой или состоять из столбцов базы данных. Часто |требуется просто послать сообщение; для этого используется функция |MQSEND. Если такое сообщение необходимо послать одновременно нескольким |получателям, можно воспользоваться средством интерфейса MQSeries AMI Список |распределения.

|Список распределения задается при помощи инструмента AMI |Administration. Такой список содержит названия отдельных служб. |Сообщение, посланное в список распределения, отправляется каждой службе из |этого списка. Это особенно полезно, если известно, что каждое сообщение |всегда будет представлять интерес для нескольких служб. В следующем |примере показана отправка сообщения в список распределения |interestedParties:

|Пример 20:

|DB2MQ.MQSEND('interestedParties','интересная для всех информация');

|Когда требуется более сложное управление сообщениями для конкретных службы, |лучше использовать средство Publish/Subscribe - публикация/подписка. |Системы Publish/Subscribe,как правило, предоставляют масштабируемую, |защищенную среду, в которой множество подписчиков могут зарегистрироваться на |получение сообщений от ряда издателей. Для поддержки этой возможности |может использоваться интерфейс MQPublish в совокупности с MQSeries Integrator |или MQSeries Publish/Subscribe.

|MQPublish позволяет пользователям по желанию задать тему, которая будет |связана с сообщением. Темы позволяют подписчикам более точно описать |сообщения, которые будут приниматься. Используется следующая |последовательность действий: |

  1. |Администратор MQSeries конфигурирует возможности публикации/подписки |интегратора MQSeries.
  2. |Заинтересованные программы подписываются в пунктах подписки, определяемых |конфигурацией MQSI, задавая по желанию интересующие их темы. Каждый |подписчик выбирает подходящие темы; он может также использовать технику |подписки на основе содержания, применяемую в MQSeries Integrator V2. |Важно отметить, что программу подписки определяют очереди, представленные |именами служб.
  3. |Программа DB2 выпускает сообщение в точке службы Weather (Погода). |В сообщении указывается, что идет дождь со снегом и тема Austin, тем самым |подписчики оповещаются, что в Остине идет дождь со снегом.
  4. |Механика реальной публикации сообщений осуществляется функциями MQSeries, |предоставляемыми DB2. Сообщение отправляется интегратору MQSeries с |использованием службы Weather.
  5. |MQSI принимает сообщение от службы Weather, выполняет всю обработку, |определяемую конфигурацией MQSI, и определяет, каким подпискам оно |соответствует. После этого MQSI отправляет это сообщение в очереди |подписчиков, которых оно интересует.
  6. |Программы, которые подписались на службу Weather и зарегистрировали тему |Austin, получат сообщение Дождь со снегом в своей службе |приема. |

|Чтобы опубликовать данные с использованием всех умолчаний, не задавая |тему, следует воспользоваться примерно таким оператором:

|Пример 21:

|SELECT DB2MQ.MQPUBLISH(LASTNAME || ' ' || FIRSTNAME || ' ' || DEPARTMENT|| ' ' ||char(AGE))
|   FROM EMPLOYEE
|      WHERE DEPARTMENT = '5LGA'

|Оператор, который полностью задает все параметры и упрощает сообщение, |чтобы в нем содержалась только фамилия, выглядит так:

|Пример 22:

|SELECT DB2MQ.MQPUBLISH('HR_INFO_PUB', 'SPECIAL_POLICY', LASTNAME,
|   'ALL_EMP:5LGA', 'MANAGER')
|   FROM EMPLOYEE
|      WHERE DEPARTMENT = '5LGA'

|Этот оператор выпускает сообщения для издательской службы HR_INFO_PUB с |использованием правил обслуживания SPECIAL_POLICY. В сообщениях |указывается, что тема отправителя - MANAGER. В строке темы показана |возможность указания нескольких тем, разделенных двоеточиями |':'. В этом примере использование двух тем позволяет |подписчикам для получения сообщений зарегистрировать тему ALL_EMP или только |5LGA.

|Для получения опубликованных сообщений сначала вы должны зарегистрировать |свою заинтересованность в сообщениях на данную тему, и указать имя службы |подписчика, куда следует посылать сообщения. Важно отметить, что службы |подписчика интерфейса AMI определяет службу посредника и службу |получателя. Служба посредника определяет, как подписчик взаимодействует |с посредником публикации/подписки, а служба получателя - куда будут посылаться |сообщения, удовлетворяющие требованию подписчика. Следующий оператор |регистрирует заинтересованность в теме ALL_EMP.

|Пример 23:

|DB2MQ.MQSUBSCRIBE('aSubscriber', 'ALL_EMP')

|После подписки программы сообщения с темой ALL_EMP будут отправляться в |службу получателя, определенную службой подписчика. У программы может |быть несколько одновременных подписок. Для сообщений, отвечающих |подписке, можно пользоваться любой стандартной функцией получения |сообщений. Например, если служба подписчика aSubscriber задает, что |служба получателя - aSubscriberReceiver,тогда следующий оператор прочтет |первое сообщение, не удаляя его:

|Пример 24:

|DB2MQ.MQREAD('aSubscriberReceiver')

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

|Пример 25:

|SELECT t.msg, t.topic
|   FROM table (DB2MQ.MQRECEIVEALL('aSubscriberReceiver',5)) t

|Для чтения всех сообщений с темой ALL_EMP можно применить средства |SQL:

|Пример 26:

|SELECT t.msg FROM table (DB2MQ.MQREADALL('aSubscriberReceiver')) t
|   WHERE t.topic = 'ALL_EMP'
|Прим.:
Важно понять, что если MQRECEIVEALL используется с ограничением, будет |использована вся очередь, а не только сообщения с темой ALL_EMP. Вот |почему табличная функция выполняется перед применением этого |ограничения. |

|Если вы больше не нуждаетесь в подписке на конкретную тему, нужно явно |отменить подписку, воспользовавшись таким оператором:

|Пример 27:

|DB2MQ.MQUNSUBSCRIBE('aSubscriber', 'ALL_EMP')

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

|Автоматическая публикация сообщений

|Другим важным способом передачи сообщений базы данных является |автоматическая публикация сообщений. С помощью триггера DB2 можно |автоматически публиковать сообщения при вызове триггера. Существуют и |другие способы автоматической публикации сообщений, но подход с использованием |триггера предоставляет администраторам или разработчикам большую свободу в |конструировании содержания сообщений и гибкость при определении действий |триггера. Как и при любом другом использовании триггера, следует |обратить внимание на частоту и стоимость его работы. Следующие примеры |показывают, как можно использовать триггеры с функциями DB2 MQSeries.

|В примере ниже показано, как просто при помощи триггера публиковать |сообщение при найме каждого нового служащего. Любые пользователи или |программы, подписывающиеся в службе HR_INFO_PUB с регистрацией темы NEW_EMP, |будут получать сообщение, содержащее дату, имя и отдел для каждого нового |сотрудника.

|Пример 28:

|CREATE TRIGGER new_employee AFTER INSERT ON employee REFERENCING NEW ASn
|      FOR EACH ROW MODE DB2SQL
|      VALUES DB2MQ.MQPUBLISH('HR_INFO_PUB&',  'NEW_EMP',
|      current date || ' ' || LASTNAME || ' ' || DEPARTMENT)


[ Начало страницы | Страница назад | Страница вперед | Содержание | Индекс ]