使用Spring的JMSTAME将消息发送到ActiveMQ Artemis非常慢
我只能向Apache Artemis发布大约1600个小字符串MSGS/sec。我已经尝试了两台机器,并获得了相同的性能。我期望的速度更快。那是一个线程的预期发送速度吗?我应该与几个线程并行化发送吗?
经纪人和出版应用程序在同一主机上。没有听众订阅该主题。我正在使用:
- JMS API
- APACHE ARTEMIS 2.20.0
- JAVA 18 64位
- Oracle Linux 8
- Spring Boot 2.6.5
Spring Boot application.properties include:
spring.jms.pub-sub-domain=true
broke> broker.xml
has:
<persistence-enabled>false</persistence-enabled>
Spring的JMstemplate是这样的设置(这是错误的):
import org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory;
import org.messaginghub.pooled.jms.JmsPoolConnectionFactory;
import org.springframework.jms.core.JmsTemplate;
...
JmsPoolConnectionFactory poolingFactory = new JmsPoolConnectionFactory();
poolingFactory.setConnectionFactory(new ActiveMQConnectionFactory());
jmsTemplate = new JmsTemplate(poolingFactory);
要发布消息,我只是在循环中调用此消息:
jmsTemplate.convertAndSend(jmsQueue, message);
在弹簧中设置JMstemplate这样的工作:
@Autowired
JmsTemplate jmsTemplate;
@PostConstruct
void setup() {
JmsPoolConnectionFactory poolingFactory = new JmsPoolConnectionFactory();
poolingFactory.setConnectionFactory(new ActiveMQConnectionFactory());
jmsTemplate.setConnectionFactory(poolingFactory);
}
I can only publish about 1600 small string msgs/sec to Apache Artemis. I have tried on two machines and gotten same performance. I expected something much faster. Is that expected sending speed for a single thread? Should I parallelize the sending with a few threads?
The broker and the publishing app are on the same host. No listener is subscribed to the topic. I'm using:
- JMS API
- Apache Artemis 2.20.0
- Java 18 64 bit
- Oracle Linux 8
- Spring Boot 2.6.5
Spring Boot application.properties
includes:
spring.jms.pub-sub-domain=true
broker.xml
has:
<persistence-enabled>false</persistence-enabled>
Spring's JmsTemplate is setup like this (THIS WAS WRONG):
import org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory;
import org.messaginghub.pooled.jms.JmsPoolConnectionFactory;
import org.springframework.jms.core.JmsTemplate;
...
JmsPoolConnectionFactory poolingFactory = new JmsPoolConnectionFactory();
poolingFactory.setConnectionFactory(new ActiveMQConnectionFactory());
jmsTemplate = new JmsTemplate(poolingFactory);
To publish messages I just call this in a loop:
jmsTemplate.convertAndSend(jmsQueue, message);
Setting up the JmsTemplate in Spring like this works:
@Autowired
JmsTemplate jmsTemplate;
@PostConstruct
void setup() {
JmsPoolConnectionFactory poolingFactory = new JmsPoolConnectionFactory();
poolingFactory.setConnectionFactory(new ActiveMQConnectionFactory());
jmsTemplate.setConnectionFactory(poolingFactory);
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我认为您正在使用 Spring 的
JmsTemplate 遇到 长期存在的反模式
。简而言之,它每次发送消息时都会创建和关闭 JMS 连接、会话和生产者。它并非设计用于与裸露的 javax.jms.ConnectionFactory 实现一起使用。它旨在与提供某种池化的实现一起使用。作为概念验证,我启动了 ActiveMQ Artemis 2.20.0 的新实例,并在
broker.xml
false
设置代码>.然后我运行以下命令:该命令将启动 50 个线程,每个线程将使用核心 JMS 客户端向 JMS 主题
foo
发送 100,000 条消息,总共 5,000,000 条消息。在我的笔记本电脑上,该命令在大约 40.6 秒内完成,平均速率为 122,980.1 条消息/秒,这比您看到的 1,600 条消息要快得多。ActiveMQ Artemis 具有非阻塞架构,旨在大规模最大化吞吐量,因此仅运行几个线程并不是测试性能的好方法。我建议修改您的“测试”以使用具有更多线程的池连接工厂,或者可能使用代理附带的命令行工具。 此池是从 ActiveMQ 项目中分叉出来的,并且经过了实际测试。您还可以使用 Spring 的
CachingConnectionFactory
一个简单的解决方案。您可能还对新的性能工具感兴趣刚刚与 ActiveMQ Artemis 2.21.0 一起发布。
I think you're running into a long-standing anti-pattern with Spring's
JmsTemplate
. In short, it creates and closes a JMS connection, session, and producer every time it sends a messages. It was not designed to be used with a barejavax.jms.ConnectionFactory
implementation. It was meant to be used with an implementation that provides some kind of pooling.As a proof-of-concept I spun up a fresh instance of ActiveMQ Artemis 2.20.0 and set
<persistence-enabled>false</persistence-enabled>
inbroker.xml
. Then I ran this command:This command will start 50 threads which will each use the core JMS client to send 100,000 messages to the JMS topic
foo
for a total of 5,000,000 messages. On my laptop that command finished in around 40.6 seconds for an average rate of 122,980.1 msgs/sec which is significantly faster than the 1,600 you're seeing.ActiveMQ Artemis has a non-blocking architecture designed to maximize throughput at scale so running just a couple of threads isn't a good way to test performance. I recommend revising your "test" to use a pooling connection factory with significantly more threads or perhaps use the command-line tools that ship with the broker. This pool was forked from the ActiveMQ project and it is battle tested. You could also potentially use Spring's
CachingConnectionFactory
for a simple solution.You may also be interested in the new performance tools just released with ActiveMQ Artemis 2.21.0.