【问题标题】:Azure Service Bus - MaxConcurrentCalls=1 - The lock supplied is invalid. Either the lock expiredAzure 服务总线 - MaxConcurrentCalls=1 - 提供的锁无效。要么锁过期
【发布时间】:2021-01-10 03:25:40
【问题描述】:

我正在使用 Azure 服务总线,并且我有以下代码 (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);
}

【问题讨论】:

    标签: c# .net-core azureservicebus


    【解决方案1】:

    我正在为我的问题编写解决方案,因为它可能对其他人有所帮助。

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

    我写的时候:

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

    后来证明这种说法是不正确的。当我启用多个失败的队列时。

    我在这里发布的代码块实际上是有效的。它周围的东西被打破了。我试图获得一些时间并最终编写了糟糕的代码。我修复了我的设计以正确管理事物,现在一切运行顺利。

    【讨论】:

      【解决方案2】:

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

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

      我建议:

      1. 在队列中增加MaxLockDuration
      2. 验证预取计数

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

      【讨论】:

      • 我写的那句话是不正确的。我发布了我的问题的答案。这是我的错。
      猜你喜欢
      • 2020-08-30
      • 2021-11-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-04-25
      • 2017-11-19
      • 2020-12-27
      相关资源
      最近更新 更多