【问题标题】:Message Queues with different message types具有不同消息类型的消息队列
【发布时间】:2012-06-03 15:31:48
【问题描述】:

我正在调查 Microsoft Message Queues 以进行进程间跨网络消息传递。但是当我收到消息时,我先验不知道我得到的是什么类型的对象,所以代码

queue.Formatter = new XmlMessageFormatter(new Type[] { typeof(Wibble) });

无法应用之前 我收到消息是因为我不知道它是否是 Wibble。那么如何接收不同类型的消息呢?

【问题讨论】:

  • 我想到了两个选项; 1) 有一个 Wibbles 队列和一个 Gizmos 队列; 2) 尝试合并到 Wibble,如果失败则尝试转换到 Gizmo
  • typeof(Object) 并将类反射到对象上直到它适合?

标签: c# msmq


【解决方案1】:

在 MSMQ 上存在大量错误信息,主要是因为 Microsoft 文档在如何正确设计消息发送接收方面非常稀少。我有两本关于这个主题的 MSMQ 书籍,我仍在互联网上寻找合理的设计。

因此,这些参考资料都没有说队列要求只有一种消息类型。这将使 PeakMessage 和变体变得不必要甚至愚蠢。 Microsoft 的文档含糊不清,但我曾在那里工作过,他们从不傻。

使用 CLSID 作为标识符的建议一直很烦人,这种做法非常短视。尝试在 LABEL 中嵌入消息类型怎么样???然后使用 PeadMessage 运行队列,直到您找到一条专门针对您的特定队列的消息,并且具有可用于格式化消息属性以在第一次尝试时正确接收消息的消息类型?

我知道这会产生复杂的代码集,但您愿意不这样做吗?或者您是否真的会尝试实施上述响应者的建议,他暗示如果您有一个由 200 个用户和 200 种消息类型组成的系统,他们应该创建 80,000 个队列来管理所有一对一的需求?有些人只是没有考虑这些事情。

【讨论】:

    【解决方案2】:

    正如joocer 在评论中指出的那样:对不同的消息类型使用不同的队列。

    或者,您可以与消息发送者达成一致,即所有消息都是 XML(任何不解析为 XML 的内容都会被拒绝)。然后还要同意 XML 模式的一些基础知识:带有消息类型(和版本)的标头元素。

    然后处理(您自己或通过序列化程序)到内部类型。

    当然,在许多情况下——反序列化​​并没有真正的好处——只需根据需要读取 XML 的内容。

    【讨论】:

      【解决方案3】:

      您可能会考虑不在 MSMQ 消息中存储您的对象,而是在可能的情况下放置对它的持久位置的引用。 MSMQ 的消息队列空间有限,因此最好使用较小的消息。

      如果您不能这样做,您可以使用您喜欢的任何序列化程序直接将您的对象序列化为消息 BodyStream。然后也存储类型名称,最好在消息标签中。

      与此非常相似的东西(在这里刮掉,这台计算机上没有 IDE)将其放入,以及退出时的类似操作:

      public void FormatObject(object toFormat, Message message)
      {
          var serializer = new XmlSerializer(toFormat.GetType());
          var stream = new MemoryStream();
          serializer.Serialize(toFormat, stream);
      
          //don't dispose the stream
          message.BodyStream = stream;
          message.Label = toFormat.GetType().AssemblyQualifiedName;
      }
      

      【讨论】:

      • 我对 RabbitMQ 做了类似的事情。我使用消息头来指示消息体中序列化的对象的类型。
      • @tallseth:在接收端,我们怎么做?我们是否将 label 与我们拥有的所有类的 typeof 进行比较?可以是多个
      • 关于评论//不要释放流。那么流什么时候被释放呢?
      • 不完全是@RajeshMishra。您有一个完整的类型名称,因此只需使用它创建您的序列化程序。前var serializer = new XmlSerializer(message.Label)
      • @bornfromanegg 我看了这个已经 5 年了,不记得了。 :) 我认为当您发送消息时,MSMQ 一定想戳它。但是你可以试着把它拿出来看看会发生什么。如果我不在基地,我会编辑答案。
      【解决方案4】:

      您已经在使用 XmlMessageFormatter 的构造函数重载,它接受 array 类型。因此,只需将所有您希望接收的类型添加到该数组中,而不仅仅是一种类型。

      queue.Formatter = new XmlMessageFormatter(new Type[] {
          typeof(Wibble),
          typeof(Fleem),
          typeof(Boo)
      });
      

      来自TargetTypes

      消息正文中序列化的实例必须符合类型数组中表示的一种模式。当您使用 Receive 方法读取消息时,该方法会创建一个类型与标识的架构相对应的对象,并将消息正文读入其中。

      (已添加重点)

      【讨论】:

      • 文档给出了这个例子: MessageQueue queue = new MessageQueue(queuePath); ((XmlMessageFormatter)queue.Formatter).TargetTypeNames = new string[] {“Order”}; 但是,这给出了一个例外,即在 System.Messaging 命名空间中找不到 Order 类型。由于队列有一个默认的 XMLMessageFormatter,如果这段代码有效,我们不需要构建另一个格式化程序。所以感兴趣。
      猜你喜欢
      • 2011-02-21
      • 2017-06-14
      • 1970-01-01
      • 1970-01-01
      • 2016-04-26
      • 1970-01-01
      • 2017-03-22
      • 2015-10-21
      • 2012-01-21
      相关资源
      最近更新 更多