我可以使用_subscriptionClient.PeekBatch(10)来显示消息列表;但是,当我们想要实际删除其中一条消息时,我们会陷入困境.
工作流程将是:
>获取所有消息的列表
>将特定消息(例如集合中的第5个)发送回原始队列以进行重新处理
>将关联的死信消息标记为.Complete().
问题是,虽然我们有消息列表,但我们不能在不使用.subscriptionClient.Receive()的情况下调用特定的消息列表上的.Complete().
你不能.通过MessageId接收消息(),这是否意味着我们必须像下面一样逐个循环消息?
public BrokeredMessage GetMessageById(string messageIdentifier) { BrokeredMessage matchingMessage = null; var messageNotFound = true; var messagesToAbandon = new List<BrokeredMessage>(); while (messageNotFound) { var message = _subscriptionClient.Receive(); if (message == null) { throw new Exception("Could not find the message on the queue"); } if (message.MessageId == messageIdentifier) { messageNotFound = false; matchingMessage = message; } else { messagesToAbandon.Add(message); } } // Unlock all messages that do not match the matching one received. foreach (var message in messagesToAbandon) { message.Abandon(); } return matchingMessage; }
我对这种方法的问题是:
>它不可扩展;如果消息是集合中的第100个怎么办?我们必须循环到99并将每个标记为废弃
>如果要放弃的项目太多,我们可能会失去对matchMessage的锁定
>这是一个漫长的过程
如果在循环中不匹配,我已经玩弄了将每条消息标记为已放弃的想法;然而,这会产生我们无限循环遍历相同项目的风险(因为.Abandon()将它们放回队列中).
有没有人找到一个有效的方法呢?也许使用.Defer()和.Receive(sequenceNumber)?
解决方法
更新:
作为特殊队列的DeadLetter队列不允许会话,并且也不能使用sequenceNumber从DeadLetter队列接收消息,如果您想要选择消息,这些是我找到的两个选项.
所以这是在所述情况下应该做的事情,从DeadLetter获取所有消息,将某些消息重播到原始队列以进行重新处理,将其余消息移动到另一个队列(ErrorQueue)并清除死信队列.我认为这更合适,因为DeadLetter队列更像是ServicBus处理错误/到期的内部队列.如果应用程序需要处理错误,那么将它们移动到特定于应用程序的队列将提供更大的灵活性,而不是过载系统队列(DeadLetter Queue)