Поделиться через


Удаление опасных сообщений

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

Опасное сообщение не является поврежденным сообщением и может не быть недопустимым запросом. Компонент Service Broker содержит проверку целостности сообщений, которая обнаруживает поврежденные сообщения. Приложения обычно также оценивают содержимое сообщений и отбрасывают те из них, которые содержат недопустимый запрос. В отличие от них, многие опасные сообщения были допустимыми во время создания, но позже их обработка стала невозможной.

Автоматическое определение опасных сообщений

Компонент Service Broker обеспечивает автоматическое определение опасных сообщений. Если откат транзакции, содержащей инструкцию RECEIVE, происходит пять раз, компонент Service Broker отключает все очереди, из которых транзакция получала сообщения, автоматически присваивая состоянию очереди значение OFF. Кроме того, компонент Service Broker формирует событие типа Broker:Queue Disabled.

Администратор может использовать предупреждения агента SQL Server, чтобы получать уведомления, когда происходит отключение очереди. Разработчик может также создать приложение, которое обнаруживает, когда компонент Service Broker отключает очередь. Такое приложение регулярно проверяет сообщения в очереди в поисках опасного сообщения. Как только приложение определяет, какое сообщение невозможно обработать, оно присваивает состоянию очереди значение ON и завершает диалог этого сообщения ошибкой. Приложение, определяющее опасные сообщения, при завершении диалога должно тщательно очищать любые состояния, связанные с диалогом. Дополнительные сведения о создании приложения для удаления опасных сообщений см. в разделе Обработка сообщений о сбое.

Административное удаление опасных сообщений

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

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

Пример

В следующем примере показано, как надежным образом проанализировать сообщение для дескриптора диалога e29059bb-9922-40f4-a575-66b2e4c70cf9 в очереди ExpenseQueue.

use AdventureWorks2008R2 ;
GO

-- Sample to show the content of a message, then return
-- the message to the queue. This may be useful to determine
-- whether a specific message cannot be processed due to the
-- content of the message.

-- Every exit path from the transaction rolls back the transaction.
-- This code is intended to inspect the message, not remove the
-- message from the queue permanently. The transaction must roll
-- back to return the message to the queue.

BEGIN TRANSACTION ;

  -- To print the body, the code needs the message_body and
  -- the encoding_format.

  DECLARE @messageBody VARBINARY(MAX),
          @validation NCHAR ;

  -- Receive the message. The WAITFOR handles the case where
  -- an application is attempting to process the message when
  -- this batch is submitted. Replace the name of the queue and
  -- the conversation_handle value.

  WAITFOR(
    RECEIVE TOP(1) 
            @messageBody = message_body,
            @validation = validation
      FROM dbo.ExpenseQueue
      WHERE conversation_handle =
           'e29059bb-9922-40f4-a575-66b2e4c70cf9'
  ), TIMEOUT 2000 ;

  -- Roll back and exit if the message is not available
  -- in two seconds.

  IF @@ROWCOUNT = 0
    BEGIN
      ROLLBACK TRANSACTION ;
      PRINT 'No message available.' ;
      RETURN ;
    END

  -- Print the message based on the encoding format of
  -- the message body.

  IF (@validation = 'E')
    BEGIN
      PRINT 'Empty message.' ;
    END ;
  ELSE IF (@validation = 'X')
    BEGIN
      PRINT CONVERT(nvarchar(MAX), @messageBody) ;
    END ;
  ELSE IF (@validation = 'N')
    BEGIN
      PRINT 'No validation -- binary message:'
      PRINT @messageBody ;
    END

ROLLBACK TRANSACTION
GO

Если найдено опасное сообщение, следует завершить диалог. Следующий пример завершает диалог e29059bb-9922-40f4-a575-66b2e4c70cf9.

-- End the conversation. Do this only if the message cannot be
-- processed by the normal procedure.

END CONVERSATION 'e29059bb-9922-40f4-a575-66b2e4c70cf9'
    WITH ERROR = 127 DESCRIPTION = N'Unable to process message.' ;
GO

При завершении диалога компонент Service Broker сбрасывает сообщения этого диалога. Обратите внимание, что приложение, в обычных условиях обрабатывающее это сообщение, не получает сообщения EndDialog или Error для этого диалога. Поэтому, если приложение сохраняет свое состояние, необходимо снять это состояние, связанное с диалогом, по завершении диалога с ошибкой.

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

См. также

Справочник

Основные понятия