13

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

我想知道是否有任何经验丰富的 Java 消息传递专家可以在这里权衡并澄清一些技术细节:

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

4 回答 4

25

1)主要的,Spring JMS 的开销是使用 JmsTemplate 在没有底层缓存机制的情况下发送消息。本质上,JmsTemplate 将为您发送的每条消息执行以下操作:

  • 创建连接
  • 创建会话
  • 创建生产者
  • 创建消息
  • 发信息
  • 关闭会话
  • 关闭连接

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

  • 创建连接
  • 创建会话
  • 创建生产者
  • 创建消息
  • 发信息
  • 创建消息
  • 发信息
  • 创建消息
  • 发信息
  • 关闭会话
  • 关闭连接

由于创建连接、会话和生产者需要您的客户端和 JMS 提供者之间的通信,当然还有资源分配,这将为大量小消息产生相当大的开销。

您可以通过缓存 JMS 资源轻松解决此问题。例如,使用 spring CachingConnectionFactory或 ActiveMQs PooledConnectionFactory(如果您使用的是 ActiveMQ,您使用它标记了这个问题)。

如果您在一个完整的 JavaEE 容器中运行,那么当您检索 JNDI 连接工厂时,池/缓存通常是内置的并且是隐式的。

接收时,使用 spring Default Message Listening Container,spring 中有一个薄层,可能会增加很少的开销,但主要方面是您可以在并发等方面调整性能。这篇文章很好地解释了它。

2)

PubSub 是一种使用模式,发布者不需要知道存在哪些订阅者。你不能简单地用 p2p 来模拟它。而且,在没有任何证据的情况下,我认为如果您想从一个应用程序向其他十个应用程序发送相同的消息,那么 pub-sub 设置将比发送消息快十倍 p2p。

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

ActiveMQ 也有一个混合版本,VirtualDestinations - 它本质上是具有负载平衡的主题。

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

  • 坚持?(=较慢)
  • 消息选择器?(=较慢)
  • 并发?
  • 持久订户?(=较慢)
  • 请求/回复,与临时队列“同步”(= 开销 = 较慢)
  • 队列预取(=在某些方面影响性能)
  • 缓存
于 2012-08-07T09:17:38.767 回答
4

你是在谈论马克理查兹的幻灯片吗?他为他的基准测试发布了源代码,因此您可以实际测试他关于 JmsTemplate 性能的断言。他的基准代码确实使用了 Spring 的 CachingConnectionFactory,但尽管有缓存,它仍然显示出 JmsTemplate 的显着性能损失。我已经执行、分析和分析了他的代码。简短的回答是 JmsTemplate 的开销可以忽略不计,而且他的代码中可测量的性能差异与 ActiveMQ 的异步与同步发送模式有关。我在这里发表了我的分析:

JmsTemplate 并不邪恶

于 2013-01-06T04:18:56.200 回答
2

1) Spring 模板为发送/接收的每条消息打开/关闭连接/会话。这就是为什么它更慢。大多数 JMS 实现在连接/会话保持打开状态时性能更好,因此它们可以使用消息预取等优化,更不用说避免执行所有连接设置/拆除位的开销。

2) 如果主题将数据复制/复制给多个消费者,主题通常会较慢。这只是一个物理问题。如果 10 兆的消息被队列发送到一个队列,那么只需要 10 兆的数据传输给消费者。在主题上,如果您有 10 个消费者,并且您向其发送 10 兆数据,那么必须将 100 兆数据传输给消费者。因此,对于大多数 JMS 实现:

  • 将消费者添加到主题只会降低您的消费速度。
  • 将消费者添加到队列通常有助于提高出队率。
于 2012-08-07T12:56:33.987 回答
1

我不是消息大师,我希望你不要在这里分享我的想法;)

  1. 总会有开销,因为你有额外的间接性。即使它只是调用堆栈中的一个额外级别,它仍然是开销。但是,我相信这样的开销是最小的。您可以查看 JmsTemplate 的源代码。Spring在发送期间没有添加太多额外的东西。如果您仍然使用 JMS,JmsTemplate 主要是在做您需要做的事情。您总是可以争辩说,那些额外的检查和更深入的方法调用总是需要更多的 CPU 周期和内存。这是真的,但我想知道它有多重要。

  2. PubSub 和 P2P(JMS 术语中的主题和队列)只是两种不同的模型。我相信它们是无法相互替代的。您不能通过使用队列来获得“一次发送并广播到多个接收者”行为,同时在使用主题时您不能拥有保证交付行为(除非使用持久订阅者,但这是另一个主题)。所以,选择合适的类型取决于你在做什么,而不是一味的说P2P优于PubSub(我认为这是无稽之谈)

于 2012-08-07T07:48:54.170 回答