对话优先级

适用范围:SQL ServerAzure SQL 托管实例

会话优先级是一组用户定义的规则,每个规则分别指定一个优先级别以及用于确定哪些 Service Broker 会话分配该优先级别的条件。 通常,先发送或接收优先级别较高的会话的消息,再发送或接收优先级别较低的会话的消息。

会话优先级的使用

会话优先级可用于执行以下操作:

  • 标识会话是否优先于其他会话。

  • 支持不同的服务层,其中,支付较高价格的客户的消息先发送,支付较低价格的客户的消息后发送。

  • 优先处理客户请求而非后台任务。 例如,新客户注册应比向数据仓库发送业务事务摘要具有更高的优先级。

会话优先级和转换终结点

使用 CREATE BROKER PRIORITY 语句在每个数据库中创建会话优先级。 每个会话优先级均定义了以下内容:

  • 会话优先级的名称。

  • 分配给 Service Broker 会话的优先级别。 该级别被指定为从 1(最低)到 10(最高)的整数。 默认值为 5。

  • 用于确定优先级别应用于哪些会话的条件如下:

    • 协定名称,或 ANY
    • 本地服务名称,或 ANY
    • 远程服务名称,或 ANY

Service Broker 在创建会话端点时为其分配优先级别。 每个会话均有两个会话端点:

  • 发起方会话端点将会话的一端与发起方服务和发起方队列相关联。 在运行语句时 BEGIN DIALOG ,将创建发起程序会话终结点。 与发起方会话端点关联的操作包括:

    • 从发起程序服务发送
    • 从发起程序队列接收
    • 从发起程序队列获取下一个会话组
  • 目标会话端点将会话的另一端与目标服务和队列相关联。 目标会话端点是在将来自发起方的第一个消息放入目标队列时创建的。 与目标会话端点关联的操作包括:

    • 从目标队列接收
    • 从目标服务发送
    • 从目标队列获取下一个聊天组

哪个服务被认定为本地或远程服务取决于会话端点的类型:

  • 对于发起方会话端点,发起方服务为本地服务,目标服务为远程服务。
  • 对于目标会话端点,目标服务为本地服务,发起方服务为远程服务。

Service Broker 如何分配优先级

Service Broker 在创建会话端点时分配会话优先级别。 会话端点将优先级别一直保留到会话结束。 新的优先级或更改现有优先级不会应用于现有对话。

Service Broker 将合同和服务条件与端点属性最匹配的会话优先级中的优先级别分配给会话端点。 下表显示了匹配优先顺序:

终结点协定 终结点本地服务 终结点远程服务
优先级约定 优先级本地服务 优先级远程服务
优先级约定 优先级本地服务 ANY
优先级约定 ANY 优先级远程服务
优先级约定 ANY ANY
ANY 优先级本地服务 优先级远程服务
ANY 优先级本地服务 ANY
ANY ANY 优先级远程服务
ANY ANY ANY

Service Broker 首先查找其指定的协定、本地服务和远程服务与会话终结点使用的优先级匹配。 如果未找到服务代理,则 Service Broker 会查找与终结点使用的协定和本地服务匹配的优先级,以及指定远程服务 ANY的位置。 此过程会一直继续下去,直到优先顺序表中列出的所有变体均已比对过为止。 如果未找到匹配项,将为端点分配默认优先级 5。

Service Broker 通信协议不会在会话终结点之间传输优先级级别。 Service Broker 独立地为每个端点分配优先级别。 若要让 Service Broker 将优先级别同时分配给发起方会话端点和目标会话端点,必须确保会话优先级同时涵盖这两个端点。 如果发起方会话端点和目标会话端点分别在不同的数据库中,则必须在每个数据库中创建会话优先级。 如果发起方端点和目标端点在同一个数据库中:

  • 可以使用一个会话优先级来涵盖这两个会话终结点,该优先级指定会话使用的协定名称,以及 ANY 本地和远程服务名称。

  • 可以使用两个会话优先级分别涵盖每个会话端点:

    • 为发起方终结点指定发起方服务名称和 LOCAL_SERVICE_NAME 目标服务名称的 REMOTE_SERVICE_NAME一个会话。

    • 目标终结点的一个会话,指定目标服务名称和 LOCAL_SERVICE_NAME 发起方服务名称 REMOTE_SERVICE_NAME

通常为会话的两个会话端点指定相同的优先级别。 尽管可以为每个终结点指定不同的优先级级别,但这样做并不意味着消息的发送速度比另一个方向要快。 消息从一个会话端点发出,在另一个端点上接收。 因此,每次消息传输都会受到分配给这两个端点的优先级别的影响。 例如,您可以配置一个会话,使发起方会话端点的优先级别为 10,而目标端点的优先级别为 1。 在这种情况下:

  • 消息从发起方服务传输时使用优先级别 10,从目标队列接收时使用优先级别 1。

  • 消息从目标服务传输时使用优先级别 1,从发起方队列接收时使用优先级别 10。

在以下情况下,分配给会话组的优先级别与分配给任意会话的最高优先级别相同:

  • 会话是组的成员。
  • 会话当前在服务队列中拥有消息。

如果未在数据库中创建任何会话优先级,将为数据库中的所有会话端点分配默认优先级 5。

会话优先级不会影响消息转发,该转发始终在默认优先级为 5 的级别运行。

对话优先级示例

假定系统配置如下:

  • 一个InitiatorDBInitiatorService包含和 InitiatorQueue.

  • TargetDB包含 TargetService a 和 TargetQueue.

  • 命名的 SimpleContract协定,指定 RequestMessagesInitiatorService 中发送到的 TargetService协定。 它还指定ReplyMessagesTargetService中发送到 .InitiatorService

此脚本指定发起方会话端点的优先级别及其关联操作:

  • SENDRequestMessageInitiatorServiceTargetQueue
  • RECEIVEReplyMessageInitiatorQueue
USE InitiatorDB;
GO

CREATE BROKER PRIORITY InitiatorToTargetPriority FOR CONVERSATION
    SET
    (
            CONTRACT_NAME = SimpleContract,
            LOCAL_SERVICE_NAME = InitiatorService,
            REMOTE_SERVICE_NAME = N'TargetService',
            PRIORITY_LEVEL = 3
    );
GO

此脚本指定目标会话端点的优先级别及其关联操作:

  • RECEIVERequestMessageTargetQueue
  • SENDReplyMessageTargetServiceInitiatorQueue
USE TargetDB;
GO

CREATE BROKER PRIORITY TargetToInitiatorPriority FOR CONVERSATION
    SET
    (
            CONTRACT_NAME = SimpleContract,
            LOCAL_SERVICE_NAME = TargetService,
            REMOTE_SERVICE_NAME = N'InitiatorService',
            PRIORITY_LEVEL = 3
    );
GO

优先级如何运行

通常,Service Broker 在发送和接收低优先级会话的消息之前,先发送和接收高优先级会话的消息。 来自高优先级对话的消息在队列中花费的时间比来自低优先级对话的消息花费的时间更少。

接收优先级

优先级别总是应用于从队列接收消息或会话组标识符的操作。

优先级是确定由 a RECEIVE 和检索消息的顺序检索的消息集的因素之一:

  • 每个 RECEIVE 语句始终从一个会话组检索消息:

    • 没有RECEIVE子句的检索WHERE属于队列中消息的最高优先级解锁会话组的消息。

    • 具有子句的一 RECEIVEWHERE 子句检索子句中指定的 WHERE 会话组的消息。

  • 在聊天组中, RECEIVE 根据组中聊天的优先级检索消息。 首先检索具有最高优先级别的会话的所有消息,其次检索具有第二高优先级别的会话的消息,依此类推。

  • 在会话中,消息的检索顺序与消息的发送顺序相同。

GET CONVERSATION GROUP 从队列中具有消息的已解锁组集中返回优先级最高的组。

传输优先级

一个实例的传输队列中的消息按照以下顺序传输:

  • 与其关联的会话端点的优先级别。
  • 在优先级别内,依照它们在会话中的发送顺序。

Service Broker 跨数据库引擎实例中的所有传输队列协调优先级别。 Service Broker 先传输所有传输队列中优先级别为 10 的会话的消息,再传输优先级别为 9 的会话的消息,依此类推。

优先级别间的差异越大,消息传输性能的相对差异也越大。 在采用两个相邻优先级别(如 9 和 10)的系统中,优先级别较高的消息仅具有较小的性能优势。 在采用两个相差很大的优先级别(如 1 和 10)的系统中,优先级别较高的消息将具有较大的性能优势。 在使用多个优先级别的系统中,大部分处理资源都将分配给前两个或前三个优先级别。

在会话优先级中指定的优先级仅应用于传输队列中的消息(如果 HONOR_BROKER_PRIORITY 数据库选项设置为 ON)。 如果 HONOR_BROKER_PRIORITY 设置为 OFF,则使用默认优先级 5 发送该数据库的传输队列中的所有消息。 使用 sys.transmission_queue时,消息仍显示从终结点接收的优先级级别,但默认优先级用于传输消息。

由于优先级级别应用于传输队列中的消息,因此它们通常不会影响在同一数据库引擎实例中的服务之间发送的消息。 发送到相同实例中的服务的消息被直接放入该服务的队列中,而不会先放入传输队列中。 某些情况可能会导致本地消息被放入传输队列中,比如出现了某些类型的错误或目标队列处于非活动状态。 如果将消息存储在传输队列中,将应用相关的优先级别。

消息和消息片段可能按优先级顺序发送:

  • Service Broker 使用消息片段块在数据库引擎实例之间发送消息。 如果有多个消息片段具有不同的优先级,可以发送到一个实例,Service Broker 可能会发送一个块中的所有片段。 块末尾的某些片段的优先级可能低于等待传输到另一个实例的消息片段。

  • Service Broker 中包含一个饥饿防范机制,以防止大量高优先级消息阻塞低优先级消息。 即使队列中存在高优先级消息,也可能会发送等待很长时间的低优先级消息。

虽然单个消息或消息片段可能按优先级顺序发送,但当考虑跨多个消息发送时,效果应较小。