MessageLockLostException:提供的锁无效锁已过期,或者消息已从队列中删除

问题描述

我正在尝试使用服务总线队列触发器从队列中消耗一条消息,并完成一些工作,这需要一些时间才能完成。我不希望其他处理器在我处理消息时选择该消息。我在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}");
        }
    
    }

解决方法

在将my @a = (undef,q{},1); # All of these test whether 'array' has four elements: print q{array has four elements} if @a == 4; print q{array has four elements} unless @a != 4; @a == 4 and print q{array has four elements}; !(@a != 4) and print q{array has four elements}; # All of the above print: # array has four elements # All of these test whether array is not empty: print q{array is not empty} if @a; print q{array is not empty} unless !@a; @a and print q{array is not empty}; !(!@a) and print q{array is not empty}; # All of the above print: # array is not empty 设置为10分钟的情况下配置由Azure Service Bus触发的Azure功能时,您要求触发器将锁定延长长达10分钟。这不是不是的保证操作,因为它是由客户端发起的,并且最长一次锁定时间为5分钟。鉴于此,扩展锁的操作可能会失败,并且锁将被释放,从而导致函数的另一个实例同时进行处理,而原始处理仍在进行。

要查看的另一方面是将maxAutoRenewDuration设置为100,将prefetchCount设置为32。这意味着您要提取多达100条消息并进行处理到32那我不知道实际的功能代码是否运行了超过50秒(在您的示例中),但是预取的消息锁不会自动更新。因此,如果在队列的maxConcurrentCalls时间(默认情况下少于5分钟)内未对预提取的消息进行处理,则其中一些预提取的消息将在丢失后开始处理,可选续订和完成方式锁。

我建议:

  1. 检查MaxLockDuration的长度不要太短以适应您的预取和并发。
  2. 更新MaxLockDuration,以确保您不会超量获取。
  3. 如果可以在5分钟或更短的时间内完成一次邮件处理,则宁愿选择此方法,也不希望自动续订。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...