我的这个问题是对我另一个问题的延伸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();
}
如果我指定, .taskExecutor(simpleAsyntaskExecutor)
为奴隶步骤,则作业失败 . 主步骤中的行 .taskExecutor(simpleAsyntaskExecutor)
工作正常,但块并行处理串行和分区步骤 .
是否可以并行化 slaveLuceneIndexerStep()
的块?
基本上,每个块都以顺序方式将Lucene索引写入单个目录,并且我希望进一步并行化每个目录中的索引编写过程,因为Lucene IndexWriter
是线程安全的 .
1 回答
我可以通过以下方式从分区的从属步骤中启动并行块,
1.我首先照顾我的读者,处理器和编写器是线程安全的,以便这些组件可以参与并行块而不会出现并发问题 .
2.我将任务执行程序保留为主步骤为
SimpleAsyntaskExecutor
,因为从属步骤长时间运行,我希望在某个时间点准确启动N线程 . 我通过设置任务 Actuator 的concurrencyLimit
来控制N.然后我将
ThreadPoolTaskExecutor
设置为slave步骤的任务执行程序 . 此池被所有从属步骤用作公共池,因此我将其核心池大小设置为最小值N,以便每个从属步骤至少获得一个线程并且不会发生饥饿 . 您可以根据系统容量增加此线程池大小,并且我使用了线程池,因为块是较小的运行进程 .使用线程池还可以处理我的应用程序的特定情况,即我的分区是
client_id
所以当较小的客户端完成时,较大的客户端会自动重用相同的线程,并且处理client_id分区创建的不对称因为每个客户端要处理的数据会有所不同许多 .主步骤任务执行程序只是启动所有从属步骤线程并进入
WAITING
状态,而从属步骤块由从属步骤中指定的线程池处理 .