文章目录
分区原理
Spring Batch提供了一个SPI,用于对Step进行分区和远程执行。
在这种情况下,远程参与者只是Step实例,可以很容易地配置。
一个Step在左侧作为一系列子Step执行,其中在本地的Step被标记为Master。
图中的 Slave 都是一个Step的相同实例,对于整个Step来说,这些Slave的执行结果最终实际上等价于就是Master的结果
Slaves通常是远程服务,但也可能是本地执行线程。
Master在这种模式下发送给Slaves的消息不需要持久,或者保证交付:JobRepository中的Spring Batch元数据将确保每个Slave执行一次,每次Job执行只执行一次。因为它会持久化对应的Job上下文和Slave上下文。
如
BATCH_STEP_EXECUTION_CONTEXT
BATCH_JOB_EXECUTION_CONTEXT
分区Step
分区原理如下图所示
-
分区任务执行时调用
PationHandler
的handle()
方法。 -
PationHandler handle方法内会先调用
StepExecutionSplitter
把一个完整的Step按照某种规则分隔为多个子Step -
PationHandler 然后返回子Step的执行结果集合
-
PationStep 去汇总PartitionHandler的集合
源码解析
下面以PartitionHandler 和 PartitionStep 为入口探索一下这个处理过程
1. PartitionStep 的 execute 入口
/**
* @param stepExecution 这个分区step的masterStep
*/
protected void doExecute(StepExecution stepExecution) throws Exception {
// reduce 在这里的作用就是分区job的整个生命周期的扩展点
if(hasReducer) {
reducer.beginPartitionedStep();
}
// (1). 调用PartitionHandler执行业务逻辑,并且这是一个同步方法,会等待所有的结果返回,所以这里是否会出现一个问题,如果这个宕机了怎么办?
Collection<StepExecution> stepExecutions = getPartitionHandler().handle(null, stepExecution);
// (2). 更新masterStep的状态
stepExecution.upgradeStatus(BatchStatus.COMPLETED);
// (3). 聚集统计结果
stepExecutionAggregator.aggregate(stepExecution, stepExecutions);
// (4). 如果没有成功
if (stepExecution.getStatus().isUnsuccessful()) {
if (hasReducer) {
reducer.rollbackPartitionedStep();
reducer.afterPartitionedStepCompletion(PartitionStatus.ROLLBACK);
}
throw new JobExecutionException("Partition handler returned an unsuccessful step");
}
if (hasRe