Service Broker 要点
--Service Broker 简介
Service Broker是使SQL Server成为一个构建可靠的分布式异步应用程序平台。
Service Broker并不是一个通用的消息处理系统。
Service Broker支持事务性消息处理,事务性消息处理是保证消息只被处理一次且按顺序处理的唯一方法。
--应用场景
1 可靠的面向服务构架Service Oriented Architecture (SOA)
2 异步处理:数据仓库每天夜间进行的数据抽取工作
If each message is a SQL statement or stored procedure to process, a service could be written that receives messages from the queue and executes the contents of the message by passing it to a SQL EXEC statement.
A typical example of this is the night processing for a data warehouse.
--适合场景
Service Broker 和 MSMQ(Microsoft Message Queue )
MSMQ消息最大可以是4MB,而Service Broker消息最大可以是2GB。
MSMQ提供快速的,可靠,事务性的消息风格,而Service Broker仅提供事务性。
MSMQ可以在任意两个Windows应用程序之间通讯。而Service Broker只能在连接到SQL Server的应用程序之间通讯。
Service Broker 和 BizTalk
BizTalk可以操作消息的内容、映射消息格式、管理消息处理、管理工作流、管理状态、
通过多个不同的传送器发送消息等。
Service Broker 和 WCF(Windows Communication Foundation)
WCF支持在Windows和任何实现WCF所支持的标准协议的操作系统之间通过多种基于标准的协议完成多种形式的消息处理。
--会话
对话会话(dialog conversation )是两个端点之间的可靠的、顺序的、双向的消息传递。
独白会话(monolog conversation )是从发送端到多个接收端的可靠的、顺序的消息流;是从一个发送端到一批接收端的一组对话。
此功能SQL Server 2005中尚未实现。
Service Broker三个特征:可靠的、顺序的和异步的。
--消息(Messages)
Service Broker由消息头和消息体组成。、
消息体的数据类型是VARBINARY(MAX),它最大可以包含2GB的任何可以转换为VARBINARY(MAX)的SQL Server数据。
注:消息类型名称和消息头中其它的Service Broker元数据都是使用二进制排序规则。因此,名称必须完全匹配,而且区分大小写和重音。
建议,采用复制,防止出错。
CREATE MESSAGE TYPE message_type_name
[ VALIDATION = { NONE
| EMPTY
| WELL_FORMED_XML
| VALID_XML WITH SCHEMA COLLECTION
schema_collection_name
} ]
VALIDATION
指定 Service Broker 对此类型消息的消息正文的验证方式。如果未指定此子句,则验证默认为 NONE。
NONE
不执行验证。消息正文可以包含任何数据,也可以为 NULL。
EMPTY
消息正文必须为 NULL。例如:不需要携带任何数据的“SUCESS”类型的消息。
WELL_FORMED_XML
消息正文必须包含采用格式正确的 XML。
VALID_XML WITH SCHEMA COLLECTION schema_collection_name
消息正文必须包含与指定架构集合中架构一致的 XML。schema_collection_name 必须是现有 XML 架构集合的名称。
--约定(Contracts)
SQL Server 2005中没有提供用于添加或移除消息类型的ALTER CONTRACT语句,你必须保证创建约定正确无误。
更改消息类型列表的唯一方法是删除约定后在重建。
注:如果你没有指定消息类型和约定,将使用DEFAULT的消息类型和一个包含DEFAULT消息类型DEFAULT约定。
--队列(Queues)
队列是唯一实际存储数据的Services Broker对象,因此可以指定存储消息的文件组。
队列可以是 SELECT 语句的目标。但是,只能使用在 Service Broker 会话中运行的语句(如 SEND、RECEIVE 和 END CONVERSATION)来修改队列的内容。
队列不能是 INSERT、UPDATE、DELETE 或 TRUNCATE 语句的目标。
队列不能是临时对象。所以,以 # 开头的队列名称是无效的名称。
以STATUS 设置为OFF创建队列,可以先准备好服务的基础结构,然后再允许在队列中接收消息。
STATUS(激活)指定 Service Broker 是否激活该存储过程。当 STATUS = ON 时,如果当前运行的过程数小于 MAX_QUEUE_READERS,并且消息抵达队列的速度比存储过程接收消息的速度快,则队列将启动用 PROCEDURE_NAME 指定的存储过程。当 STATUS = OFF 时,队列不激活存储过程。如果未指定该子句,则默认为 ON。
MAX_QUEUE_READERS = max_readers 指定队列同时启动的激活存储过程的最大实例数。max_readers 的值必须是 0 到 32767 之间的数字。
注:设置RETENTION为ON 队列的status被设为0,表示它已经被应用程序接收和处理而且事务已经提交。并且消息不会被删除,
而是保留副本在队列中。这时队列很快会变得非常大,性能也会急剧下降。
但是你需要通过运行补偿事务回退长时间运行的业务事务,会很有用!
每个数据库只有一个sys.transmission_queue 视图,临时存放消息。
情景:目标位于不同的SQL Server实例中;目标队列无效,STATUS = OFF;
目标队列所在的数据库的ENABLE_BROKER 未设置;目的地未知。
--服务(Services)
服务是会话端点的名称.
注:创建会话时,发起会话的会话端点不检查发起方的服务列表。因此发起方的服务列表通常为空。
如果发起方的没有约定,一旦发起方的服务列表出现问题,你永远不知道。
--发起和结束会话
BEGIN DIALOG CONVERSATION @Dialog
FROM SERVICE [//microsoft.com/ManufacturingService]
TO SERVICE '//microsoft.com/InventoryService'
ON CONTRACT [//microsoft.com/Inventory/AddItemContract]
WITH ENCRYPTION = OFF, LIFETIME = 3600;
O SERVICE参数是一个长度为256的字符串。target_service_name 的类型为 nvarchar(256)。Service Broker 会逐个字节进行比较,确保与 target_service_name 字符串匹配。
换言之,比较时将区分大小写,且不考虑当前的排序规则。
LIFETIME = dialog_lifetime
指定对话将保持打开状态的最长时间。为使对话成功完成,两个端点都必须在生存期内显式结束对话。dialog_lifetime 的值必须以秒为单位。生存期的类型为 int。
如果未指定 LIFETIME 子句,则对话的生存期为 int 数据类型的最大值。
ENCRYPTION
将此对话发送和接收的消息向 Microsoft SQL Server 实例外发送时,是否必须对消息加密。
必须加密的对话是安全对话。如果 ENCRYPTION = ON,但未配置支持加密所需的证书,
则 Service Broker 将返回针对该会话的错误消息。ENCRYPTION = OFF 时,
如果为 target_service_name 配置了远程服务绑定,则使用加密 ;否则,发送消息时不加密。
如果未使用此子句,则默认值为 ON。
数据库主密钥是指用于保护证书私钥的对称密钥以及数据库中存在的非对称密钥。
当创建主密钥时,会使用 Triple DES 算法以及用户提供的密码对其进行加密。
创建主密钥:
CREATE MASTER KEY ENCRYPTION BY PASSWORD = 'Pass.word1';
--发送和接收
WAITFOR (
RECEIVE top(1)
@message_type = message_type_name,
@message_body = message_body,
@dialog = conversation_handle
FROM dbo.InventoryQueue
), TIMEOUT 2000;
为了确保分析器能知道SEND和RECEIVE正是在开始一个新命令,SEND或RECEIVE之前的命令必须以
分号(;)结束,但是WAITFOR语句是个例外。
如果忽略TIMEOUT参数,但WAITFOR语句中的RECEIVE语句是个例外。
--会话安全
--要允许使用模拟的安全上下文跨数据库访问的权限,可以把模拟数据库表示为“可信任的(TRUSTWORTHY)”
ALTER DATABASE Manufacturing SET TRUSTWORTHY ON;
--非对称密码技术用于安全地传输对称密钥,而对称密钥技术用于数据交换。
-- 路由
Service Broker路由是从服务到网络地址的映射,该网络地址就是要把消息发送到底地方。
服务的路由可以指定实例上的数据库
路由的地址是LOCAL时表示Service Broker将在SQL Server实例中查找与名称匹配的服务。
路由的地址是TRANSPORT时Service Broker将尝试使用服务的名称作为路由。
如:如果每个发起方使用它们的网络地址和端口作为FROM SERVICE的参数,目标只需要包含一个地址
TRANSPORT的通配符路由就可以把影响路由到所有的发起方。
CREATE ROUTE TransportRoute
WITH ADDRESS = 'TRANSPORT' ;
--均衡负载
如果数据库中有多个服务名称相同的路由,在会话中发送第一个消息时Service Broker将随即选择一个路由。
应用程序必须确定由哪个服务启动该会话,并使用BEGIN DIALOG 命令中的broker实例选择一个服务。
service_broker_guid
指定承载目标服务的数据库。如果有多个数据库承载一个目标服务实例,则可通过提供 service_broker_guid 与特定数据库通信。
service_broker_guid 的类型为 nvarchar(128)。若要查找数据库的 service_broker_guid,请在数据库中运行以下查询:
SELECT service_broker_guid
FROM sys.databases
WHERE database_id = DB_ID() ;
启动带特定 broker 实例的对话
该示例将启动一个对话会话,并将对话的标识符存储在 @dialog_handle 中。//Adventure-Works.com/ExpenseClient 服务是对话的发起方,而 //Adventure-Works.com/Expenses 服务是对话的目标。该对话遵循约定 //Adventure-Works.com/Expenses/ExpenseSubmission。
broker 将此对话的消息路由到 GUID a326e034-d4cf-4e8b-8d98-4d7e1926c904 标识的 broker。
DECLARE @dialog_handle UNIQUEIDENTIFIER ;
BEGIN DIALOG CONVERSATION @dialog_handle
FROM SERVICE [//Adventure-Works.com/ExpenseClient]
TO SERVICE '//Adventure-Works.com/Expenses',
'a326e034-d4cf-4e8b-8d98-4d7e1926c904'
ON CONTRACT [//Adventure-Works.com/Expenses/ExpenseSubmission] ;
--转发
MESSAGE_FORWARDING = { ENABLED | DISABLED* }
确定是否将转发此端点所收到的位于其他位置的服务的消息。
ENABLED
如果提供了转发地址,则转发消息。
DISABLED
放弃位于其他位置的服务的消息。
MESSAGE_FORWARDING_SIZE = forward_size
指定存储要转发的消息时为要使用的端点分配的最大存储量 (MB)。
ALTER ENDPOINT InventoryEndpoint FOR SERVICE_BROKER
(MESSAGE_FORWARDING = ENABLED,
MESSAGE_FORWARD_SIZE = 50);