我的这个问题是对我另一个SO Question的扩展。由于这看起来不可能,我试图并行执行块并行/分区从属步骤。
Article表示只需将SimpleAsyncTaskExecutor
指定为步骤的任务执行程序即可开始并行执行块。
@Bean
public Step masterLuceneIndexerStep() throws Exception{
return stepBuilderFactory.get("masterLuceneIndexerStep")
.partitioner(slaveLuceneIndexerStep())
.partitioner("slaveLuceneIndexerStep", partitioner())
.gridSize(Constants.PARTITIONER_GRID_SIZE)
.taskExecutor(simpleAsyntaskExecutor)
.build();
}
@Bean
public Step slaveLuceneIndexerStep()throws Exception{
return stepBuilderFactory.get("slaveLuceneIndexerStep")
.<IndexerInputVO,IndexerOutputVO> chunk(Constants.INDEXER_STEP_CHUNK_SIZE)
.reader(luceneIndexReader(null))
.processor(luceneIndexProcessor())
.writer(luceneIndexWriter(null))
.listener(luceneIndexerStepListener)
.listener(lichunkListener)
.throttleLimit(Constants.THROTTLE_LIMIT)
.build();
}
如果我为slave步骤指定.taskExecutor(simpleAsyntaskExecutor)
则作业失败。主步骤中的行.taskExecutor(simpleAsyntaskExecutor)
正常工作,但块并行处理串行和分区步骤。
是否可以并行化slaveLuceneIndexerStep()
?
基本上,每个块都以顺序方式将Lucene索引写入单个目录,并且我希望进一步并行化每个目录中的索引编写过程,因为Lucene IndexWriter
是线程安全的。
答案 0 :(得分:0)
我可以通过以下方式从分区的从属步骤中启动并行块
1.我首先照顾我的读者,处理器和编写器是线程安全的,以便这些组件可以参与并行块而不会出现并发问题。
2.我将任务执行程序保留为主步骤为concurrencyLimit
,因为从属步骤长时间运行,我希望在某个时间点准确启动N线程。我通过设置任务执行器的ThreadPoolTaskExecutor
来控制N.
3.然后我将client_id
设置为slave步骤的任务执行程序。此池被所有从属步骤用作公共池,因此我将其核心池大小设置为最小值N,以便每个从属步骤至少获得一个线程,并且不会发生饥饿。您可以根据系统容量增加此线程池大小,并且我使用了线程池,因为块是较小的运行进程。
使用线程池还处理我的应用程序的特定情况我的分区是WAITING
所以当较小的客户端完成时,相同的线程会被更大的客户端自动重用,并且client_id分区创建的不对称性会被处理,因为数据到为每个客户处理的变化很大。
主步骤任务执行程序只是启动所有从属步骤线程并进入{{1}}状态,而从属步骤块由从属步骤中指定的线程池处理。