2010-11-01 76 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营销炒作抨击)...