提供的锁无效。 锁已过期,或者消息已从队列中删除

我正在使用Microsoft azure服务总线队列来处理计算,我的程序可以正常运行几个小时,但后来我开始为我从那时开始处理的每条消息获得此exception。 我不知道从哪里开始,因为前几个小时一切正常。 我的代码似乎也很准确。 我将发布处理azure服务总线消息的方法。

public static async Task processCalculations(BrokeredMessage message) { try { if (message != null) { if (connection == null || !connection.IsConnected) { connection = await ConnectionMultiplexer.ConnectAsync("connection,SyncTimeout=10000,ConnectTimeout=10000"); //connection = ConnectionMultiplexer.Connect("connection,SyncTimeout=10000,ConnectTimeout=10000"); } cache = connection.GetDatabase(); string sandpKey = message.Properties["sandp"].ToString(); string dateKey = message.Properties["date"].ToString(); string symbolclassKey = message.Properties["symbolclass"].ToString(); string stockdataKey = message.Properties["stockdata"].ToString(); string stockcomparedataKey = message.Properties["stockcomparedata"].ToString(); var sandpTask = cache.GetAsync<List>(sandpKey); var dateTask = cache.GetAsync(dateKey); var symbolinfoTask = cache.GetAsync(symbolclassKey); var stockdataTask = cache.GetAsync<List>(stockdataKey); var stockcomparedataTask = cache.GetAsync<List>(stockcomparedataKey); await Task.WhenAll(sandpTask, dateTask, symbolinfoTask, stockdataTask, stockcomparedataTask); List sandp = sandpTask.Result; DateTime date = dateTask.Result; SymbolInfo symbolinfo = symbolinfoTask.Result; List stockdata = stockdataTask.Result; List stockcomparedata = stockcomparedataTask.Result; StockRating rating = performCalculations(symbolinfo, date, sandp, stockdata, stockcomparedata); if (rating != null) { saveToTable(rating); if (message.LockedUntilUtc.Minute <= 1) { await message.RenewLockAsync(); } await message.CompleteAsync(); // getting exception here } else { Console.WriteLine("Message " + message.MessageId + " Completed!"); await message.CompleteAsync(); } } } catch (TimeoutException time) { Console.WriteLine(time.Message); } catch (MessageLockLostException locks) { Console.WriteLine(locks.Message); } catch (RedisConnectionException redis) { Console.WriteLine("Start the redis server service!"); } catch (MessagingCommunicationException communication) { Console.WriteLine(communication.Message); } catch (Exception ex) { Console.WriteLine(ex.Message); Console.WriteLine(ex.StackTrace); } } 

更新:我检查锁定到期之前的时间,如果需要它我会调用锁更新,但它更新锁定没有错误,但我仍然得到这个例外。

 timeLeft = message.LockedUntilUtc - DateTime.UtcNow; if (timeLeft.TotalMinutes <= 2) { //Console.WriteLine("Renewed lock! " + ((TimeSpan)(message.LockedUntilUtc - DateTime.UtcNow)).TotalMinutes); message.RenewLock(); } catch (MessageLockLostException locks) { Console.WriteLine("Delivery Count: " + message.DeliveryCount); Console.WriteLine("Enqueued Time: " + message.EnqueuedTimeUtc); Console.WriteLine("Expires Time: " + message.ExpiresAtUtc); Console.WriteLine("Locked Until Time: " + message.LockedUntilUtc); Console.WriteLine("Scheduled Enqueue Time: " + message.ScheduledEnqueueTimeUtc); Console.WriteLine("Current Time: " + DateTime.UtcNow); Console.WriteLine("Time Left: " + timeLeft); } 

到目前为止我所知道的是我的代码运行良好一段时间并且更新锁被调用并且工作但我仍然得到锁exception并且在该exception中,我输出timeleft并且它随着代码运行而不断增加时差这让我相信锁定到期的时间不会以某种方式改变?

我花了几个小时试着理解为什么我得到MessageLockLostException 。 我的原因是由于AutoComplete默认为true。

如果您要调用messsage.Complete() (或CompleteAsync() ),则应实例化OnMessageOptions对象,将AutoComplete设置为false,并将其传递给OnMessage调用。

 var options = new OnMessageOptions(); options.AutoComplete = false; client.OnMessage(processCalculations, options); 

我遇到了类似的问题。 消息正在成功处理,但是当它们完成时,服务总线不再具有有效锁定。 事实certificate我的TopicClient.PrefetchCount太高了。

一旦获取,锁似乎就会在所有预取消息上开始。 如果累积消息处理时间超过锁定超时,则每个其他预取消息都将无法完成。 它将返回服务总线。

在创建客户端订阅时,请尝试使用客户端的OnMessageOptions()自动续订,而不是手动更新锁定,如下所示:

  OnMessageOptions options = new OnMessageOptions(); options.AutoRenewTimeout = TimeSpan.FromMinutes(1); try { client = Subscription.CreateClient(); client.OnMessageAsync(MessageReceivedComplete, options); } catch (Exception ex) { throw new Exception (ex); }