2011-08-14 43 views
23

生產性能我創建了一個簡單的生產者消費者模擬基於Spring,JMS和ActiveMQ的, 我試圖達到雙方,生產者和消費者高性能,JMS彈簧

連接設置:

<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的消息,這是非常慢的,我發現了這個瓶頸是我使用的交易, google搜索了一下後,並用打的事實CONFIGS,我發現,同時還具有自動裝配的交易中使用DefaultMessageListenerContainer和改變cachelevel後

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); 

我不知道如何與製片達到similiar演出,因爲它現在已經成爲整個系統的瓶頸。

回答

14

對不起,如果這個答案來得晚,以幫助原來的海報。我最近調查了JmsTemplate的表現。即使使用相同的傳送和確認模式,本地JMS代碼似乎比JmsTemplate快得多。問題原來是ActiveMQ通常默認爲異步發送,但是當您使用JmsTemplate時,它會使用同步發送。這大大降低了性能。您可以將ActiveMQConnectionFactoryuseAsyncSend屬性設置爲true以強制異步發送。更多細節在這裏:JmsTemplate is not evil

0

ActiveMQ的默認傳送模式是什麼?它是一個持久隊列嗎?如果是這樣,它是如何配置的?經紀人有多遠?這些答案將通過回答服務器確認發送所花費的時間(即網絡RTT +同步將消息持久保存到磁盤的潛在成本)來確定發送到隊列的基本成本。

另一種可能性是,您實際上在每次發送時都會創建一個新連接,會話和messageproducer。至少可以說這是相當昂貴的。值得確認是否發生這種情況(例如,添加調試日誌記錄到spring,檢查amq管理控制檯連接流失)或不作爲基本的完整性檢查。從外觀上看,CachingConnectionFactory應該默認緩存單個會話和messageproducer,並且convertAndSend應該關閉它在發送後獲得的會話,這會導致將該緩存會話返回到池。這應該意味着它相對較快(Spring jms通過大量的代碼來發送消息)來獲得下一次發送的緩存會話。

+0

當前好消息是不持久的,我調試jmsTemplate和會話和生產者緩存,我決定嘗試一個沒有春天的基本示例,並且事實證明(這是有道理的)提交每個消息的會話結果都是相同的性能,只有一定數量的消息被填充,然後提交事務才能獲得理想的結果。 – Matan

+1

如果普通香草測試和基於彈簧的測試具有相同的性能,那麼您可以非常確定該代理的瓶頸。 25/s等於每條消息40ms。這可能是非常合理的,取決於代理人的方式(以及發送是否是異步的)以及取決於它如何處理消息以及它運行什麼硬件。什麼是默認傳送模式?我的猜測是'PERSISTENT',如果是這樣,嘗試切換到'NON_PERSISTENT',你應該看到吞吐量增加。如果還沒有默認發送,你還應該考慮使用異步發送。 – Matt

5

JMSTemplate執行ConnectionFactiory - > Connection - > Session - > MessageProducer,在每次發送後關閉每個對象。爲了解決這個問題,使用org.apache.activemq.pool.PooledConnectionFactory封裝你的amqConnectionFactory bean,並在模板下使用它,而不是CachingConnectionFactory。

+0

已經嘗試過,CachingConnectionFactory的默認池大小爲1,改變該值並沒有太大的改變,同樣使用PooledConnectionFactory(默認池大小爲500)也提供類似的性能 – Matan

+1

確實有東西在那裏運行 - 粘貼一個分析器通過測試本身,看看你是否可以識別熱點。出於好奇,當你將轉換器帶出等式時,性能如何?即發送簡單的測試消息。另一件事是,你正在單線程中測試線性性能;這可能不是它現場使用的方式。一個更有用的測試是通過將調用convertAndSend包裝到Runnable中並將其傳遞給ExecutorService來使其與水平負載飽和。 –

+0

反對,真的嗎?我沒有看到你對馬特答案的迴應,但我認爲這是一個合理的問題。我認爲你的生產者代碼是在JUnit測試中,儘管這裏沒有足夠的信息。使用類似的配置,我看到每秒1000條消息。 –

1

嘗試將確認方法從AUTO更改爲CLIENT_ACKNOWLEDGE。欲瞭解更多信息,請參閱Specification