SQL Server 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
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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
可以在
BEGIN DIALOG
语句:对话必须在其生命周期内完成(双方均结束),否则会出错。因此,您可以启动一个生命周期为 2 分钟的对话,并在其上发送一条或多条消息。目标必须在这 2 分钟内接收并处理该消息,否则对话框将出错。
您还可以使用对话优先级并以更高的优先级发送对时间敏感的邮件优先通道。这将确保 Service Broker 传输优先考虑您的敏感消息,并且客户端应用程序 RECEIVE 语句“冒泡”较高优先级的时间敏感消息,并且首先接收它们。
Dialog lifetime can be specified during the
BEGIN DIALOG
statement: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.
不使用对话框生命周期即可实现您想要的效果的另一种方法。
在消息负载中发送“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..)