我正在尝试使用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
对象,并且消息需要由用于获取消息的完全相同的实例来完成。
答案 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
的新实例。