SQL Server Service Broker - 消息超时

时间:2011-08-29 00:42:55

标签: sql sql-server message-queue service-broker

我正在研究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

2 个答案:

答案 0 :(得分:5)

可以在BEGIN DIALOG语句中指定对话框生存期:

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

对话框必须在其生命周期内完成(双方都是END),否则会出错。因此,您可以启动一个生命周期为2分钟的对话框,并在其上发送一条或多条消息。目标必须在2分钟内接收并处理消息,否则对话框将出错。

您还可以使用conversation priorities并在更高优先级的频道上发送时间敏感消息。这将确保Service Broker传输优先处理您的敏感消息,并且客户端应用程序RECEIVE语句“冒泡”优先级较高的时间敏感消息并首先接收它们。

答案 1 :(得分:3)

在不使用对话框生命周期的情况下实现所需内容的替代方法。

在消息有效负载中发送“SentDate”并在激活过程中处理“过期”消息。这使您能够明确决定消息过期时要执行的操作。 (即忽略过期的消息,记录到错误表,通知发件人迟到的消息等等。)