当锁定时间未过去时,Azure服务总线将未分区的队列抛出MessageLockLostException

时间:2020-11-07 08:22:22

标签: c# azure azureservicebus

我正在尝试使用PeekLock接收模式接收消息,处理消息(处理时间远低于消息锁定持续时间),然后完成消息。我已经检查了周围是否有其他类似问题,但我认为已经排除了所有建议的解决方案。

  • 队列没有 分区。
  • 在测试时,队列中只有一条消息,而且我甚至试图将PrefetchCount设置为1。
  • 只有一个接收器处于活动状态。
  • 我将LockDuration增加到了5分钟,并且处理时间约为20秒。检查收到的消息时,我看到LockedUntil属性比CompleteAsync调用晚得多。

即使如此,在调用CompleteAsync方法时,我每次都会得到MessageLockLostException

这是我正在使用的包装器类的(相关部分):

public class ServiceBusClient
{
    private readonly ServiceBusConnectionManager manager;

    public ServiceBusClient(string connectionString)
    {
        manager = new ServiceBusConnectionManager(connectionString);
    }

    public async Task<Message> GetNextDownlinkMessage(string queueName)
    {
        var messageReceiver = new MessageReceiver(manager.Connection, queueName, ReceiveMode.PeekLock);
        var message = await messageReceiver.ReceiveAsync();
        await messageReceiver.CloseAsync();
        return message;
    }

    public async Task Complete(string queueName, string lockToken)
    {
        var queueClient = new QueueClient(manager.Connection, queueName, ReceiveMode.PeekLock, null);
        await queueClient.CompleteAsync(lockToken);
    }
}

我检查了lockToken实际上是接收到的消息上的那个。我真的没办法了。


编辑:我后来意识到错误是因为我每次实例化一个新的MessageReceiver对象,并且消息需要由用于获取消息的完全相同的实例来完成。

2 个答案:

答案 0 :(得分:2)

听起来像您正在使用旧版的Service Bus SDK。有一个较新的版本将于本月底发布,以实现全面上市-您可以找到here

使用新库,您可以通过在.CompleteMessageAsync(msg)sample link)上调用SeviceBusReceiver来完成消息:

string connectionString = "<connection_string>";
string queueName = "<queue_name>";
// since ServiceBusClient implements IAsyncDisposable we create it with "await using"
await using var client = new ServiceBusClient(connectionString);

// create a receiver that we can use to receive and settle the message
ServiceBusReceiver receiver = client.CreateReceiver(queueName);

// the received message is a different type as it contains some service set properties
ServiceBusReceivedMessage receivedMessage = await receiver.ReceiveMessageAsync();

// complete the message, thereby deleting it from the service
await receiver.CompleteMessageAsync(receivedMessage);

答案 1 :(得分:0)

我终于找到了问题。每次完成一条消息时,我都会创建一个新的QueueClient实例。事实证明,您需要使用接收消息的完全相同的MessageReceiver实例来完成或放弃该消息。即使队列相同,也无法创建MessageReceiver的新实例。