【服务总线 Azure Service Bus】Service Bus在使用预提取(prefetching)后出现Microsoft.Azure.ServiceBus.MessageLockLostException异常问题

简介: 【服务总线 Azure Service Bus】Service Bus在使用预提取(prefetching)后出现Microsoft.Azure.ServiceBus.MessageLockLostException异常问题

问题描述

Service Bus接收端的日志中出现大量的MessageLockLostException异常。完整的错误消息为:

Microsoft.Azure.ServiceBus.MessageLockLostException: The lock supplied is invalid. Either the lock expired, or the message has already been removed from the queue. Reference:b2b452db-bf32-41c1-8b76-e546fbdc3856, TrackingId:625929b5-7392-4bf2-9beb-63c132837fc8_B0, SystemTracker:nchn-pr-dep-iot-bus:Queue:dep-iot-input-st-output, Timestamp:2020-12-01T06:13:15

at Microsoft.Azure.ServiceBus.Core.MessageReceiver.OnRenewLockAsync(String lockToken)

at Microsoft.Azure.ServiceBus.Core.MessageReceiver.<>c__DisplayClass74_0.<<RenewLockAsync>b__0>d.MoveNext()

--- End of stack trace from previous location where exception was thrown ---

at Microsoft.Azure.ServiceBus.RetryPolicy.RunOperation(Func`1 operation, TimeSpan operationTimeout)

at Microsoft.Azure.ServiceBus.RetryPolicy.RunOperation(Func`1 operation, TimeSpan operationTimeout)

at Microsoft.Azure.ServiceBus.Core.MessageReceiver.RenewLockAsync(String lockToken)

at Microsoft.Azure.ServiceBus.Core.MessageReceiver.RenewLockAsync(Message message)

at Microsoft.Azure.ServiceBus.MessageReceivePump.RenewMessageLockTask(Message message, CancellationToken renewLockCancellationToken) 791

 

问题原因

在接收方使用预提取后,Service Bus服务将锁定此次预提取的消息通过锁定操作,其他接收方则无法接收到此预提取的消息(保持消息唯一消费)。如果接收方在锁定过期之前无法完成此消息,则该消息便对其他接收方可用。

预提取的消息的副本则保留在缓存中。 使用过期的缓存副本的接收方会在尝试完成该消息时接收到一个异常(MessageLockLostException)

 

默认情况下,消息锁定在 30 秒后过期。 这一值可延长到 5 分钟。 通常在创建队列时进行设置。 这是队列级别的属性,不能在消息基础上进行更改。如下图中的Message lock duration(可以点击Change Link进行修改).

解决问题

方法一:修改Message Lock Duration的时间长度,最大可以修改到5分钟。

方法二:在设定消息CompleteAsync前,判断时间 message.LockedUntilUtc中的时间是否已经超过了Message Lock Duration,如果消息未到期但即将到期,可通过调用RenewLock,延续和扩展又一默认锁定时间段

if(message.LockedUntilUtc.Minute <= 1)
    message.RenewLock();


应用程序可能收到包含到期或即将到期的锁定的消息。 如果是这样,应用程序可能处理该消息,但随后发现,因锁定到期而无法完成处理。 应用程序可查看 LockedUntilUtc 属性(受代理时钟和本地计算机时钟之间的时钟偏差约束)。 如果消息锁定已到期,则应用程序必须忽略该消息,不应对该消息或通过该消息调用任何 API。 如果消息未到期但即将到期,可通过调用 message.RenewLock() 延续和扩展又一默认锁定时间段

如果锁定在预提取缓冲区静默地到期,则视为已放弃该消息,且可再次将消息用于从队列进行检索。 这可能导致将消息提取到预提取缓冲区,并置于末尾。 如果在消息过期期间往往无法使用预提取缓存区,这将导致重复预提取消息,但始终无法将其以可用(有效锁定)状态有效送达,并最终在超出最大传送数后移动到死信队列

扩展问题

1:既然预提取更快,为何不是默认选项?(https://docs.azure.cn/zh-cn/service-bus-messaging/service-bus-prefetch#if-it-is-faster-why-is-prefetch-not-the-default-option

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

通过 ReceiveAndDelete 接收模式,预提取缓存区获取的所有消息在队列中不再可用,仅驻留在内存中预提取缓存区,直到应用程序通过 Receive/ReceiveAsync 或 OnMessage/OnMessageAsync API 接收到它们 。 如果在应用程序接收到消息前终止应用程序,这些消息将丢失,且不可恢复。

在 PeekLock 接收模式下,提取到预提取缓存区的消息将以锁定状态进入缓存区,并且将超时时钟用于锁定计时。 如果预提取缓存区很大,且处理所需时间过长,以致消息锁定在驻留于预提取缓存区,甚至应用程序还在处理消息时就到期,可能出现一些令人困惑的事件要应用程序处理。 如MessageLockLostException

如果消息处理需要高度的可靠性,且处理需要大量精力和时间,则建议谨慎使用或者丝毫不用预提取功能。

如果需要较高吞吐量且消息处理通常比较便宜,则预提取会产生显著的吞吐量优势。

 

 

参考资料

Windows Azure MessageLockLostExceptionhttps://stackoverflow.com/questions/15303711/windows-azure-messagelocklostexception

使用服务总线消息传递改进性能的最佳实践https://docs.azure.cn/zh-cn/service-bus-messaging/service-bus-performance-improvements?tabs=net-standard-sdk#prefetching

相关文章
|
3月前
|
API
【Azure Cloud Service】Cloud Service(Classic) 迁移失败,找不到解决方案怎么办?
【Azure Cloud Service】Cloud Service(Classic) 迁移失败,找不到解决方案怎么办?
|
24天前
|
JSON API 数据安全/隐私保护
【Azure Cloud Service】使用RESTAPI更新Cloud Service(Extended Support) 中所配置的证书
本文介绍了在更新Azure Cloud Service (Extended Support) 证书时,若旧证书(如中间证书、根证书)存储在Key Vault Secret中,而新证书仅匹配到服务器证书时,可能导致的错误及解决方法。建议使用PowerShell或RestAPI进行涉及机密的更新。文章详细描述了使用REST API更新证书的三个步骤:上传证书到Azure Key Vault、获取Cloud Service信息并发送GET请求、更新Cloud Service信息并发送PUT请求。通过这些步骤,可以成功更新证书并在云服务节点中验证证书信息。
|
3月前
|
开发框架 .NET Docker
【Azure 应用服务】App Service .NET Core项目在Program.cs中自定义添加的logger.LogInformation,部署到App Service上后日志不显示Log Stream中的问题
【Azure 应用服务】App Service .NET Core项目在Program.cs中自定义添加的logger.LogInformation,部署到App Service上后日志不显示Log Stream中的问题
|
3月前
|
开发框架 .NET 中间件
【Azure 云服务】在Cloud Service的代码中如何修改IIS Application Pool的配置呢? 比如IdleTimeout, startMode, Recycling.PeriodicRestart.Time等
【Azure 云服务】在Cloud Service的代码中如何修改IIS Application Pool的配置呢? 比如IdleTimeout, startMode, Recycling.PeriodicRestart.Time等
【Azure 云服务】在Cloud Service的代码中如何修改IIS Application Pool的配置呢? 比如IdleTimeout, startMode, Recycling.PeriodicRestart.Time等
|
3月前
|
网络安全
【Azure Service Bus】启用诊断日志来获取客户端访问Azure Service Bus的IP地址 [2024-03-26 实验结果失败]
【Azure Service Bus】启用诊断日志来获取客户端访问Azure Service Bus的IP地址 [2024-03-26 实验结果失败]
|
3月前
|
Java Spring
【Azure Service Bus】使用Spring Cloud integration示例代码,为多个 Service Bus的连接使用 ConnectionString 方式
【Azure Service Bus】使用Spring Cloud integration示例代码,为多个 Service Bus的连接使用 ConnectionString 方式
|
3月前
|
存储 Java API
【Azure 事件中心】在Service Bus Explorer工具中查看到EventHub数据在分区中的6种属性问题
【Azure 事件中心】在Service Bus Explorer工具中查看到EventHub数据在分区中的6种属性问题
|
3月前
|
缓存 Java API
【Azure 服务总线】详解Azure Service Bus SDK中接收消息时设置的maxConcurrentCalls,prefetchCount参数
【Azure 服务总线】详解Azure Service Bus SDK中接收消息时设置的maxConcurrentCalls,prefetchCount参数
|
3月前
【Azure 应用服务】App Service运行时突然中断:There is not enough space on the disk : 'D:localTempASPNETCORE...
【Azure 应用服务】App Service运行时突然中断:There is not enough space on the disk : 'D:localTempASPNETCORE...
|
3月前
|
存储 网络安全 API
【Azure Service Bus】 Service Bus如何确保消息发送成功,发送端是否有Ack机制 
【Azure Service Bus】 Service Bus如何确保消息发送成功,发送端是否有Ack机制