java 高性能 JMS 消息传递

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11840630/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 06:35:41  来源:igfitidea点击:

High Performance JMS Messaging

javaspringjmsactivemqmessaging

提问by IAmYourFaja

I read slides from this year's UberConf and one of the speakers is making the argument that Spring JMS adds a performance overhead to your message queue system, however I don't see any evidence to support that in the slides. The speaker also makes the case that point-to-point is faster than the traditional "publish-subscribe" method because each message is sent only once instead of being broadcasted to every consumer.

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

I'm wondering if any experienced Java messaging gurus can weigh-in here and clarify a few technicalities:

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

  • Is there actually a performance overhead incurred by using Spring JMS instead of just pure JMS? If so, how and where is it introduced? Is there any way around it?
  • What actual evidence is there to support that P2P is faster than the pub-sub model, and if so, are there ever any cases when you would want to pub-sub over P2P (i.e. why go slower?!?)?
  • 使用 Spring JMS 而不是纯 JMS 实际上是否会产生性能开销?如果是这样,它是如何以及在何处引入的?有什么办法可以解决吗?
  • 有什么实际证据支持 P2P 比 pub-sub 模型更快,如果是这样,是否有任何情况下您想要通过 P2P pub-sub(即为什么要慢?!?)?

回答by Petter Nordlander

1) Primary, the overhead of Spring JMS is the use of JmsTemplate to send messages wihtout a caching mechanism underneath. Essentially, JmsTemplate will do the following for each message you send:

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

  • Create Connection
  • Create Session
  • Create Producer
  • Create Message
  • Send Message
  • Close Session
  • Close connection
  • 创建连接
  • 创建会话
  • 创建生产者
  • 创建消息
  • 发信息
  • 关闭会话
  • 关闭连接

This of could be compared to manually written code where you reuse things:

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

  • Create Connection
  • Create Session
  • Create Producer
  • Create Message
  • Send Message
  • Create Message
  • Send Message
  • Create Message
  • Send Message
  • Close Session
  • Close connection
  • 创建连接
  • 创建会话
  • 创建生产者
  • 创建消息
  • 发信息
  • 创建消息
  • 发信息
  • 创建消息
  • 发信息
  • 关闭会话
  • 关闭连接

Since the creation of connections, sessions and producers needs communication between your client and the JMS provider and, of course, resource allocation, it will create pretty large overhead for lots of small messages.

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

You can easily come around this by caching JMS resources. For instance use the spring CachingConnectionFactoryor ActiveMQs PooledConnectionFactory(if you are using ActiveMQ, which you tagged this question with).

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

If you are running inside a full JavaEE container, pooling/caching is often built in and implicit when you retrieve your JNDI connection factory.

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

When receving, using spring Default Message Listening Container, there is a thin layer in spring that might add little overhead, but the primary aspects is that you can tweak the performance in terms of concurrency etc. This articleexplains it very well.

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

2)

2)

PubSub is a pattern of usage, where the publisher does not need to know which subscribers that exists. You can't simply emulate that with p2p. And, without any proof at hand, I would argu that if you want to send an identical message from one application to ten other applications, a pub-sub setup would be faster than to send the message ten times p2p.

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

On the other hand, if you only have one producer and one consumer, choose the P2P pattern with queues instead, since it's easier to manage in some aspects. P2P (queues) allows load balancing, which pub/sub does not (as easily).

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

ActiveMQ also has a hybride version, VirtualDestinations- which essentially is topics with load balancing.

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

The actual implementation differs by different vendors, but topics and queues are not fundamentally different and should behave with similar performance. What you instead should check on is:

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

  • Persistence? (=slower)
  • Message selectors? (=slower)
  • Concurrency?
  • Durable subscribers? (=slower)
  • Request/reply, "synchronously" with temporary queues (= overhead = slower)
  • Queue prefetching (=impacts performance in some aspects)
  • Caching
  • 坚持?(=较慢)
  • 消息选择器?(=较慢)
  • 并发?
  • 持久的订阅者?(=较慢)
  • 请求/回复,与临时队列“同步”(= 开销 = 较慢)
  • 队列预取(=在某些方面影响性能)
  • 缓存

回答by Christopher Wong

Are you talking about Mark Richards' slides? He posted source code for his benchmarks, so you can actually test his assertion about JmsTemplate performance. His benchmark code does use Spring's CachingConnectionFactory, and yet in spite of the caching it still demonstrates a significant performance penalty with JmsTemplate. I have executed, profiled and analyzed his code. The short answer is that the overhead from JmsTemplate is negligible and the measurable performance disparity in his code has to do with ActiveMQ's async vs sync sending modes. I posted my analysis here:

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

JmsTemplate is not evil

JmsTemplate 不是邪恶的

回答by Hiram Chirino

1) Spring templates open/close connections/sessions for each message sent/received. That's why it's slower. Most JMS implementations performs better when connections/session remain open so that they can use optimizations like message pre-fetching not to mention avoid the overhead of doing all the connection setup/tear down bits.

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

2) Topics are generally slower if they are copying/replicating data to more than one consumer. This is just a matter of physics. If 10 megs of messages are queue sent to a queue, then only 10 megs of data need to be transmitted to consumers. While on topic, if you have 10 consumers, and you send 10 megs of data to it, then 100 megs of data have to transmitted to consumers. So, for most JMS implementations:

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

  • adding a consumer to a topic can only slow your consumption rate.
  • adding a consumer to a queue usually helps increase the dequeue rate.
  • 将消费者添加到主题只会降低您的消费速度。
  • 将消费者添加到队列通常有助于提高出队率。

回答by Adrian Shum

I am not messaging guru, I wish you don't me sharing my thought here ;)

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

  1. There will always be overhead, because you have extra indirection. Even it is simply an extra level in call stack, it is still overhead. However, I believe such overhead is minimal. You may take a look in source code of JmsTemplate. There is not much extra things added by Spring during send. JmsTemplate is doing mostly what you need to do if you are using JMS anyway. You can always argue that those extra checking and deeper method call always takes more CPU cycle and memory. That's true, but I wonder how significant it is.

  2. PubSub and P2P (Topic and Queue in JMS terminology) are just two different models. I believe they are cannot replace each other. You cannot have the "send once and broadcast to multiple receiver" behavior by using Queue, and on the same time you cannot have the guaranteed-delivery behavior when using Topic (unless using Durable Subscriber, but that's another topic). So, choose the right type depends on what you are doing, instead of saying blindly that P2P is superior than PubSub (which I believe is non-sense)

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

  2. PubSub 和 P2P(JMS 术语中的主题和队列)只是两种不同的模型。我相信它们是不能相互替代的。您不能使用 Queue 实现“发送一次并广播到多个接收器”的行为,同时在使用 Topic 时不能保证交付行为(除非使用 Durable Subscriber,但那是另一个主题)。所以,选择合适的类型取决于你在做什么,而不是盲目地说P2P优于PubSub(我认为这是无意义的)