我正在编写用于监控和修复Azure上dead letter queue
的{{1}}消息的功能。
我可以使用topic subscription
来显示消息列表;但是当我们想要删除其中一条消息时,我们就会陷入困境。
工作流程将是:
_subscriptionClient.PeekBatch(10)
。问题在于,虽然我们收到了邮件列表,但我们无法在不使用.Complete()
的情况下就特定邮件调用.Complete()
。
由于你不能通过MessageId .subscriptionClient.Receive()
发送消息,这是否意味着我们必须像下面一样逐个遍历消息?
.Receive()
我对这种方法的问题是:
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;
}
上的锁定如果在循环内没有匹配,我已经玩弄了将每条消息标记为已放弃的想法;但是这会产生我们无限循环遍历相同项目的风险(因为matchingMessage
将它们放回队列中)。
有没有人找到一个有效的方法呢?也许将.Abandon()
与.Defer()
一起使用?
答案 0 :(得分:4)
您可以在此处使用会话,为每条消息设置会话ID。稍后当您浏览DeadLetter时,选择消息及其sessionID,使用sessionID打开会话并接收消息。
<强>更新强>: 作为特殊队列的DeadLetter队列不允许会话,并且也不能使用sequenceNumber从DeadLetter队列接收消息,如果您想要选择消息,这些是我找到的两个选项。
所以这是在问题描述的情况下应该做什么,从DeadLetter获取所有消息,将某些消息重播到原始队列进行重新处理,将其余消息移动到另一个队列( ErrorQueue)并清除死信队列。 我认为这更合适,因为DeadLetter队列更像是ServicBus处理错误/到期的内部队列。如果应用程序需要处理错误,那么将它们移动到特定于应用程序的队列将提供更大的灵活性,而不是过度加载系统队列(DeadLetter Queue)
答案 1 :(得分:1)
我们和Dhana Krishnamsamy一样。
我们创建了一个DeadLetterQueueCompanionQueue 然后,对于每个订阅,我们为deadletter queue注册了一个客户端 该客户端将原始消息的副本重新提交到新队列
我们的队列有一个消息到期,也允许我们在一个地方进行监控。
然后我们在原始的死信队列中完成消息。
答案 2 :(得分:1)
如果您有消息SequenceNumber:
,您可以非常简单地从死信队列中删除特定消息public static void DeleteDeadLetterMessage(string connectionString, string queueName, long sequenceNumber)
{
var deadLetterQueue = QueueClient.CreateFromConnectionString(connectionString, QueueClient.FormatDeadLetterPath(queueName));
var msg = deadLetterQueue.Peek(sequenceNumber);
if (msg.SequenceNumber == sequenceNumber)
{
msg = deadLetterQueue.Receive();
msg.Complete();
}
}
唯一需要注意的是,如果没有任何带有指定SequenceNumber的消息,Peek可能会返回另一条消息。
因此,您需要检查SequenceNumber,以便您不会完成错误的消息。