C# MessageLockLostException:提供的锁无效。锁已过期,或者消息已从队列中删除
我正在尝试使用服务总线队列触发器使用队列中的消息,并执行一些需要一些时间才能完成的工作。我不希望其他处理器在处理消息时拾取消息。我在host.json中有以下配置。当我从队列接收消息时,等待接收方.CompleteAsync(lockToken)强> 我收到一个异常“提供的锁无效。锁已过期,或者消息已从队列中删除。” Azure函数的代码如下所示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
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
以确保不会过度提取您没有说明问题。我在推断问题-为什么锁会丢失,尽管
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}");
}
}