我对 Spring 和 Spring Batch 相当陌生,所以如果您有任何疑问,请随时提出任何澄清问题。
我发现 Spring Batch 存在问题,无法在测试或本地环境中重新创建。我们的日常工作是通过 JMS 连接到 Websphere MQ 并检索一组记录。此作业使用开箱即用的 JMS ItemReader。我们实现了自己的 ItemProcessor,但除了日志记录之外它没有做任何特殊的事情。没有任何过滤器或处理会影响传入记录。
问题是,在 MQ 上的 10,000 多条日常记录中,通常只有大约 700 条左右(每次的确切数字不同)会记录在 ItemProcessor 中。所有记录均已成功从队列中拉出。每次记录的记录数量都不同,并且似乎没有规律。通过将日志文件与 MQ 中的记录列表进行比较,我们可以看到我们的作业正在“处理”看似随机的记录子集。第一条记录可能会被选取,然后跳过 50 条记录,然后连续 5 条记录,依此类推。每次作业运行时,模式都不同。也没有记录任何异常。
在本地主机中运行相同的应用程序并使用相同的数据集进行测试时,ItemProcessor 成功检索并记录了所有 10,000 多条记录。该作业在生产中运行 20 到 40 秒(也不是恒定的),但在测试和本地需要几分钟才能完成(这显然是有道理的,因为它要处理更多的记录)。
因此,这是难以解决的问题之一,因为我们无法重现它。一个想法是实现我们自己的 ItemReader 并添加额外的日志记录,以便我们可以查看记录是否在读取器之前或之后丢失 - 我们现在所知道的是 ItemProcessor 只处理记录的子集。但即使这样也不能解决我们的问题,而且考虑到它甚至不是一个解决方案,实施它也有点及时。
还有其他人见过这样的问题吗?任何可能的想法或故障排除建议将不胜感激。以下是我们用来参考的一些 jar 版本号。
- 春季 - 3.0.5.RELEASE
- Spring 集成 - 2.0.3.RELEASE
- 春季批次 - 2.1.7.RELEASE
- Activemq-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配置:
<?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>