导读:本文主要涉及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
(二)、创建数据库主密钥
--
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
(三)、管理消息类型
使用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
--注意,此处没有定义消息的内容。实际的消息是消息类型的实例。
(四)、创建契约(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
--发起方和目标的定义必须相同
(五)、创建队列
队列用来保存数据。使用命令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
(六)、创建服务
服务定义端点,然后使用它来将消息队列绑定到一个或多个契约上。服务使用队列和契约来定义一个或一组任务。有点拗口,是不是?
服务是消息的发起方和接收方强制约定的规则,并将消息路由到正确的序列。
使用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
(七)、启动对话
对话会话(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
=
'
'
;
SEND
ON
CONVERSATION
@Conv_Handler
--
发送到BookDistribution数据库的队列中
MESSAGE TYPE
[
//SackConsulting/SendBookOrder
]
(
@OrderMsg
);
(八)、查询队列中传入的消息
--
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
查询结果:
(九)、检索并响应消息
使用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
=
'
'
;
SELECT
@ResponseMsg
=
CAST
(
@TextResponseMsg
as
xml);
--
使用既有的会话句柄,发送响应消息到发起方
SEND
ON
CONVERSATION
@Conv_Handler
MESSAGE TYPE
[
//SackConsulting/BookOrderReceived
]
(十)、结束会话
--
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
--查询会话状态
SELECT
state_desc, conversation_handle
FROM
sys.conversation_endpoints
三、小结
本文通过一个实例演示了一个用来发送图书订单消息分发控制数据库的简单的消息交换应用程序。发起方发送图书订单,发回一个响应,并在两个数据库上使用END Conservation结束会话。现实场景中可以转换为其他消息类型、契约、服务和队列。合理运用Service Broker应用程序的异步特性可以防止因应用程序挂起而导致业务系统产生瓶颈。
原文链接:http://www.cnblogs.com/downmoon/archive/2011/04/05/2005900.html
【编辑推荐】
- 简述Service Broker事件通知功能
- 一个Excel导入SQL Server的例子
- 优化你的DiscuzNT,让它跑起来
- 浅述当前模式读与一致性读续
- 浅述当前模式读与一致性读的区别
网页题目:ServiceBroker基础应用(上)
本文网址:http://www.jxjierui.cn/article/cdegjih.html


咨询
建站咨询
