高性能 JMS 消息传递

2022-09-04 06:34:11

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

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

  • 使用Spring JMS而不仅仅是纯JMS实际上会产生性能开销吗?如果是,如何以及在何处引入?有什么办法可以解决这个问题吗?
  • 有什么实际证据支持P2P比发布-订阅模型更快,如果是这样,是否有任何情况下你想在P2P上发布-sub(即为什么走得更慢?!?)?

答案 1

1)主要,Spring JMS的开销是使用JmsTemplate发送消息,而无需下面的缓存机制。从本质上讲,JmsTemplate 将为您发送的每条消息执行以下操作:

  • 创建连接
  • 创建会话
  • 创建生产者
  • 创建消息
  • 发送消息
  • 关闭会话
  • 紧密连接

这可以与手动编写的代码进行比较,您可以在其中重用内容:

  • 创建连接
  • 创建会话
  • 创建生产者
  • 创建消息
  • 发送消息
  • 创建消息
  • 发送消息
  • 创建消息
  • 发送消息
  • 关闭会话
  • 紧密连接

由于创建连接、会话和创建者需要在客户端和 JMS 提供程序之间进行通信,当然还有资源分配,因此它将为大量小消息创建相当大的开销。

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

如果在完整的 JavaEE 容器中运行,那么在检索 JNDI 连接工厂时,池化/高速缓存通常是内置的和隐式的。

在使用spring默认消息监听容器时,spring中有一个薄层可能会增加很少的开销,但主要方面是您可以在并发等方面调整性能。

2)

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

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

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

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

  • 坚持?(=较慢)
  • 消息选择器?(=较慢)
  • 并发?
  • 持久订阅者?(=较慢)
  • 请求/回复,“同步”与临时队列(= 开销 = 较慢)
  • 队列预取(=在某些方面影响性能)
  • 缓存

答案 2

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

JmsTemplate不是邪恶的


推荐