繁体   English   中英

分区作业完成后不能自行停止? 春批

[英]Partitioned Job can't stop by itself after finishing? Spring Batch

我写了一个两步作业,其中两步之一是分区步骤。 分区步骤使用 TaskExecutorPartitionHandler 并在线程中运行 5 个从步骤。 作业在 main() 方法中启动。 但它并没有在每个从属 ItemReader 返回 null 后停止 - 完成符号。 即使在程序运行通过 main() 方法(即 System.out.println("Finished"))中的最后一行代码之后,程序进程也不会停止,挂在内存中什么也不做。 我必须按下 Eclipse 面板上的停止按钮才能停止程序。

以下是 JobLauncher.run() 返回的 JobExecution 的内容,表示 Job 运行的成功状态。

JobExecution: id=0, version=2, startTime=Fri Nov 27 06:05:23 CST 2015, endTime=Fri Nov 27 06:05:39 CST 2015, lastUpdated=Fri Nov 27 06:05:39 CST 2015, status =COMPLETED, exitStatus=exitCode=COMPLETED;exitDescription=, job=[JobInstance: id=0, version=0, Job=[jobCensoredPages]], jobParameters=[{}]

7217
完成的

为什么运行成功的 Spring Batch 程序仍然挂起? 请指点我在哪里解决。 我怀疑 Spring Batch 管理的多线程部分不会停止..

简单的作业运行代码

        Job job = (Job) context.getBean("jobPages");
        try {
            JobParameters p=new JobParametersBuilder()
                .toJobParameters();
            
            JobExecution result = launcher.run(job, new JobParameters());
         
            System.out.println(result.toString());
        } catch (Exception e) {
            e.printStackTrace();
        }
        context.getBean("idSet");
        AtomicInteger n=(AtomicInteger) context.getBean("pageCount");
        System.out.println(n.get());        
        System.out.println("Finished");

Patitioner 和 PatitionHandler 的配置

    @Bean @Autowired 
    public PartitionHandler beanPartitionHandler(
        TaskExecutor beanTaskExecutor, 
        @Qualifier("beanStepSlave") Step beanStepSlave
        ) throws Exception
    {
        TaskExecutorPartitionHandler h=new TaskExecutorPartitionHandler();
        h.setGridSize(5);
        h.setTaskExecutor(beanTaskExecutor);
        h.setStep(beanStepSlave);   
        h.afterPropertiesSet(); 
        return h;
    }
    @Bean public TaskExecutor beanTaskExecutor() {
        ThreadPoolTaskExecutor e = new ThreadPoolTaskExecutor();
        e.setMaxPoolSize(5);
        e.setCorePoolSize(5);
        e.afterPropertiesSet();
        return e;
    }

唯一的一步,它是奴隶的一步

@Bean public Step beanStepMaster(
        Step beanStepSlave,
        Partitioner beanPartitioner,
        PartitionHandler beanPartitionHandler
        )   throws Exception 
    {
        return stepBuilderFactory().get("stepMaster")
        .partitioner(beanStepSlave)
        .partitioner("stepSlave", beanPartitioner)
        .partitionHandler(partitionHandler)
        .build();
    }
    @Bean @Autowired 
    public Step beanStepSlave(
        ItemReader<String> beanReaderTest,
        ItemProcessor<String, String> beanProcessorTest,
        ItemWriter<String> beanWriterTest) throws Exception{
        return stepBuilderFactory().get("stepSlave")
            .<String, String>chunk(1)
            .reader(beanReaderTest)
            .processor(beanProcessorTest)
            .writer(beanWriterTest)
            .build();
    }

我的 pom.xml 文件

<dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>RELEASE</version>
      <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-core</artifactId>
        <version>4.2.3.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>4.2.3.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-tx</artifactId>
        <version>4.2.3.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.batch</groupId>
        <artifactId>spring-batch-core</artifactId>
        <version>RELEASE</version>      
    </dependency>
    <dependency>
        <groupId>org.springframework.retry</groupId>
        <artifactId>spring-retry</artifactId>
        <version>1.1.2.RELEASE</version>
    </dependency>
    
<dependency>    
    <groupId>org.springframework</groupId>
    <artifactId>spring-beans</artifactId>
    <version>RELEASE</version>
</dependency>

当我使用 ThreadPoolTask​​Executor 时,我的分区 Spring 批处理应用程序在完成时也遇到了困难。 此外,我看到执行程序不允许所有分区的工作完成。

我找到了两种解决这些问题的方法。

第一个解决方案是使用 SimpleAsyncTaskExecutor 而不是 ThreadPoolTask​​Executor。 如果您不介意重新创建线程的额外开销,这是一个简单的解决方法。

第二种解决方案是创建一个 JobExecutionListener 来调用 ThreadPoolTask​​Executor 上的关闭。

我创建了一个这样的 JobExecutionListener:

@Bean
public JobExecutionListener jobExecutionListener(ThreadPoolTaskExecutor executor) {
    return new JobExecutionListener() {
        private ThreadPoolTaskExecutor taskExecutor = executor;
        @Override
        public void beforeJob(JobExecution jobExecution) {

        }

        @Override
        public void afterJob(JobExecution jobExecution) {
            taskExecutor.shutdown();
        }
    };
}

并将其添加到我的工作定义中,如下所示:

@Bean
public Job partitionedJob(){
    return jobBuilders.get("partitionedJob")
            .listener(jobExecutionListener(taskExecutor()))
            .start(partitionedStep())
            .build();
}

以上所有答案都是黑客/解决方法。 问题中发布的问题的根本原因是 threadPoolTask​​Executor 不共享步骤的生命周期。 因此,在销毁 step/job context 时,线程池不会自动销毁并且永远运行。 将 threadPoolExecutor 放在 stepContext "@StepScope" 中应该可以解决问题。 Spring 负责销毁它。

@Bean @StepScope public ThreadPoolTaskExecutor threadPoolTaskExecutor() {

您的问题有两种解决方案,尽管我不知道原因。

首先,您可以使用CommandLineJobRunner来启动Job 请参阅此处的文档。 此类在作业结束时自动退出程序,并将 ExitStatus 转换为返回码( COMPLETED = 0, FAILED = 1...)。 默认返回码由SimpleJvmExitCodeMapper提供。

第二种解决方案是在JobLauncher.run()之后手动调用System.exit()指令。 您还可以手动转换JobExitStatus并在手动退出时使用它:

// Create Job
JobLauncher jobLauncher = (JobLauncher) context.getBean("jobLauncher");
Job job = (Job) context.getBean(jobName);

// Create return codes mapper
SimpleJvmExitCodeMapper mapper = new SimpleJvmExitCodeMapper();

// Start Job
JobExecution execution = jobLauncher.run(job, new JobParameters());

// Close context
context.close();

// Map codes and exit
String status = execution.getExitStatus().getExitCode();
Integer returnCode = mapper.intValue(status);
System.exit(returnCode);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM