开发者

SQL Server Service Broker - Message Timeout

I am researching sql server service broker as a message processing technology for our application.

In our scenario, the messages that are sent from one client application (WPF) needs to be queued up in service broker that will be received by other client applications (android). The messages are time-sensitive and needs to be received by the receiver within "X" minutes (for instance 2 minutes) from being posted in the queue and if it cannot be received by then, the messages needs to be expired and removed from the queue.

Is there a way to tell service broker to time-out a message after "x" minutes?

Edit: Added script that I am using to test this.

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_n开发者_StackOverflow社区ame
        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


Dialog lifetime can be specified during the BEGIN DIALOG statement:

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

The dialog has to complete (END by both sides) within its lifetime, or it will error out. So you can start a dialog with a lifetime of 2 minutes and send one or more messages on it. The target must receive and process the message in those 2 minutes, or the dialog will error.

You can also use conversation priorities and send the time sensitive messages on a higher priority channel. This will ensure that the Service Broker transmission gives priority to your sensitive messages and the client application RECEIVE statement 'bubbles up' the higher priority time sensitive messages and they are received first.


Alternate way to achieve what you want without using the dialog lifetime.

Send the "SentDate" in your message payload and handle "expired" messages in your activation procedure. This gives you the ability to explicitly decide what to do when a message expires. (i.e. ignoring expired messages, logging to an error table, notifying sender of which messages are being received late etc..)

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜