我正在使用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);
}
答案 0 :(得分:1)
我决定将MaxConcurrentCalls从1增加到2,神奇地消失了错误。
并发性和锁定持续时间并不是方程式中唯一的变量。这听起来像是预取问题。如果启用,则预取的消息比处理的消息多,以节省延迟和往返。如果预取过于激进,则仍将处理已预取和等待的消息,并且尽管处理通常足够短,但是等待处理和实际处理的总时间将超过锁定持续时间。 / p>
我建议:
MaxLockDuration
关于MaxLockDuration
与MaxAutoRenewDuration
,这两个比较棘手。虽然可以保证第一个,但第二个不,是客户的最大努力。
答案 1 :(得分:0)
我正在为我的问题写解决方案,因为它可能会帮助他人。
找出问题的根本原因是一个非常基本的错误,但是这个错误让我感到非常困惑。 在同一个类实例(多队列方案)上多次调用了 OpenQueue 方法,这是一个错误。这种行为很奇怪。看起来queueManagers按预期注册了所有队列,但是令牌被覆盖,导致它始终无效。
当我写信时:
我决定将MaxConcurrentCalls从1增加到2,神奇地消失了错误。
后来该陈述被证明是不正确的。当我启用了多个失败惨重的队列。
我在这里发布的代码块实际上正在工作。周围的东西坏了。我试图争取一些时间,最终写了糟糕的代码。我修复了设计问题,以正确地进行管理,现在一切运行顺利。