2011-08-29 80 views
0

我正在研究sql server服務代理作爲我們應用程序的消息處理技術。SQL Server服務代理 - 消息超時

在我們的場景中,從一個客戶端應用程序(WPF)發送的消息需要在服務代理中排隊等待其他客戶端應用程序(android)接收。這些消息是時間敏感的,並且需要在「X」分鐘內(例如2分鐘)在接收器中被接收到,並且如果它不能被接收,那麼消息需要被過期並從隊列。

有沒有辦法告訴服務代理在「x」分鐘後超時?

編輯:添加了我用來測試這個腳本。

CREATE DATABASE ServiceBrokerTest 
GO 

ALTER DATABASE ServiceBrokerTest SET ENABLE_BROKER WITH ROLLBACK IMMEDIATE 
GO 

/****** Object: MessageType [SampleMsgType] ***/ 
CREATE MESSAGE TYPE [SampleMsgType] AUTHORIZATION [dbo] VALIDATION = NONE 
GO 

/****** Object: ServiceContract [MsgContract] ******/ 
CREATE CONTRACT [MsgContract] AUTHORIZATION [dbo] ([SampleMsgType] SENT BY INITIATOR) 
GO 

/****** Object: ServiceQueue [dbo].[Queue1] ******/ 
CREATE QUEUE [dbo].[Queue1] WITH STATUS = ON , RETENTION = OFF , POISON_MESSAGE_HANDLING (STATUS = ON) ON [PRIMARY] 
GO 

/****** Object: BrokerService [MsgService] ******/ 
CREATE SERVICE [MsgService] AUTHORIZATION [dbo] ON QUEUE [dbo].[Queue1] ([MsgContract]) 
GO 

/****** Object: StoredProcedure [dbo].[SendMsg] ******/ 
CREATE PROC [dbo].[SendMsg] 
@msg NVARCHAR(MAX) 
AS 

BEGIN 
    SET NOCOUNT ON 
    DECLARE @handle UNIQUEIDENTIFIER 

    BEGIN TRANSACTION 
     BEGIN dialog @handle 
      FROM SERVICE [MsgService] 
      TO SERVICE 'MsgService' 
      ON CONTRACT [MsgContract] 
      WITH ENCRYPTION = OFF, LIFETIME = 20 

     ;SEND ON CONVERSATION @handle 
      MESSAGE TYPE [SampleMsgType] (@msg) 
     END CONVERSATION @handle 
    COMMIT TRANSACTION 
END 

/****** Object: StoredProcedure [dbo].[ReceiveMsg] ******/ 
CREATE PROC [dbo].[ReceiveMsg] 
@msg NVARCHAR(MAX) OUT 

AS 

BEGIN 
    SET NOCOUNT ON 
    DECLARE @handle UNIQUEIDENTIFIER 

    DECLARE @msgTable TABLE (
     handle UNIQUEIDENTIFIER, 
     msg NVARCHAR(MAX), 
     msgType VARCHAR(300)); 

    SET @handle = NULL 

    WAITFOR (
     RECEIVE [conversation_handle], message_body, message_type_name 
     FROM [dbo].[Queue1] 
     INTO @msgTable 
     ), TIMEOUT 25000 

     SELECT @handle = handle 
     FROM @msgTable 
     WHERE msgType = 'http://schemas.microsoft.com/SQL/ServiceBroker/EndDialog' 

     IF @handle is not null 
      BEGIN 
       END CONVERSATION @handle 
      END 

     SELECT @msg = msg 
     FROM @msgTable 
     WHERE msgType = 'SampleMsgType' 
END 

GO 

回答

4

對話框壽命可以在BEGIN DIALOG語句中指定:

BEGIN DIALOG @handle 
FROM SERVICE [...] 
TO SERVICE '...' 
ON CONTRACT [...] 
, LIFETIME = <dialog lifetime>; 

對話框有其生命週期內完成(雙方END),否則會報錯了。所以你可以開始一個2分鐘的對話並在其上發送一個或多個消息。目標必須在2分鐘內收到並處理消息,否則對話框將出錯。

您也可以使用conversation priorities並在較高優先級的通道上發送對時間敏感的消息。這將確保Service Broker傳輸優先考慮您的敏感消息,並且客戶端應用程序的RECEIVE語句會將優先級較高的時間敏感消息「冒起來」,並首先收到它們。

+0

感謝您的回覆。我按照你的建議嘗試過,但這些消息在設置的生命週期(25秒)後沒有過期。即使在25秒後,我仍能收到消息。我編輯了我的問題以包含我正在使用的腳本。如果我可以指出我在那裏做錯了什麼,那將會很棒。 – muruge

+2

@muruge - 我相信你需要在對話的發起者一側留下對話框,以便獲取代理超時錯誤消息。 – etliens

+0

@muruge - 你還在使用SSB的「消防和遺忘」反模式,Remus可以告訴你一切。 – etliens

3

替代方式來實現你想要的東西,而不使用對話框的生命週期。

發送消息載荷中的「SentDate」並在激活過程中處理「過期」消息。這使您能夠明確決定消息何時到期應該如何處理。 (即忽略過期的消息,記錄到錯誤表,通知發送者哪些消息遲到等。)