Spring Batch失败任务重启未重处理失败Chunk问题咨询
Spring Batch 任务重启异常与配置疑问
问题复现背景
有一个用于复现问题的Maven示例工程,执行mvn install后会在\target目录生成SamplebatchApplication-0.0.1-SNAPSHOT.jar,通过java -jar SamplebatchApplication-0.0.1-SNAPSHOT.jar即可启动这个集成Liquibase的Spring Boot应用。
应用的application.properties配置指向PostgreSQL数据库,批量任务核心配置在FEBPDBConfig.java中。
任务执行与失败流程
- 首次执行:调用POST接口
http://localhost:8080/batch/trigger-or-resume-application-batch-job,请求体传{"appRestartJobExecutionId": ""},执行链路为:BatchController.triggerOrResumeApplicationBatchJobByB2E()→FebpApplicationJobServiceImpl.triggerApplicationBatchJob()→JobLauncher.run()。正常情况下,任务会从febp_emp_detail_test读取50条记录,处理后写入febp_emp_tax_detail_test。 - 触发失败:再次调用该接口时,任务先提交
emp0001至emp0030的数据,处理emp0032时触发预设的失败逻辑,任务进入FAILED状态,失败代码如下:
private static int counter=1; if(item.getEmpId().equals("emp0032")) { if(counter==1) { counter++; throw new Exception(); } }
- 重启异常:重启服务器后,调用接口并传入失败任务的execution ID,执行链路变为:
BatchController.triggerOrResumeApplicationBatchJobByB2E()→FebpApplicationJobServiceImpl.resumeApplicationBatchJob()→jobOperator.restart(failedBatchExecutionId)。但重启后任务直接从emp0036及之后的记录开始处理,未重新执行失败的Chunk,不符合“重新处理未完成数据”的预期(任务配置为单线程)。
补充配置信息(2024/03/20更新)
步骤定义的核心代码如下:
@Bean public Step step1() { return new StepBuilder("step1", jobRepository) .partitioner(slaveStep().getName(), partitioner()) .step(slaveStep()) .gridSize(febpEmployeeTaxCalculationBatchProperties.getTaxCalculationStep1PartitionGridSize()) .taskExecutor(actStmntTaskExecutor()) .build(); } // slave step @Bean public Step slaveStep() { try { return new StepBuilder("slaveStep", jobRepository) .<EmployeeDetail, EmployeeTaxDetail>chunk(febpEmployeeTaxCalculationBatchProperties.getTaxCalculationStep1ReaderPageSize(),transactionManager) .reader(pagingItemReader(null,null)) .processor(processor()) .writer(customerItemWriter()) .taskExecutor(actStmntTaskExecutor()) .build(); } catch (Exception ex) { throw new RuntimeException("Error creating slave step: " + ex.getMessage()); } } /** * Act stmnt task executor. * * @return the simple async task executor */ public SimpleAsyncTaskExecutor actStmntTaskExecutor() { SimpleAsyncTaskExecutor acctStmtTaskExecuter = new SimpleAsyncTaskExecutor(); acctStmtTaskExecuter.setConcurrencyLimit(febpEmployeeTaxCalculationBatchProperties.getTaxCalculationStep1TaskExecuterThreadConcurrencyLimit()); acctStmtTaskExecuter.setThreadPriority(febpEmployeeTaxCalculationBatchProperties.getTaxCalculationStep1TaskExecuterThreadPriority()); acctStmtTaskExecuter.setThreadNamePrefix("FEBP_TAX_CALCULATION_GEN"); return acctStmtTaskExecuter; }
待解答问题
- 之前了解到Spring Batch重启场景下不应使用TaskExecutor,那
step1()和slaveStep()中是否都需要移除该组件? - Chunk大小应该如何与
gridSize、Reader的pageSize和fetchSize匹配?当前发现Chunk值设得较小时,重启后不会重新处理失败的数据。
内容的提问来源于stack exchange,提问作者Shreyas Holla P
相关产品推荐
相关产品推荐

