【问题标题】:How to get queue message type如何获取队列消息类型
【发布时间】:2017-09-09 09:04:09
【问题描述】:

我正在使用 Azure 存储队列,我想编写一些代码来检索所有队列,然后找到可以处理此队列中的消息的处理程序。为此,我定义了一个这样的接口:

public interface IHandler<T>

我有这个接口的多个实现,例如:IHandler&lt;CreateAccount&gt;IHandler&lt;CreateOrder&gt;。我对每种消息类型使用 1 个队列,因此 CreateAccount 消息将进入 create-account-queue

如何连接这些?为了找到适合消息的 Handler 类,我首先需要知道消息类型,但似乎 CloudQueueMessage 对象不包含该信息。

【问题讨论】:

    标签: azure queue azure-storage message-queue azure-storage-queues


    【解决方案1】:

    不是您的问题的真正答案,但我将分享我们如何在我们的应用程序中处理完全相同的情况。

    在我们的应用程序中,我们像您一样发送不同类型的消息,并在后台进程中处理这些消息。

    我们正在做的是将消息类型包含在消息正文本身中。所以我们的消息通常如下所示:

            message: {
              type: 'Type Of Message',
              contents: {
                //Message contents
              }
            }
    

    一个关键区别是所有消息都放在一个队列中(而不是在您的情况下是不同的队列)。接收者(后台进程)只是轮询一个队列,获取消息并识别消息的类型并相应地调用该消息的处理程序。

    【讨论】:

    • 我也是这么想的。也许您甚至可以将类型放在标题中?我担心的一个问题是:如果你重构代码并重命名一个类会发生什么? IDE 不会告诉您代码会中断,但它仍然会中断。
    • Maybe you could even put the type in the headers? - 你能解释一下Headers 是什么意思吗?我同意您的评论,但是如果您在发送端序列化一个对象并反序列化它以在接收端构造相同的对象,那么您可以最大限度地降低发生这种情况的风险。
    • 我实际上认为CloudQueueMessage 对象也有标题(用于存储您已经重试处理消息的次数以及它来自哪里),但显然它们没有标题.
    【解决方案2】:

    您可以将元数据与每个队列相关联。由于您提到每种消息类型使用一个队列,因此您可以将处理程序名称放在每个队列的元数据中。然后,您可以枚举所有队列并获取每个队列的元数据,告诉您应该使用哪种类型的处理程序。这是一个快速控制台应用程序,它演示了我认为您所要求的内容:

    using System;
    using System.Collections.Generic;
    using Microsoft.WindowsAzure.Storage;
    using Microsoft.WindowsAzure.Storage.Queue; 
    
    namespace QueueDemo
    {
        class Program
        {
            static void Main(string[] args)
            {
                //get a ref to our account.
                CloudStorageAccount storageAccount = CloudStorageAccount.Parse("UseDevelopmentStorage=true;");
                CloudQueueClient cloudQueueClient = storageAccount.CreateCloudQueueClient();
    
                //create our queues and add metadata showing what type of class each queue contains. 
                CloudQueue queue1 = cloudQueueClient.GetQueueReference("queue1"); 
                queue1.Metadata.Add("classtype", "classtype1");
                queue1.CreateIfNotExists();
    
                CloudQueue queue2 = cloudQueueClient.GetQueueReference("queue2");
                queue2.Metadata.Add("classtype", "classtype2");
                queue2.CreateIfNotExists();
    
                //enumerate our queues in a storage account and look at their metadata...
                QueueContinuationToken token = null;
                List<CloudQueue> cloudQueueList = new List<CloudQueue>();
                List<string> queueNames = new List<string>();
    
                do
                {
                    QueueResultSegment segment = cloudQueueClient.ListQueuesSegmented(token);
                    token = segment.ContinuationToken;
                    cloudQueueList.AddRange(segment.Results);
                }
                while (token != null);
    
                try
                {
                    foreach (CloudQueue cloudQ in cloudQueueList)
                    {
                        //call this, or else your metadata won't be included for the queue. 
                        cloudQ.FetchAttributes(); 
                        Console.WriteLine("Cloud Queue name = {0}, class type = {1}", cloudQ.Name, cloudQ.Metadata["classtype"]);
                        queueNames.Add(cloudQ.Name);
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine("Exception thrown listing queues: " + ex.Message);
                    throw;
                }
    
                //clean up after ourselves and delete queues. 
                foreach (string oneQueueName in queueNames)
                {
                    CloudQueue cloudQueue = cloudQueueClient.GetQueueReference(oneQueueName);
                    cloudQueue.DeleteIfExists();
                }
                Console.ReadKey(); 
            }
        }
    }
    

    但是,将 QueueMessage 子类化可能更容易,然后将每条消息出列并确定您当前正在查看的子类,然后将其传递给适当的处理程序。

    【讨论】:

    • 谢谢,我想这就是这样做的方法。我将消息类型存储在元数据中,然后我将枚举队列并使用反射来查找消息类型的 IHandler 实现。还没有测试它,但我认为它会工作。顺便说一句,感谢您提供有关 FetchAttributes 的提示。
    猜你喜欢
    • 2011-02-21
    • 1970-01-01
    • 1970-01-01
    • 2012-06-03
    • 1970-01-01
    • 1970-01-01
    • 2020-12-14
    • 1970-01-01
    • 2020-03-01
    相关资源
    最近更新 更多