如何从Azure Service Bus主题获取指定的消息,然后从Topic中删除它?

时间:2019-06-07 07:34:35

标签: .net-core azureservicebus azure-servicebus-topics

我正在编写用于从Azure Service Bus主题接收消息并从主题中删除指定消息的功能。在删除该消息之前,我需要将该消息发送给其他主题。

   static async Task ProcessMessagesAsync(Message message, CancellationToken token)
    {
        // Process the message.
        Console.WriteLine($"Received message: WorkOrderNumber:{message.MessageId} SequenceNumber:{message.SystemProperties.SequenceNumber} Body:{Encoding.UTF8.GetString(message.Body)}");
        Console.WriteLine("Enter the WorkOrder Number you want to delete:");
        string WorkOrderNubmer = Console.ReadLine();
        if (message.MessageId == WorkOrderNubmer)
        {
            //TODO:Post message into other topic(Priority) then delete from this current topic.
            var status=await SendMessageToBus(message);
            if (status == true)
            {
                await normalSubscriptionClient.CompleteAsync(message.SystemProperties.LockToken);
                Console.WriteLine($"Successfully deleted your message from Topic:{NormalTopicName}-WorkOrderNumber:" + message.MessageId);
            }
            else
            {
                Console.WriteLine($"Failed to send message to PriorityTopic:{PriorityTopicName}-WorkOrderNumber:" + message.MessageId);
            }

        }
        else
        {
            Console.WriteLine($"Failed to delete your message from Topic:{NormalTopicName}-WorkOrderNumber:" + WorkOrderNubmer);
            // Complete the message so that it is not received again.
            // This can be done only if the subscriptionClient is created in ReceiveMode.PeekLock mode (which is the default).
            await normalSubscriptionClient.CompleteAsync(message.SystemProperties.LockToken);

            // Note: Use the cancellationToken passed as necessary to determine if the subscriptionClient has already been closed.
            // If subscriptionClient has already been closed, you can choose to not call CompleteAsync() or AbandonAsync() etc.
            // to avoid unnecessary exceptions.
        }

    }

这种方法的问题是:

  1. 它不可扩展;如果消息在集合中排第50位怎么办?我们必须迭代49次并标记为已删除。

  2. 这是一个长期运行的过程。

为避免这些问题,我想基于索引或序列号从队列中获取指定的消息,然后可以将其从主题中删除。

那么,有人可以建议我如何解决此问题吗?

1 个答案:

答案 0 :(得分:0)

因此,如果我正确理解了您的问题和评论,则您正在尝试执行以下操作:

  1. 传入消息属于标准主题或优先级 话题。
  2. 某些进程检查标准主题中的消息,然后 根据某些条件将它们“移动”到优先主题 从标准主题中删除它们并将其添加到 优先主题。
  3. 邮件正常处理。

enter image description here

正如肖恩(Sean)所述,步骤2根本行不通。服务总线是先进先出的系统,在此系统中,消费者只需拿起下一条可用消息即可。您可以通过拉出所有消息并根据特定条件放弃/完成消息来对队列进行排序,但是扩展是一个问题。此外,您可以将每个主题订阅视为自己的单独队列-从一个订阅中删除一条消息不会将其从其他任何订阅中删除。

我建议不要尝试从主题中抽出所有内容,然后放回要保留的内容,而是在两个主题前添加排序队列。如果您不需要对高优先级邮件进行排序,则可以将此排序过程仅放在标准优先级主题的前面。

这是该过程的工作方式:

  1. 将传入消息添加到排序队列中请注意,这是单个队列,而不是主题。在此过程中,我们现在要确保每封邮件只有一个副本。
  2. 排序过程将邮件从排序队列适当地移动到标准队列或优先级队列。使用类似Azure Functions的工具,您可以相当轻松地扩展此过程。
  3. 正常处理来自主题的消息。

enter image description here