【SQL Server】Service Broker(SQL Server 内置的消息队列)——1.在单个数据库建完成对话

一般来说,在SQL Server中调用存储过程,是同步的。如果一个操作比较长或者处于分布式系统,那么我们我们希望执行异步操作。这时候,可以启用SQL Server Service Broker,这是一种内置的消息传递机制,用于在数据库内部或者数据库之间进行异步通信。

消息队列概念 。消息队列在SQL Server里,是一种存储消息的结构。消息生产者将消息发送到队列中,而消息消费者则从队列中读取并处理消息。这种机制实现了应用程序组件之间的异步通信,提高了系统的可扩展性和响应能力。

基本概念

服务(Service): 一个服务代表了一个可以接收或发送消息的组件。

队列(Queue):用于存储消息。

对话(Conversation):两个服务之间的一个对话,用于发送和接收消息。

消息类型(Message Type):定义了消息的结构和内容。

前提

数据库环境:SQL Server 2019

测试数据库名:myTest

消息队列位置

 接下来,我们会在同一个数据库间完成对话。

步骤

1.启用Server Broker(如果已启用,可跳过)。

2. 创建消息类型。

3. 创建协议。

4. 创建队列和服务。

5.启用会话并发发送消息。

6.接收消息。

1. 启用Server Broker;请确保数据库支持Server Broker (SQL Server 2008r2及其以上,请参考官网)。https://learn.microsoft.com/zh-cn/sql/database-engine/service-broker/lesson-1-creating-the-conversation-objects?view=sql-server-ver16

1 ALTER DATABASE myTest
2     SET ENABLE_BROKER;

 查看消息队列是否启用,可以使用视图:

SELECT   name,  is_broker_enabled  --9未启用,1:启用
FROM     sys.databases
WHERE   name = 'myTest'; --name:对照你的数据库名 

 2. 创建消息类型。消息队列类型包括XML、空消息、任意数据或二进制。

XML消息 WELL_FORMED_XML。如果消息类型指定为XML,Service Broker会在发送消息之前验证小时是否包含有效的XML.如果消息不符合XML格式,如果不符合XML格式,Service Broker会返回错误。
空消息  CREATE MESSAGE TYPE EmptyMessageType; 如果消息不符合XML格式,Service Broker会返回错误。
任意数据或二进制 NONE。消息类型可以执行为不进行任何验证,即Server Broker不会验证消息内容

消息类型名称以URL格式指定,例如 //服务器名/数据库名/消息类型名称 ,这样能确保它们在多台计算机上名称唯一。通常我们希望传递的消息是需要经过验证的,所以启用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;

 3.创建协定。 约定指定了使用此约定的会话必须将类型为 指定的发起方和接收方。

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

4. 创建队列和服务。需要创建发起方的队列和服务、接收方的队列和服务。在服务中,我们需要指定:服务名称、队列、约定。

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]);

以上步骤已经完成了基础数据的建设。接下来可以发送和接收请求了。

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

6. 接收请消息并结束会话。

 1 DECLARE @RecvReplyMsg NVARCHAR(100);            -- 返回消息
 2 DECLARE @RecvReplyDlgHandle UNIQUEIDENTIFIER;    -- 句柄
 3 
 4 
 5 BEGIN TRANSACTION;
 6 
 7 WAITFOR
 8 ( RECEIVE TOP(1)
 9     @RecvReplyDlgHandle = conversation_handle,
10     @RecvReplyMsg = message_body
11     FROM queue_reply
12 ), TIMEOUT 1000;
13 
14 END CONVERSATION @RecvReplyDlgHandle;
15 
16 -- 设置句柄
17 SELECT @RecvReplyMsg AS ReceivedReplyMsg;
18 
19 COMMIT TRANSACTION;
20 GO

查看队列信息

SELECT *
FROM queue_reply

 

posted @ 2025-01-20 13:39  陆陆无为而治者  阅读(173)  评论(0)    收藏  举报