默认情况下,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属性来处理每条记录:
public class RetryItemProcessor implements ItemProcessor<Transaction, Transaction> { @Override public Transaction process(Transaction transaction) throws IOException { log.info("RetryItemProcessor, attempting to process: {}", transaction); HttpResponse response = fetchMoreUserDetails(transaction.getUserId()); //parse user's age and postCode from response and update transaction ... return transaction; } ... }
|
最后,它生成一个合并的输出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 public Step retryStep( ItemProcessor<Transaction, Transaction> processor, ItemWriter<Transaction> writer) throws ParseException { return stepBuilderFactory .get("retryStep") .<Transaction, Transaction>chunk(10) .reader(itemReader(inputCsv)) .processor(processor) .writer(writer) .faultTolerant() .retryLimit(3) .retry(ConnectTimeoutException.class) .retry(DeadlockLoserDataAccessException.class) .build(); }
|
在这里,我们调用faultTolerant() 以启用重试功能。此外,我们使用retry和retryLimit分别定义了符合重试条件的异常和项的最大重试计数。看一下上述配置的XML等效配置:
<batch:job id="retryBatchJob"> <batch:step id="retryStep"> <batch:tasklet> <batch:chunk reader="itemReader" writer="itemWriter" processor="retryItemProcessor" commit-interval="10" retry-limit="3"> <batch:retryable-exception-classes> <batch:include class="org.apache.http.conn.ConnectTimeoutException"/> <batch:include class="org.springframework.dao.DeadlockLoserDataAccessException"/> </batch:retryable-exception-classes> </batch:chunk> </batch:tasklet> </batch:step> </batch:job>
|