高性能JMS消息传递


问题内容

我阅读了今年的UberConf的幻灯片,其中一位发言者认为Spring
JMS给您的消息队列系统增加了性能开销,但是在幻灯片中我看不到任何证据支持这一点。演讲者还提出了点对点比传统“发布-
订阅”方法更快的情况,因为每个消息仅发送一次,而不是广播给每个消费者。

我想知道是否有经验的Java消息传递专家可以在这里介绍一些技术问题:

  • 使用Spring JMS而不是单纯的JMS实际上会产生性能开销吗?如果是这样,将在哪里引入?有什么办法解决吗?
  • 有什么实际证据支持P2P比pub-sub模型更快,如果是这样,那么在任何情况下您都想通过P2P进行pub-sub(即 为什么要慢一些?!? )?

问题答案:

1)首先,Spring JMS的开销是使用JmsTemplate通过下面的缓存机制发送消息。本质上,JmsTemplate将对您发送的每条消息执行以下操作:

  • 建立连接
  • 建立工作阶段
  • 创建生产者
  • 建立讯息
  • 发信息
  • 闭幕会议
  • 紧密连接

可以将此与可以重用事物的手动编写的代码进行比较:

  • 建立连接
  • 建立工作阶段
  • 创建生产者
  • 建立讯息
  • 发信息
  • 建立讯息
  • 发信息
  • 建立讯息
  • 发信息
  • 闭幕会议
  • 紧密连接

由于创建连接,会话和生产者需要在客户端和JMS提供者之间进行通信,并且当然需要进行资源分配,因此它将为许多小消息带来相当大的开销。

您可以通过缓存JMS资源来轻松解决此问题。例如,使用spring
CachingConnectionFactory或ActiveMQs
PooledConnectionFactory(如果使用的是ActiveMQ,则将其标记为该问题)。

如果您在完整的JavaEE容器中运行,则在检索JNDI连接工厂时通常会内置并隐含池/缓存。

使用Spring默认消息侦听容器进行接收时,spring的薄层可能增加很少的开销,但是主要方面是可以在并发性等方面调整性能。本文对此进行了很好的说明。

2)

PubSub是一种使用模式,发布者无需知道存在哪些订阅者。您不能简单地用p2p来模仿它。而且,在手头没有任何证据的情况下,我会争辩说,如果您要将相同的消息从一个应用程序发送到其他十个应用程序,则发布-
订阅设置将比发送消息十倍p2p更快。

另一方面,如果您只有一个生产者和一个消费者,请选择带有队列的P2P模式,因为在某些方面它更易于管理。P2P(队列)允许负载平衡,而pub /
sub则不允许(很容易)。

ActiveMQ还具有混合版本VirtualDestinations-本质上是具有负载平衡的主题。

实际的实现因供应商的不同而有所不同,但是主题和队列在本质上并没有什么不同,并且应具有相似的性能。您应该检查的是:

  • 坚持不懈?(=较慢)
  • 消息选择器?(=较慢)
  • 并发?
  • 耐用的订户?(=较慢)
  • 请求/答复,与临时队列“同步”(=开销=较慢)
  • 队列预取(在某些方面影响性能)
  • 快取