Compartilhar via

消息会话

Azure Service Bus会话允许对相关消息的未绑定序列进行联合有序处理。 在先进先出(FIFO)和请求响应模式中使用会话。 本文介绍如何在使用Service Bus时使用会话来实现这些模式。

注释

Service Bus的基本层不支持会话。 标准层和高级层支持会话功能。 有关这些层之间的差异,请参阅 Service Bus 定价

先入、先出(FIFO)模式

若要在处理来自 Service Bus 的队列或订阅的消息时实现 FIFO 处理,请使用会话。 Service Bus对消息之间的关系的性质没有规定性,也不定义用于确定消息序列开始或结束位置的特定模型。

发送方可以将消息提交到主题或队列时启动会话,方法是将 会话 ID 属性设置为应用程序定义的唯一标识符。 在 AMQP 1.0 协议级别,此值映射到 group-id 属性。

在会话感知的队列或订阅中,当至少有一条消息包含会话 ID 时,会话才会存在。 会话存在后,会话过期或消失时没有定义的时间或 API。 理论上,今天可以为会话接收一条消息,一年后可以接收下一条消息,如果会话 ID 匹配,则从Service Bus的角度来看,会话是相同的。

但是,应用程序通常定义一组相关消息的开始和结束位置。 Service Bus不会施加任何特定规则。 例如,应用程序可以将第一条消息的 Label 属性设置为“开始”,将中间消息设置为内容,最后一条消息结束。 content 消息相对位置的计算方式为,当前消息的 SequenceNumber 与 start 消息的 SequenceNumber 的增量值。

重要

在队列或订阅上启用会话时,客户端应用程序 无法再 发送或接收常规消息。 客户端必须通过设置会话 ID 来将消息作为会话的一部分发送,并通过接受会话来接收消息。 客户端仍然可以查看已启用会话的队列或订阅。 有关详细信息,请参阅 消息浏览

会话 API 存在于队列和订阅客户端上。 有两种方法可以接收会话和消息:命令性模型、手动控制消息接收的时间和方式,以及基于处理程序的模型,通过自动管理消息循环和处理来简化作。

对于示例,请使用“ 示例 ”部分中的链接。

会话功能

会话支持对交错消息流进行并发解多路复用,同时保留和保证有序传递。

显示会话功能如何保留有序传递的示意图。

客户端创建会话接收器以接受会话。 当客户端接受并保存会话时,它会对队列或订阅中具有该会话 会话 ID 的所有消息持有独占锁。 它会保留所有消息的排他锁,其中包含稍后到达的会话 ID。

在接收器上调用 close 方法或锁过期时,锁将被释放。 接收方还具有更新锁的方法。 可以选择使用自动续订锁定功能,而不是使用其他方法。在自动续订锁定功能中,您可以指定希望续订锁定的时间持续长度。 将会话锁视为文件的独占锁,这意味着应用程序在不再需要会话或不需要任何进一步消息后立即关闭会话。

当多个并发接收器从队列中提取消息时,属于特定会话的消息将被分派给当前持有该会话锁定状态的特定接收器。 通过使用该操作,一个队列或订阅中的交错消息流将被干净地解复用到不同的接收方。 这些接收器也可以位于不同的客户端计算机上,因为锁管理发生在服务端内部Service Bus。

上图显示了三个并发会话接收器。 具有 SessionId = 4 的某个会话没有活跃的拥有者客户端,这意味着不会从此特定会话传递任何消息。 会话在很多方面都起着一个子队列的作用。

会话接收程序保留的会话锁定是速览锁定安排模式使用的消息锁的保护伞。 只有一个接收方可以锁定会话。 一个接收程序可能有许多正在传送中的消息,但会按顺序接收消息。 放弃消息会导致下一个接收操作再次接收到相同的消息。

消息会话状态

在大规模、高可用性云系统中处理工作流时,与特定会话关联的工作流处理程序必须能够从意外故障中恢复,并恢复从工作开始的不同进程或计算机上部分完成的工作。

会话状态设施允许在中转站内对消息会话进行应用程序定义的批注,以便在新处理器获取会话时,相对于该会话的记录处理状态立即可用。

从Service Bus的角度来看,消息会话状态是一个不透明的二进制对象,可以保存一条消息大小的数据,对于Service Bus标准为 256 KB,Service Bus Premium 为 100 MB。 相对于会话的处理状态可以保存在会话状态内,或者会话状态可以指向保存此类信息的某些存储位置或数据库记录。

会话接收器对象具有管理会话状态的方法, SetState 以及 GetState。 以前没有会话状态的会话返回一个空引用 GetState。 通过将 null 传递给 SetState 接收方上的方法,可以清除以前设置的会话状态。

只要会话状态未清除(返回 null),即使会话中的所有消息都已使用,会话状态也会保持不变。

队列或订阅中保留的会话状态计入相应实体的存储配额。 应用程序完成会话后,应清理其保留状态,以避免外部管理成本。

传递计数的影响

会话上下文中每个消息的传递计数定义与缺少会话时的定义略有不同。 下面是在递增传递计数时汇总的表。

情景 消息的传递计数是否递增
会话已接受,但会话锁过期(由于超时) 是的
会话已接受,但会话中的消息未完成(即使它们已锁定),且会话已关闭。
接受会话,完成消息,然后显式关闭会话 N/A (这是标准流。在这里,邮件将从会话中删除)

“请求-响应”模式

请求-回复模式是一种成熟的集成模式,使发送方应用程序能够发送请求,并为接收方正确发送回发送方应用程序发送响应提供了一种方法。 此模式通常需要一个生存期较短的队列或主题,应用程序才能向其发送响应。 在这种情况下,会话提供一种具有相似语义的简单替代解决方案。

多个应用程序可以将请求发送到单个请求队列,并将特定的标头参数设置为唯一标识发送方应用程序。 接收方应用程序可以处理队列中传入的请求,并在启用了会话的队列上发送答复,将会话 ID 设置为发送方在请求消息上发送的唯一标识符。 然后,发送请求的应用程序可以接收特定会话 ID 上的消息,并正确处理答复。

注释

发送初始请求的应用程序应了解会话 ID,并用它来接受会话,由此锁定需要响应的会话。 使用用于唯一标识应用程序实例的 GUID 作为会话 ID。 为了确保特定接收方能够锁定和处理响应,队列不应在会话接收器上指定会话处理程序或超时。

先后顺序与会话

序列号 本身可以保证消息的排队顺序和提取顺序,但不保证需要会话的处理顺序。

假设队列中有三条消息和两个使用者。

  1. 使用者 1 拾取消息 1。

  2. 使用者 2 拾取消息 2。

  3. 使用者 2 完成处理消息 2 并选取消息 3,而使用者 1 尚未处理消息 1。

  4. 使用者 2 完成处理消息 3,但使用者 1 尚未处理消息 1。

  5. 最后,使用者 1 完成对消息 1 的处理。

因此,消息按以下顺序进行处理:消息 2、消息 3 和消息 1。 如果需要按顺序处理消息 1、2 和 3,则需要使用会话。

如果需要按顺序检索消息,则无需使用会话。 如果需要按顺序处理消息,则使用会话。 对属于同一组的消息设置相同的会话 ID,例如,一组中的消息有 1、4 和 8,另一组中的消息有 2、3 和 6。

邮件过期

对于已启用会话的队列或主题订阅,消息在会话级别锁定。 如果任何消息的生存时间(TTL)过期,系统会根据实体上启用的消息过期处理设置,丢弃或将与该会话相关的所有消息移至死信队列。 换句话说,如果会话中有一条消息通过 TTL,则会话中的所有消息都将过期。 仅当存在活动侦听器时,消息才会过期。 有关详细信息,请参阅 消息过期

示例

可以使用 Azure 门户、PowerShell、CLI、Resource Manager 模板、.NET、Java、Python和 JavaScript 创建队列时启用消息会话。 有关详细信息,请参阅 “启用消息会话”。

尝试使用所选语言的示例来探索Azure Service Bus功能。