[英]Getting a Message by MessageId on the Azure Service Bus Dead Letter queue
I'm writing functionality for monitoring and fixing messages in the dead letter queue
of a topic subscription
on Azure. 我正在编写用于监视和修复Azure上
topic subscription
dead letter queue
中的消息的功能。
I can get a list of messages using _subscriptionClient.PeekBatch(10)
for display; 我可以使用
_subscriptionClient.PeekBatch(10)
来显示消息列表; however we are stuck when we want to actually remove one of the messages. 但是,当我们想要实际删除其中一条消息时,我们会陷入困境。
The workflow would be: 工作流程将是:
.Complete()
. .Complete()
。 The issue is that whilst we have the list of messages, we cannot call .Complete()
on a specific one without using .subscriptionClient.Receive()
first. 问题是,虽然我们的邮件列表,我们不能称之为
.Complete()
上的特定一个不使用.subscriptionClient.Receive()
第一。
As you cannot .Receive()
a message by MessageId, does this mean we have to loop through the messages one by one like below? 你不能。通过MessageId接收消息
.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;
}
My issue with this approach is: 我对这种方法的问题是:
matchingMessage
if there are too many items to abandon matchingMessage
如果有太多项目放弃 I've toyed with the idea of marking each message as abandoned if not matched within the loop; 如果在循环中不匹配,我已经玩弄了将每条消息标记为已放弃的想法; however this creates the risk of us looping through the same items infinitely (as
.Abandon()
puts them back on the queue). 然而,这会产生我们无限循环遍历相同项目的风险(因为
.Abandon()
将它们放回队列中)。
Has anyone found an efficient way around this? 有没有人找到一个有效的方法? Maybe using
.Defer()
with .Receive(sequenceNumber)
? 也许使用
.Defer()
和.Defer()
.Receive(sequenceNumber)
?
You may use sessions here, set the session id for each message. 您可以在此处使用会话,为每条消息设置会话ID。 Later on when you browse the DeadLetter, pick the message and its sessionID, open a session using the sessionID and receive on the message.
稍后当您浏览DeadLetter时,选择消息及其sessionID,使用sessionID打开会话并接收消息。
Update : The DeadLetter queue, being a special queue, doesnt allow sessions and one cannot receive a message from DeadLetter queue using sequenceNumber as well, those are the two options i found if you want to cherry pick a message. 更新 :作为特殊队列的DeadLetter队列不允许会话,并且也不能使用sequenceNumber从DeadLetter队列接收消息,如果您想要选择消息,这些是我找到的两个选项。
So here is what one shall do in the cases described in question , Take all the messages from DeadLetter, Replay certain messages to original queue for reprocessing, move the rest of the messages to another queue (ErrorQueue) and clear the dead letter queue. 所以这是在所讨论的情况下应该做的事情,从DeadLetter获取所有消息,将某些消息重播到原始队列以进行重新处理,将其余消息移动到另一个队列(ErrorQueue)并清除死信队列。 I think this will be more appropriate as DeadLetter queue is more of an internal queue for ServicBus to handle errors/expiry.
我认为这更合适,因为DeadLetter队列更像是ServicBus处理错误/到期的内部队列。 If application needs to deal with the error , moving those to app specific queue will give more flexibility and not to over load the system queue (DeadLetter Queue)
如果应用程序需要处理错误,那么将它们移动到特定于应用程序的队列将提供更大的灵活性,而不是过载系统队列(DeadLetter Queue)
We do the same as Dhana Krishnamsamy. 我们和Dhana Krishnamsamy一样。
We created a DeadLetterQueueCompanionQueue Then for each subscriptions we registered a client for the deadletter queue That client re-submits a copy of the original message to the new queue 我们创建了一个DeadLetterQueueCompanionQueue然后,对于每个订阅,我们为deadletter queue注册了一个客户端。客户端将原始消息的副本重新提交到新队列
Our queue has a message expiration and also allows for us to monitor in a single place. 我们的队列有一个消息到期,也允许我们在一个地方进行监控。
We then complete the message in the original deadletter queue. 然后,我们在原始deadletter队列中完成消息。
You can delete a specific message from the dead letter queue quite simply if you have the message SequenceNumber: 如果您有消息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();
}
}
The only thing you have to be careful about is that Peek may return another message if there isn't any message with the specified SequenceNumber. 您唯一需要注意的是,如果没有任何带有指定SequenceNumber的消息,Peek可能会返回另一条消息。
Therefore you'll need to check the SequenceNumber, so that you don't Complete the wrong message. 因此,您需要检查SequenceNumber,以便您不会完成错误的消息。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.