完成锁定的消息时,Azure服务总线MessageLockLostException

时间:2020-06-08 08:40:45

标签: c# azure azureservicebus

在执行30分钟到一个小时以上的长时间操作后,在Azure Service Bus上执行完整操作时,出现MessageLockLostException。我希望此过程能够扩展并能够对故障进行恢复,因此我保留了Message锁,并在默认的1分钟锁定时间内 well 对其进行了续订。但是,当我尝试在最后完成消息时,即使我看到所有锁更新都已在正确的时间发生,我仍收到MessageLockLostException。我想在将来扩大规模,但是目前只有该应用程序的一个实例,我可以确认该消息在错误后仍在服务总线订阅上存在,因此问题肯定在锁上。

这是我要采取的步骤。

  1. 获取消息并配置锁
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)));
  1. 执行长期运行的过程

  2. 完成邮件

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年开始的。
  • 我无法使它在独立的控制台应用程序中失败,所以我不知道它是否正在我的应用程序中执行,但是我可以确认在处理期间发生了锁更新,并返回了正确的DateTime以用于更新的锁,我希望如果锁确实丢失了,那么CompleteAsync将会失败
  • 我正在使用Microsoft.Azure.ServiceBus nuget包Version =“ 4.1.3”
  • 我的应用程序是Dotnet Core 3.1,并使用以Dotnet Standard 2.1编写的Service Bus Wrapper软件包
  • 如果您长时间不按住该消息,则该消息会完成;即使如此,有时也会完成该消息。

一个小时后如何成功完成服务总线消息的任何帮助或建议都很好

1 个答案:

答案 0 :(得分:0)

这里的问题与我的代码无关。与“服务总线”主题上的“分区”有关。如果您四处搜索,则在Microsoft GitHub上会出现一些有关消息完成的问题。无论如何,这并不重要,因为我在这里使用的修复方法是使用订阅转发功能将消息移动到禁用了分区的新主题,然后从该新主题中读取消息,并且我能够使用完全相同的代码来保持邮件已锁定很长时间,但仍成功完成了