完成锁定消息时出现 Azure 服务总线 MessageLockLostException
Azure Service Bus MessageLockLostException when Completing Locked Message
我在执行 30 分钟到一个多小时的长时间操作后在 Azure 服务总线上执行完整操作时收到 MessageLockLostException。我希望此过程能够扩展并能够应对故障,因此我保留了 Message 锁并在默认的 1 分钟锁定持续时间内 well 更新它。但是,当我尝试在最后完成消息时,即使我可以看到所有锁更新都在正确的时间发生,我还是收到了 MessageLockLostException。我想在将来扩大规模,但是目前只有一个应用程序实例,我可以确认消息在出错后仍然存在于服务总线订阅上,所以问题肯定是在锁定附近。
这是我采取的步骤。
- 获取消息并配置锁
messages = await Receiver.ReceiveAsync(1, TimeSpan.FromSeconds(10)).ConfigureAwait(false);
var message = messages[0];
var messageBody = GetTypedMessageContent(message);
Messages.TryAdd(messageBody, message);
LockTimers.TryAdd(
messageBody,
new Timer(
async _ =>
{
if (Messages.TryGetValue(messageBody, out var msg))
{
await Receiver.RenewLockAsync(msg.SystemProperties.LockToken).ConfigureAwait(false);
}
},
null,
TimeSpan.FromSeconds(Config.ReceiverInfo.LockRenewalTimeThreshold),
TimeSpan.FromSeconds(Config.ReceiverInfo.LockRenewalTimeThreshold)));
执行漫长的 运行 过程
完成留言
internal async Task Complete(T message)
{
if (Messages.TryGetValue(message, out var msg))
{
await Receiver.RenewLockAsync(msg.SystemProperties.LockToken);
await Receiver.CompleteAsync(msg.SystemProperties.LockToken).ConfigureAwait(false);
}
}
上面的代码是其中的精简版本,我删除了一些 try catch 错误处理和日志记录,但我可以确认在调试问题时我可以看到计时器按时执行。只是 "CompleteAsync" 失败了。
附加信息;
- 服务总线主题已启用分区
- 我试过在阈值的 80%(48 秒)、阈值的 30%(18 秒)和阈值的 10%(6 秒)时更新它
- 我四处寻找答案,我找到的最接近的答案是 this article,但它是 2016 年的。
- 我无法让它在独立的控制台应用程序中失败,所以我不知道这是否是我在我的应用程序中做的事情,但我可以确认锁更新发生在处理期间,并且returns 更新锁的正确日期时间,我预计如果锁真的丢失了 CompleteAsync 将失败
- 我正在使用 Microsoft.Azure.ServiceBus nuget 包 Version="4.1.3"
- 我的应用程序是 Dotnet Core 3.1 并使用以 Dotnet 标准 2.1 编写的服务总线包装程序包
- 如果您长时间不按,消息就会完成,即使您按时偶尔也会完成。
任何关于如何在一个小时后成功完成我的服务总线消息的帮助或建议都是很好的
这里的问题不是我的代码。这是关于服务总线主题的分区。如果您四处搜索,Microsoft GitHub 上有一些关于消息完成的问题。这无论如何都不重要,因为我在这里使用的修复是使用订阅转发功能将消息移动到禁用分区的新主题,然后从该新主题读取消息,我能够使用完全相同的代码来保留消息锁了很久还顺利完成
我在执行 30 分钟到一个多小时的长时间操作后在 Azure 服务总线上执行完整操作时收到 MessageLockLostException。我希望此过程能够扩展并能够应对故障,因此我保留了 Message 锁并在默认的 1 分钟锁定持续时间内 well 更新它。但是,当我尝试在最后完成消息时,即使我可以看到所有锁更新都在正确的时间发生,我还是收到了 MessageLockLostException。我想在将来扩大规模,但是目前只有一个应用程序实例,我可以确认消息在出错后仍然存在于服务总线订阅上,所以问题肯定是在锁定附近。
这是我采取的步骤。
- 获取消息并配置锁
messages = await Receiver.ReceiveAsync(1, TimeSpan.FromSeconds(10)).ConfigureAwait(false);
var message = messages[0];
var messageBody = GetTypedMessageContent(message);
Messages.TryAdd(messageBody, message);
LockTimers.TryAdd(
messageBody,
new Timer(
async _ =>
{
if (Messages.TryGetValue(messageBody, out var msg))
{
await Receiver.RenewLockAsync(msg.SystemProperties.LockToken).ConfigureAwait(false);
}
},
null,
TimeSpan.FromSeconds(Config.ReceiverInfo.LockRenewalTimeThreshold),
TimeSpan.FromSeconds(Config.ReceiverInfo.LockRenewalTimeThreshold)));
执行漫长的 运行 过程
完成留言
internal async Task Complete(T message)
{
if (Messages.TryGetValue(message, out var msg))
{
await Receiver.RenewLockAsync(msg.SystemProperties.LockToken);
await Receiver.CompleteAsync(msg.SystemProperties.LockToken).ConfigureAwait(false);
}
}
上面的代码是其中的精简版本,我删除了一些 try catch 错误处理和日志记录,但我可以确认在调试问题时我可以看到计时器按时执行。只是 "CompleteAsync" 失败了。
附加信息;
- 服务总线主题已启用分区
- 我试过在阈值的 80%(48 秒)、阈值的 30%(18 秒)和阈值的 10%(6 秒)时更新它
- 我四处寻找答案,我找到的最接近的答案是 this article,但它是 2016 年的。
- 我无法让它在独立的控制台应用程序中失败,所以我不知道这是否是我在我的应用程序中做的事情,但我可以确认锁更新发生在处理期间,并且returns 更新锁的正确日期时间,我预计如果锁真的丢失了 CompleteAsync 将失败
- 我正在使用 Microsoft.Azure.ServiceBus nuget 包 Version="4.1.3"
- 我的应用程序是 Dotnet Core 3.1 并使用以 Dotnet 标准 2.1 编写的服务总线包装程序包
- 如果您长时间不按,消息就会完成,即使您按时偶尔也会完成。
任何关于如何在一个小时后成功完成我的服务总线消息的帮助或建议都是很好的
这里的问题不是我的代码。这是关于服务总线主题的分区。如果您四处搜索,Microsoft GitHub 上有一些关于消息完成的问题。这无论如何都不重要,因为我在这里使用的修复是使用订阅转发功能将消息移动到禁用分区的新主题,然后从该新主题读取消息,我能够使用完全相同的代码来保留消息锁了很久还顺利完成