我基于spring,jms和activemq创建了一个简单的生产者消费者模拟, 我试图从双方,生产者和消费者那里获得高绩效,
连接设置:
<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" />
消费者设置:
<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"/>
制作人设置:
<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" />
从消费者开始,我设法每秒消耗大约25条消息,这非常慢,我发现瓶颈是我正在使用交易的事实, 谷歌搜索了一下,并使用配置,我发现自动装配DefaultMessageListenerContainer并将缓存级别更改为
listenerContainer.setCacheLevelName("CACHE_SESSION")
我的表现增加到每秒约1500条消息,同时仍有交易。
我的问题是现在生产商仍然停留在每秒约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);
我想知道如何与制作人达成类似的表演,因为它现在已经成为整个系统的瓶颈。
答案 0 :(得分:14)
对不起,如果这个答案来得太晚,以帮助原始海报。我最近调查了JmsTemplate
表现。即使使用相同的传递和确认模式,本机JMS
代码似乎比JmsTemplate
快得多。结果问题是ActiveMQ
通常默认为异步发送,但是当您使用JmsTemplate
时,它会使用同步发送。这大大降低了性能。您可以将ActiveMQConnectionFactory
的{{1}}属性设置为useAsyncSend
以强制执行异步发送。更多详情:JmsTemplate is not evil
答案 1 :(得分:5)
JMSTemplate散步ConnectionFactiory - &gt;连接 - &gt;会话 - &gt; MessageProducer,每次发送后关闭每个对象。要解决此问题,请使用org.apache.activemq.pool.PooledConnectionFactory包装amqConnectionFactory bean,并在模板下使用它而不是CachingConnectionFactory。
答案 2 :(得分:1)
尝试将确认方法更改为从AUTO更改为CLIENT_ACKNOWLEDGE。有关详细信息,请查看Specification。
答案 3 :(得分:0)
ActiveMQ的默认投放模式是什么?它是一个持久队列吗?如果是这样,它是如何配置的?经纪人有多远?这些答案将通过回答服务器响应发送所需的时间(即网络RTT +同步将消息持久保存到磁盘的潜在成本)来确定发送到队列的基本成本。
另一种可能性是,您实际上是在每次发送时创建新的连接,会话和消息生成器。至少可以说这是非常昂贵的。值得确认是否发生这种情况(例如,将调试日志记录添加到spring,检查amq管理控制台是否存在连接流失)或不作为基本健全性检查。通过它的外观CachingConnectionFactory
应该默认缓存单个会话和消息生成器,并且convertAndSend
应该关闭它在发送后获得的会话,这导致将该缓存的会话返回到池。这应该意味着它相对较快(spring jms经历了大量的代码只是为了发送消息)以在下一次发送时获得缓存的会话。