Azure 服务总线会话允许对未绑定相关消息序列进行联合有序处理。 会话可在 先出(FIFO) 和 请求-响应 模式中使用。 本文介绍如何在使用服务总线时使用会话来实现这些模式。
注意
基本层的服务总线不支持会话。 标准层和高级层支持会话功能。 有关这些层之间的差异,请参阅服务总线定价。
若要在处理来自服务总线队列或订阅的消息时实现 FIFO 处理,请使用会话。 服务总线对消息之间的关系的性质没有规定性,也没有定义用于确定消息序列开始或结束位置的特定模型。
发送方可以将消息提交到主题或队列时启动会话,方法是将 会话 ID 属性设置为应用程序定义的唯一标识符。 在 AMQP 1.0 协议级别,此值映射到 group-id 属性。
在会话感知队列或订阅中,如果有至少一个消息带有会话 ID,会话就诞生了。 会话存在后,会话过期或消失时没有定义的时间或 API。 从理论上讲,今天可以接收到一个会话的消息,一年后接收下一条消息,如果会话 ID 匹配,那么从服务总线的角度来看,会话是相同的。
但是,应用程序通常定义一组相关消息的开始和结束位置。 服务总线未设定任何具体规则。 例如,应用程序可以将第一条消息的 Label 属性设置为“开始”,将中间消息设置为内容,最后一条消息结束。 content 消息相对位置的计算方式为,当前消息的 SequenceNumber 与 start 消息的 SequenceNumber 的增量值。
重要
在队列或订阅上启用会话时,客户端应用程序 无法再 发送/接收常规消息。 客户端必须将消息作为会话的一部分进行发送(通过设置会话 ID)并通过接受会话进行接收。 客户端仍可能查看已启用会话的队列或订阅。 请参阅 消息浏览。
会话 API 存在于队列和订阅客户端上。 有一个命令性模型,用于控制何时接收会话和消息,以及一个基于处理程序的模型,用于隐藏管理接收循环的复杂性。
对于示例,请使用“ 示例 ”部分中的链接。
会话支持对交错消息流进行并发解多路复用,同时保留和保证有序传递。
客户端创建会话接收器以接受会话。 当客户端接受并保存会话时,客户端对队列或订阅中具有该会话 会话 ID 的所有消息持有独占锁。 它会保留所有消息的排他锁,其中包含稍后到达的会话 ID。
在接收器上调用 close 方法或锁过期时,锁将被释放。 接收方上还提供了一些方法来续订锁。 相反,你可以使用自动锁定续订功能,你可以在其中指定要使锁定得到续订的持续时间。 会话锁应被视为文件的独占锁,这意味着应用程序在不再需要会话时应立即关闭会话,并且/或不需要任何进一步的消息。
当多个并发接收器从队列中提取消息时,属于特定会话的消息将被分派给当前持有该会话锁定状态的特定接收器。 通过此操作,位于一个队列或订阅中的交错消息流可以明确解多路复用到各个接收程序,这些接收程序也可以驻留在不同的客户端计算机上,因为锁定管理是在服务总线内的服务端执行。
上图显示了三个并发会话接收器。 某个 SessionId
= 4 的会话不具有活动的、所属的客户端,这意味着此特定会话不传递任何消息。 会话在很多方面都起着一个子队列的作用。
会话接收程序保留的会话锁定是速览锁定安排模式使用的消息锁的保护伞。 只有一个接收方可以锁定会话。 一个接收程序可能有许多正在传送中的消息,但会按顺序接收消息。 放弃消息会导致在下一次接收操作时再次收到相同的消息。
在大规模、高可用性云系统中处理工作流时,与特定会话关联的工作流处理程序必须能够从意外故障中恢复,并且可以从工作开始的不同进程或计算机上恢复部分完成的工作。
会话状态设施允许在中转站内对消息会话进行应用程序定义的批注,以便在新处理器获取会话时,相对于该会话的记录处理状态立即可用。
从服务总线的角度来看,消息会话状态是一个不透明的二进制对象,可以保存一条消息大小的数据,对于服务总线标准为 256 KB,服务总线高级版为 100 MB。 相对于会话的处理状态可以保存在会话状态内,或者会话状态可以指向保存此类信息的某些存储位置或数据库记录。
在会话接收器对象上可以找到用于管理会话状态的SetState
和GetState
方法。 以前没有会话状态的会话返回空引用 GetState
。 通过将 null 传递给 SetState
接收方上的方法,可以清除以前设置的会话状态。
只要会话状态未清除(返回 null),即使会话中的所有消息都已使用,会话状态也会保持不变。
队列或订阅中保留的会话状态计入相应实体的存储配额。 当应用程序完成会话后,建议应用程序清理其保留状态,以避免外部管理成本。
会话上下文中每个消息的传递计数定义与缺少会话时的定义略有不同。 下面是在递增传递计数时汇总的表。
情景 | 消息的传递计数是否递增 |
---|---|
会话已被接受,但由于超时,会话锁已过期。 | 是的 |
会话已接受,但会话中的消息未完成(即使它们已锁定),且会话已关闭。 | 否 |
接受会话,完成消息,然后显式关闭会话 | N/A (这是标准流。在这里,邮件将从会话中删除) |
请求-回复模式是一种成熟的集成模式,使发送方应用程序能够发送请求,并为接收方正确发送回发送方应用程序发送响应提供了一种方法。 此模式通常需要一个生存期较短的队列或主题,应用程序才能向其发送响应。 在这种情况下,会话提供一种具有相似语义的简单替代解决方案。
多个应用程序可以将请求发送到单个请求队列,并将特定的标头参数设置为唯一标识发送方应用程序。 接收方应用程序可以处理队列中传入的请求,并在启用了会话的队列上发送答复,将会话 ID 设置为发送方在请求消息上发送的唯一标识符。 然后,发送请求的应用程序可以接收特定会话 ID 上的消息,并正确处理答复。
注意
发送初始请求的应用程序应了解会话 ID,并用它来接受会话,由此锁定需要响应的会话。 最好使用一个能够唯一标识应用程序实例的 GUID 作为会话 ID。 队列的会话接收器上不应指定会话处理程序或超时,以确保特定接收方能够锁定和处理响应。
序列号 本身可以保证消息的排队顺序和提取顺序,但不保证需要会话的处理顺序。
假设队列中有三条消息和两个使用者。
- 使用者 1 拾取消息 1。
- 使用者 2 拾取消息 2。
- 使用者 2 完成处理消息 2 并选取消息 3,而使用者 1 尚未处理消息 1。
- 使用者 2 完成处理消息 3,但使用者 1 尚未处理消息 1。
- 最后,使用者 1 完成对消息 1 的处理。
因此,消息按以下顺序进行处理:消息 2、消息 3 和消息 1。 如果需要按顺序处理消息 1、2 和 3,则需要使用会话。
如果需要按顺序检索消息,则无需使用会话。 如果需要按顺序处理消息,则使用会话。 应在属于同一组的消息上设置相同的会话 ID,该 ID 可以是集合中的消息 1、4 和 8,在另一个集中设置 2、3 和 6。
对于已启用会话的队列或主题订阅,消息在会话级别锁定。 如果任何消息的生存时间 (TTL) 过期,则与该会话相关的所有消息都将根据实体上启用的死信过期设置删除或死信。 换句话说,如果会话中有一条消息已通过 TTL,则会话中的所有消息都已过期。 仅当存在活动侦听器时,消息才会过期。 有关详细信息,请参阅 消息过期。
可以使用 Azure 门户、PowerShell、CLI、资源管理器模板、.NET、Java、Python 和 JavaScript 创建队列时启用消息会话。 有关详细信息,请参阅 “启用消息会话”。
尝试采用所选语言的示例,了解 Azure 服务总线功能。
- .NET
- 爪哇岛
- 蟒
- JavaScript