我有带有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();
}
}
问题是,无论我想做什么-应用程序最多同时运行10个作业。我尝试使用TaskExecutor
进行实验-我的第一个逻辑选择是SimpleAsyncTaskExecutor
,它似乎藏起来了
每个多余的请求,然后以不希望的随机顺序运行它们。
因此,后来我尝试操纵该限制,并且如您在代码中所见,我开始使用ThreadPoolTaskExecutor
,例如,它允许我将限制设置为5,并且可以正常工作如预期的那样-最多可以同时运行5个线程,而在这5个线程运行时,下一个线程将被拒绝。但是,将限制设置为15会导致行为与上一个类似。尽管如此,第11个请求仍在排队,而第16个请求却被拒绝。这几乎是我的预期行为,但是我需要能够完全控制线程执行。
正在使用@RestController
通过jobLauncher.run()
调用作业。每个过多的请求都会导致浏览器加载,直到能够开始执行为止。似乎程序被冻结在jobLauncher.run()
内部的某个地方(当能够开始执行作业时,它就会退出-这就是异步运行的工作方式。)
答案 0 :(得分:1)
有点晚了,但请尝试检查您是否使用 HikariCP,它具有默认的 10 个同时数据库连接限制
刚刚遇到类似问题并通过增加 spring.datasource.hikari.maximum-pool-size
见:Number of parallel threads processing is capped to 10 with Spring Batch