默认情况下,Spring批处理作业因执行期间引发的任何错误而失败。但是,有时,我们可能需要提高应用程序的弹性来处理间歇性故障。在本快速教程中,我们将探索如何在Spring Batch框架中配置重试逻辑。
假设我们有一个批处理作业,它读取输入的CSV文件:
username, userid, transaction_date, transaction_amount sammy, 1234, 31/10/2015, 10000 john, 9999, 3/12/2015, 12321
然后,它通过点击REST端点以获取用户的age和postCode属性来处理每条记录:
<b>public</b> <b>class</b> RetryItemProcessor implements ItemProcessor<Transaction, Transaction> { @Override <b>public</b> Transaction process(Transaction transaction) throws IOException { log.info(<font>"RetryItemProcessor, attempting to process: {}"</font><font>, transaction); HttpResponse response = fetchMoreUserDetails(transaction.getUserId()); </font><font><i>//parse user's age and postCode from response and update transaction</i></font><font> ... <b>return</b> transaction; } ... } </font>
最后,它生成一个合并的输出XML:
<transactionRecord> <transactionRecord> <amount>10000.0</amount> <transactionDate>2015-10-31T00:00:00+05:30</transactionDate> <userId>1234</userId> <username>sammy</username> <age>10</age> <postCode>430222</postCode> </transactionRecord> ... </transactionRecord>
现在,如果由于某些网络缓慢而导致与REST端点的连接超时怎么办?如果是这样,我们的批处理作业将失败。
在这种情况下,我们希望重试失败的项目两次。因此,让我们将批处理作业配置为在失败的情况下最多执行三个重试:
@Bean <b>public</b> Step retryStep( ItemProcessor<Transaction, Transaction> processor, ItemWriter<Transaction> writer) throws ParseException { <b>return</b> stepBuilderFactory .get(<font>"retryStep"</font><font>) .<Transaction, Transaction>chunk(10) .reader(itemReader(inputCsv)) .processor(processor) .writer(writer) .faultTolerant() .retryLimit(3) .retry(ConnectTimeoutException.<b>class</b>) .retry(DeadlockLoserDataAccessException.<b>class</b>) .build(); } </font>
在这里,我们调用faultTolerant() 以启用重试功能。此外,我们使用retry和retryLimit分别定义了符合重试条件的异常和项的最大重试计数。
看一下上述配置的XML等效配置:
<batch:job id=<font>"retryBatchJob"</font><font>> <batch:step id=</font><font>"retryStep"</font><font>> <batch:tasklet> <batch:chunk reader=</font><font>"itemReader"</font><font> writer=</font><font>"itemWriter"</font><font> processor=</font><font>"retryItemProcessor"</font><font> commit-interval=</font><font>"10"</font><font> retry-limit=</font><font>"3"</font><font>> <batch:retryable-exception-classes> <batch:include <b>class</b>=</font><font>"org.apache.http.conn.ConnectTimeoutException"</font><font>/> <batch:include <b>class</b>=</font><font>"org.springframework.dao.DeadlockLoserDataAccessException"</font><font>/> </batch:retryable-exception-classes> </batch:chunk> </batch:tasklet> </batch:step> </batch:job> </font>