Azure服务总线队列:如何从队列中读取单个消息

时间:2020-05-23 19:33:09

标签: azure azureservicebus azure-servicebus-queues

我有一个应用程序,可以在过程的一部分中以JSON格式将消息写入Azure服务总线队列。我有一个下游进程,我想将该消息从队列中弹出,将json转换为对象,然后处理该对象。

我将消息推送到队列没有问题,但是我找不到一次或循环将消息从队列弹出的任何示例。我在Microsoft或Github上看到的每个示例都是一个控制台应用程序(在Web应用程序中无用),它设置某种侦听器,以侦听队列中的所有消息并编写一条控制台消息。我没有发现弹出消息然后对数据进行一些处理的示例。有没有人有示例说明如何从队列中弹出一条消息,然后对其进行处理或调用另一种方法来对消息中的数据进行处理?

更新: 我使用了下面的由Guru Pasupathy提供的WindowsAzure.ServiceBus示例,并使用了Azure Service Bus Queues: How To Read Individual Messages From A Queue中的以下代码片段来从BrokeredMessage对象获取消息文本:

Stream stream = message.GetBody<Stream>();
StreamReader reader = new StreamReader(stream);
string messageBody =  reader.ReadToEnd();

然后我可以使用messageBody并将嵌入的JSON反序列化为POCO对象,然后就可以了!现在,我可以在应用程序中更有效地使用队列来执行各种任务。

1 个答案:

答案 0 :(得分:1)

您可以使用“窥视锁定”接收模式从队列中获取消息,进行处理,然后根据您的业务逻辑选择“放弃”或“完成”。

如果您使用 WindowsAzure.ServiceBus nuget包发送/接收消息,则可以使用以下方法基于循环或单个调用从队列中逐个使用消息,而不必使用监听器。

        public void Receive()
        {
            QueueClient myQueueClient = QueueClient.CreateFromConnectionString("<connectionString>;<queueName>", ReceiveMode.PeekLock);

            int someCount = 2; //some random value for testing
            try
            {
                for (int i = 0; i < someCount; i++)
                {
                    BrokeredMessage message = myQueueClient.Receive();
                    Console.WriteLine("The message is " + message);
                    message.Complete();
                }
            }
            catch(Exception e)
            {
                //Handle your expection
            }

        }

如果您使用的是 Microsoft.Azure.Service nuget包,那么我将无法找到一种不使用侦听器而仅读取一条消息的直接方法。我看到侦听器将继续轮询和处理队列,直到没有更多消息为止。

如果您要停止轮询并继续获取所有可用消息,那么作为一种解决方法,您可以在读取一条消息后关闭QueueClient实例,并在过程准备好接收下一条消息时打开qc并注册处理程序

        public async Task ProcessMessagesAsync(Message message, CancellationToken token)
        {
            Console.WriteLine($"Received message: {Encoding.UTF8.GetString(message.Body)}");

            BinaryFormatter bf = new BinaryFormatter();
            using (MemoryStream ms = new MemoryStream(message.Body))
            {
                Payload payload = (Payload) bf.Deserialize(ms);

                //Based on your needs you may have a condition here based on which you could Abandon or Complete the mesage

                await qc.CompleteAsync(message.SystemProperties.LockToken);
                Console.WriteLine("Completed the message --> " + payload.Message + " -- Id --> " + payload.Id);

                //await qc.AbandonAsync(message.SystemProperties.LockToken);
                //Console.WriteLine("Abandon the message --> " + payload.Message + " -- Id --> " + payload.Id);

                qc.CloseAsync(); //If you close the QueueClient instance here, no more messages will be picked up from queue.
            }
        }

以上示例基于https://docs.microsoft.com/en-us/azure/service-bus-messaging/service-bus-dotnet-get-started-with-queues#receive-messages-from-the-queue,我只是在最后添加了qc.CloseAsync()调用。没有此行,侦听器将继续处理,直到队列中没有剩余消息为止。我不确定是否有更好的方法可以实现这一目标,但我想共享。

希望这会有所帮助

编辑-

发送消息时,如果您使用的是自定义类型,则可以使用以下内容

                BrokeredMessage message = new BrokeredMessage(new Payload() { Id = 4332, Message = "WindowsAzure package" });
                myQueueClient.Send(message);

在接收时,应使用GetBody,如下所示

                BrokeredMessage message = myQueueClient.Receive();
                var incoming = message.GetBody<Payload>();
                Console.WriteLine("The message is " + incoming.Id + " and " + incoming.Message);
                message.Complete();

下面是供您参考的自定义对象

    [Serializable]
    public class Payload
    {
        public int Id { get; set; }
        public string Message { get; set; }
    }

同样适用于字符串

在收到您可以使用的同时

var incoming = message.GetBody<string>();

发送时,您可以发送

BrokeredMessage message = new BrokeredMessage("WindowsAzure package" );

您将在以下链接上获得有关不同内容格式的更多详细信息 https://abhishekrlal.com/2012/03/30/formatting-the-content-for-service-bus-messages/