SQL Server Service Broker - 消息超时

发布于 2024-12-01 14:49:16 字数 2387 浏览 0 评论 0原文

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

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_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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

久夏青 2024-12-08 14:49:17

可以在BEGIN DIALOG 语句:

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

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

您还可以使用对话优先级并以更高的优先级发送对时间敏感的邮件优先通道。这将确保 Service Broker 传输优先考虑您的敏感消息,并且客户端应用程序 RECEIVE 语句“冒泡”较高优先级的时间敏感消息,并且首先接收它们。

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.

怎会甘心 2024-12-08 14:49:17

不使用对话框生命周期即可实现您想要的效果的另一种方法。

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

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..)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文