Конечная резьба с разделителем Spring Batch - PullRequest
0 голосов
/ 06 марта 2019

Пакетное приложение My Spring потребляет слишком много ресурсов (+4 к Ram).

Когда я смотрю на jvm, приложение создает 10 потоков.

  • Я использую разделитель для обработки файла за файлом без планировщика
  • jobExecutionListener используется для остановки пакета в конце выполнения

    @Bean
    public Job mainJob() throws IOException {
    SimpleJobBuilder mainJob = this.jobBuilderFactory.get("mainJob")
                .start(previousStep())    
                .next(partitionStep())
                .next(finalStep())
                .listener(jobExecutionListener(taskExecutor()));;
        return mainJob.build();
    }
    
    @Bean
    public Step partitionStep() throws IOException {
        Step mainStep = stepBuilderFactory.get("mainStep")
                .<InOut, InOut>chunk(1)
                .reader(ResourceReader())
                .processor(processor())
                .writer(itemWriter())
                .build();
    
        return this.stepBuilderFactory.get("partitionStep")
                .partitioner(mainStep)
                .partitioner("mainStep", partitioner())
                .build();
    }
    
    @Bean(name = "taskExecutor")
    public ThreadPoolTaskExecutor taskExecutor() {
        ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
        taskExecutor.setCorePoolSize(1);
        taskExecutor.setMaxPoolSize(1);
        taskExecutor.setQueueCapacity(1);
        taskExecutor.setThreadNamePrefix("MyBatch-");
        taskExecutor.initialize();
    
        return taskExecutor;
    }
    
    //This jobExecutionListener stop the batch
    @Bean
    public JobExecutionListener jobExecutionListener(@Qualifier("taskExecutor") 
    ThreadPoolTaskExecutor executor) {
        return new JobExecutionListener() {
            private ThreadPoolTaskExecutor taskExecutor = executor;
            @Override
            public void beforeJob(JobExecution jobExecution) {
            }
    
            @Override
            public void afterJob(JobExecution jobExecution) {
                taskExecutor.shutdown();
                System.exit(0);
            }
        };
    }
    
    @Bean
    public Partitioner partitioner() {
        MultiResourcePartitioner partitioner = new MultiResourcePartitioner();
        ResourcePatternResolver patternResolver = new 
        PathMatchingResourcePatternResolver();
    
        try {
            partitioner.setResources(patternResolver.getResources(FILE + 
        configProperties.getIn()+ "/*.xml"));
        } catch (IOException e) {
            throw new RuntimeException("I/O problems when resolving the input file pattern.",e);
        }
        partitioner.setKeyName("file");
        return partitioner;
    }
    

Как я могу применить свое приложение в монопоточности? Taskexecutor не работает.

1 Ответ

1 голос
/ 06 марта 2019

Ваше приложение создает 10 потоков, но это не обязательно потоки Spring Batch. Согласно вашей конфигурации, должен быть создан только один поток с префиксом MyBatch-.

Кроме того, вы объявили исполнителя задач как компонент, но не задали его на шаге разбиения. Ваш partitionStep должен выглядеть примерно так:

@Bean
public Step partitionStep() throws IOException {
   Step mainStep = stepBuilderFactory.get("mainStep")
        .<InOut, InOut>chunk(1)
        .reader(ResourceReader())
        .processor(processor())
        .writer(itemWriter())
        .build();

   return this.stepBuilderFactory.get("partitionStep")
        .step(mainStep) // instead of .partitioner(mainStep)
        .partitioner("mainStep", partitioner())
        .taskExecutor(taskExecutor())
        .build();
}

Как я могу применить свое приложение в мононитях? Taskexecutor не работает.

После установки исполнителя задач на шаг с разделами вы должны увидеть, что этот шаг выполняется единственным потоком, как определено в ThreadPoolTaskExecutor. Однако я не вижу преимущества использования одного потока для шага с разделами, потому что обычной целью такой установки является обработка разделов параллельно (локально с несколькими потоками или удаленно с несколькими рабочими JVM).

В качестве примечания, хорошо, что вы выключаете исполнителя задач с помощью прослушивателя Job в afterJob, но не System.exit. Вы должны позволить корректно завершить работу JVM.

Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...