简体   繁体   English

通过MessageId在Azure Service Bus死信队列上获取消息

[英]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: 工作流程将是:

  1. Get a list of all messages 获取所有邮件的列表
  2. Send a specific message (say the 5th on in the collection) back to the original queue for reprocessing 将特定消息(例如集合中的第5个)发送回原始队列以进行重新处理
  3. Mark the associated dead letter message as .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: 我对这种方法的问题是:

  • It's not scalable; 它不可扩展; what if the message is the 100th in the collection? 如果消息是集合中的第100个怎么办? We'd have to loop through 99 and mark each as abandoned 我们必须循环到99并将每个标记为已放弃
  • We risk losing the lock on the matchingMessage if there are too many items to abandon 我们可能会失去对锁matchingMessage如果有太多项目放弃
  • It's a long running process 这是一个漫长的过程

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.

相关问题 我们可以使用 .net 代码从 Azure 服务总线中的死信队列中删除基于序列号的特定死信消息吗? - can we delete a specific dead letter message based on the sequence number from dead letter queue in Azure service bus using .net code? 如何在 Azure 服务总线中显式向主题订阅死信队列发送消息 - How to send message to Topic Subscription Dead Letter Queue Explicitly in Azure Service Bus Azure 服务总线 | 重新处理死信消息返回队列 | 如何接收来自死信队列的所有消息? - Azure service bus | Re process dead letter messages back to queue | How to receive all messages from dead letter queue? 使用存储队列和服务总线时,Azure 死信队列和毒药队列有什么区别? - What is the difference between Azure Dead Letter Queues and Poison Queues when using Storage Queue and Service Bus? 死信队列中的服务总线克隆不起作用 - Service Bus Clone from Dead Letter Queue Not Working Azure Service Bus中死信队列中的邮件是否过期? - Do messages in dead letter queues in Azure Service Bus expire? 如何删除Azure Service Bus队列中的死信? - How do you delete the dead letters in an Azure Service Bus queue? Azure Service Bus读取消息队列 - Azure Service Bus Read Message Queue 死信 Azure 服务总线消息的 DeadLetterErrorDescription 的最大长度是多少? - What is the maximum length of DeadLetterErrorDescription for dead lettering an Azure Service Bus message? 如何使用Azure Functions输出绑定设置Service Bus消息的MessageId? - How can you set the MessageId of a Service Bus message using the Azure Functions output binding?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM