Spring Batch – 并非所有记录都是从MQ检索中处理的

我是Spring和Spring Batch的新手,如果你有任何问题,请随时提出任何澄清问题。

我看到Spring Batch的问题,我无法在我们的测试或本地环境中重新创建。 我们有一个日常工作,通过JMS连接到Websphere MQ并检索一组记录。 此作业使用开箱即用的JMS ItemReader。 我们实现了自己的ItemProcessor,但它除了记录之外没有做任何特殊的事情。 没有应该影响传入记录的filter或处理。

问题是,在MQ上的每日10,000多条记录中,只有大约700个左右(确切的数字每次不同)通常会记录在ItemProcessor中。 所有记录都已成功从队列中删除。 记录的记录数每次都不同,似乎没有模式。 通过将日志文件与MQ中的记录列表进行比较,我们可以看到一个看似随机的记录子集正在被我们的工作“处理”。 可能会拾取第一条记录,然后跳过50条记录,然后连续5条等等。每次作业运行时,模式都不同。 也没有记录exception。

在localhost中运行相同的应用程序并使用相同的数据集进行测试时,ItemProcessor将成功检索并记录所有10,000多条记录。 该作业在生产中运行20到40秒(也不是常数),但在测试和本地,它需要几分钟才能完成(这显然是有意义的,因为它处理了更多的记录)。

因此,这是解决问题的难题之一,因为我们无法重新创建它。 一个想法是实现我们自己的ItemReader并添加额外的日志记录,以便我们可以看到记录是否在读者之前或读者之后丢失 – 我们现在知道的是ItemProcessor只处理了一部分记录。 但即使这样也无法解决我们的问题,并且考虑到它甚至不是一个解决方案,它将在某种程度上及时实施。

还有其他人看过像这样的问题吗? 任何可能的想法或疑难解答建议将不胜感激。 以下是我们用于参考的一些jar版本号。

  • spring – 3.0.5.RELEASE
  • Spring Integration – 2.0.3.RELEASE
  • Spring Batch – 2.1.7.RELEASE
  • 活动MQ – 5.4.2
  • Websphere MQ – 7.0.1

提前感谢您的意见。

编辑:每个请求,处理器的代码:

public SMSReminderRow process(Message message) throws Exception { SMSReminderRow retVal = new SMSReminderRow(); LOGGER.debug("Converting JMS Message to ClaimNotification"); ClaimNotification notification = createClaimNotificationFromMessage(message); retVal.setShortCode(BatchCommonUtils .parseShortCodeFromCorpEntCode(notification.getCorpEntCode())); retVal.setUuid(UUID.randomUUID().toString()); retVal.setPhoneNumber(notification.getPhoneNumber()); retVal.setMessageType(EventCode.SMS_CLAIMS_NOTIFY.toString()); DCRContent content = tsContentHelper.getTSContent(Calendar .getInstance().getTime(), BatchCommonConstants.TS_TAG_CLAIMS_NOTIFY, BatchCommonConstants.TS_TAG_SMSTEXT_TYP); String claimsNotificationMessage = formatMessageToSend(content.getContent(), notification.getCorpEntCode()); retVal.setMessageToSend(claimsNotificationMessage); retVal.setDateTimeToSend(TimeUtils .getGMTDateTimeStringForDate(new Date())); LOGGER.debug( "Finished processing claim notification for {}. Writing row to file.", notification.getPhoneNumber()); return retVal; } 

JMS配置:

                 false   20000   

请参见http://activemq.apache.org/jmstemplate-gotchas.html 。

使用JMSTemplate存在问题。 当我升级硬件并突然暴露出预先存在的竞争条件时,我才遇到这些问题。

简短forms是,通过设计和意图,JMS模板打开并关闭每个invocaton上的连接。 它不会看到早于其创建的消息。 在高容量和/或高吞吐量情况下,它将无法读取某些消息。

通常,MQ在正确配置时不会丢失消息。 那么问题是“正确配置”是什么样的?

通常,丢失的消息是由非持久性或非事务性GET引起的。

如果非持久性消息正在遍历QMgr到QMgr通道并且已设置NPMSPEED(FAST) ,则MQ将不会记录错误(如果它们丢失)。 这就是那些选项的用途,因此不会出现错误。

修复:在QMgr-to-QMgr通道上设置NPMSPEED(NORMAL)或使消息持久化。

如果客户端在同步点之外获取消息,则消息可能会丢失。 这与MQ没有任何关系,它只是一般的消息传递方式。 如果您告诉MQ从队列中破坏性地获取消息并且无法将该消息传递给远程应用程序,则MQ将其回滚的唯一方法是在同步点下检索消息。

修复:使用事务处理会话。

还有一些额外的笔记,源于经验。

  • 每个人都发誓消息持久性设置为他们认为的。 但是当我停止应用程序并手动检查消息时,往往不是预期的。 这很容易validation,所以不要假设。
  • 如果消息在队列中回滚,则在MQ或TCP超出孤立通道之前不会发生这种情况。这可能长达2小时,因此调整通道参数和TCP Keepalive以减少该消息。
  • 检查MQ的错误日志(QMgr而不是客户端)以查找有关回滚事务的消息。
  • 如果仍然无法确定消息的去向 ,请尝试使用SupportPac MA0W进行跟踪。 此跟踪作为退出运行,并且非常易于配置。 您可以跟踪单个队列上的所有GET操作,只跟踪该队列。 输出是人类可读的forms。