2012-05-16 3 views
4

내부 활성화를 사용하여 단일 컴퓨터 서비스 브로커를 설정했지만 브로커가 대기열에있는 항목을 처리 중이므로 대화를 올바르게 닫을 수 있습니다 (프로필 참조). 자세한 내용은 아래 참조).30 분 후에 닫힌 항목을 sys.conversation_endpoints에 남김

향후 30 분으로 설정되어 있지만이 레코드는 절대로 삭제되지 않는 security_timestamp와 함께 CD - CLOSED 상태의 sys.conversation_endpoints에 남아있는 단일 레코드입니다.

나는 또한 내 자신의 로그를 보여주고있는 어떤 그 이상한 표시되는 유일한 일어나는 것은 개시 절차가 (내 로그 정보의 마지막 항목) conversation_handle, message_type 및 MESSAGE_BODY

I에 대한 널 (null) 값으로 호출되는 것입니다

dbo.usp_QueueRequest 2, null, 'Trial' 

는 당신에게 동일한 결과를 제공해야한다 : 내가 사용하는 모든 개체를 만드는 것입니다, 나는 그들이 단순히 실행 사용하고 방법을 모방하는 (이름은 실제 이름을 표시하지 변경) 스크립트를 포함했다 내가 일관되게 보았던 것

추적 : (단축)

EventClass    TextData    SPID Event Sequence EventSubClass 
Broker:Activation        30 1394   1 - Start 
Broker:Conversation  CONVERSING   30 1395   1 - SEND Message 
Broker:Message Classify       30 1396   1 - Local 
Broker:Conversation  CONVERSING   30 1397   6 - Received Sequenced Message 
Broker:Activation        31 1398   1 - Start 
Broker:Conversation  DISCONNECTED_OUTBOUND 31 1399   2 - END CONVERSATION 
Broker:Conversation Group      31 1400   2 - Drop 
Broker:Message Classify       31 1401   1 - Local 
Broker:Conversation  DISCONNECTED_INBOUND 31 1402   7 - Received END CONVERSATION 
Broker:Conversation  CLOSED    31 1403   10 - Received END CONVERSATION Ack 
Broker:Conversation  CLOSED    30 1404   2 - END CONVERSATION 
Broker:Conversation Group      30 1405   2 - Drop 
Broker:Activation        30 1406   2 - Ended 
Broker:Activation        31 1407   2 - Ended 

내 로그

Sequence Description 
1  Target activation for message type: RequestMessage 
2  Call fake processing procedure 
3  In fake processing procedure 
4  Send ReplyMessage for conversation 8B355311-5D9F-E111-93EC-A4BADBFBB13B 
5  Initiator activation 
6  Initiator conversation 88355311-5D9F-E111-93EC-A4BADBFBB13B message type: ReplyMessage 
7  Initiator received reply from target, end converstion 
8  Initiator activation 
9  Target activation for message type: http://schemas.microsoft.com/SQL/ServiceBroker/EndDialog 
10  Target received end dialog 
11  Initiator No conversation message type:No message type 

sys.converstation_endpoints 기록

conversation_handle      is_initiator state state_desc far_service  security_timestamp  dialog_timer 
8B355311-5D9F-E111-93EC-A4BADBFBB13B 0   CD  CLOSED  InitiatorService 2012-05-16 14:13:38.923 1900-01-01 00:00:00.000 

스크립트 개체를 만들 수는

(이름은 실제적인 이름 변경)
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[Log]') AND type in (N'U')) 
DROP TABLE [dbo].[Log] 
GO 

CREATE TABLE [dbo].[Log](
    [Id] [int] IDENTITY(1,1) NOT NULL, 
    [Description] [varchar](max) NULL, 
    [DateTime] [date] NULL DEFAULT (getdate())) 

GO 

IF EXISTS (SELECT * FROM sys.database_principals WHERE name = N'BrokerUser') 
DROP USER [BrokerUser] 
GO 

CREATE USER [BrokerUser] WITHOUT LOGIN WITH DEFAULT_SCHEMA=[dbo] 
GO 

IF NOT EXISTS (SELECT * FROM sys.service_message_types WHERE name = N'RequestMessage') 
    CREATE MESSAGE TYPE [RequestMessage] VALIDATION = WELL_FORMED_XML 

IF NOT EXISTS (SELECT * FROM sys.service_message_types WHERE name = N'AReplyMessage') 
    CREATE MESSAGE TYPE [ReplyMessage] VALIDATION = WELL_FORMED_XML 
GO 

IF NOT EXISTS (SELECT * FROM sys.service_contracts WHERE name =N'MessageContract') 
    CREATE CONTRACT [MessageContract] 
     ([RequestMessage] SENT BY INITIATOR, 
     [ReplyMessage] SENT BY TARGET) 
GO 

IF NOT EXISTS (SELECT * FROM sys.service_queues WHERE name = N'TargetQueue') 
    CREATE QUEUE TargetQueue 
GO 

IF EXISTS (SELECT * FROM sys.service_queues WHERE name = N'TargetQueue') 
    GRANT RECEIVE ON [TargetQueue] TO [BrokerUser] 
GO 

IF NOT EXISTS (SELECT * FROM sys.services WHERE name = N'TargetService') 
    CREATE SERVICE [TargetService] 
        ON QUEUE TargetQueue 
        ([MessageContract]) 
GO 

IF EXISTS (SELECT * FROM sys.services WHERE name = N'TargetService') 
    GRANT SEND ON SERVICE::[TargetService] TO [BrokerUser] 
GO 

IF NOT EXISTS (SELECT * FROM sys.service_queues WHERE name = N'InitiatorQueue') 
    CREATE QUEUE InitiatorQueue; 
GO 

IF EXISTS (SELECT * FROM sys.service_queues WHERE name = N'InitiatorQueue') 
    GRANT RECEIVE ON [InitiatorQueue] TO [BrokerUser] 
GO 

IF NOT EXISTS (SELECT * FROM sys.services WHERE name = N'InitiatorService') 
CREATE SERVICE [InitiatorService] 
       ON QUEUE InitiatorQueue 
GO 

IF EXISTS (SELECT * FROM sys.services WHERE name = N'InitiatorService') 
    GRANT SEND ON SERVICE::[InitiatorService] TO [BrokerUser] 
GO 

IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[usp_FakeProcessing]') AND type in (N'P', N'PC')) 
DROP PROCEDURE [dbo].[usp_FakeProcessing] 
GO 

CREATE PROCEDURE [dbo].[usp_FakeProcessing] 
AS 
BEGIN 

    insert [Log] ([Description]) 
    VALUES ('In fake processing procedure'); 

END 
GO 

IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[usp_TargetActivation]') AND type in (N'P', N'PC')) 
DROP PROCEDURE [dbo].[usp_TargetActivation] 
GO 

CREATE PROCEDURE [dbo].[usp_TargetActivation] 
AS 
    DECLARE @Handle UNIQUEIDENTIFIER; 
    DECLARE @Message XML; 
    DECLARE @MessageType sysname; 

    WHILE (1=1) 
    BEGIN 

    BEGIN TRANSACTION; 

    WAITFOR 
    (RECEIVE TOP(1) 
     @Handle = conversation_handle, 
     @Message = message_body, 
     @MessageType = message_type_name 
     FROM TargetQueue 
    ), TIMEOUT 5000; 

    IF (@@ROWCOUNT = 0) 
    BEGIN 
     ROLLBACK TRANSACTION; 
     BREAK; 
    END 


    INSERT [Log] ([Description]) VALUES ('Target activation for message type: ' + + COALESCE(@MessageType,'No message type')) 

    -- it's an error message (some error occurred on the initiator side). 
    --This type of message is automatically created by SB when an END CONVERSATION command is executed with the WITH ERROR clause for the initiator 
    IF @MessageType =N'http://schemas.microsoft.com/SQL/ServiceBroker/Error' 
    BEGIN 

     ROLLBACK TRANSACTION; -- roll back the message transaction. In this example there was nothing done to roll back but it is good practice 
           -- in the event of an error 

     INSERT [Log] ([Description]) VALUES ('Error occured with SB') 
     END CONVERSATION @Handle; -- and end the conversation (dialog) on this side (target) 
     BREAK; -- break out of the loop (and end the stored proc) 

    END 
    ELSE IF @MessageType = N'RequestMessage' 
    BEGIN 


     INSERT [Log] ([Description]) VALUES ('Call fake procedure') 

     EXEC [usp_FakeProcessing]; 

     INSERT [Log] ([Description]) VALUES ('Add reply message for conversation ' + CAST(@Handle AS varchar(80)) + ' with message : ' + CAST(@Message as VARCHAR(4000))); 

     SEND ON CONVERSATION @Handle 
       MESSAGE TYPE [ReplyMessage] (@message) 

    END 
    ELSE IF @MessageType = N'http://schemas.microsoft.com/SQL/ServiceBroker/EndDialog' 
    BEGIN 
     INSERT [Log] ([Description]) VALUES ('Target received end dialog') 
     END CONVERSATION @Handle; 
    END  

    COMMIT TRANSACTION; 

    END 
GO 


IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[usp_InitiatorActivation]') AND type in (N'P', N'PC')) 
DROP PROCEDURE [dbo].[usp_InitiatorActivation] 
GO 

CREATE PROCEDURE [dbo].[usp_InitiatorActivation] 
AS 

    DECLARE @Handle UNIQUEIDENTIFIER; 
    DECLARE @Message XML; 
    DECLARE @MessageType sysname; 

BEGIN 

    INSERT [Log] ([Description]) VALUES ('Initiator activation') 

    WAITFOR 
    (RECEIVE TOP(1) 
     @Handle = conversation_handle, 
     @Message = message_body, 
     @MessageType = message_type_name 
     FROM InitiatorQueue 
    ), TIMEOUT 5000; 


    INSERT [Log] ([Description]) VALUES ('Initiator ' + ISNULL(CAST(@Handle AS VARCHAR(100)) , 'No handle') + ' message type:' + COALESCE(@MessageType,'No message type') + ' Body: ' + COALESCE(CAST(@Message AS varchar(1000)),'No body')) 

    IF @Handle IS NOT NULL 
    BEGIN 

     IF @MessageType = N'ReplyMessage' 
     BEGIN 
      INSERT [Log] ([Description]) VALUES ('Initiator received reply from target, end converstion') 
      END CONVERSATION @Handle; 
     END 


     IF @MessageType = N'http://schemas.microsoft.com/SQL/ServiceBroker/EndDialog' 
     BEGIN 
      INSERT [Log] ([Description]) VALUES ('Initiator received end dialog message') 
      END CONVERSATION @Handle; 
     END 
    END 
END 
GO 

GRANT EXECUTE ON [usp_TargetActivation] to [BrokerUser] 
GO 

GRANT EXECUTE ON [usp_InitiatorActivation] to [BrokerUser] 
GO 

IF EXISTS (SELECT * FROM sys.service_queues WHERE name = N'TargetQueue') 
ALTER QUEUE TargetQueue 
    WITH ACTIVATION 
    (STATUS = ON, 
     PROCEDURE_NAME = [usp_TargetActivation], 
     MAX_QUEUE_READERS = 1, 
     EXECUTE AS 'BrokerUser' 
    ); 
GO 

IF EXISTS (SELECT * FROM sys.service_queues WHERE name = N'InitiatorQueue') 
ALTER QUEUE InitiatorQueue 
    WITH ACTIVATION 
    (STATUS = ON, 
     PROCEDURE_NAME = [usp_InitiatorActivation], 
     MAX_QUEUE_READERS = 1, 
     EXECUTE AS 'BrokerUser' 
    ); 
GO 


IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[usp_QueueRequest]') AND type in (N'P', N'PC')) 
DROP PROCEDURE [dbo].[usp_QueueRequest] 
GO 

CREATE PROCEDURE [dbo].[usp_QueueRequest] 
    @numericvalue INT, 
    @StartDate DATE, 
    @TriggeredBy VARCHAR(50) 
AS 
BEGIN 
    DECLARE @Handle UNIQUEIDENTIFIER; 
    DECLARE @RequestMsg NVARCHAR(100); 

    DECLARE @MessageBody XML 
    DEClare @Params TABLE 
    (
     ReadingDate SMALLDATETIME, 
     SiteNumber INT, 
     TriggeredBy VARCHAR(50) 
    ) 
    INSERT INTO @Params(ReadingDate,SiteNumber, TriggeredBy) 
    VALUES(@StartDate, @numericvalue, @TriggeredBy) 

    SELECT @MessageBody = (SELECT * FROM @Params FOR XML PATH ('Params'), TYPE); 

    BEGIN TRANSACTION; 

    BEGIN DIALOG @Handle 
      FROM SERVICE [InitiatorService] 
      TO SERVICE 'TargetService' 
      ON CONTRACT [MessageContract] 
      WITH ENCRYPTION = OFF; 

    SEND ON CONVERSATION @Handle 
     MESSAGE TYPE 
      [RequestMessage] 
      (@MessageBody); 

    COMMIT TRANSACTION; 
END 
GO 
+0

Btw - 빈 메시지 본문의 이유는 초기화 프로그램 활성화 절차가 대상 활성화 절차와 동일한 패턴을 따르지 않기 때문입니다. (0 개의 메시지를 받으면 초보자 sproc이 종료되지 않습니다.) – etliens

답변

1

내 이해와 경험으로 대화가 끝나면 아무 것도하지 않아도됩니다. SQL Server는 자동으로 대화 정리를 관리합니다.

정말로 행이 사라 지길 원한다면; END CONVERSATION을 호출하면 WITH CLEANUP을 추가하면 SQL Server가 해당 트랜잭션의 일부로 대화를 정리합니다. 그러나 SQL Server에서 정리 작업을 관리하도록하면 성능이 향상됩니다.

+0

안녕하세요 Joseph, 대화가 정상적으로 완료 될 수 없을 때만 사용하도록되어 있으므로 CLEANUP을 사용하여 END CONVERSATION을하지 않아도된다는 점에서 저의 의견은 약간 다릅니다. (MSDN 문서 http://msdn.microsoft.com/en-us/library/ms177521%28v=sql.105%29.aspx) 상황에서 나는 대화 제거 호출의 양쪽에 자동 제거를위한 올바른 상태 인 것처럼 보이는 레코드를 넣는 END CONVERSATION을 설명했다. – Nathan

+1

이것이 정확히 적용되지는 않지만이 동작과 가장 가까운 것은 다음과 같습니다. http://social.msdn.microsoft.com/Forums/en/sqlservicebroker/thread/1605e757-0395-45e0 -82ba-7a247cced78f (Remus Rusanu의 게시물 참조) – etliens

관련 문제