Java Spring批处理-并非所有记录都是从MQ检索处理的
我对Spring和Spring Batch相当陌生,所以如果您有任何澄清问题,请随时提问 我发现Spring批处理有一个问题,无法在测试或本地环境中重新创建。我们有一个日常作业,它通过JMS连接到WebSphereMQ并检索一组记录。此作业使用现成的JMS ItemReader。我们实现了自己的ItemProcessor,但除了日志记录之外,它没有做任何特殊的事情。没有影响传入记录的筛选器或处理 问题是,在MQ上10000多条每日记录中,只有大约700条(每次的确切数字都不同)被记录到ItemProcessor中。所有记录都已成功从队列中拉出。每次记录的记录数不同,似乎没有规律。通过将日志文件与MQ中的记录列表进行比较,我们可以看到我们的作业正在“处理”看似随机的记录子集。第一条记录可能会被拾取,然后跳过50条,然后连续5条,等等。每次作业运行时,模式都不同。也没有记录任何异常 在localhost中运行相同的应用程序并使用相同的数据集进行测试时,ItemProcessor会成功检索并记录所有10000+条记录。该作业在生产环境中运行20到40秒(也不是恒定的),但在测试和本地环境中,它需要几分钟才能完成(这显然是有道理的,因为它处理的记录太多了) 所以这是一个很难解决的问题,因为我们无法重新创建它。一个想法是实现我们自己的ItemReader并添加额外的日志记录,这样我们就可以看到记录是在读卡器之前丢失还是在读卡器之后丢失——现在我们只知道ItemProcessor只处理了记录的一个子集。但是,即使这样也不能解决我们的问题,考虑到这甚至不是一个解决办法,实施这项计划将是相当及时的 还有谁见过这样的问题吗?如有任何可能的想法或故障排除建议,将不胜感激。下面是我们用来参考的一些jar版本号Java Spring批处理-并非所有记录都是从MQ检索处理的,java,spring,activemq,spring-batch,ibm-mq,Java,Spring,Activemq,Spring Batch,Ibm Mq,我对Spring和Spring Batch相当陌生,所以如果您有任何澄清问题,请随时提问 我发现Spring批处理有一个问题,无法在测试或本地环境中重新创建。我们有一个日常作业,它通过JMS连接到WebSphereMQ并检索一组记录。此作业使用现成的JMS ItemReader。我们实现了自己的ItemProcessor,但除了日志记录之外,它没有做任何特殊的事情。没有影响传入记录的筛选器或处理 问题是,在MQ上10000多条每日记录中,只有大约700条(每次的确切数字都不同)被记录到ItemP
- 弹簧-3.0.5.1释放
- Spring集成-2.0.3.0版本
- 弹簧批-2.1.7.1发布
- 主动MQ-5.4.2
- WebSphereMQ-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配置:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
<bean id="claimsQueueConnectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="jms/SMSClaimNotificationCF" />
<property name="lookupOnStartup" value="true" />
<property name="cache" value="true" />
<property name="proxyInterface" value="javax.jms.ConnectionFactory" />
</bean>
<bean id="jmsDestinationResolver"
class="org.springframework.jms.support.destination.DynamicDestinationResolver">
</bean>
<bean id="jmsJndiDestResolver"
class=" org.springframework.jms.support.destination.JndiDestinationResolver"/>
<bean id="claimsJmsTemplate" class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory" ref="claimsQueueConnectionFactory" />
<property name="defaultDestinationName" value="jms/SMSClaimNotificationQueue" />
<property name="destinationResolver" ref="jmsJndiDestResolver" />
<property name="pubSubDomain">
<value>false</value>
</property>
<property name="receiveTimeout">
<value>20000</value>
</property>
</bean>
假的
20000
通常,MQ在正确配置时不会丢失消息。那么问题是“正确配置”看起来像什么 通常,消息丢失是由非持久性或非事务性GET造成的 如果非持久性消息正在通过QMgr到QMgr通道,并且设置了
NPMSPEED(FAST)
,则如果错误丢失,MQ不会记录错误。这就是这些选项的目的,因此不会出现错误
修复:在QMgr-to-QMgr通道上设置NPMSPEED(NORMAL)
,或使消息持久化
如果客户端正在同步点之外获取消息,则消息可能会丢失。具体来说,这与MQ无关,它只是消息传递的一般工作方式。如果您告诉MQ以破坏性方式从队列中获取消息,而它无法将该消息传递到远程应用程序,则MQ回滚该消息的唯一方法是在同步点下检索该消息
修复:使用事务处理会话
还有一些额外的注释,出自经验
- 每个人都发誓,消息持久性设置为他们认为的值。但是,当我停止应用程序并手动检查消息时,它通常不是预期的。这很容易验证,所以不要假设
- 如果消息在队列上回滚,则在MQ或TCP使孤立通道超时之前不会发生。这可能长达2小时,因此请调整通道参数和TCP Keepalive以减少该时间
- 检查MQ的错误日志(QMgr上的错误日志而不是客户机上的错误日志),以查找有关事务回滚的消息
- 如果仍然无法确定消息的去向,请尝试使用跟踪。此跟踪作为出口运行,并且非常可配置。您可以跟踪单个队列上的所有
操作,并且只能跟踪该队列。输出是人类可读的形式GET
- 请参阅
使用JMSTemplate时出现问题。我只是在升级硬件并突然暴露出预先存在的竞争条件时才遇到这些问题
简而言之,通过设计和意图,JMS模板在每个invocaton上打开和关闭连接。它不会看到早于其创建时间的消息。在高容量和/或高吞吐量的情况下,它将无法读取某些消息。我认为在任何人能够帮助您之前,您需要一个可重复性最低的样本。除此之外,这一切都只是猜测:一定有一个例外的地方或日志文件,将提供更多的信息。是否存在正在进行垃圾回收的线程,或者是否存在对正在进行垃圾回收的对象的weakreference?我可能会将GC与“跳过”进行比较,看看对象是否在完成工作之前被收集(很难相信会是这样,但值得一看)。您在生产中是否遇到网络或其他超时?感谢@mttdbrd的输入。我知道这是一个在黑暗中拍摄,但我们只是没有太多的信息进行下去。我希望有人以前见过类似的行为,能给我指出正确的方向。我们最好的猜测是Websphere、Spring Batch和/或MQ之间存在某种兼容性问题。到目前为止,我们还没有在任何生产日志中发现任何类型的异常或错误,但我将对垃圾收集问题的任何迹象做一些额外的研究