Spring batch Spring批处理:java配置文件中的并行步骤执行

Spring batch Spring批处理:java配置文件中的并行步骤执行,spring-batch,Spring Batch,我试图在java配置文件中创建一个关于并行步骤执行的示例应用程序,但对于有多少文件(作业存储库、作业启动程序和执行等)正在配置和初始化以及如何配置感到困惑? 简单地说,我需要一个示例应用程序来阐明作业中步骤并行执行的基本原理。这里是不同数据集上的基本并行步骤执行,基本上您必须提供一个分区器,它将为每个步骤创建seprate上下文,并基于上下文,您可以处理其数据集 <batch:job id="myJob" job-repository="jobRepository">

我试图在java配置文件中创建一个关于并行步骤执行的示例应用程序,但对于有多少文件(作业存储库、作业启动程序和执行等)正在配置和初始化以及如何配置感到困惑?
简单地说,我需要一个示例应用程序来阐明作业中步骤并行执行的基本原理。

这里是不同数据集上的基本并行步骤执行,基本上您必须提供一个分区器,它将为每个步骤创建seprate上下文,并基于上下文,您可以处理其数据集

<batch:job id="myJob" job-repository="jobRepository">
                <batch:step id="master">
                    <batch:partition step="step1" partitioner="stepPartitioner ">
                        <batch:handler grid-size="4" task-executor="taskExecutor"/>
                    </batch:partition>
                </batch:step>

            </batch:job>

        <batch:step id="step1">
                <batch:tasklet>
                    <batch:chunk reader="myReader" processor="myProcessor" writer="myWriter"
                                 commit-interval="10"/>
                </batch:tasklet>
            </batch:step>


    public class stepPartitioner implements Partitioner {

        @Autowired
        DaoInterface daoInterface;

        @Override
        public Map<String, ExecutionContext> partition(int i) {
            Map<String, ExecutionContext> result = new HashMap<>();

            List<String> keys= daoInterface.getUniqueKeyForStep();
            for(String key: keys){


                    ExecutionContext executionContext = new ExecutionContext();
                    executionContext.putString("key", key);

                    result.put(key,executionContext);


            }

            return result;
        }
    }

公共类stepPartitioner实现了分区器{
@自动连线
dao接口dao接口;
@凌驾
公共地图分区(int i){
映射结果=新的HashMap();
List keys=daoInterface.getUniqueKeyForStep();
用于(字符串键:键){
ExecutionContext ExecutionContext=新的ExecutionContext();
putString(“key”,key);
result.put(key,executionContext);
}
返回结果;
}
}

下面是一个通过java配置使用拆分的示例。在此示例中,流1和2将并行执行:

@Configuration
public class BatchConfiguration {

    @Autowired
    private JobBuilderFactory jobBuilderFactory;

    @Autowired
    private StepBuilderFactory stepBuilderFactory;

    @Bean
    public Tasklet tasklet() {
        return new CountingTasklet();
    }

    @Bean
    public Flow flow1() {
        return new FlowBuilder<Flow>("flow1")
                .start(stepBuilderFactory.get("step1")
                        .tasklet(tasklet()).build())
                .build();
    }

    @Bean
    public Flow flow2() {
        return new FlowBuilder<Flow>("flow2")
                .start(stepBuilderFactory.get("step2")
                        .tasklet(tasklet()).build())
                .next(stepBuilderFactory.get("step3")
                        .tasklet(tasklet()).build())
                .build();
    }

    @Bean
    public Job job() {
        return jobBuilderFactory.get("job")
                .start(flow1())
                .split(new SimpleAsyncTaskExecutor()).add(flow2())
                .end()
                .build();
    }

    public static class CountingTasklet implements Tasklet {

        @Override
        public RepeatStatus execute(StepContribution stepContribution, ChunkContext chunkContext) throws Exception {
            System.out.println(String.format("%s has been executed on thread %s", chunkContext.getStepContext().getStepName(), Thread.currentThread().getName()));
            return RepeatStatus.FINISHED;
        }
    }
}
@配置
公共类批处理配置{
@自动连线
私人JobBuilderFactory JobBuilderFactory;
@自动连线
私人StepBuilderFactory StepBuilderFactory;
@豆子
公共Tasklet Tasklet(){
返回新的CountingTasklet();
}
@豆子
公共流量1(){
返回新的FlowBuilder(“flow1”)
.start(stepBuilderFactory.get(“step1”)
.tasklet(tasklet()).build())
.build();
}
@豆子
公共流量2(){
返回新的FlowBuilder(“flow2”)
.start(stepBuilderFactory.get(“step2”)
.tasklet(tasklet()).build())
.next(stepBuilderFactory.get(“step3”)
.tasklet(tasklet()).build())
.build();
}
@豆子
公职{
返回jobBuilderFactory.get(“作业”)
.start(flow1())
.split(新的SimpleAsyncTaskExecutor()).add(flow2())
(完)
.build();
}
公共静态类CountingTasklet实现Tasklet{
@凌驾
public RepeatStatus execute(StepContribution StepContribution,ChunkContext ChunkContext)引发异常{
System.out.println(String.format(“%s”已在线程%s上执行),chunkContext.getStepContext().getStepName(),thread.currentThread().getName());
返回RepeatStatus.FINISHED;
}
}
}

假设您有步骤A、B1、B2、B3、C。您希望并行运行B1、B2和B3。首先需要为它们创建子流,然后使用SimpleAsynctAskeExecutor()将其添加到一个流中:

@Bean
公职
{
最终流flowB1=新的FlowBuilder(“子流B1”)。从(stepb1()).end();
最终流flowB2=新的FlowBuilder(“子流B2”)。从(步骤B2()).end();
最终流flowB3=新的FlowBuilder(“子流B3”)。来自(步骤B3())。结束();
最终流量拆分流量=新流量生成器(“拆分流量”)
.启动(流程B1)
.split(新的SimpleAsyncTaskExecutor())
.add(flowB2,flowB3).build();
返回jobBuilderFactory
.flow(stepA())
.下一步(分流)
.next(stepC())
(完)
.build();
}

这不是javaconfig示例Yeah@sandeep这不是javaconfig示例。。我需要javaconfig.Yes中的所有内容。因为我只想知道多个步骤如何并行运行。因此,这给了我一个想法。@MichaelMinella我有一个场景,其中流的数量取决于表中的行数。因此,每个流都应该以每一行作为输入来运行。有没有办法做到这一点?这就是答案!如果需要,也不需要设置tasklet。在每个步骤中,它都可以在没有tasklet的情况下工作also@NitishKumar您的评论是对我的吗?@Ganapathi004 noth语法有点混乱:在开始时调用flowB1,然后调用split,然后添加确保所有3个都并行运行,还是只运行B2和B3?
@Bean
public Job job()
{
    final Flow flowB1 = new FlowBuilder<Flow>("subflowb1").from(stepb1()).end();
    final Flow flowB2 = new FlowBuilder<Flow>("subflowb2").from(stepb2()).end();
    final Flow flowB3 = new FlowBuilder<Flow>("subflowb3").from(stepb3()).end();

    final Flow splitFlow = new FlowBuilder<Flow>("splitFlow")
        .start(flowB1)
        .split(new SimpleAsyncTaskExecutor())
        .add(flowB2, flowB3).build();

    return jobBuilderFactory
       .flow(stepA())
       .next(splitFlow)
       .next(stepC())
       .end()
       .build();
}