预提取 Azure 服务总线消息

为任何官方服务总线客户端启用“预提取”功能后,接收方获得的消息要比应用程序最初请求的消息还要多,该消息数最多将达到指定的预提取计数。 当消息返回到应用程序时,客户端在后台获取更多消息,以填充预取缓冲区。

启用预提取

若要启用预提取功能,请将队列或订阅客户端的预提取计数设置为大于零的数字。 将该值设为零可关闭预提取。

ServiceBusReceiverServiceBusProcessor 对象上设置预取计数属性。

注意

Java 脚本 SDK 不支持预提取功能。

尽管消息在预提取缓存区中提供,但后续接收的任何调用均可立即从缓冲区完成。 空间可用时,系统将在后台对缓冲区进行补充。 如果没有消息用于传送,接收操作将清空缓存区,并按预期进行等待或阻止。

预提取为何不是默认选项?

预提取可加快消息流,方法是在应用程序请求消息前,先准备好用于本地检索的消息。 这种吞吐量提升是应用程序作者不得不明确作出的某种权衡的结果。

使用“接收-删除”模式时,所有进入预取缓冲区的消息在队列中将不再可用。 消息仅保留在内存预提取缓冲区中,直到系统将其接收到应用程序中。 如果在应用程序接收到消息前终止应用程序,这些消息将丢失,且不可恢复。

在“Peek-Lock(查看-锁定)接收模式下,从预取缓存区中取出的消息将以锁定状态进入缓存区。 并会将超时时钟用于锁定计时。 如果预提取缓存区很大且所需处理时间过长,以致消息于锁在预提取缓冲区时,甚至于应用程序处理消息时过期,则应用程序可能需要处理出现的一些混乱事件。 应用程序可能收到包含到期或即将到期的锁定的消息。 如有收到,应用程序可能会处理该消息,但随后发现其因锁定到期而无法完成处理。 应用程序可查看 LockedUntilUtc 属性(受代理时钟和本地计算机时钟之间的时钟偏差约束)。

如果消息锁定已到期,则应用程序必须忽略该消息,并且不应对该消息或通过该消息调用任何 API。 如果消息未到期但即将到期,则可更新锁定并延长另一个默认的锁定时间。 如果锁定在预提取缓冲区静默地到期,则视为已放弃该消息,且可再次将消息用于从队列进行检索。 这可能导致将消息提取到预提取缓冲区,并置于末端。 如果在消息过期期间,预提取缓冲区通常无法使用,则将导致重复预提取消息,但始终无法将其以可用(有效锁定)状态有效送达,并最终在超出最大传送数后移动到死信队列。

如果应用程序明确放弃消息,则可以再次从队列中检索该消息。 启用预取功能后,该消息会再次被提取到预取缓冲区中,并放置在末尾。 由于预取缓冲区中的消息按照先进先出 (FIFO) 顺序排空,因此应用程序可能会无序地接收消息。 例如,应用程序可能会收到 ID 为 2 的消息,然后收到来自缓冲区的 ID 为 1 的消息(之前已放弃)。

如果消息处理需要高度可靠性,且处理需要花费大量精力和时间,则建议谨慎使用或者避免使用预提取功能。 如果需要较高吞吐量且消息处理通常比较便宜,则预提取会产生显著的吞吐量优势。

需要均衡对队列或订阅配置的最大预提取数和锁定持续时间,以便锁定超时至少超出最大预提取缓存区大小外加一条消息的累积预期消息处理时间。 同时,锁定超时不应过长,以防消息在遭到意外丢弃后超出其最大生存时间,因此需要消息的锁定在重新传送消息前到期。

后续步骤

尝试采用所选语言的示例,了解 Azure 服务总线功能。

旧版 .NET 和 Java 客户端库示例如下:

注意

2026 年 9 月 30 日,我们将停用 Azure 服务总线 SDK 库 WindowsAzure.ServiceBus、Microsoft.Azure.ServiceBus 和 com.microsoft.azure.servicebus,这些库不符合 Azure SDK 准则。 我们还将结束对 SBMP 协议的支持,因此在 2026 年 9 月 30 日之后,你将无法再使用此协议。 请在该日期之前迁移到最新的 Azure SDK 库,新库提供了关键安全更新和改进功能。

尽管旧库在 2026 年 9 月 30 日之后仍可使用,但它们将不再获得 Azure 的官方支持和更新。 有关详细信息,请参阅支持停用公告