Структура приложения компонента Service Broker
Большинство приложений компонента Service Broker выполняют одни и те же основные действия по получению и обработке сообщений.
Приложение начинает транзакцию.
Если приложение сохраняет сведения о состоянии, оно получает идентификатор группы сообщений. С помощью этого идентификатора приложение восстанавливает состояние из таблицы состояний. Если отсутствует группа сообщений, содержащая сообщения, готовые к получению, то приложение выполняет откат транзакции и завершает работу.
Приложение получает из очереди одно или несколько сообщений. Если приложение имеет идентификатор группы сообщений, оно получает сообщения из этой группы с его помощью. Когда больше не остается доступных для получения сообщений, приложение фиксирует транзакцию и возвращается к шагу 1.
Приложение проверяет содержимое сообщений на основании имени типа сообщений.
Приложение обрабатывает содержимое сообщений на основании имени типа сообщений и содержимого сообщения.
Приложение отправляет сообщения, полученные в результате обработки.
Если приложение сохраняет сведения о состоянии, оно обновляет таблицу состояний, используя в качестве первичного ключа для таблицы идентификатор группы сообщений.
Приложение возвращается к шагу 3, чтобы проверить, доступны ли другие сообщения.
Фактическая структура приложения зависит от его требований, стиля передачи данных в приложении, роли приложения (целевая служба или вызывающая служба) и от того, выполняет ли компонент Service Broker активацию этого приложения.
Например, вызывающее приложение отправляет сообщение перед началом цикла обработки, описанного в предыдущих шагах. Служба вызывающей стороны может отправлять сообщение из другой программы или хранимой процедуры, а затем использовать хранимую процедуру активации для очереди обслуживания вызывающей стороны. Например, в приложение для регистрации заказов может входить внешнее приложение, которое запускает диалог для добавления заказа. После добавления заказа внешнее приложение не должно продолжать работу. Хранимая процедура активации для службы вызывающей стороны отправляет подтверждение запроса, когда служба заказов возвращает ответ. Хранимая процедура активации также обрабатывает все сообщения об ошибках компонента Service Broker, которые возвращаются целевой службой, и отправляет уведомления о том, что не удалось подтвердить заказ.
Вместо отправки сообщения из другой программы вызывающее приложение может отправить сообщение, а затем запустить цикл обработки в пределах одной программы. Независимо от этих вариантов реализации, общая структура приложения остается прежней.
Приложение, которое обрабатывает большое количество сообщений в одной группе сообщений, может вести счетчик полученных сообщений и фиксировать транзакцию после обработки определенного числа сообщений. Такая стратегия подсчета и фиксации позволяет приложению сохранять относительно небольшой размер транзакций и дает возможность обрабатывать различные группы сообщений.
Пример
В следующем примере кода Transact-SQL обрабатываются все сообщения в очереди MyServiceQueue. Выполняется минимальная обработка сообщений. Если принимается сообщение EndDialog или Error, код завершает диалог. Для любого другого сообщения код создает XML-представление и формирует результирующий набор, который содержит дескриптор диалога, имя типа сообщений и XML-код. Если в течение 500 миллисекунд не доступно ни одного сообщения, код завершает работу.
В целях упрощения скрипт создает результирующий набор для каждого сообщения. Если во время чтения из очереди происходит ошибка, скрипт фиксирует изменения, не формируя никаких результатов. Таким образом скрипт автоматически удаляет сообщения, вызвавшие ошибку.
Примечание |
---|
Поскольку скрипт просто отображает сообщения, для этого скрипта невозможно появление опасных сообщений. Поэтому он не содержит код для обработки опасных сообщений. В рабочем приложении необходимо предусмотреть обработку опасных сообщений. Дополнительные сведения об опасных сообщениях см. в разделе Обработка сообщений о сбое. |
USE AdventureWorks2008R2 ;
GO
-- Process all conversation groups.
WHILE (1 = 1)
BEGIN
DECLARE @conversation_handle UNIQUEIDENTIFIER,
@conversation_group_id UNIQUEIDENTIFIER,
@message_body XML,
@message_type_name NVARCHAR(128);
-- Begin a transaction, one per conversation group.
BEGIN TRANSACTION ;
-- Get next conversation group.
WAITFOR(
GET CONVERSATION GROUP @conversation_group_id FROM MyServiceQueue),
TIMEOUT 500 ;
-- Restore the state for this conversation group here
-- If there are no more conversation groups, break.
IF @conversation_group_id IS NULL
BEGIN
ROLLBACK TRANSACTION ;
BREAK ;
END ;
-- Process all messages in the conversation group.
WHILE 1 = 1
BEGIN
-- Get the next message.
RECEIVE
TOP(1)
@conversation_handle = conversation_handle,
@message_type_name = message_type_name,
@message_body =
CASE
WHEN validation = 'X' THEN CAST(message_body AS XML)
ELSE CAST(N'<none/>' AS XML)
END
FROM MyServiceQueue
WHERE conversation_group_id = @conversation_group_id;
-- If there is no message, or there is an error
-- reading from the queue, break.
IF @@ROWCOUNT = 0 OR @@ERROR <> 0
BREAK;
-- Process the message. In this case, the program ends the conversation
-- for Error and EndDialog messages. For all other messages, the program
-- produces a result set with information about the message.
SELECT @conversation_handle,
@message_type_name,
@message_body ;
-- If the message is an end dialog message or an error,
-- end the conversation. Notice that other conversations
-- in the same conversation group may still have messages
-- to process. Therefore, the program does not break after
-- ending the conversation.
IF @message_type_name =
'https://schemas.microsoft.com/SQL/ServiceBroker/EndDialog'
OR @message_type_name =
'https://schemas.microsoft.com/SQL/ServiceBroker/Error'
BEGIN
END CONVERSATION @conversation_handle ;
END ;
END ; -- Process all messages in conversation group.
COMMIT TRANSACTION ;
END ; -- Process all conversation groups.
См. также