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



我正在使用Azure服务总线,我有下面的代码(c#.NetCore 3.1(提供的锁无效。锁已过期,或者消息已从队列中删除,或者由其他接收器实例接收";当我呼叫";CompleteAsync";

正如你在代码中看到的;"ReceiveMode.PeekLock"自动完成=false";MaxAutoRenewDuration为5分钟。处理消息的代码在不到1秒的时间内完成,但我每次都会收到错误。

让我抓狂的是,在数小时后阅读帖子、重写代码和大量";尝试和错误";我决定将MaxConcurrentCall从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);
}

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

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

我建议:

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

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

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

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

当我写道:

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

后来那句话被证明是不正确的。当我启用了多个失败得很惨的队列时。

我在这里发布的代码块实际上正在工作。它周围的东西坏了。我试图争取一些时间,结果写了糟糕的代码。我修改了我的设计以正确地管理事情,现在一切都很顺利。

最新更新