Azure服务总线-MaxConcurrentCalls = 1-提供的锁无效。锁已过期

时间:2020-09-23 21:07:00

标签: c# .net-core azureservicebus

我正在使用Azure Service Bus,并且具有下面的代码(c#.NetCore 3.1)。我不断收到错误消息“ 提供的锁无效。该锁已过期,或者消息已从队列中删除,或者已由其他接收者实例接收。”,当我调用“ CompleteAsync”

如您在代码中所见,我将“ ReceiveMode.PeekLock”,“ AutoComplete = false”和MaxAutoRenewDuration设置为5分钟。处理该消息的代码在不到1秒的时间内完成,但我仍然每次都会收到该错误。

让我发疯的是,经过数小时的阅读,重写代码和大量的“尝试和错误”,我决定将MaxConcurrentCalls从1增加到2,魔术消失了。

有人知道这是怎么回事吗?

public void OpenQueue(string queueName)
{
  var messageHandlerOptions = new MessageHandlerOptions(exceptionReceivedEventArgs =>
  {
    Log.Error($"Message handler encountered an exception {exceptionReceivedEventArgs.Exception}.");
    return Task.CompletedTask;
  });
  messageHandlerOptions.MaxConcurrentCalls = 1;
  messageHandlerOptions.AutoComplete = false;
  messageHandlerOptions.MaxAutoRenewDuration = TimeSpan.FromSeconds(300);

  messageReceiver = queueManagers.OpenReceiver(queueName, ReceiveMode.PeekLock);
  messageReceiver.RegisterMessageHandler(async (message, token) =>
  {
    if (await ProcessMessage(message)) //really quick operation less than 1 second
    {
      await messageReceiver.CompleteAsync(message.SystemProperties.LockToken);
    }
    else
    {
      await messageReceiver.AbandonAsync(message.SystemProperties.LockToken);
    }
  }, messageHandlerOptions);
}

2 个答案:

答案 0 :(得分:1)

我决定将MaxConcurrentCalls从1增加到2,神奇地消失了错误。

并发性和锁定持续时间并不是方程式中唯一的变量。这听起来像是预取问题。如果启用,则预取的消息比处理的消息多,以节省延迟和往返。如果预取过于激进,则仍将处理已预取和等待的消息,并且尽管处理通常足够短,但是等待处理和实际处理的总时间将超过锁定持续时间。 / p>

我建议:

  1. 增加队列上的MaxLockDuration
  2. 验证预取计数

关于MaxLockDurationMaxAutoRenewDuration,这两个比较棘手。虽然可以保证第一个,但第二个,是客户的最大努力。

答案 1 :(得分:0)

我正在为我的问题写解决方案,因为它可能会帮助他人。

找出问题的根本原因是一个非常基本的错误,但是这个错误让我感到非常困惑。 在同一个类实例(多队列方案)上多次调用了 OpenQueue 方法,这是一个错误。这种行为很奇怪。看起来queueManagers按预期注册了所有队列,但是令牌被覆盖,导致它始终无效。

当我写信时:

我决定将MaxConcurrentCalls从1增加到2,神奇地消失了错误。

后来该陈述被证明是不正确的。当我启用了多个失败惨重的队列。

我在这里发布的代码块实际上正在工作。周围的东西坏了。我试图争取一些时间,最终写了糟糕的代码。我修复了设计问题,以正确地进行管理,现在一切运行顺利。