SQL 服务器服务代理结束对话在启动器队列上创建新条目
SQL Server service broker end conversation creates new entries on initiator queue
我们正在使用 SQL Service Broker,为启动器和目标使用两个服务,然后我们有一个 C# 服务侦听和接收来自队列的消息。
在 SQL 端,设置是这样的:
CREATE MESSAGE TYPE [http://mycompany.com/MyEventRequestMessage] VALIDATION = WELL_FORMED_XML
GO
CREATE MESSAGE TYPE [http://mycompany.com/MyEventResponseMessage] VALIDATION = WELL_FORMED_XML
GO
CREATE CONTRACT [http://mycompany.com/MyMessageContract] ([http://mycompany.com/MyEventRequestMessage] SENT BY INITIATOR,
[http://mycompany.com/MyEventResponseMessage] SENT BY TARGET)
GO
CREATE QUEUE [dbo].[MyEventInitiatorQueue] WITH STATUS = ON , RETENTION = OFF , POISON_MESSAGE_HANDLING (STATUS = ON) ON [PRIMARY]
GO
CREATE QUEUE [dbo].[MyEventTargetQueue] WITH STATUS = ON , RETENTION = OFF , POISON_MESSAGE_HANDLING (STATUS = ON) ON [PRIMARY]
GO
CREATE SERVICE [MyEventInitiatorService] ON QUEUE [dbo].[MyEventInitiatorQueue] ([http://mycompany.com/MyMessageContract])
GO
CREATE SERVICE [MyEventTargetService] ON QUEUE [dbo].[MyEventTargetQueue] ([http://mycompany.com/MyMessageContract])
GO
然后如果我插入一条消息:
DECLARE @MessageType NVARCHAR(128) = 'http://mycompany.com/MyEventRequestMessage'
DECLARE @MessageBody NVARCHAR(128) = 'loremipsum'
DECLARE @FromService NVARCHAR(128) = 'MyEventInitiatorService'
DECLARE @ToService NVARCHAR(128) = 'MyEventTargetService'
DECLARE @Contract NVARCHAR(128) = 'http://mycompany.com/MyMessageContract'
DECLARE @conversation_handle UNIQUEIDENTIFIER;
BEGIN DIALOG CONVERSATION @conversation_handle
FROM SERVICE @FromService
TO SERVICE @ToService
ON CONTRACT @Contract
WITH ENCRYPTION = OFF;
SEND ON CONVERSATION @conversation_handle
MESSAGE TYPE @MessageType(@MessageBody);
如期到达目标队列。
然后在服务上我们从目标队列接收消息并执行结束对话。
消息从目标队列中消失,但随后在启动器队列中插入一条类型为 http://schemas.microsoft.com/SQL/ServiceBroker/EndDialog 的新消息。
尽管我们的服务已准备好结束这些对话,但它正在侦听目标队列。
我们如何清除这些结束对话消息?我们是否也应该在发起者队列中监听这些类型的消息,以便结束对话,或者我们应该做其他事情吗?
如果不采取任何措施,我们担心这是否会对数据库或服务器造成任何副作用。
谢谢。
How can we clear these end dialog messages? Should we listen also on
the initiator queue these kind of messages, in order to end the
conversation, or should we do anything else?
是的,您还需要一个服务(技术上是任何 SQL 进程)来侦听启动器队列消息,以便在收到 EndDialog 或 Error 消息时结束对话的那一侧。考虑记录任何意外消息类型(即 EndDialog 以外的消息类型)。
如果不采取任何措施,您最终会用不需要的启动器队列消息填满数据数据库,
我认为我们找到了符合 Dan 评论的解决方案:
CREATE PROCEDURE spHandleInitiatorQueueMessages
AS
DECLARE @dh UNIQUEIDENTIFIER;
DECLARE @message_type SYSNAME;
DECLARE @message_body NVARCHAR(4000);
BEGIN TRANSACTION;
WAITFOR (
RECEIVE @dh = [conversation_handle],
@message_type = [message_type_name],
@message_body = CAST([message_body] AS NVARCHAR(4000))
FROM MyInitiatorQueue), TIMEOUT 1000;
WHILE @dh IS NOT NULL
BEGIN
IF @message_type = N'http://schemas.microsoft.com/SQL/ServiceBroker/Error'
BEGIN
RAISERROR (N'Received error %s from service [Target]', 10, 1, @message_body) WITH LOG;
END
END CONVERSATION @dh;
COMMIT;
SELECT @dh = NULL;
BEGIN TRANSACTION;
WAITFOR (
RECEIVE @dh = [conversation_handle],
@message_type = [message_type_name],
@message_body = CAST([message_body] AS NVARCHAR(4000))
FROM MyInitiatorQueue), TIMEOUT 1000;
END
COMMIT;
GO
ALTER QUEUE MyInitiatorQueue
WITH ACTIVATION (
STATUS = ON,
MAX_QUEUE_READERS = 1,
PROCEDURE_NAME = spHandleInitiatorQueueMessages,
EXECUTE AS OWNER);
GO
消息开始实际结束
我们正在使用 SQL Service Broker,为启动器和目标使用两个服务,然后我们有一个 C# 服务侦听和接收来自队列的消息。
在 SQL 端,设置是这样的:
CREATE MESSAGE TYPE [http://mycompany.com/MyEventRequestMessage] VALIDATION = WELL_FORMED_XML
GO
CREATE MESSAGE TYPE [http://mycompany.com/MyEventResponseMessage] VALIDATION = WELL_FORMED_XML
GO
CREATE CONTRACT [http://mycompany.com/MyMessageContract] ([http://mycompany.com/MyEventRequestMessage] SENT BY INITIATOR,
[http://mycompany.com/MyEventResponseMessage] SENT BY TARGET)
GO
CREATE QUEUE [dbo].[MyEventInitiatorQueue] WITH STATUS = ON , RETENTION = OFF , POISON_MESSAGE_HANDLING (STATUS = ON) ON [PRIMARY]
GO
CREATE QUEUE [dbo].[MyEventTargetQueue] WITH STATUS = ON , RETENTION = OFF , POISON_MESSAGE_HANDLING (STATUS = ON) ON [PRIMARY]
GO
CREATE SERVICE [MyEventInitiatorService] ON QUEUE [dbo].[MyEventInitiatorQueue] ([http://mycompany.com/MyMessageContract])
GO
CREATE SERVICE [MyEventTargetService] ON QUEUE [dbo].[MyEventTargetQueue] ([http://mycompany.com/MyMessageContract])
GO
然后如果我插入一条消息:
DECLARE @MessageType NVARCHAR(128) = 'http://mycompany.com/MyEventRequestMessage'
DECLARE @MessageBody NVARCHAR(128) = 'loremipsum'
DECLARE @FromService NVARCHAR(128) = 'MyEventInitiatorService'
DECLARE @ToService NVARCHAR(128) = 'MyEventTargetService'
DECLARE @Contract NVARCHAR(128) = 'http://mycompany.com/MyMessageContract'
DECLARE @conversation_handle UNIQUEIDENTIFIER;
BEGIN DIALOG CONVERSATION @conversation_handle
FROM SERVICE @FromService
TO SERVICE @ToService
ON CONTRACT @Contract
WITH ENCRYPTION = OFF;
SEND ON CONVERSATION @conversation_handle
MESSAGE TYPE @MessageType(@MessageBody);
如期到达目标队列。
然后在服务上我们从目标队列接收消息并执行结束对话。
消息从目标队列中消失,但随后在启动器队列中插入一条类型为 http://schemas.microsoft.com/SQL/ServiceBroker/EndDialog 的新消息。
尽管我们的服务已准备好结束这些对话,但它正在侦听目标队列。
我们如何清除这些结束对话消息?我们是否也应该在发起者队列中监听这些类型的消息,以便结束对话,或者我们应该做其他事情吗?
如果不采取任何措施,我们担心这是否会对数据库或服务器造成任何副作用。
谢谢。
How can we clear these end dialog messages? Should we listen also on the initiator queue these kind of messages, in order to end the conversation, or should we do anything else?
是的,您还需要一个服务(技术上是任何 SQL 进程)来侦听启动器队列消息,以便在收到 EndDialog 或 Error 消息时结束对话的那一侧。考虑记录任何意外消息类型(即 EndDialog 以外的消息类型)。
如果不采取任何措施,您最终会用不需要的启动器队列消息填满数据数据库,
我认为我们找到了符合 Dan 评论的解决方案:
CREATE PROCEDURE spHandleInitiatorQueueMessages
AS
DECLARE @dh UNIQUEIDENTIFIER;
DECLARE @message_type SYSNAME;
DECLARE @message_body NVARCHAR(4000);
BEGIN TRANSACTION;
WAITFOR (
RECEIVE @dh = [conversation_handle],
@message_type = [message_type_name],
@message_body = CAST([message_body] AS NVARCHAR(4000))
FROM MyInitiatorQueue), TIMEOUT 1000;
WHILE @dh IS NOT NULL
BEGIN
IF @message_type = N'http://schemas.microsoft.com/SQL/ServiceBroker/Error'
BEGIN
RAISERROR (N'Received error %s from service [Target]', 10, 1, @message_body) WITH LOG;
END
END CONVERSATION @dh;
COMMIT;
SELECT @dh = NULL;
BEGIN TRANSACTION;
WAITFOR (
RECEIVE @dh = [conversation_handle],
@message_type = [message_type_name],
@message_body = CAST([message_body] AS NVARCHAR(4000))
FROM MyInitiatorQueue), TIMEOUT 1000;
END
COMMIT;
GO
ALTER QUEUE MyInitiatorQueue
WITH ACTIVATION (
STATUS = ON,
MAX_QUEUE_READERS = 1,
PROCEDURE_NAME = spHandleInitiatorQueueMessages,
EXECUTE AS OWNER);
GO
消息开始实际结束