【问题标题】:MessageLockLostException: The lock supplied is invalid. Either the lock expired, or the message has already been removed from the queueMessageLockLostException:提供的锁无效。锁已过期,或消息已从队列中删除
【发布时间】:2020-12-13 23:37:36
【问题描述】:

我正在尝试使用服务总线队列触发器从队列中使用消息并执行一些需要一些时间才能完成的工作。我不希望其他处理器在我处理消息时选择消息。我在 host.json 中有以下配置。当我在 await receiver.CompleteAsync(lockToken); 处收到来自队列的消息时 我收到一个异常“提供的锁无效。锁已过期,或者消息已从队列中删除。”

 "serviceBus": {
  "prefetchCount": 1,
  "autoRenewTimeout": "00:05:00",
  "messageHandlerOptions": {
    "autoComplete": false,
    "maxConcurrentCalls": 1,
    "maxAutoRenewDuration": "00:04:00"
  }
}

来自 Azure Function 的代码如下

 public static void Run([ServiceBusTrigger("testqueue", Connection = "AzureServiceBus.ConnectionString")]Message message, MessageReceiver messageReceiver,ILogger log)
    {
        log.LogInformation($"C# ServiceBus queue trigger function processed message: {messageReceiver.ClientId}");
        log.LogInformation($"Message={Encoding.UTF8.GetString(message.Body)}");
        string lockToken = message.SystemProperties.LockToken;
        log.LogInformation($"Processing Message:={Encoding.UTF8.GetString(message.Body)}");
        DoSomeJob(messageReceiver, lockToken,log);
    }
    public static async void DoSomeJob(MessageReceiver receiver,string lockToken, ILogger log)
    {
        try
        {

            await Task.Delay(360000);
            await receiver.CompleteAsync(lockToken);

        }
        catch (Exception ex)
        {

            log.LogInformation($"Error In Job={ex}");
        }
    
    }

【问题讨论】:

  • 你没有说有问题。
  • 我在推断问题 - 尽管 maxAutoRenewDuration 设置为 10 分钟,为什么锁会丢失?

标签: c# azure azure-functions azureservicebus azure-servicebus-queues


【解决方案1】:

当您配置由 Azure 服务总线触发的 Azure 函数并将 maxAutoRenewDuration 设置为 10 分钟时,您要求触发器将锁定延长最多 10 分钟。这不是有保证的操作,因为它是由客户端发起的,并且单个锁定时间最长为 5 分钟。鉴于此,扩展锁的操作可能会失败并且锁将被释放,导致您的函数的另一个实例同时处理它,而原始处理仍在进行中。

要查看的另一个方面是设置为 100 的 prefetchCount 和设置为 32 的 maxConcurrentCalls。这意味着您要获取多达 100 条消息并处理多达 32 条。我不知道实际的功能代码是否运行超过 50 秒(在您的示例中),但预取的消息锁不会自动更新。因此,如果预取消息没有在队列的MaxLockDuration 时间(默认小于 5 分钟)内得到处理,则其中一些预取消息将在失去锁定后开始处理、可选更新和完成方式.

我会推荐:

  1. 检查MaxLockDuration 不要太短以适应您的预取和并发。
  2. 更新 prefetchCount 以确保您不会过度获取。
  3. 如果可以在 5 分钟或更短的时间内完成单条消息的处理,则宁愿这样做而不是自动续订。

【讨论】:

  • 如果一条消息的处理时间超过 5 分钟怎么办?
  • 要么您依赖无法保证的自动续订,要么以不同的方式设计您的解决方案?
猜你喜欢
  • 2020-07-12
  • 1970-01-01
  • 2020-08-30
  • 1970-01-01
  • 2023-03-03
  • 1970-01-01
  • 2022-09-23
  • 1970-01-01
  • 2019-11-02
相关资源
最近更新 更多