Quitar mensajes dudosos

Un mensaje dudoso es un mensaje que contiene información que una aplicación no puede procesar correctamente. Por ejemplo, una estación de trabajo de fabricación puede presentar una solicitud para retirar una parte del inventario justo antes de que una orden de cambio determine que la pieza está obsoleta. La orden de cambio se activa mientras la solicitud de inventario está en tránsito. La aplicación de administración de inventario recibe la solicitud de la estación de trabajo pero no puede procesarla correctamente por lo que la operación de base de datos para actualizar el número de piezas en las existencias genera un error. La transacción que contiene la operación de recepción se revierte y devuelve el mensaje a la cola. En esta situación, la aplicación recibe el mismo mensaje, la actualización vuelve a generar un error y el mensaje vuelve a la cola.

Un mensaje dudoso no es un mensaje incorrecto y puede que no sea una solicitud no válida. Service Broker contiene comprobaciones de integridad de mensajes que detectan mensajes incorrectos. También las aplicaciones suelen validar el contenido de un mensaje y descartan los que contienen una solicitud no permitida. Por otra parte, muchos mensajes dudosos eran válidos cuando se crearon pero, más tarde, se volvieron imposibles de procesar.

Detección automática de mensajes dudosos

Service Broker proporciona detección automática de mensajes dudosos. Cuando una transacción que contiene una instrucción RECEIVE se revierte cinco veces, Service Broker deshabilita todas las colas desde las que la transacción recibe mensajes mediante el establecimiento automático del estado de la cola en OFF. Además, Service Broker genera un evento de tipo Broker:Queue Disabled.

Un administrador puede utilizar alertas del Agente SQL Server para que se notifique la deshabilitación de una cola. Un programador también puede crear una aplicación que detecte cuándo Service Broker deshabilita una cola. Esta aplicación inspecciona a menudo los mensajes de la cola para encontrar el mensaje dudoso. Una vez que determina qué mensaje no se puede procesar, establece el estado de la cola en ON y finaliza la conversación para el mensaje con un error. Una aplicación que detecta mensajes dudosos debe limpiar cualquier estado asociado con la conversación cuando la finaliza. Para obtener más información sobre cómo crear una aplicación para establecer una recuperación después de mensajes dudosos, vea Controlar mensajes dudosos.

Quitar mensajes dudosos mediante administración

La mayoría de las aplicaciones deben realizar un seguimiento y eliminar mensajes dudosos mediante programación. Sin embargo, en ocasiones puede ser necesario eliminar un mensaje dudoso manualmente. Por ejemplo, puede que la parte de la aplicación que realiza la recuperación no pueda detectar el mensaje dudoso o limpiar de forma segura el estado guardado de la conversación.

Si se quita un mensaje de forma manual se corre el riesgo de interrumpir una conversación importante. Por tanto, siempre debe inspeccionar un mensaje dudoso antes de quitarlo de la cola. Para ver el contenido del mensaje, inicie una transacción, reciba el cuerpo del mensaje, muestre el cuerpo del mensaje y, a continuación, revierta la transacción. Hasta que esté seguro de que el mensaje en cuestión es un mensaje dudoso, es preferible revertir la transacción.

Ejemplo

En el siguiente ejemplo se muestra cómo inspeccionar un mensaje de forma segura para el identificador de conversación e29059bb-9922-40f4-a575-66b2e4c70cf9 de la cola ExpenseQueue.

use AdventureWorks ;
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 ;

  -- Rollback 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

Cuando encuentra un mensaje dudoso, finaliza la conversación. En el siguiente ejemplo se finaliza la conversación 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

Cuando una conversación finaliza, Service Broker descarta los mensajes de esa conversación. Observe que la aplicación que suele procesar el mensaje no recibe ningún mensaje EndDialog ni Error para esta conversación. Por tanto, si la aplicación mantiene el estado, debe eliminar con cuidado el estado asociado con la conversación después de finalizar la conversación con un error.

Si un servicio no puede procesar un mensaje, significa que el servicio no puede finalizar la tarea de la conversación. Al finalizar la conversación con un error se notifica al otro participante de la conversación que la tarea ha generado un error.