Removendo mensagens suspeitas
Uma mensagem suspeita é uma mensagem que contém informações que um aplicativo não pode processar com sucesso. Por exemplo, uma estação de trabalho de manufatura pode enviar uma solicitação para retirar uma peça do estoque um pouco antes de uma ordem de alteração tornar a peça obsoleta. A ordem de alteração torna-se efetiva enquanto a solicitação do estoque está em trânsito. O aplicativo de gerenciamento de estoques recebe a solicitação da estação de trabalho, mas não pode processar a solicitação com sucesso e a operação do banco de dados para atualizar o número de peças em estoque falha. A transação que contém a operação de recebimento é, então, revertida, retornando a mensagem para a fila. Nessa situação, o aplicativo continua a receber a mesma mensagem, a atualização continua a falhar e a mensagem retorna à fila.
Uma mensagem suspeita não é uma mensagem corrompida e pode não ser uma solicitação inválida. O Service Broker contém verificações de integridade de mensagem que detectam mensagens corrompidas. Um aplicativo também geralmente valida o conteúdo de uma mensagem e descarta uma mensagem que contém uma solicitação ilegal. Em contraste, muitas mensagens suspeitas eram válidas quando a mensagem foi criada, mas depois se tornaram impossíveis de processar.
Detecção automática de mensagens suspeitas
O Service Broker fornece detecção automática de mensagens suspeitas. Quando uma transação que contém uma instrução RECEIVE é revertida cinco vezes, o Service Broker desabilita todas as filas das quais a transação recebeu mensagens, definindo automaticamente o status da fila como OFF. Além disso, o Service Broker gera um evento do tipo Broker:Queue Disabled.
Um administrador pode usar os alertas de Agente SQL Server para ser notificado quando uma fila for desabilitada. Um desenvolvedor também pode criar um aplicativo que detecta quando uma fila for desabilitada pelo Service Broker. Esse aplicativo frequentemente inspeciona as mensagens na fila para localizar a mensagem suspeita. Após o aplicativo determinar qual mensagem não pode ser processada, o aplicativo define o status da fila como ON e encerra a conversa da mensagem com um erro. Um aplicativo que detecta as mensagens suspeitas deve ser cuidadoso ao limpar qualquer estado associado à conversa quando a mesma é encerrada. Para obter mais informações sobre como criar um aplicativo para recuperar as mensagens suspeitas, consulte Tratando de mensagens suspeitas.
Removendo mensagens suspeitas administrativamente
A maioria dos aplicativos deve localizar e remover mensagens suspeitas programaticamente. Porém, às vezes pode ser necessário remover uma mensagem suspeita manualmente. Por exemplo, a parte do aplicativo que executa a recuperação pode não ser capaz de detectar a mensagem suspeita ou pode não ser capaz de limpar com segurança o estado salvo da conversa.
A remoção manual de uma mensagem corre o risco de interromper uma conversa importante. Portanto, sempre inspecione uma mensagem suspeita antes de removê-la da fila. Para verificar o conteúdo da mensagem, inicie a transação, receba o corpo da mensagem, exiba o corpo da mensagem e, então, reverta a transação. Até ter certeza de que a mensagem em questão é uma mensagem suspeita, é importante reverter a transação.
Exemplo
O exemplo a seguir mostra como inspecionar uma mensagem seguramente para o identificador de conversa e29059bb-9922-40f4-a575-66b2e4c70cf9 na fila 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
Quando você localizar uma mensagem suspeita, encerre a conversa. O exemplo a seguir encerra a conversa 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
Quando uma conversa é encerrada, o Service Broker descarta as mensagens para essa conversa. Observe que o aplicativo que normalmente processa a mensagem não recebe uma mensagem EndDialog ou Error para essa conversa. Portanto, se o aplicativo mantiver o estado, você deve ser cuidadoso ao remover o estado associado à conversa após o encerramento desta com um erro.
Se um serviço não puder processar uma mensagem, isso significa que o serviço não pode completar a tarefa para a conversa. Encerrar a conversa com um erro notifica o outro participante na conversa de que a tarefa falhou.
Consulte também