如何控制并行Spring批处理作业的数量
How to control the number of parallel Spring Batch jobs
我有一个报告生成应用程序。由于准备此类报告是重量级的,因此使用 Spring Batch 异步准备它们。此类报告的请求是使用 HTTP 通过 REST 接口创建的。
目标是 REST 资源只是将报告执行排队并完成 (as described in documentation)。因此,为 JobLauncher 提供了一个 TaskExecutor:
<bean id="jobLauncher" class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
<property name="jobRepository" ref="jobRepository" />
<property name="taskExecutor">
<bean class="org.springframework.core.task.SimpleAsyncTaskExecutor"/>
</property>
</bean>
由于报告非常重量级,在给定时间只能生成指定数量的报告。希望能够配置 Spring Batch 一次只生产 2 个实例,已指定 concurrencyLimit:
<bean id="jobLauncher" class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
<property name="jobRepository" ref="jobRepository" />
<property name="taskExecutor">
<bean class="org.springframework.core.task.SimpleAsyncTaskExecutor">
<property name="concurrencyLimit" value="2" />
</bean>
</property>
</bean>
不幸的是,当 2 个作业已经 运行 时,启动作业调用被阻止:
jobLauncher.run(工作,builder.toJobParameters());
显然 jobLauncher 会立即尝试执行作业。我想它宁愿在线程可用时立即排队执行作业。这样我就可以通过简单地添加额外的处理实例来扩展我的应用程序,所有这些都使用相同的作业存储库数据库。
类似的问题是 asked here. I'm about to start exploring Spring Batch Integration,但我不确定这是否是正确的方向。
我的用例对我来说似乎并不罕见,难道不应该有一个我显然找不到的广泛讨论的模式吗?
谢谢
f
SimpleAsyncTaskExecutor
不建议大量使用,因为它会为每个任务生成一个新线程。它也不支持更强大的概念,如线程池和任务队列。
如果您查看 ThreadPoolTaskExecutor
,它支持更强大的任务执行范例,例如任务排队和使用线程池而不是生成随机的、未重用的线程。
您可以在此处的 javadoc 中阅读有关 ThreadPoolTaskExecutor
的更多信息:http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/scheduling/concurrent/ThreadPoolTaskExecutor.html
很有帮助,非常感谢。更换 SimpleAsyncTaskExecutor 后,我得到了我需要的东西。代码:
@Bean
public TaskExecutor jobLauncherTaskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setMaxPoolSize(executorsPoolSize);
executor.setCorePoolSize(executorsPoolSize);
return executor;
}
谢谢
f
我有一个报告生成应用程序。由于准备此类报告是重量级的,因此使用 Spring Batch 异步准备它们。此类报告的请求是使用 HTTP 通过 REST 接口创建的。
目标是 REST 资源只是将报告执行排队并完成 (as described in documentation)。因此,为 JobLauncher 提供了一个 TaskExecutor:
<bean id="jobLauncher" class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
<property name="jobRepository" ref="jobRepository" />
<property name="taskExecutor">
<bean class="org.springframework.core.task.SimpleAsyncTaskExecutor"/>
</property>
</bean>
由于报告非常重量级,在给定时间只能生成指定数量的报告。希望能够配置 Spring Batch 一次只生产 2 个实例,已指定 concurrencyLimit:
<bean id="jobLauncher" class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
<property name="jobRepository" ref="jobRepository" />
<property name="taskExecutor">
<bean class="org.springframework.core.task.SimpleAsyncTaskExecutor">
<property name="concurrencyLimit" value="2" />
</bean>
</property>
</bean>
不幸的是,当 2 个作业已经 运行 时,启动作业调用被阻止: jobLauncher.run(工作,builder.toJobParameters());
显然 jobLauncher 会立即尝试执行作业。我想它宁愿在线程可用时立即排队执行作业。这样我就可以通过简单地添加额外的处理实例来扩展我的应用程序,所有这些都使用相同的作业存储库数据库。
类似的问题是 asked here. I'm about to start exploring Spring Batch Integration,但我不确定这是否是正确的方向。
我的用例对我来说似乎并不罕见,难道不应该有一个我显然找不到的广泛讨论的模式吗?
谢谢 f
SimpleAsyncTaskExecutor
不建议大量使用,因为它会为每个任务生成一个新线程。它也不支持更强大的概念,如线程池和任务队列。
如果您查看 ThreadPoolTaskExecutor
,它支持更强大的任务执行范例,例如任务排队和使用线程池而不是生成随机的、未重用的线程。
您可以在此处的 javadoc 中阅读有关 ThreadPoolTaskExecutor
的更多信息:http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/scheduling/concurrent/ThreadPoolTaskExecutor.html
很有帮助,非常感谢。更换 SimpleAsyncTaskExecutor 后,我得到了我需要的东西。代码:
@Bean
public TaskExecutor jobLauncherTaskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setMaxPoolSize(executorsPoolSize);
executor.setCorePoolSize(executorsPoolSize);
return executor;
}
谢谢 f