java jms 生产者表现与 spring
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7056241/
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
jms producer performance with spring
提问by Matan
i created a simple producer consumer simulation based on spring, jms and activemq, i'm trying to reach high performance from both sides, producers and consumers,
我基于spring、jms和activemq创建了一个简单的生产者消费者模拟,我试图从生产者和消费者双方达到高性能,
Connection settings :
连接设置:
<tx:annotation-driven />
<bean id="transactionManager" class="org.springframework.jms.connection.JmsTransactionManager">
<property name="connectionFactory" ref="connectionFactory" />
</bean>
<amq:connectionFactory id="amqConnectionFactory" brokerURL="failover:(tcp://${broker.url}:61616)" />
<bean id="connectionFactory"
class="org.springframework.jms.connection.CachingConnectionFactory">
<property name="targetConnectionFactory" ref="amqConnectionFactory" />
</bean>
<amq:queue id="queue" physicalName="queue" />
<beans:bean id="jsonMessageConverter" class="XXXXX.converter.JsonMessageConverter" />
Consumer settings :
消费者设置:
<jms:listener-container concurrency="10"
acknowledge="auto" prefetch="1" message-converter="jsonMessageConverter" transaction-manager="transactionManager"
>
<jms:listener id="queueListener_1" destination="ooIntegrationQueue"
ref="myMessageListenerAdapter" />
</jms:listener-container>
<beans:bean id="myMessageListenerAdapter"
class="org.springframework.jms.listener.adapter.MessageListenerAdapter" >
<beans:property name="delegate" ref="consumer"/>
</beans:bean>
<beans:bean id="consumer" class="XXX.ConsumerImpl"/>
Producer settings :
生产者设置:
<beans:bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate"
p:connectionFactory-ref="connectionFactory" p:messageConverter-ref="jsonMessageConverter"
p:defaultDestination-ref="ooIntegrationQueue" p:sessionTransacted="true" />
starting with the consumer, i managed to consume about 25 messages per second, which is extremely slow, i discovered the bottleneck to be the fact that i am using transactions, after googling for a bit, and playing with the configs, i found out that after autowiring the DefaultMessageListenerContainer and changing the cachelevel to
从消费者开始,我设法每秒消耗大约 25 条消息,这非常慢,我发现瓶颈是我正在使用事务,在谷歌搜索了一下并使用配置后,我发现在自动装配 DefaultMessageListenerContainer 并将缓存级别更改为
listenerContainer.setCacheLevelName("CACHE_SESSION")
my performance increases to about 1500 messages per second while still having transactions.
我的性能增加到每秒大约 1500 条消息,同时仍然有事务。
my problem is now with the producer which is still stuck at about 25 operations per sec, my producer test is simple :
我的问题现在是生产者仍然停留在每秒大约 25 次操作,我的生产者测试很简单:
int numOfMessages = getNumberOfMessages();
double startTime = System.currentTimeMillis();
for (int i = 1; i <= numOfMessages; i++) {
jmsTemplate.convertAndSend("HelloWorld" + i);
}
double endTime = System.currentTimeMillis();
double totalTime=(endTime-startTime)/1000;
System.out.println("Time - "+totalTime+" seconds");
System.out.println("EPS - "+numOfMessages/totalTime);
i'm wondering how to reach similiar performances with the producer, since it now bottlenecks the entire system.
我想知道如何与制作人达到类似的表现,因为它现在使整个系统成为瓶颈。
采纳答案by Christopher Wong
Sorry if this answer comes to late to help the original poster. I recently investigated JmsTemplate
performance. Even with the same delivery and acknowledgment modes, native JMS
code seemed much faster than JmsTemplate
. The problem turned out to be that ActiveMQ
normally defaults to async sending, but when you use JmsTemplate
it instead uses sync sending. This dramatically reduces performance. You can set ActiveMQConnectionFactory
's useAsyncSend
property to true
to force async sending. More details here: JmsTemplate is not evil
对不起,如果这个答案来晚了,以帮助原始海报。我最近调查了JmsTemplate
性能。即使使用相同的交付和确认模式,本机JMS
代码似乎也比JmsTemplate
. 问题原来是ActiveMQ
通常默认为异步发送,但是当您使用JmsTemplate
它时使用同步发送。这会大大降低性能。您可以将ActiveMQConnectionFactory
的useAsyncSend
属性设置true
为强制异步发送。更多细节在这里:JmsTemplate 不是邪恶的
回答by Jakub Korab
JMSTemplate does a walk of ConnectionFactiory -> Connection -> Session -> MessageProducer, closing each object after each send. To get around this, wrap your amqConnectionFactory bean with a org.apache.activemq.pool.PooledConnectionFactory, and use that under the template rather than a CachingConnectionFactory.
JMSTemplate 遍历 ConnectionFactiory -> Connection -> Session -> MessageProducer,在每次发送后关闭每个对象。要解决此问题,请使用 org.apache.activemq.pool.PooledConnectionFactory 包装您的 amqConnectionFactory bean,并在模板下使用它而不是 CachingConnectionFactory。
回答by Andrey Lyubimov
Try to change acknowledge method to from AUTO to CLIENT_ACKNOWLEDGE. For more information look to the Specification.
尝试将确认方法从 AUTO 更改为 CLIENT_ACKNOWLEDGE。有关更多信息,请查看规范。
回答by Matt
What is the default delivery mode for ActiveMQ? is it a persistent queue? if so, how is it configured? how remote is the broker? These answers will determine the basic cost of sending to queue by answering how long it takes the server to ack the send (i.e. network RTT + potential cost of persisting the message to disk synchronously).
ActiveMQ 的默认交付模式是什么?它是一个持久队列吗?如果是这样,它是如何配置的?经纪人有多远?这些答案将通过回答服务器确认发送需要多长时间来确定发送到队列的基本成本(即网络 RTT + 将消息同步保存到磁盘的潜在成本)。
The other possibility is that you're actually creating a new connection, session and messageproducer on every send. This is pretty costly to say the least. It will be worth confirming whether this is happening (e.g. add debug logging to spring, check amq admin console for connection churn) or not as a basic sanity check. By the looks of it CachingConnectionFactory
should cache a single session and messageproducer by default and convertAndSend
should close the session it obtains after sending which results in a returning that cached session to the pool. This should mean it is relatively quick (spring jms goes through an awful lot of code just to send a message) to get the cached session on the next send.
另一种可能性是您实际上是在每次发送时创建一个新的连接、会话和消息生产者。至少可以说这是相当昂贵的。值得确认这是否正在发生(例如,将调试日志添加到 spring,检查 amq 管理控制台是否存在连接流失)作为基本的健全性检查。从外观CachingConnectionFactory
上看,默认情况下它应该缓存单个会话和消息生产者,并且convertAndSend
应该关闭它在发送后获得的会话,这会导致将该缓存的会话返回到池中。这应该意味着在下一次发送时获取缓存会话相对较快(spring jms 需要通过大量代码来发送消息)。