消息传递调整之外的一些建议,因为这似乎不是您的 [主要] 瓶颈:
- 您提到您将数据存储到高度规范化的数据库中。这总是意味着一个或多个参考数据或 PK 查找会创建多次额外的数据库访问以获取此数据。为避免或减少这种情况,请使用所有参考数据创建本地缓存并随时更新缓存。在内存中查找将比访问数据库快得多。
- 如果你觉得你没有足够的内存来缓存你所有的解码和参考数据,那就去寻找一个基于磁盘的缓存(例如 EHCache,它会做 RAM、磁盘或溢出)或者像 HyperSonic 或 H2 这样的轻量级本地数据库,它仍然可以让你更好地查找比去甲骨文旅行好几次(除非你在同一台主机上,即使那样......)
- 最终,如果每条消息都需要多次往返 DB,您可能会受益于将消息处理迁移到 DB 本身,您可以在其中使用 PL/SQL 或 Java 实现该过程。
- 如果您为处理的一条消息写入数据库涉及多次插入/更新,请确保使用准备好的语句批处理。这将在一次调用中向数据库发送多个插入/更新。
- 说到准备好的语句,请确保您的 Oracle的JBoss 数据源配置已将prepared-statement-cache-size设置为足够高的数字,以处理您在处理期间创建的所有准备好的语句(而不是默认值,即零或不缓存)。
- 您正在使用的 XML 解析器可能会增加不必要的开销,即使(或特别是)对于小消息也是如此。如果您使用的是 JAXB,请确保您没有多次(或不必要地)重新创建解组器。或者,尝试使用Pull/Streaming 解析器。如果您使用的是 DOM 解析器,则所需的额外内存可能会导致大量垃圾收集。
- 愚蠢的事情,但值得一提的是,如果您为每条消息执行大量日志记录,那将花费您的时间,因此请将其关闭。
- 使用 JBoss MQ 作为中间缓冲区很优雅,但它可能不是存储消息以进行延迟处理的最快方式,因为对于各种 JMS 消息类型而言,持久性更加复杂和通用。在那一点上,如果 JBoss MQ 仍然坚持到 Oracle,那么自定义的持久性过程似乎不太可能更快。如果 JBoss MQ 正在存储到 HyperSonic(默认情况下),您仍然可以使用一些自定义代码来胜过 JMS 消息的存储。这也意味着您将需要一种新机制来将消息从数据库中拉出进行处理,但与 JMS 存储一样,自定义进程的性能可能优于 JBoss MQ 实现的更通用的过程。
- 将中间消息存储到 DB 还可以提供更大的查询灵活性,以确定不必串行处理消息的位置。(例如,来自不同客户端的消息可能不需要按顺序处理)。当然,您也可以通过在中间消息中放置适当的标头来使用 JBoss MQ 做到这一点。这将允许您通过在多个不同的消息侦听器/处理器中使用不同的选择器来进行并行化。
关于消息传递的一项快速项目......
您没有提及是否将消息驱动的 bean 与 WebSphere MQ 一起使用,但如果您使用了,则入站配置中有一个名为pollingInterval的设置,引用文档中的内容,这意味着:
如果会话中的每个消息侦听器在其队列中没有合适的消息,则这是每个消息侦听器再次尝试从其队列中获取消息之前经过的最大间隔(以毫秒为单位)。如果会话中的任何消息侦听器经常没有合适的消息可用,请考虑增加此属性的值。仅当 TRANSPORT 的值为 BIND 或 CLIENT 时,此属性才相关。
默认轮询时间为 5000 毫秒。您当前的消息处理时间是
(3.5 * 60 * 1000 / 2000)
= 每条消息 105 毫秒。
If you introduce a 5000 ms pause here-and-there, that will seriously cut down on your throughput, so you might want to look into this by measuring the ongoing difference between the message enqueue time and the time that you receive the message in your JBoss message listener. The enqueue time can be determined from these message headers:
- JMS_IBM_PutDate
- JMS_IBM_PutTime
All in all, your best bet is going to be to figure out how to parallelize.
Good luck.
//Nicholas