导读:本文主要涉及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://jxjierui.cn/article/cdegjih.html

 建站
建站
 咨询
咨询 售后
售后
 建站咨询
建站咨询 
 