Spring Batch 将并发线程数限制为 10

dom*_*don 5 java spring multithreading spring-batch spring-boot

我有带有 Spring Batch 框架的 Spring Boot 应用程序。我的目标很简单——同时运行某些工作。比方说,我希望能够同时运行 15 个线程并拒绝每个多余的线程。这是我的配置类:

import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.configuration.JobRegistry;
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.core.configuration.support.JobRegistryBeanPostProcessor;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.batch.core.launch.support.SimpleJobLauncher;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.task.TaskExecutor;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

@Configuration
@EnableBatchProcessing
public class GeneratingReportJobConfiguration {

    @Autowired
    private GeneratingReportTask task;

    @Autowired
    private JobRepository jobRepository;

    @Autowired
    private JobBuilderFactory jobBuilderFactory;

    @Autowired
    private StepBuilderFactory stepBuilderFactory;

    @Bean
    public JobRegistryBeanPostProcessor jobRegistryBeanPostProcessor(JobRegistry jobRegistry) {
        JobRegistryBeanPostProcessor jobRegistryBeanPostProcessor = new JobRegistryBeanPostProcessor();
        jobRegistryBeanPostProcessor.setJobRegistry(jobRegistry);
        return jobRegistryBeanPostProcessor;
    }

    @Bean
    public TaskExecutor taskExecutor() {
        ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
        taskExecutor.setCorePoolSize(15);
        taskExecutor.setMaxPoolSize(15);
        taskExecutor.setQueueCapacity(0);
        return taskExecutor;
    }

    @Bean
    public JobLauncher jobLauncher(TaskExecutor taskExecutor) {
        SimpleJobLauncher jobLauncher = new SimpleJobLauncher();
        jobLauncher.setJobRepository(jobRepository);
        jobLauncher.setTaskExecutor(taskExecutor);
        return jobLauncher;
    }

    @Bean
    public Job job() {
        return jobBuilderFactory.get("generatingReportJob")
                .start(step())
                .build();
    }

    @Bean
    public Step step() {
        return stepBuilderFactory.get("generatingReportTask")
                .tasklet(task)
                .build();
    }
}
Run Code Online (Sandbox Code Playgroud)

问题是,无论我想做什么 - 应用程序最多同时运行 10 个作业。我尝试过尝试TaskExecutor- 我的第一个合乎逻辑的选择是SimpleAsyncTaskExecutor,它似乎隐藏了所有过多的请求,然后以不符合预期的随机顺序运行它们。

所以后来我尝试操纵这个限制,正如你在代码中看到的,我开始使用ThreadPoolTaskExecutor,它允许我将限制设置为 5,例如,它按预期工作 - 最多 5 个线程可以同时运行,下一个在这 5 个运行时被拒绝。然而,将限制设置为 15 会导致与前一个类似的行为。尽管如此,第 11 个请求仍在排队,而第 16 个请求则被拒绝。这几乎是我的预期行为,但是我需要能够完全控制线程执行。

正在通过@RestController使用调用作业jobLauncher.run()。每个过多的请求都会导致浏览器加载,直到能够开始执行。看起来,程序被冻结在内部的某个地方jobLauncher.run()(当能够开始作业执行时,它就会退出 - 这就是异步运行的工作原理)。

小智 2

有点晚了,但请尝试检查您是否使用 HikariCP,它具有默认的 10 个并发数据库连接限制

刚刚遇到类似的问题并通过增加解决spring.datasource.hikari.maximum-pool-size

请参阅:Spring Batch 的并行线程处理数量上限为 10