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..)
精彩评论