服务总线消息传送异常(已弃用)
本文列出了 .NET Framework API 生成的 .NET 异常。
注意
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 的官方支持和更新。 有关详细信息,请参阅支持停用公告。
异常类别
消息传送 API 会生成以下类别的异常,以及在尝试修复这些异常时可以采取的相关操作。 异常的含义和原因会因消息传送实体的类型而异:
用户代码错误(System.ArgumentException、System.InvalidOperationException、System.OperationCanceledException、System.Runtime.Serialization.SerializationException)。 常规操作:继续之前尝试修复代码。
设置/配置错误(Microsoft.ServiceBus.Messaging.MessagingEntityNotFoundException、System.UnauthorizedAccessException)。 常规操作:检查配置,必要时进行更改。
暂时性异常(Microsoft.ServiceBus.Messaging.MessagingException、Microsoft.ServiceBus.Messaging.ServerBusyException、Microsoft.ServiceBus.Messaging.MessagingCommunicationException)。 常规操作:重试操作或通知用户。 客户端 SDK 中的
RetryPolicy
类可以配置为自动处理重试。 有关详细信息,请参阅重试指南。其他异常(System.Transactions.TransactionException、System.TimeoutException、Microsoft.ServiceBus.Messaging.MessageLockLostException、Microsoft.ServiceBus.Messaging.SessionLockLostException)。 常规操作:特定于异常类型;请参考以下部分中的表:
重要
- Azure 服务总线不会重试某个操作,以免在该操作位于事务范围内时出现异常。
- 有关特定于 Azure 服务总线的重试指南,请参阅服务总线的重试指南。
异常类型
下表列出了消息异常的类型及其原因,并说明可以采取的建议性操作。
异常类型 | 说明/原因/示例 | 建议的操作 | 自动/立即重试注意事项 |
---|---|---|---|
TimeoutException | 服务器在 OperationTimeout 控制的指定时间内未响应请求的操作。 服务器可能已完成请求的操作。 这可能是由于网络或其他基础结构延迟造成的。 | 检查系统状态的一致性,并根据需要重试。 请参阅超时异常。 | 在某些情况下,重试可能会有帮助;在代码中添加重试逻辑。 |
InvalidOperationException | 不允许在服务器或服务中执行请求的用户操作。 有关详细信息,请查看异常消息。 例如,如果在 ReceiveAndDelete 模式下收到消息,则 Complete() 将生成此异常。 | 检查代码和文档。 确保请求的操作有效。 | 重试不起作用。 |
OperationCanceledException | 尝试对已关闭、中止或释放的对象调用某个操作。 在极少数情况下,环境事务已释放。 | 检查代码并确保代码不会对已释放的对象调用操作。 | 重试不起作用。 |
UnauthorizedAccessException | TokenProvider 对象无法获取令牌,该令牌无效,或者令牌不包含执行操作所需的声明。 | 确保使用正确的值创建令牌提供程序。 检查访问控制服务的配置。 | 在某些情况下,重试可能会有帮助;在代码中添加重试逻辑。 |
ArgumentException ArgumentNullException ArgumentOutOfRangeException |
提供给该方法的一个或多个参数均无效。 提供给 NamespaceManager 或 Create 的 URI 包含路径段。 提供给 NamespaceManager 或 Create 的 URI 方案无效。 属性值大于 32 KB。 |
检查调用代码并确保参数正确。 | 重试不起作用。 |
MessagingEntityNotFoundException | 与操作关联的实体不存在或已被删除。 | 确保该实体存在。 | 重试不起作用。 |
MessageNotFoundException | 尝试接收具有特定序列号的消息。 找不到此消息。 | 确保该消息尚未接收。 检查死信队列,以确定该消息是否被视为死信。 | 重试不起作用。 |
MessagingCommunicationException | 客户端无法与服务总线建立连接。 | 确保提供的主机名正确并且主机可访问。 如果你的代码在使用防火墙/代理的环境中运行,请确保到服务总线域/IP 地址和端口的流量未被阻止。 |
如果存在间歇性的连接问题,重试可能会有帮助。 |
ServerBusyException | 服务目前无法处理请求。 | 客户端可以等待一段时间,并重试操作。 | 客户端可在特定间隔后重试。 如果重试导致其他异常,请检查该异常的重试行为。 |
MessagingException | 在以下情况下,可能会引发一般消息异常: 尝试使用属于其他实体类型(例如主题)的名称或路径创建 QueueClient。 尝试发送大于 256 KB 的消息。 服务器或服务在处理请求期间遇到错误。 有关详细信息,请查看异常消息。 这通常是暂时性异常。由于实体正受到限制,因此已终止请求。 错误代码:50001、50002、50008。 |
检查代码,并确保只对消息正文使用可序列化对象(或使用自定义序列化程序)。 在文档中查看属性支持的值类型,并只使用支持的类型。 检查 IsTransient 属性。 如果为 true,可以重试操作。 |
如果异常是由于限制导致的,请等待几秒钟,然后重试该操作。 重试行为未定义,在其他场景中可能没有帮助。 |
MessagingEntityAlreadyExistsException | 尝试使用已被该服务命名空间中另一实体使用的名称创建实体。 | 删除现有的实体,或者选择不同的名称来创建实体。 | 重试不起作用。 |
QuotaExceededException | 消息实体已达到其允许的最大大小,或已超出到命名空间的最大连接数。 | 通过从实体或其子队列接收消息在该实体中创建空间。 请参阅QuotaExceededException。 | 如果同时已删除消息,则重试可能会有帮助。 |
RuleActionException | 如果尝试创建无效的规则操作,服务总线将返回此异常。 如果在处理该消息的规则操作时出错,服务总线会将此异常附加到死信消息。 | 检查规则操作是否正确。 | 重试不起作用。 |
FilterException | 如果尝试创建无效的筛选器,服务总线将返回此异常。 如果在处理该消息的筛选器时出错,服务总线会将此异常附加到死信消息。 | 检查筛选器是否正确。 | 重试不起作用。 |
SessionCannotBeLockedException | 尝试接受具有特定会话 ID 的会话,但该会话当前已被另一客户端锁定。 | 确保该会话未由其他客户端锁定。 | 如果在此期间会话已释放,则重试可能会有帮助。 |
TransactionSizeExceededException | 事务包含过多的操作。 | 减少此事务中操作的数目。 | 重试不起作用。 |
MessagingEntityDisabledException | 对已禁用的实体请求运行时操作。 | 激活实体。 | 如果在此期间该实体已激活,则重试可能会有帮助。 |
NoMatchingSubscriptionException | 如果向已启用预筛选的主题发送消息并且所有筛选器都不匹配,则服务总线会返回此异常。 | 确保至少有一个筛选器匹配。 | 重试不起作用。 |
MessageSizeExceededException | 消息有效负载超出 256 KB 限制。 256-KB 限制是指总消息大小,可能包括系统属性和任何 .NET 开销。 | 减少消息负载的大小,并重试操作。 | 重试不起作用。 |
TransactionException | 环境事务 (Transaction.Current ) 无效。 它可能已完成或已中止。 内部异常可能会提供其他信息。 |
重试不起作用。 | |
TransactionInDoubtException | 已对未决事务尝试进行操作,或尝试提交该事务并且事务进入不确定状态。 | 应用程序必须处理此异常(作为特例),因为此事务可能已提交。 | - |
QuotaExceededException
QuotaExceededException 指示已超出某个特定实体的配额。
注意
有关服务总线配额,请参阅配额。
队列和主题
对队列和主题而言,这通常指队列的大小。 错误消息属性会包含更多详细信息,如以下示例所示:
Microsoft.ServiceBus.Messaging.QuotaExceededException
Message: The maximum entity size has been reached or exceeded for Topic: 'xxx-xxx-xxx'.
Size of entity in bytes:1073742326, Max entity size in bytes:
1073741824..TrackingId:xxxxxxxxxxxxxxxxxxxxxxxxxx, TimeStamp:3/15/2013 7:50:18 AM
该消息指出,主题超过其大小限制,本例中为 1 GB(默认大小限制)。
命名空间
对于命名空间,QuotaExceededException 可指示应用程序已超出到命名空间的最大连接数。 例如:
Microsoft.ServiceBus.Messaging.QuotaExceededException: ConnectionsQuotaExceeded for namespace xxx.
<tracking-id-guid>_G12 --->
System.ServiceModel.FaultException`1[System.ServiceModel.ExceptionDetail]:
ConnectionsQuotaExceeded for namespace xxx.
常见原因
此错误有两个常见原因:死信队列和无法正常运行的消息接收器。
死信队列 读取器无法完成消息,当锁定过期后,消息将返回至队列/主题。 如果读取器发生异常,以致无法调用 BrokeredMessage.Complete,就会出现这种情况。 消息读取 10 次后,默认移至死信队列。 此行为由 QueueDescription.MaxDeliveryCount 属性控制,默认值为 10。 消息堆积在死信队列中会占用空间。
若要解决此问题,请读取并完成死信队列中的消息,就像处理任何其他队列一样。 可以使用 FormatDeadLetterPath 方法帮助格式化死信队列路径。
接收方已停止。 接收方已停止从队列或订阅接收消息。 识别这种情况的方法是查看 QueueDescription.MessageCountDetails 属性,它会显示消息的完整细目。 如果 ActiveMessageCount 属性很高或不断增加,则表示消息写入的速度超过读取的速度。
TimeoutException
TimeoutException 指示用户启动的操作所用的时间超过操作超时值。
应检查 ServicePointManager.DefaultConnectionLimit 属性的值,因为达到此限制也会导致 TimeoutException 异常。
预计会在维护操作(例如,服务总线服务更新或运行服务的资源上的 OS 更新)期间或操作间隙发生超时。 在 OS 更新期间,实体会四处移动,节点会更新或重启,这可能会导致超时。 有关 Azure 服务总线服务的服务级别协议 (SLA) 详细信息,请参阅服务总线的 SLA。
队列和主题
对于队列和主题,超时在 MessagingFactorySettings.OperationTimeout 属性中作为连接字符串的一部分指定,或通过 ServiceBusConnectionStringBuilder 指定。 错误消息本身可能会有所不同,但它始终包含当前操作的指定超时值。
MessageLockLostException
原因
当使用 PeekLock 接收模式接收到消息并且客户端持有的消息锁在服务端过期时,将引发 MessageLockLostException。
消息上的锁定可能会因多种原因过期:
- 锁计时器在客户端应用程序续订之前已过期。
- 客户端应用程序获取了锁,将其保存到持久存储区,然后重新启动。 重新启动后,客户端应用程序会查看即时消息并尝试完成这些操作。
在以下情况下,也可能会收到此异常:
- 服务更新
- OS 更新
- 在持有锁时更改实体(队列、主题、订阅)的属性。
解决方法
当客户端应用程序收到 MessageLockLostException 时,它将无法再处理该消息。 客户端应用程序可以选择记录异常以进行分析,但客户端必须释放消息才行。
由于消息上的锁定已过期,因此它将返回到队列(或订阅),可由调用接收的下一个客户端应用程序进行处理。
如果超出了 MaxDeliveryCount,则消息可能会移至 DeadLetterQueue。
SessionLockLostException
原因
如果接受了某个会话,且客户端持有的锁在服务端过期,将引发 SessionLockLostException。
会话上的锁定可能会因多种原因过期:
- 锁计时器在客户端应用程序续订之前已过期。
- 客户端应用程序获取了锁,将其保存到持久存储区,然后重新启动。 重新启动后,客户端应用程序会查看即时会话,并尝试处理这些会话中的消息。
在以下情况下,也可能会收到此异常:
- 服务更新
- OS 更新
- 在持有锁时更改实体(队列、主题、订阅)的属性。
解决方法
当客户端应用程序收到 SessionLockLostException 时,它无法再处理会话上的消息。 客户端应用程序可以考虑记录异常以进行分析,但客户端必须释放消息才行。
由于会话上的锁定已过期,因此它将返回到队列(或订阅),并且可由接受会话的下一个客户端应用程序锁定。 由于会话锁由单个客户端应用程序在任意给定的时间持有,因此保证了有序处理。
SocketException
原因
以下情况下会引发 SocketException:
- 当由于主机在指定时间后没有正确响应而导致连接尝试失败时(TCP 错误代码 10060)。
- 建立的连接失败,因为连接的主机未能响应。
- 处理消息时出错,或者远程主机超过了规定的超时时间。
- 基础网络资源问题。
解决方法
SocketException 错误表明承载应用程序的 VM 无法将名称 转换为相应的 IP 地址。
检查以下命令是否成功映射到 IP 地址。
PS C:\> nslookup <mynamespace>.servicebus.chinacloudapi.cn
应提供如下所示的输出:
Name: <cloudappinstance>.chinacloudapp.cn
Address: XX.XX.XXX.240
Aliases: <mynamespace>.servicebus.chinacloudapi.cn
如果上述名称未解析为 IP 和命名空间别名,请与网络管理员联系,开展进一步调查。 名称解析是通过 DNS 服务器完成的,通常是客户网络中的资源。 如果 DNS 解析由 Azure DNS 完成,请与 Azure 支持部门联系。
如果名称解析按预期工作,请在此处检查是否允许连接到 Azure 服务总线。
MessagingException
原因
MessagingException 是可能出于各种原因引发的一般异常。 一些原因包括:
- 尝试在“主题”或“订阅”上创建“QueueClient” 。
- 发送的消息大小大于给定层的限制。 阅读有关服务总线配额和限制的详细信息。
- 由于限制,特定的数据平面请求(发送、接收、完成、放弃)已终止。
- 由于服务升级和重启而导致的暂时性问题。
注意
上述异常列表非完整列表。
解决方法
解决方法步骤取决于引发 MessagingException 的原因。
- 对于暂时性问题(其中 isTransient 设置为 true)或限制问题,重试操作可能会解决问题。 SDK 上的默认重试策略可用于此目的。
- 对于其他问题,异常中的详细信息表明可以从相同地方推断问题和解决步骤。
StorageQuotaExceededException
原因
当高级命名空间中实体的总大小超过每个消息传送单元 1 TB 的限制时,将生成 StorageQuotaExceededException。
解决方案
- 增加分配给高级命名空间的消息传送单元数
- 如果已对命名空间使用允许的最大消息传送单元数,请创建一个单独的命名空间。
后续步骤
有关服务总线 .NET API 的完整参考,请参阅 Azure .NET API 参考。 有关故障排除提示,请参阅故障排除指南。