简体   繁体   English

在Azure Service Bus上的死信队列中完成一条消息

[英]Complete a message in a dead letter queue on Azure Service Bus

I want to be able to remove selected messages from my deadletter queue. 我希望能够从我的死信队列中删除选定的邮件。

How is this accomplished? 这是如何完成的?

I constantly get an error: 我不断收到错误:

The operation cannot be completed because the RecieveContext is Null 由于RecieveContext为Null,因此无法完成操作

I have tried every approach I can think of and read about, here is where I am now: 我尝试了所有我能想到和阅读的方法,这就是我现在所处的位置:

public void DeleteMessageFromDeadletterQueue<T>(string queueName, long sequenceNumber)
        {
     var client = GetQueueClient(queueName, true);
                var messages = GetMessages(client);
                foreach(var m in messages)
                {
                    if(m.SequenceNumber == sequenceNumber)
                    {
                        m.Complete();
                    }
                    else
                    {
                        m.Abandon();
                    }
                }
}

/// <summary>
        /// Return a list of all messages in a Queue
        /// </summary>
        /// <param name="client"></param>
        /// <returns></returns>
        private IEnumerable<BrokeredMessage> GetMessages(QueueClient client)
        {
            var peekedMessages = client.PeekBatch(0, peekedMessageBatchCount).ToList();
            bool getmore = peekedMessages.Count() == peekedMessageBatchCount ? true : false;

            while (getmore)
            {
                var moreMessages = client.PeekBatch(peekedMessages.Last().SequenceNumber, peekedMessageBatchCount);
                peekedMessages.AddRange(moreMessages);
                getmore = moreMessages.Count() == peekedMessageBatchCount ? true : false;
            }

            return peekedMessages;
        }

Not sure why this seems to be such a difficult task. 不知道为什么这似乎是一项如此艰巨的任务。

The issue here is that you've called PeekBatch which returns the messages that are just peeked. 这里的问题是你调用了PeekBatch,它返回刚刚查看过的消息。 There is no Receive context which you can then use to either complete or abandon the message. 没有接收上下文,您可以使用它来完成或放弃该消息。 The Peek and PeekBatch operations only return the messages and does not lock them at all, even if the receivedMode is set to PeekLock. Peek和PeekBatch操作仅返回消息,并且根本不锁定它们,即使receiveMode设置为PeekLock也是如此。 It's mostly for skimming the queue, but you can't take an action on them. 它主要用于浏览队列,但您无法对其进行操作。 Note the docs for both Abandon and Complete state, "must only be called on a message that has been received by using a receiver operating in Peek-Lock ReceiveMode." 请注意Abandon和Complete状态的文档,“只能在使用Peek-Lock ReceiveMode中运行的接收器接收到的消息上调用”。 It's not clear here, but Peek and PeekBatch operations don't count in this as they don't actually get a receive context. 这里不太清楚,但Peek和PeekBatch操作不计入其中,因为它们实际上并没有获得接收上下文。 This is why it fails when you attempt to call abandon. 这就是为什么当你试图调用放弃时失败的原因。 If you actually found the one you were looking for it would throw a different error when you called Complete. 如果你真的找到了你正在寻找的那个,当你调用Complete时会抛出一个不同的错误。

What you want to do is use a ReceiveBatch operation instead in PeekBatch RecieveMode. 你想要做的是在PeekBatch RecieveMode中使用ReceiveBatch操作。 This will actually pull a batch of the messages back and then when you look through them to find the one you want you can actually affect the message complete. 这实际上会将一批消息拉回来,然后当您查看它们以找到您想要的消息时,实际上可以影响消息的完成。 When you fire the abandon it will immediately release the message that isn't what you want back to the queue. 当您触发放弃时,它将立即释放不是您想要返回队列的消息。

If your deadletter queue is pretty small usually this won't be bad. 如果您的死信队列非常小,通常这也不错。 If it is really large then taking this approach isn't the most efficient. 如果它真的很大,那么采用这种方法并不是最有效的。 You're treating the dead letter queue more like a heap and digging through it rather than processing the messages "in order". 您将死信队列更像堆,并通过它来处理,而不是“按顺序”处理消息。 This isn't uncommon when dealing with dead letter queues which require manual intervention, but if you have a LOT of these then it may be better to have something processing the dead letter queue into a different type of store where you can more easily find and destroy messages, but can still recreate the messages that are okay to push to a different queue to reprocess. 这在处理需要人工干预的死信队列时并不少见,但是如果你有很多这样的话,那么将死​​信队列处理成不同类型的商店可能会更容易找到,销毁消息,但仍然可以重新创建可以推送到不同队列进行重新处理的消息。

There may be other options, such as using Defer, if you are manually dead lettering things. 可能还有其他选项,例如使用Defer,如果您手动对文字进行刻字。 See How to use the MessageReceiver.Receive method by sequenceNumber on ServiceBus . 请参见如何在ServiceBus上使用sequenceNumber使用MessageReceiver.Receive方法

I was unsuccessful with MikeWo's suggestion, because when I used the combination of instantiating the DLQ QueueClient with ReceiveMode.PeekLock and pulling messages with ReceiveBatch, I was using the versions of Receive/ReceiveBatch requesting the message by its SequenceNumber. 我没有成功使用MikeWo的建议,因为当我使用将DLQ QueueClient与ReceiveMode.PeekLock实例化并使用ReceiveBatch拉取消息的组合时,我正在使用Receive / ReceiveBatch的版本通过其SequenceNumber请求消息。

[aside: in my app, I peek all the messages and list them, and have another handler to re-queue to the main queue a dead-lettered message based on it's specific sequence number...] [旁白:在我的应用程序中,我查看所有消息并列出它们,然后让另一个处理程序根据它的特定序列号重新排队到主队列中的死信消息...]

But the call to Receive(long sequenceNumber) or ReceiveBatch(IEnumerable sequenceNumber) on the DLQClient always throws the exception, "Failed to lock one or more specified messages. The message does not exist." 但是对DLQClient上的Receive(long sequenceNumber)或ReceiveBatch(IEnumerable sequenceNumber)的调用总是抛出异常,“无法锁定一条或多条指定的消息。消息不存在。” (even when I only passed 1 and it is definitely in the queue). (即使我只通过1并且它肯定在队列中)。

Additionally, for reasons that aren't clear, using ReceiveBatch(int messageCount), always only returns the next 1 message in the queue no matter what value is used as the messageCount. 此外,由于原因不明确,使用ReceiveBatch(int messageCount),无论使用什么值作为messageCount,始终只返回队列中的下一条消息。

What finally worked for me was the following: 最终对我有用的是以下内容:

QueueClient queueClient, deadLetterClient;
GetQueueClients(qname, ReceiveMode.PeekLock, out queueClient, out deadLetterClient);

BrokeredMessage msg = null;
var mapSequenceNumberToBrokeredMessage = new Dictionary<long, BrokeredMessage>();
while (msg == null)
{
#if UseReceive
    var message = deadLetterClient.Receive();
#elif UseReceiveBatch
    var messageEnumerable = deadLetterClient.ReceiveBatch(CnCountOfMessagesToPeek).ToList();
    if ((messageEnumerable == null) || (messageEnumerable.Count == 0))
        break;
    else if (messageEnumerable.Count != 1)
        throw new ApplicationException("Invalid expectation that there'd always be only 1 msg returned by ReceiveBatch");

    // I've yet to get back more than one in the deadletter queue, but... 
    var message = messageEnumerable.First();
#endif
    if (message.SequenceNumber == lMessageId)
    {
        msg = message;
        break;
    }
    else if (mapSequenceNumberToBrokeredMessage.ContainsKey(message.SequenceNumber))
    {
        // this means it's started the list over, so we didn't find it...
        break;
    }
    else
        mapSequenceNumberToBrokeredMessage.Add(message.SequenceNumber, message);
    message.Abandon();
}                        

if (msg == null)
    throw new ApplicationException("Unable to find a message in the deadletter queue with the SequenceNumber: " + msgid);

var strMessage = GetMessage(msg);
var newMsg = new BrokeredMessage(strMessage);
queueClient.Send(newMsg);

msg.Complete();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Azure服务总线 - 消息直接进入死信队列 - Azure service bus - message going straight to dead letter queue 从死信队列重新提交消息 - Azure 服务总线 - Resubmitting a message from dead letter queue - Azure Service Bus 通过MessageId在Azure Service Bus死信队列上获取消息 - Getting a Message by MessageId on the Azure Service Bus Dead Letter queue Azure Service Bus消息遗弃和死信队列 - Azure Service Bus message abandon and dead letter queue azure 服务总线方法中的 Abandon() 将特定消息发送到死信队列 - Abandon() in azure service bus method makes a specific message to dead letter queue 如何将消息从逻辑应用程序发送到死信队列(天蓝色总线服务) - How to send message from a logic app to dead letter queue (azure bus service) 如何将消息直接发送到 azure 服务总线(java)中的死信队列? - How can I send a message directly into a dead letter queue in azure service bus (java)? 如何在 Azure 服务总线中显式向主题订阅死信队列发送消息 - How to send message to Topic Subscription Dead Letter Queue Explicitly in Azure Service Bus 从节点js客户端将消息放入azure服务总线的死信队列中 - Put message in dead letter queue in azure service bus from node js client 如何手动将消息发送到 Azure Function 中的服务总线死信队列? - How to manually send message to service bus dead letter queue in Azure Function?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM