포이즌 메시지 제거
포이즌 메시지는 응용 프로그램이 제대로 처리할 수 없는 정보가 포함된 메시지입니다. 예를 들어 제조 워크스테이션은 주문 변경으로 인해 부품이 필요 없게 되기 직전에 재고에서 해당 부품을 철회하는 요청을 전송할 수 있습니다. 재고에 대한 요청이 전송되는 동안 주문 변경이 적용됩니다. 재고 관리 응용 프로그램은 워크스테이션에서 요청을 받지만 해당 요청을 제대로 처리할 수 없으며 재고의 부품 수 업데이트를 위한 데이터베이스 작업에도 오류가 발생합니다. 수신 작업이 포함된 트랜잭션이 롤백되고 메시지는 큐로 반환됩니다. 이 경우 응용 프로그램은 계속해서 동일한 메시지를 받고, 업데이트가 계속해서 실패하고, 메시지는 큐로 반환됩니다.
포이즌 메시지는 손상된 메시지가 아니므로 유효하지 않은 요청일 수는 없습니다. Service Broker에는 손상된 메시지를 검색하는 메시지 무결성 검사가 있습니다. 일반적으로 응용 프로그램도 메시지 내용의 유효성을 검사하고 잘못된 요청이 포함된 메시지는 삭제합니다. 메시지가 생성될 때는 대부분의 포이즌 메시지가 유효하더라도 나중에는 처리할 수 없게 되는 경우가 많습니다.
포이즌 메시지 자동 검색
Service Broker는 포이즌 메시지를 자동으로 검색합니다. RECEIVE 문이 포함된 트랜잭션이 5번 롤백되면 Service Broker는 자동으로 큐 상태를 OFF로 설정하여 트랜잭션이 메시지를 받은 모든 큐를 비활성화합니다. 또한 Service Broker는 Broker:Queue Disabled 유형의 이벤트를 생성합니다.
관리자는 SQL Server 에이전트 경고를 사용하여 큐가 비활성화될 때 알림을 받을 수 있습니다. 개발자는 Service Broker가 큐를 비활성화하는 경우를 검색하는 응용 프로그램을 만들 수도 있습니다. 그러한 응용 프로그램은 큐의 메시지를 검사하여 포이즌 메시지를 찾는 경우가 많습니다. 응용 프로그램이 처리할 수 없는 메시지를 확인하면 응용 프로그램은 큐 상태를 ON으로 설정하고 오류와 함께 메시지에 대한 대화를 종료합니다. 포이즌 메시지를 검색하는 응용 프로그램은 대화를 종료할 때 대화에 연결된 상태를 반드시 정리해야 합니다. 응용 프로그램을 만들어 포이즌 메시지에서 복구하는 방법은 포이즌 메시지 처리를 참조하십시오.
관리 목적으로 포이즌 메시지 제거
대부분의 응용 프로그램은 포이즌 메시지를 프로그래밍 방식으로 추적하고 제거해야 합니다. 그러나 때로는 포이즌 메시지를 수동으로 제거해야 할 경우가 있습니다. 예를 들어 복구를 수행하는 응용 프로그램의 일부가 포이즌 메시지를 검색하지 못하거나 대화에 대해 저장된 상태를 안전하게 정리하지 못할 수 있습니다.
메시지를 수동으로 제거하면 중요한 대화가 중단될 위험이 있습니다. 따라서 큐에서 메시지를 제거하기 전에 항상 포이즌 메시지를 검사합니다. 메시지 내용을 보려면 트랜잭션을 시작하고 메시지 본문을 받아 표시한 다음 트랜잭션을 롤백합니다. 해당 메시지가 포이즌 메시지인지 확신할 때까지는 트랜잭션을 롤백해야 합니다.
예
다음 예에서는 ExpenseQueue 큐의 대화 핸들 e29059bb-9922-40f4-a575-66b2e4c70cf9에 대한 메시지를 안전하게 검사하는 방법을 보여 줍니다.
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
포이즌 메시지를 찾으면 대화를 종료합니다. 다음 예에서는 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 메시지를 받지 않습니다. 따라서 응용 프로그램의 상태가 유지 관리되는 경우에는 오류와 함께 대화를 종료한 후 대화에 연결된 상태를 반드시 제거해야 합니다.
서비스가 메시지를 처리할 수 없다면 서비스가 대화에 대한 태스크를 완료할 수 없다는 의미입니다. 오류와 함께 대화가 종료되면 대화의 다른 참가자에게 태스크 실패에 대한 알림이 전달됩니다.