【发布时间】:2017-04-19 08:16:52
【问题描述】:
我有一个 Spring Batch 应用程序 (3.0.7),它通过 Spring Boot 启动,它并行读取多个 XML 文件、处理它们,然后针对 Oracle DB “吐出” INSERT 或 UPDATE 语句。
为了并行处理文件,我使用了Partitioner。这项工作工作正常,除了JdbcWriter 似乎只绑定到一个线程。由于我使用的是ThreadPoolTaskExecutor,因此我希望 Step 可以为读取器、处理器和写入器并行运行。但是,似乎 JdbcWriter 总是绑定到Thread-1 (我可以在日志中看到,也可以在分析数据库连接时看到,只有一个连接处于活动状态 - 请注意,我的数据源配置为使用具有 20 个连接的池)。
我已将阅读器、处理器和编写器注释为@StepScope。如何有效地使用 taskExecutor 中的所有配置线程并行读取 AND WRITE?
这是我的配置摘录:
@Bean
public Job parallelJob() throws Exception {
return jobBuilderFactory.get("parallelJob")
.start(splitFileStep())
.next(recordPartitionStep())
.build();
}
@Bean
public Step recordPartitionStep() {
return stepBuilderFactory.get("factiva-recordPartitionStep")
.partitioner(recordStep())
.partitioner("recordStep", recordPartitioner(null)) <!-- this is used to inject some data from the job context
.taskExecutor(taskExecutor())
.build();
}
@Bean
public Step recordStep() {
return stepBuilderFactory.get("recordStep")
.<Object, StatementHolderMap>chunk(1000)
.reader(recordReader(null)) <!-- this is used to inject some data from the job context
.processor(recordProcessor) <!-- this is @Autowired, and the bean is marked as @StepScope
.writer(jdbcItemWriter())
.build();
}
@Bean
@StepScope
public ItemStreamReader recordReader(@Value("#{stepExecutionContext['record-file']}") Resource resource) {
// THIS IS A StaxEventItemReader
}
@Bean
@StepScope
public JdbcItemWriter jdbcItemWriter() {
JdbcItemWriter jdbcItemWriter = new JdbcItemWriter();
jdbcItemWriter.setDataSource(dataSource);
...
return jdbcItemWriter;
}
@Value("${etl.factiva.partition.cores}")
private int threadPoolSize;
@Bean
public TaskExecutor taskExecutor() {
ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
if (threadPoolSize == 0) {
threadPoolSize = Runtime.getRuntime().availableProcessors();
}
taskExecutor.setMaxPoolSize(threadPoolSize);
taskExecutor.afterPropertiesSet();
return taskExecutor;
}
【问题讨论】:
-
查看示例github.com/spring-projects/spring-batch/blob/master/… 这个示例从目录中读取所有文件并并行处理文件
-
您确认
TaskExecutor配置了多个线程吗?另外,您的DataSource是如何配置的?最后,您如何证明您只获得了一个执行线程? -
嗨迈克尔,该进程正在单线程运行。来自 writer 或 reader 的 log statements 始终绑定到 [thread-1]。我还可以看到,连接池中只有一个连接(共 20 个)用于执行 SQL 语句。
标签: spring multithreading spring-batch