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

C# MessageLockLostException:提供的锁无效。锁已过期,或者消息已从队列中删除,c#,azure,azure-functions,azureservicebus,azure-servicebus-queues,C#,Azure,Azure Functions,Azureservicebus,Azure Servicebus Queues,我正在尝试使用服务总线队列触发器使用队列中的消息,并执行一些需要一些时间才能完成的工作。我不希望其他处理器在处理消息时拾取消息。我在host.json中有以下配置。当我从队列接收消息时,等待接收方.CompleteAsync(lockToken) 我收到一个异常“提供的锁无效。锁已过期,或者消息已从队列中删除。” Azure函数的代码如下所示 public static void Run([ServiceBusTrigger("testqueue", Connection

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

Azure函数的代码如下所示

 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}");
        }
    
    }

当您将Azure Service Bus触发的Azure功能配置为
maxAutoRenewDuration
设置为10分钟时,您要求触发器将锁定时间延长到10分钟。这不是一个有保证的操作,因为它是由客户端启动的,最大单次锁定时间为5分钟。因此,扩展锁的操作可能会失败,锁将被释放,导致函数的另一个实例同时处理它,而原始处理仍在进行

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

我建议:

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

  • 您没有说明问题。我在推断问题-为什么锁会丢失,尽管
    maxautronewduration
    设置为10分钟?如果一条消息处理时间超过5分钟怎么办?要么依赖不保证的自动续订,要么设计不同的解决方案
     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}");
            }
        
        }