jms生产商与春天的表现

时间:2011-08-14 10:19:29

标签: java spring jms activemq spring-jms

我基于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);

我想知道如何与制作人达成类似的表演,因为它现在已经成为整个系统的瓶颈。

4 个答案:

答案 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经历了大量的代码只是为了发送消息)以在下一次发送时获得缓存的会话。