Springboot 批处理 - 使用 JdbcPagingItemReader,当没有数据 select 时,作业就会挂起
Springboot batch - Using JdbcPagingItemReader and the job is getting is getting hung up when there is no data to select
我遇到了一个问题,看起来像是使用 JdbcPagingItemReader 的方法被挂断了。
当 reader 到 return 中有信息时一切正常,但是当 select 没有信息到 return 时下面的 select 运行时,事情就不会了不太好用(即工作挂起)。
此外,当删除 taskExecutor(和 throttleLimit)步骤时,reader 步骤运行到完成,即使 select 没有信息,一切看起来也很好。考虑到这一点,我不确定多线程在其中扮演什么角色(如果有的话)或者我的 reader 方法是否有缺陷。
在下面的例子中,你会看到
select 非常简单,因为它从一个 table 读取,连接到另一个,然后 selects 具有特定状态和给定日期范围内的行。
如果有帮助,请提供其他信息...
Springboot版本2.5.6,数据库使用java17,MySql
感谢您提供的任何建议或见解,因为我现在很困惑。
谢谢。
@Configuration
@EnableBatchProcessing
public class BuildOpenStatusConfigurationJob {
@Autowired
JobBuilderFactory jobBuilderFactory;
@Autowired
StepBuilderFactory stepBuilderFactory;
@Autowired
DataSource dataSource;
....
@Bean
public TaskExecutor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(12);
executor.setMaxPoolSize(16);
executor.setQueueCapacity(12);
executor.initialize();
return executor;
}
@Bean
public Step createStsActivity() {
return this.stepBuilderFactory.get("createStsActivity")
.<StsActivity, StsActivity>chunk(1000)
.reader(stsActivityItemReader(null, null))
.processor(stsActivityItemProcessor())
.writer(stsActivityItemWriter())
.taskExecutor(taskExecutorRows())
.throttleLimit(16)
.listener(statusStepExecutionListener())
.build();
}
@Bean
@StepScope
public JdbcPagingItemReader<StsActivity> stsActivityItemReader(
@Value("#{jobParameters['lowerDateThreshold']}") String lowerDateThreshold,
@Value("#{jobParameters['upperDateThreshold']}") String upperDateThreshold) {
JdbcPagingItemReader<StsActivity> pagingItemReader = new JdbcPagingItemReader<>();
pagingItemReader.setDataSource(dataSource);
pagingItemReader.setFetchSize(10000);
pagingItemReader.setPageSize(10000);
pagingItemReader.setRowMapper(new BeanPropertyRowMapper<>(StsActivity.class));
MySqlPagingQueryProvider mySqlPagingQueryProvider = new MySqlPagingQueryProvider();
mySqlPagingQueryProvider.setSelectClause(ta.statusId as statusId, tb.eventDate as maxEventDate, tb.id as maxEventId ");
mySqlPagingQueryProvider.setFromClause("FROM TableA ta"
+ "join TableB tb on tb.statusId = ta.statusId");
mySqlPagingQueryProvider.setWhereClause("WHERE tb.status = 'OPEN' "
+ "and (date(tb.eventDate) >= date('" + lowerDateThreshold + "') "
+ "and date(tb.eventDate) < date('" + upperDateThreshold + "'))");
Map<String, Order> orderByKeys = new HashMap<>();
orderByKeys.put("rbpai.statusId", Order.ASCENDING);
mySqlPagingQueryProvider.setSortKeys(orderByKeys);
pagingItemReader.setQueryProvider(mySqlPagingQueryProvider);
return pagingItemReader;
}
这已在 v4.3.4 中修复:https://github.com/spring-projects/spring-batch/issues/3898。
使用 Spring Boot 2.5.6,您将获得 Spring Batch v4.3.3,其中不包含修复程序。
如果您升级到包含 Batch 4.3.4+ 的启动版本,您的问题应该会得到解决。否则,它可能是一个回归。在这种情况下,请在 Github 上添加一条评论,其中包含重现该问题的 minimal complete example,我们将 re-open 进行调查。先谢谢你。
我遇到了一个问题,看起来像是使用 JdbcPagingItemReader 的方法被挂断了。
当 reader 到 return 中有信息时一切正常,但是当 select 没有信息到 return 时下面的 select 运行时,事情就不会了不太好用(即工作挂起)。
此外,当删除 taskExecutor(和 throttleLimit)步骤时,reader 步骤运行到完成,即使 select 没有信息,一切看起来也很好。考虑到这一点,我不确定多线程在其中扮演什么角色(如果有的话)或者我的 reader 方法是否有缺陷。
在下面的例子中,你会看到 select 非常简单,因为它从一个 table 读取,连接到另一个,然后 selects 具有特定状态和给定日期范围内的行。
如果有帮助,请提供其他信息...
Springboot版本2.5.6,数据库使用java17,MySql
感谢您提供的任何建议或见解,因为我现在很困惑。
谢谢。
@Configuration
@EnableBatchProcessing
public class BuildOpenStatusConfigurationJob {
@Autowired
JobBuilderFactory jobBuilderFactory;
@Autowired
StepBuilderFactory stepBuilderFactory;
@Autowired
DataSource dataSource;
....
@Bean
public TaskExecutor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(12);
executor.setMaxPoolSize(16);
executor.setQueueCapacity(12);
executor.initialize();
return executor;
}
@Bean
public Step createStsActivity() {
return this.stepBuilderFactory.get("createStsActivity")
.<StsActivity, StsActivity>chunk(1000)
.reader(stsActivityItemReader(null, null))
.processor(stsActivityItemProcessor())
.writer(stsActivityItemWriter())
.taskExecutor(taskExecutorRows())
.throttleLimit(16)
.listener(statusStepExecutionListener())
.build();
}
@Bean
@StepScope
public JdbcPagingItemReader<StsActivity> stsActivityItemReader(
@Value("#{jobParameters['lowerDateThreshold']}") String lowerDateThreshold,
@Value("#{jobParameters['upperDateThreshold']}") String upperDateThreshold) {
JdbcPagingItemReader<StsActivity> pagingItemReader = new JdbcPagingItemReader<>();
pagingItemReader.setDataSource(dataSource);
pagingItemReader.setFetchSize(10000);
pagingItemReader.setPageSize(10000);
pagingItemReader.setRowMapper(new BeanPropertyRowMapper<>(StsActivity.class));
MySqlPagingQueryProvider mySqlPagingQueryProvider = new MySqlPagingQueryProvider();
mySqlPagingQueryProvider.setSelectClause(ta.statusId as statusId, tb.eventDate as maxEventDate, tb.id as maxEventId ");
mySqlPagingQueryProvider.setFromClause("FROM TableA ta"
+ "join TableB tb on tb.statusId = ta.statusId");
mySqlPagingQueryProvider.setWhereClause("WHERE tb.status = 'OPEN' "
+ "and (date(tb.eventDate) >= date('" + lowerDateThreshold + "') "
+ "and date(tb.eventDate) < date('" + upperDateThreshold + "'))");
Map<String, Order> orderByKeys = new HashMap<>();
orderByKeys.put("rbpai.statusId", Order.ASCENDING);
mySqlPagingQueryProvider.setSortKeys(orderByKeys);
pagingItemReader.setQueryProvider(mySqlPagingQueryProvider);
return pagingItemReader;
}
这已在 v4.3.4 中修复:https://github.com/spring-projects/spring-batch/issues/3898。
使用 Spring Boot 2.5.6,您将获得 Spring Batch v4.3.3,其中不包含修复程序。
如果您升级到包含 Batch 4.3.4+ 的启动版本,您的问题应该会得到解决。否则,它可能是一个回归。在这种情况下,请在 Github 上添加一条评论,其中包含重现该问题的 minimal complete example,我们将 re-open 进行调查。先谢谢你。