2010-11-01 77 views
1

我有一個Java應用程序,其中有許多通過JMS(ActiveMQ)進行通信的組件。目前應用程序和JMS Hub位於同一臺服務器上,儘管我們最終計劃拆分組件的可伸縮性。目前,我們在性能方面存在重大問題,尤其是在JMS方面,最顯着的是,這個問題的焦點在於向主題發佈消息所花費的時間。JMS(ActiveMQ)性能

我們有大約50個動態創建的主題用於應用程序組件之間的通信。一個組件從表中讀取記錄並逐個處理它們,處理過程涉及創建JMS對象消息並將其發佈到其中一個主題。這個處理跟不上記錄寫入源表的速度〜23/sec,所以我們改變了處理過程來創建JMS對象消息並將它添加到隊列中。創建一個新線程,從該隊列中讀取並將消息發佈到適當的主題。顯然,這並不能加快處理速度,但它確實讓我們看到了排隊的大小後面到底有多遠。

在一天的開始時間裏,沒有任何信息通過整個系統,在第一個小時內從1560000(433 /秒)信息通過集線器快速增加到第三個小時的2100000(582/sec)然後停留在那個水平。在第一個小時開始時,從數據庫表中讀取組件的消息發佈的消息保持不變,但在那一小時結束時,在等待發送的隊列中有2000條消息,並且在第3個小時的時間隊列中有9000條消息在裏面。

下面是發送JMS消息的代碼的相關章節,關於我們做錯了什麼的建議或者我們如何改進這種性能非常感謝。查看Web上的統計信息JMS應該能夠輕鬆處理〜1000-2000條大消息/秒或〜10000條小消息/秒。我們的消息每個都是500字節左右,所以我想可以坐在這個規模的中間。

代碼用於獲取出版商:

private JmsSessionPublisher getJmsSessionPublisher(String topicName) throws JMSException { 
     if (!this.topicPublishers.containsKey(topicName)) { 
      TopicSession pubSession = (ActiveMQTopicSession) topicConnection.createTopicSession(false, Session.AUTO_ACKNOWLEDGE); 

      ActiveMQTopic topic = getTopic(topicName, pubSession); 

      // Create a JMS publisher and subscriber 
      TopicPublisher publisher = pubSession.createPublisher(topic); 

      this.topicPublishers.put(topicName, new JmsSessionPublisher(pubSession, publisher)); 
     } 
     return this.topicPublishers.get(topicName); 
    } 

發送消息:

JmsSessionPublisher jmsSessionPublisher = getJmsSessionPublisher(topicName); 

     ObjectMessage objMessage = jmsSessionPublisher.getSession().createObjectMessage(messageObj); 
     objMessage.setJMSCorrelationID(correlationID); 
     objMessage.setJMSTimestamp(System.currentTimeMillis()); 
     jmsSessionPublisher.getPublisher().publish(objMessage, false, 4, 0); 

代碼這增加了消息到隊列:

List<EventQueue> events = eventQueueDao.getNonProcessedEvents(); 
for (EventQueue eventRow : events) { 
    IEvent event = eventRow.getEvent(); 
    AbstractEventFactory.EventType eventType = AbstractEventFactory.EventType.valueOf(event.getEventType()); 
    String topic = event.getTopicName() + topicSuffix; 
    EventMsgPayload eventMsg = AbstractEventFactory.getFactory(eventType).getEventMsgPayload(event); 
    synchronized (queue) { 
     queue.add(new QueueElement(eventRow.getEventId(), topic, eventMsg)); 
     queue.notify(); 
    } 
} 

代碼在螺紋去除的物品隊列:

jmsSessionFactory.publishMessageToTopic(e.getTopic(), e.getEventMsg(), Integer.toString(e.getEventMsg().hashCode())); 

publishMessageToTopic執行上面的'發送消息'代碼。

如果您認爲ActiveMQ可能不是最佳選擇,那麼其他JMS實現是一種選擇。

謝謝

詹姆斯

+0

您使用的是交易?你有什麼配置的隊列?他們真的排隊嗎?還是話題?這麼多的問題 :)。什麼版本的ActiveMQ?獨立?在應用程序服務器上? – 2010-11-01 17:57:01

+0

除非默認使用,否則我們不明確使用交易。我們不在hub上創建任何配置,而是使用以下命令動態創建主題:topic =(ActiveMQTopic)this.initialContext.lookup(「dynamicTopics /」+ topicName);我們使用運行在獨立實例中的ActiveMQ版本5.3.2。 – James 2010-11-02 07:48:57

+0

那麼這個問題有什麼問題?你解決了嗎? – 2012-10-28 18:42:36

回答

0

我們不使用ActiveMQ的,但我們遇到了類似的問題,我們發現,這些問題均與後端處理,而不是與Java的一面。這裏可能有多個問題:

  1. 處理隊列中的消息的程序可能很慢(例如,大型機上的CICS),它可能無法跟上發送到隊列的消息。一種可能的解決方案是增加處理能力(或優化處理消息的後端代碼)
  2. 檢查隊列上的消息,有時隊列上會有很多未提交的有害消息,我們使用單獨的排隊這樣的消息。

很高興知道Karianna提出的問題的答案。

+0

我不認爲有處理問題。該應用程序運行在4臺CPU服務器上,運行率約爲50%,查看率不高於70%。將消息添加到隊列並將其關閉的代碼非常簡單。我已將它添加到我的帖子中。 – James 2010-11-02 07:59:43

0

這是不是100%清楚你在哪裏遇到性能下降,但它聽起來像你所描述的是發佈消息緩慢。您是否每次發佈消息時都創建新的發佈者?如果是這樣,這是非常低效的,你應該考慮創建一個發佈者並反覆使用它來發送消息。此外,如果您發送持久性消息,那麼您可能正在使用同步發送給代理。您可能想考慮使用異步發送來加快速度。欲瞭解更多信息,請參閱文檔Async Sends

另外,消費者的表現如何?有多少消費者正在使用?他們是否能夠跟上發佈信息的速度?

此外,您正在使用的代理配置是什麼?它是否已經調整了?

布魯斯

0

儘管這是一個老問題,有一個非常非常重要的建議缺少:

  • 調查主題和隊列,你有量。

ActiveMQ將訂閱主題保留在單獨的線程中。特別是,當你有很多不同的主題時,這會拖拽任何服務器。考慮使用JMS選擇器。

我遇到了類似的情況,每秒有數千條市場數據消息。當我天真地將每條消息轉儲到一個市場儀器專用頻道時,服務器在向消息製作者吐出錯誤消息之前能夠保持大約一個小時。我將設計更改爲擁有ONE通道「MARKET_DATA」,然後在所有生成的消息上設置標題屬性,並在消費者端設置選擇器以僅選擇我想要的消息。請注意,我的選擇器像SQL語法,並在服務器上運行,雖然...(是的,讓我們跳過CEP營銷炒作抨擊)...