如何提高基于MQ的批处理应用程序的性能?

时间:2011-06-03 14:08:18

标签: xml performance jboss ibm-mq mq

我有一个应用程序,其中消息以每小时70K XML的速率传输。我们使用这些XML消息并将其存储到中间队列中。创建中间队列是因为我们需要满足24小时消耗所有消息的SLA。我们能够在24小时内使用XMLS并将其加载到内部队列中。在将其加载到内部队列之后,我们处理XMLS(解析,应用非常少的转换,执行很少的验证)并将数据存储到严格规范化的数据模型中。我知道数据模型会对性能产生巨大影响,遗憾的是,我们无法控制数据模型。目前,我们需要3.5分钟来处理2K消息,这是不可接受的。对于2K消息,我们希望将其降低到1分钟。以下是我们迄今为止所做的工作:

1)适用的应用指数 2)使用XMLBeans来解析XML(每个XML的大小不是很大) 3)删除了所有不必要的验证,transformatios等。

应用程序运行于:
操作系统:RHEL 5.4 64位
平台:JDK 1.6.0_17,64位
数据库:Oracle 11g R2 64位(2节点集群)
外部MQ:IBM队列
内部临时存储MQ:JBoss MQ
Application Server:Jboss 5.1.0.GA(EAP版本)

我们使用和处理XML消息的顺序非常重要,因此我们无法进行并行处理。

我们还能做些什么来改善表现吗?

2 个答案:

答案 0 :(得分:2)

消息传递调整之外的一些建议,因为它似乎不是您的[主要]瓶颈:

  • 您提到您正在将数据存储到高度规范化的数据库中。这总是意味着一个或多个参考数据或PK查找,它们创建了几次额外的数据库访问以获取此数据。要避免或减少此问题,请使用所有参考数据创建本地缓存,并随时更新缓存。在内存中查找将明显快于数据库之旅。
  • 如果您认为没有足够的RAM来缓存所有解码和参考数据,请拍摄基于磁盘的缓存(例如,将执行RAM,磁盘或溢出的EHCache)或者像HyperSonic或H2这样的轻量级本地数据库你最好的查找时间比去甲骨文(除非你在同一台主机,甚至那时......)
  • 最终,如果每条消息需要多次往返数据库,您可以将消息处理迁移到数据库本身,您可以在其中实现PL / SQL或Java中的过程。
  • 如果为处理的一条消息写入数据库涉及多次插入/更新,请确保使用预准备语句批处理。这将在一次调用DB中发送多个插入/更新。
  • 说到预准备语句,请确保您的JBoss DataSource configuration for Oracle已将 prepared-statement-cache-size 设置为足够高的数字,以处理在处理过程中创建的所有预准备语句(以及不是默认值为零,或者没有缓存)。
  • 您正在使用的XML解析器可能会产生比必要更多的开销,甚至(特别是)小消息。如果您使用的是JAXB,请确保不要多次重新创建unmarshaller(或者超过必要的次数)。或者,尝试Pull/Streaming parser。如果您使用的是DOM解析器,则所需的额外内存可能会导致大量垃圾回收。
  • 愚蠢的事,但值得一提的是,如果你为每条消息执行大量的日志记录,那将花费你的时间,所以关掉它。
  • 使用JBoss MQ作为中间缓冲区很优雅,但它可能不是存储延迟处理消息的最快方法,因为持久性对于各种JMS消息类型来说更复杂和通用。在这方面,如果JBoss MQ仍然持久化到Oracle,那么自定义持久化过程似乎不太可能更快。如果JBoss MQ存储到HyperSonic(默认情况下),您仍然可以通过一些自定义代码超越JMS消息的存储。这也意味着您需要一种新机制将消息从数据库中拉回来进行处理,但与JMS存储一样,自定义进程可能胜过JBoss MQ实现的更通用的过程。
  • 将中间消息存储到数据库还可以提供更多查询灵活性,以确定不必连续处理消息的位置。 (例如,可能不需要按顺序处理来自不同客户端的消息)。当然,您也可以通过在中间消息中放置适当的标头来对JBoss MQ执行此操作。这将允许您通过在多个不同的消息侦听器/处理器中使用不同的选择器来并行化。

关于消息传递的一个快速项目.....

您没有提及是否使用带有WebSphere MQ的消息驱动bean,但如果您使用,则Inbound Configuration中有一个名为 pollingInterval 的设置,引用文档引用,意思是:

如果会话中的每个消息侦听器在其队列中没有合适的消息,则这是在每个消息侦听器再次尝试从其队列中获取消息之前经过的最大间隔(以毫秒为单位)。如果经常发生会话中没有适当的消息可用于任何消息侦听器,请考虑增加此属性的值。仅当TRANSPORT具有值BIND或CLIENT时,此属性才相关。

默认 pollingTime 为5000毫秒。您当前的消息处理时间是

  

(3.5 * 60 * 1000/2000)

=每条消息105毫秒。

如果你在这里引入5000毫秒的暂停,这将严重降低你的吞吐量,所以你可能想要通过测量消息入队时间和你收到的时间之间的持续差异来研究这个问题。 JBoss消息监听器中的消息。可以从以下消息标题中确定入队时间:

  • JMS_IBM_PutDate
  • JMS_IBM_PutTime

总而言之,您最好的选择是找出如何并行化。

祝你好运。

//尼古拉斯

答案 1 :(得分:1)

WebSphere MQ,即使在小型服务器上,也可以比您描述的速率更快地卸载消息。 Windows Performance Report for WMQ V7通过客户端渠道每秒超过2,200次2k持续往返(一次请求和一次回复)测试。这是每秒超过4,000条消息。

您的案例中的瓶颈似乎是处理消息的延迟以及以特定顺序处理消息的依赖性。可以为您提供最佳性能提升的选项是消除顺序依赖性。当我在银行工作时,我们有一个系统按照他们到达的确切顺序发布交易,每个人都说这个要求是强制性的。但是,我们最终修改了系统,以便在白天执行备忘录,然后在稍后的步骤中重新发布。备忘录发布以任何顺序发生,并支持并行性,故障转移和多实例处理的所有其他好处。最后的帖子在逻辑顺序中(并且实际上以对客户最有利的顺序)应用了交易,一旦它们都在数据库中。序列依赖关系将您锁定为单例模型,并且是异步消息传递的最坏情况要求。尽可能消除它们。

另一个需要改进的方面是解析和处理消息。只要您遇到顺序依赖,这是提高性能的最佳选择。

最后,您总是可以选择以更多内存,CPU,更快的磁盘I / O等形式来解决问题。从本质上讲,这是针对具有强大功能的软件架构,并且永远不是最好的解决方案,但通常会为您提供足够的时间来解决根本原因。