如何删除 Azure 服务总线主题上的死信消息

Posted

技术标签:

【中文标题】如何删除 Azure 服务总线主题上的死信消息【英文标题】:How do I delete a DeadLetter message on an Azure Service Bus Topic 【发布时间】:2013-12-21 02:35:50 【问题描述】:

我正在编写一段代码,它可以让我们:

    查看 Azure 服务总线主题 (Peek) 中存在的所有死信消息的列表 修复并将它们发送回主题 重新发送时将它们从死信队列中删除。

我对前 2 点没有意见;使用 Peek 接收模式,我可以显示消息列表,我们可以毫无问题地编辑和重新发送。

当我想真正从死信队列中删除消息时,问题就来了。

我们如何按消息级别对消息执行此操作?我们可能只想删除死信队列中的 2 条消息,并保留其他消息以供稍后查看。对死信队列中的消息调用.Complete() 是否会像在主订阅中那样删除它?

供参考;这是我们为死信队列获取SubscriptionClient 的代码:

private SubscriptionClient GetOrCreateSubscriptionClient(string connectionString)

    if (!NamespaceManager.TopicExists(_topicName))
    
        NamespaceManager.CreateTopic(new TopicDescription(_topicName)
        
            MaxSizeInMegabytes = 5120,
            DefaultMessageTimeToLive = TimeSpan.FromSeconds(DEFAULT_LOCK_DURATION_IN_SECONDS)
        );
    

    if (!NamespaceManager.SubscriptionExists(_topicName, _subscriptionName))
    
        NamespaceManager.CreateSubscription(_topicName, _subscriptionName);
    

    var deadLetterPath = SubscriptionClient.FormatDeadLetterPath(_topicName, _subscriptionName);

    var client = SubscriptionClient.CreateFromConnectionString(
        connectionString, deadLetterPath, _subscriptionName, ReceiveMode.PeekLock);

    return client;


【问题讨论】:

【参考方案1】:

是的,对您从死信队列收到的代理消息的引用调用完成会将其从死信队列中删除。

【讨论】:

【参考方案2】:

以下是获取死信队列中所有消息列表的方法:

public async Task<IEnumerable<BrokeredMessage>> GetDeadLetterMessagesAsync(string connectionString,
    string queueName)

    var queue = QueueClient.CreateFromConnectionString(connectionString, QueueClient.FormatDeadLetterPath(queueName));
    var messageList = new List<BrokeredMessage>();
    BrokeredMessage message;
    do
    
        message = await queue.PeekAsync();
        if (message != null)
        
            messageList.Add(message);
        
     while (message != null);
    return messageList;

然后您可以使用 SequenceNumber 删除特定消息:

public async Task DeleteDeadLetterMessageAsync(string connectionString, string queueName, long sequenceNumber)

    var deadLetterQueue = QueueClient.CreateFromConnectionString(connectionString, QueueClient.FormatDeadLetterPath(queueName));
    var msg = await deadLetterQueue.PeekAsync(sequenceNumber);
    if (msg.SequenceNumber == sequenceNumber)
    
        msg = await deadLetterQueue.ReceiveAsync();
        await msg.CompleteAsync();
    

请注意,如果没有任何具有指定 SequenceNumber 的消息,Peek 可能会返回另一条消息。因此,您需要检查 SequenceNumber,以免删除错误消息。

【讨论】:

我的测试表明 Peek 和 Receive 使用不同的“光标”。因此,当您按序列号查看目标消息时,以下接收操作将加载队列中的第一条消息,而不是被 Peek 的消息。那是使用较旧的 WindowsAzure.ServiceBus 库。可能在较新的 lib 中有不同的行为?

以上是关于如何删除 Azure 服务总线主题上的死信消息的主要内容,如果未能解决你的问题,请参考以下文章

Azure 服务总线中的死信队列中的消息是不是过期?

如何在服务总线队列触发功能中将服务总线消息移动到死信

如何使用 Java 将错误消息移动到 Azure 死信队列(主题 - 订阅)?

查看Azure服务总线死信的申请

从逻辑应用程序设置死信原因

是否可以创建 WCF 服务端点来处理来自 Azure 服务总线的死信?