【SQL Server】Service Broker(SQL Server 内置的消息队列)——2.实现内部激活

前面我已经能够通过SQL Server Broker完成简单的内置消息队列。接下来,我们要了解内部激活流程。

是什么意思呢?我们在需要的时候发送了消息队列?那什么时候接收呢?

1. 使用SQL Server Agnent,创建作业,设置了作业调度。在作业中调度消息队列。(SQL Server作业调度:https://www.cnblogs.com/luyj00436/p/18724042

2. 完成接收消息的存储过程。在接收的队列中,设置激活的存储过程。

回顾基础的消息队里,关键代码如下:

1. 创建消息类型(XML)

1 CREATE MESSAGE TYPE [//AWD/myTest/msgType_request_xml] VALIDATION=WELL_FORMED_XML;
2 CREATE MESSAGE TYPE [//AWD/myTest/msgType_reply_xml] VALIDATION=WELL_FORMED_XML;

2. 创建协定

1 CREATE CONTRACT [//AWD/myTest/contract_default] (
2     [//AWD/myTest/msgType_request_xml] SENT BY INITIATOR,
3     [//AWD/myTest/msgType_reply_xml] SENT BY TARGET
4 );

3. 创建队列和服务

1 -- 发送方方队列和服务(由于未指定约定名称,其他服务不可将此服务用作目标服务)
2 CREATE QUEUE queue_request;
3 CREATE SERVICE [//AWD/myTest/service_request]
4     ON QUEUE queue_request;
5 -- 接收方队列和服务
6 CREATE QUEUE queue_reply;
7 CREATE SERVICE [//AWD/myTest/service_reply]
8     ON QUEUE queue_reply
9     ([//AWD/myTest/contract_default]);

4. 启用会话并发送消息

 1 DECLARE @InitDlgHandle UNIQUEIDENTIFIER; -- 发送句柄
 2 DECLARE @RequestMsg NVARCHAR(100);   -- 发送消息
 3 
 4 BEGIN TRANSACTION;
 5 
 6 BEGIN DIALOG @InitDlgHandle
 7         FROM SERVICE
 8         [//AWD/myTest/service_request]    -- 发送方服务请求
 9         TO SERVICE
10         '//AWD/myTest/service_reply'    -- 接收方服务请求(注意要写正确)
11         ON CONTRACT
12         [//AWD/myTest/contract_default]    -- 约定
13         WITH
14             ENCRYPTION = OFF;
15 
16 SELECT @RequestMsg =
17         N'<RequestMsg>Message for Target service.</RequestMsg>';
18 
19 SEND ON CONVERSATION @InitDlgHandle
20         MESSAGE TYPE
21         [//AWD/myTest/msgType_request_xml]    -- 消息类型
22         (@RequestMsg);
23 
24 SELECT @RequestMsg AS SentRequestMsg;
25 
26 COMMIT TRANSACTION;
27 GO

5. 接收消息并结束会话。

 1 DECLARE @InitDlgHandle UNIQUEIDENTIFIER; -- 发送句柄
 2 DECLARE @RequestMsg NVARCHAR(100);   -- 发送消息
 3 
 4 BEGIN TRANSACTION;
 5 
 6 BEGIN DIALOG @InitDlgHandle
 7         FROM SERVICE
 8         [//AWD/myTest/service_request]    -- 发送方服务请求
 9         TO SERVICE
10         '//AWD/myTest/service_reply'    -- 接收方服务请求(注意要写正确)
11         ON CONTRACT
12         [//AWD/myTest/contract_default]    -- 约定
13         WITH
14             ENCRYPTION = OFF;
15 
16 SELECT @RequestMsg =
17         N'<RequestMsg>Message for Target service.</RequestMsg>';
18 
19 SEND ON CONVERSATION @InitDlgHandle
20         MESSAGE TYPE
21         [//AWD/myTest/msgType_request_xml]    -- 消息类型
22         (@RequestMsg);
23 
24 SELECT @RequestMsg AS SentRequestMsg;
25 
26 COMMIT TRANSACTION;
27 GO

 实现内部激活

实现内部激活。消息、协定、服务、队列的方法与前文一致。现在已创建内如如下:

消息类型:[//AWD/myTest/msgType_request_xml]  [//AWD/myTest/msgType_reply_xml]

协定:[//AWD/myTest/contract_default]

队列:QUEUE queue_requestQUEUE queue_reply

服务:[//AWD/myTest/service_reply][//AWD/myTest/service_reply]

1. 新建接收消息的存储过程。只要队列中有消息,存储过程就会持续接收和处理( 这里直接抄官网,队列名称等可能不一致)。

 1 CREATE PROCEDURE TargetActiveProc
 2     AS
 3       DECLARE @RecvReqDlgHandle UNIQUEIDENTIFIER;
 4       DECLARE @RecvReqMsg NVARCHAR(100);
 5       DECLARE @RecvReqMsgName sysname;
 6 
 7       WHILE (1=1)
 8       BEGIN
 9 
10         BEGIN TRANSACTION;
11 
12         WAITFOR
13         ( RECEIVE TOP(1)
14             @RecvReqDlgHandle = conversation_handle,
15             @RecvReqMsg = message_body,
16             @RecvReqMsgName = message_type_name
17           FROM TargetQueueIntAct
18         ), TIMEOUT 5000;
19 
20         IF (@@ROWCOUNT = 0)
21         BEGIN
22           ROLLBACK TRANSACTION;
23           BREAK;
24         END
25 
26         IF @RecvReqMsgName =
27            N'//AWDB/InternalAct/RequestMessage'
28         BEGIN
29            DECLARE @ReplyMsg NVARCHAR(100);
30            SELECT @ReplyMsg =
31            N'<ReplyMsg>Message for Initiator service.</ReplyMsg>';
32 
33            SEND ON CONVERSATION @RecvReqDlgHandle
34                   MESSAGE TYPE
35                   [//AWDB/InternalAct/ReplyMessage]
36                   (@ReplyMsg);
37         END
38         ELSE IF @RecvReqMsgName =
39             N'https://schemas.microsoft.com/SQL/ServiceBroker/EndDialog'
40         BEGIN
41            END CONVERSATION @RecvReqDlgHandle;
42         END
43         ELSE IF @RecvReqMsgName =
44             N'https://schemas.microsoft.com/SQL/ServiceBroker/Error'
45         BEGIN
46            END CONVERSATION @RecvReqDlgHandle;
47         END
48 
49         COMMIT TRANSACTION;
50 
51       END
52     GO

 2. 更改目标队列,以指定激活。

1 ALTER QUEUE TargetQueueIntAct
2         WITH ACTIVATION
3         ( STATUS = ON,
4           PROCEDURE_NAME = TargetActiveProc,
5           MAX_QUEUE_READERS = 10,
6           EXECUTE AS SELF
7         );
8     GO

MAX_QUEUE_READERS 指:MAX_QUEUE_READERS‌ 是 SQL ServerService Broker 的一个属性,用于限制同时读取队列消息的进程数量。当你在 CREATE QUEUEALTER QUEUE 语句中设置 MAX_QUEUE_READERS 时,可以指定一个最大值,该值表示同时可以激活的最大队列读取器数量。如果激活任务的数量超过这个限制,Service Broker 会忽略 MAX_QUEUE_READERS 设置,继续运行额外的激活任务‌1。

posted @ 2025-02-20 16:21  陆陆无为而治者  阅读(37)  评论(0)    收藏  举报