Service Broker基础应用(上)

数据库 SQL Server
本文主要涉及Service Broker的基本概念及建立一个Service Broker应用程序的基本步骤。

导读:本文主要涉及Service Broker的基本概念及建立一个Service Broker应用程序的基本步骤。

一、前言

Service Broker为SQL Server提供消息队列,这提供了从数据库中发送异步事务性消息队列的方法。Service Broker消息可以保证以适当的顺序或原始的发送顺序不重复地一次性接收。并且因为内建在SQL Server中,这些消息在数据库发生故障时是可以恢复的,也可以随数据库一起备份。在SQL Server 2008中,还引入了使用Create Broker Priority命令对会话设定优先级,可以对重要的或不重要的会话进行优先级设定,以保证消息合理地处理。

本文假定一个在线数据库BookStore中存储了一些业务订单。我们使用Service Broker应用程序将消息发送到另一个数据库BookDistribution,该数据库是分离的应用程序调用,该应用程序控制仓库入库和出库交付, 并返回消息给BookStore。

创建Service Broker应用程序大体步骤如下:

1、定义希望应用程序执行的异步任务。

2、确定Service Broker的发起方服务和目标服务是否创建在同一个SQL Server实例中。如果是两个实例,实例间的通信还需要创建经过证书认证或NT安全的身份认证,并且要创建端点、路由以及对话安全模式。

3、如果没有启用,则在多方参与的数据库中使用Alter Database命令设置Enable_broker以及Truseworthy数据库选项。

4、为所有多方参与的数据库创建数据库主密钥。

5、创建希望在服务之间发送的消息类型。

6、创建契约(Contract)来定义可以由发起方发送的各种消息以及由目标发送的消息类型的种类。

7、同时在两方参与的数据库中创建用于保存消息的队列。

8、同时在绑定特定约定到特定队列的多方参与的数据库中创建服务。

二、实例

下面我们通过一个示例来实现以上步骤:

(一)、启用数据库的Service Broker活动

-- Enabling Databases for Service Broker Activity USE master GO IF NOT EXISTS (SELECT name FROM sys.databases WHERE name = 'BookStore') CREATE DATABASE BookStore GO IF NOT EXISTS (SELECT name FROM sys.databases WHERE name = 'BookDistribution') CREATE DATABASE BookDistribution GO ALTER DATABASE BookStore SET ENABLE_BROKER GO ALTER DATABASE BookStore SET TRUSTWORTHY ON GO ALTER DATABASE BookDistribution SET ENABLE_BROKER GO ALTER DATABASE BookDistribution SET TRUSTWORTHY ON
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.

(二)、创建数据库主密钥

-- Creating the DatabaseMaster Key for Encryption USE BookStore GO CREATE MASTER KEY ENCRYPTION BY PASSWORD = 'I5Q7w1d3' GO USE BookDistribution GO CREATE MASTER KEY ENCRYPTION BY PASSWORD = 'D1J3q5z8X6y4' GO
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.

(三)、管理消息类型

使用CREATE MESSAGE TYPE(http://msdn.microsoft.com/en-us/library/ms187744.aspx)命令,

-- Managing Message Types Use BookStore GO -- 发送图书订单的消息类型 CREATE MESSAGE TYPE [//SackConsulting/SendBookOrder] VALIDATION = WELL_FORMED_XML GO --目标数据库发送的消息类型 CREATE MESSAGE TYPE [//SackConsulting/BookOrderReceived] VALIDATION = WELL_FORMED_XML GO --执行同样的定义 Use BookDistribution GO -- 发送图书订单的消息类型 CREATE MESSAGE TYPE [//SackConsulting/SendBookOrder] VALIDATION = WELL_FORMED_XML GO --目标数据库发送的消息类型 CREATE MESSAGE TYPE [//SackConsulting/BookOrderReceived] VALIDATION = WELL_FORMED_XML GO
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.

--注意,此处没有定义消息的内容。实际的消息是消息类型的实例。

(四)、创建契约(Contract)

使用Create Contract(http://msdn.microsoft.com/en-us/library/ms178528.aspx

-- Creating Contracts Use BookStore GO CREATE CONTRACT [//SackConsulting/BookOrderContract] ( [//SackConsulting/SendBookOrder] SENT BY INITIATOR, [//SackConsulting/BookOrderReceived] SENT BY TARGET ) GO USE BookDistribution GO CREATE CONTRACT [//SackConsulting/BookOrderContract] ( [//SackConsulting/SendBookOrder] SENT BY INITIATOR, [//SackConsulting/BookOrderReceived] SENT BY TARGET ) GO
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.

--发起方和目标的定义必须相同

(五)、创建队列

队列用来保存数据。使用命令Create queue(http://msdn.microsoft.com/en-us/library/ms190495.aspx

-- Creating Queues Use BookStore GO --保存BookDistribution过来的消息 CREATE QUEUE BookStoreQueue WITH STATUS=ON GO USE BookDistribution GO --保存BookStore过来的消息 CREATE QUEUE BookDistributionQueue WITH STATUS=ON GO
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.

(六)、创建服务

服务定义端点,然后使用它来将消息队列绑定到一个或多个契约上。服务使用队列和契约来定义一个或一组任务。有点拗口,是不是?

服务是消息的发起方和接收方强制约定的规则,并将消息路由到正确的序列。

使用Create Service(http://msdn.microsoft.com/en-us/library/ms190332.aspx)命令。

-- Creating Services Use BookStore GO CREATE SERVICE [//SackConsulting/BookOrderService] ON QUEUE dbo.BookStoreQueue--指定的队列绑定到契约 ([//SackConsulting/BookOrderContract]) GO USE BookDistribution GO CREATE SERVICE [//SackConsulting/BookDistributionService] ON QUEUE dbo.BookDistributionQueue--指定的队列绑定到契约 ([//SackConsulting/BookOrderContract]) GO
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.

(七)、启动对话

对话会话(dialog conservation)是在服务之间进行消息交换的操作。

使用Begin Dialog Conversation(http://msdn.microsoft.com/en-us/library/ms187377.aspx) 命令创建新的会话。使用Send(http://msdn.microsoft.com/en-us/library/ms188407.aspx)来发送消息。使用End Conversation命令(http://msdn.microsoft.com/en-us/library/ms177521.aspx)结束会话。

-- Initiating a Dialog Use BookStore GO --保存会话句柄和订单信息 DECLARE @Conv_Handler uniqueidentifier DECLARE @OrderMsg xml; BEGIN DIALOG CONVERSATION @Conv_Handler--创建会话 FROM SERVICE [//SackConsulting/BookOrderService] TO SERVICE '//SackConsulting/BookDistributionService' ON CONTRACT [//SackConsulting/BookOrderContract]; SET @OrderMsg = '<order id="3439" customer="22" orderdate="2/15/2011"> <LineItem ItemNumber="1" ISBN="1-59059-592-0" Quantity="1" /> </order>'; SEND ON CONVERSATION @Conv_Handler--发送到BookDistribution数据库的队列中 MESSAGE TYPE [//SackConsulting/SendBookOrder] (@OrderMsg);
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.

(八)、查询队列中传入的消息

-- Querying the Queue for IncomingMessages USE BookDistribution GO SELECT message_type_name, CAST(message_body as xml) message, queuing_order, conversation_handle, conversation_group_id FROM dbo.BookDistributionQueue
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.

查询结果:

(九)、检索并响应消息

使用Receive语句(http://msdn.microsoft.com/en-us/library/ms186963.aspx)从队列中读取行(消息),也可以删除已经读取的消息。Receive的结果可以填充到常规表中,也可以在局部变量中执行其他操作,或发送到其他service Broker消息。如果消息是XML数据类型的消息,则可以直接借助TSQL的XQuery来操作。

-- Receiving and Responding to aMessage USE BookDistribution GO --创建一个表存放接收到的订单信息 CREATE TABLE dbo.BookOrderReceived (BookOrderReceivedID int IDENTITY (1,1) NOT NULL, conversation_handle uniqueidentifier NOT NULL, conversation_group_id uniqueidentifier NOT NULL, message_body xml NOT NULL) GO -- 声明变量 DECLARE @Conv_Handler uniqueidentifier DECLARE @Conv_Group uniqueidentifier DECLARE @OrderMsg xml DECLARE @TextResponseMsg varchar(8000) DECLARE @ResponseMsg xml DECLARE @OrderID int; --从队列中获取消息,将接收值赋于局部变量 RECEIVE TOP(1) @OrderMsg = message_body,--TOP指定最多一条消息 @Conv_Handler = conversation_handle, @Conv_Group = conversation_group_id FROM dbo.BookDistributionQueue; -- 将变量值插入表中 INSERT dbo.BookOrderReceived (conversation_handle, conversation_group_id, message_body) VALUES (@Conv_Handler,@Conv_Group, @OrderMsg ) -- 使用XQuery进行抽取以响应消息订单 SELECT @OrderID = @OrderMsg.value('(/order/@id)[1]', 'int' ) SELECT @TextResponseMsg = '<orderreceived id= "' + CAST(@OrderID as varchar(10)) + '"/>'; SELECT @ResponseMsg = CAST(@TextResponseMsg as xml); -- 使用既有的会话句柄,发送响应消息到发起方 SEND ON CONVERSATION @Conv_Handler MESSAGE TYPE [//SackConsulting/BookOrderReceived]
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.

(十)、结束会话

-- Ending a Conversation USE BookStore GO -- 创建订单确认表 CREATE TABLE dbo.BookOrderConfirmation (BookOrderConfirmationID int IDENTITY (1,1) NOT NULL, conversation_handle uniqueidentifier NOT NULL, DateReceived datetime NOT NULL DEFAULT GETDATE(), message_body xml NOT NULL) DECLARE @Conv_Handler uniqueidentifier DECLARE @Conv_Group uniqueidentifier DECLARE @OrderMsg xml DECLARE @TextResponseMsg varchar(8000); RECEIVE TOP(1) @Conv_Handler = conversation_handle, @OrderMsg = message_body FROM dbo.BookStoreQueue INSERT dbo.BookOrderConfirmation (conversation_handle, message_body) VALUES (@Conv_Handler,@OrderMsg ); END CONVERSATION @Conv_Handler; GO USE BookDistribution GO DECLARE @Conv_Handler uniqueidentifier DECLARE @Conv_Group uniqueidentifier DECLARE @OrderMsg xml DECLARE @message_type_name nvarchar(256); RECEIVE TOP(1) @Conv_Handler = conversation_handle, @OrderMsg = message_body, @message_type_name = message_type_name FROM dbo.BookDistributionQueue -- 双方必须都结束会话 IF @message_type_name = 'http://schemas.microsoft.com/SQL/ServiceBroker/EndDialog' BEGIN END CONVERSATION @Conv_Handler; END
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.

--查询会话状态

SELECT state_desc, conversation_handle FROM sys.conversation_endpoints
  • 1.
  • 2.

三、小结

本文通过一个实例演示了一个用来发送图书订单消息分发控制数据库的简单的消息交换应用程序。发起方发送图书订单,发回一个响应,并在两个数据库上使用END Conservation结束会话。现实场景中可以转换为其他消息类型、契约、服务和队列。合理运用Service Broker应用程序的异步特性可以防止因应用程序挂起而导致业务系统产生瓶颈。

原文链接:http://www.cnblogs.com/downmoon/archive/2011/04/05/2005900.html

【编辑推荐】

  1. 简述Service Broker事件通知功能
  2. 一个Excel导入SQL Server的例子
  3. 优化你的DiscuzNT,让它跑起来
  4. 浅述当前模式读与一致性读续
  5. 浅述当前模式读与一致性读的区别

 

责任编辑:艾婧 来源: 博客园
相关推荐

2011-05-06 15:48:35

Service BroSQL Server

2015-03-30 14:57:03

paascloudfoundrservice bro

2011-05-06 15:00:52

Service BroSQL Server

2011-05-06 15:54:47

Service BroSQL Server

2015-03-30 15:15:00

CloudFoundrPaaS开源

2011-08-29 11:25:29

清空service bSQL Server

2011-07-06 15:33:02

ASP

2021-06-02 08:07:59

LinuxService应用

2011-04-15 09:49:33

NAT

2016-09-20 21:32:16

DockerLinux Names

2022-08-31 09:21:40

MQTT BrokeOthers

2014-06-05 10:21:29

HTTP

2020-12-22 06:05:43

Mbedtls应用基础

2010-06-13 15:28:56

UML基础与应用

2015-01-12 13:48:55

Android应用组件

2012-10-29 11:15:46

IBMdw

2013-01-18 10:45:38

IBMdW

2016-07-29 10:37:00

互联网httphtml

2018-07-12 11:48:31

微服务Service mes服务

2010-02-24 15:20:23

WCF Message
点赞
收藏

51CTO技术栈公众号