Service Broker“Hello World”
大多数编程语言书籍都以“Hello World”示例开始,因此我们也在 Service Broker 中使用 Hello World 作为示例。为简化示例,我使用可以从 SQL Server Management Studio 查询窗口运行的 T-SQL 进行编写。大多数 Service Broker 应用程序将作为普通的数据库应用程序,这些应用程序由通过 ADO 或 ADO.NET 与数据库进行通信的可执行程序和使用 T-SQL 或 .NET 语言编写的 SQL Server 存储过程构成。
要发送和接收消息,必须首先创建向 Service Broker 描述应用程序的消息传送部分的元数据对象。在 SQL Server 2005 中,使用新添加的 DDL 语句来创建、修改和删除 Service Broker 元数据。
-- 创建要使用的数据库
Create Database HelloWorldDB
go
Use HelloWorldDB
go
-- 创建要使用的两种消息类型。我们要使用的消息将是
-- 字符串而不是 XML - 因此无需进行验证
CREATE MESSAGE TYPE [HelloWorldRequest] VALIDATION = NONE
CREATE MESSAGE TYPE [HelloWorldResponse] VALIDATION = NONE
-- 创建一个限制此对话框中消息类型
-- 的规范。请求由对话框的初始化程序发出
-- 响应消息由对话框目标发送。
CREATE CONTRACT [HelloWorldContract]
(
[HelloWorldRequest] SENT BY initiator,
[HelloWorldResponse] SENT BY target
)
-- 创建对话框在其间通信的两个队列。A
-- 对话框请求两个队列。
CREATE QUEUE [HelloWorldTargetQueue]
CREATE QUEUE [HelloWorldInitiatorQueue]
-- 创建命名对话框端点的服务。服务会将
-- 会话端点连接到队列。
CREATE SERVICE [HelloWorldRequestService] ON QUEUE [HelloWorldTargetQueue]
(
[HelloWorldContract]
)
CREATE SERVICE [HelloWorldResponseService] ON QUEUE [HelloWorldInitiatorQueue]
go
现在已经设置了元数据,可以发送消息了。请注意,由于初始化程序和目标服务位于同一 SQL Server 实例中,因此消息将直接转到目标队列而不会通过传送队列传送。由于 Service Broker 内置在数据库中,因此可以进行此项性能优化。
Use HelloWorldDB
go
SET NOCOUNT ON
DECLARE @conversationHandle uniqueidentifier
Begin Transaction
-- 开始 Hello World 服务的对话
BEGIN DIALOG @conversationHandle
FROM SERVICE [HelloWorldResponseService]
TO SERVICE 'HelloWorldRequestService'
ON CONTRACT [HelloWorldContract]
WITH ENCRYPTION = OFF, LIFETIME = 600;
-- 发送消息
SEND ON CONVERSATION @conversationHandle
MESSAGE TYPE [HelloWorldRequest] (N'Hello World')
commit
Use HelloWorldDB
go
-- 检查目标队列以确认消息已送达
select * from [HelloWorldTargetQueue]
go
-- 将消息主体转换为字符串,以便我们查看其中包含的内容
select cast(message_body as nvarchar(MAX)) from [HelloWorldTargetQueue]
go
现在可以从目标队列中接收消息并将响应发送回初始化程序。
-- 使用 Receive 命令可从队列接收消息
-- 声明变量以存储接收到的数据
SET NOCOUNT ON
DECLARE @conversationHandle uniqueidentifier
declare @message_body nvarchar(MAX)
declare @message_type_name sysname;
-- Service Broker 命令总是位于事务中
Begin Transaction;
-- Receive 命令的格式类似于一个选择列表。首先列出
-- 要获取的列,然后指定要从中获取消息
-- 的队列
RECEIVE top(1) -- 只接收一条消息,因此我们可以直接保存到变量中。
@message_type_name=message_type_name,
-- 接收的消息类型
@conversationHandle=conversation_handle,
-- 对话的标识符
-- 我们通过下列语句接收该消息
@message_body=message_body
-- 作为
-- varbinary(MAX) blob 的消息内容
FROM [HelloWorldTargetQueue]
print @message_body
-- 如果这是一条 hello world 消息,则用相应的问候语回答
if @message_type_name = N'HelloWorldRequest'
Begin
SEND ON CONVERSATION @conversationHandle
-- 使用下列消息接收语句的相同会话
MESSAGE TYPE [HelloWorldResponse]
(N'Hello From '+@@servername )
-- 这是我们希望从初始化程序接收的唯一消息,因此
-- 现在可以安全地结束对话。
END CONVERSATION @conversationHandle
End
-- 提交事务
-- 如果此时我们回滚,所有内容将退回到
-- 我们开始时的状态 – 消息会返回到队列,并且没有发送响应
Commit
go
-- 确认我们从队列中删除了消息
select cast(message_body as nvarchar(MAX)) from [HelloWorldTargetQueue]
go
响应已在对话中发送回初始化程序队列,现在检查响应是否成功到达:
Use HelloWorldDB
go
select cast(message_body as nvarchar(MAX)) from [HelloWorldInitiatorQueue]
go
RECEIVE
cast(message_body as nvarchar(MAX))
FROM [HelloWorldInitiatorQueue]
现在已经成功地向 Service Broker 发送了消息并收到了响应。如果希望查看刚刚运行的命令的详细说明,请参见 SQL Server 联机书籍所提供的丰富消息。如果希望扩展此示例以在两个数据库之间使用,您需要添加从发起程序服务器到目标服务器的路由和从目标返回到初始化程序的路由。Service Broker 路由将 BEGIN DIALOG CONVERSATION 命令中指定的服务名称映射到发送消息所需的实际网络地址信息。有关路由和安全性的详细信息,请参见 SQL Server 联机书籍。