Spring boot Spring批处理作业调度器在多次运行后停止执行
在一个项目中,我们必须运行一个定期启动的作业(现在QA env上每5分钟一次),为40k用户处理一些任务。 我们决定使用Spring批处理,因为它非常适合并使用几乎默认的配置实现它(例如,它在引擎盖下使用Spring boot Spring批处理作业调度器在多次运行后停止执行,spring-boot,spring-batch,scheduler,Spring Boot,Spring Batch,Scheduler,在一个项目中,我们必须运行一个定期启动的作业(现在QA env上每5分钟一次),为40k用户处理一些任务。 我们决定使用Spring批处理,因为它非常适合并使用几乎默认的配置实现它(例如,它在引擎盖下使用SyncTaskExecutor)。 好的,有一个作业由一个步骤组成: 开箱即用HibernatePagingItemReader 在内存中执行轻量级计算的自定义ItemProcessor 自定义ItemWriter,通过几个JPQL和本机查询将数据持久化到同一个PostgreSQL数据库 作业
SyncTaskExecutor
)。
好的,有一个作业由一个步骤组成:
HibernatePagingItemReader
ItemProcessor
ItemWriter
,通过几个JPQL和本机查询将数据持久化到同一个PostgreSQL数据库@EnableScheduling
进行调度,并且每5分钟由cron expression触发一次:
@Scheduled(cron=“${job.assignment rules}”)
void processAssignments(){
试一试{
调试(“正在运行分配处理作业”);
运行(assignmentProcessingJob,populateJobParameters());
}捕获(作业执行异常e){
日志错误(“作业处理失败”,e);
}
}
下面是application.yml
中的cron表达式:
job:
assignment-rules: "0 0/5 * * * *"
问题在于,在多次运行(每次运行的次数不同)后,它将停止计划。让我们来看看Spring批处理模式:
选择ex.job\u instance\u id、ex.create\u time、ex.start\u time、ex.end\u time、ex.status、ex.exit\u code、ex.exit\u message
从批处理作业执行ex内部联接批处理作业实例bji on ex.job\u instance\u id=bji.job\u instance\u id
按开始时间描述、作业实例描述、id描述排序;
然后是沉默。原木没有什么特别的。
我认为唯一有意义的是,在该实例上还有两个作业在运行。其中一个很耗时,因为它通过SMTP发送电子邮件。
整个作业计划是:
job:
invitation-email: "0 0/10 * * * *"
assignment-rules: "0 0/5 * * * *"
rm-subordinates-count: "0 0/30 * * * *"
各位同事,有谁能告诉我解决这个问题的方法吗
非常感谢您使用默认的
SyncTaskExecutor
启动作业在您的用例中并不安全,因为所有作业都将由单个线程执行。如果其中一个作业的运行时间超过5分钟,则下一个作业将堆积起来,无法在某个点启动
我会在您的用例中配置一个带有异步TaskExecutor
实现的JobLauncher
(比如org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor
)。您可以在本节中找到一个示例(请参见“图3.异步作业启动程序序列”)
除了配置为Spring Batch的
JobLauncher
使用的任务执行器之外,您还需要确保Spring Boot使用了正确的任务执行器来调度任务(因为您使用的是@EnableScheduling
)。有关更多详细信息,请参阅本节。我认为原因可能是spring批处理或计划程序未配置,但同样,两者都是“默认值”。似乎SyncTaskExecutor
是同步的,但它丢失了自以来计划的作业。如果您可以记录线程
,这将是一件非常棒的事情,默认情况下线程队列
很小,如果您自定义它可能会工作的话。“试试看!”乔纳桑霍克斯,这正是我整个上午一直在思考的问题。是的,看起来SMTP发送者持有该线程。我会尝试将其移动到单独的线程池,并且一定会让我知道这是否是原因,让我知道@IgorPetrov@JonathanJohx对不起,忘了联系你了。您是对的,问题出在同一个SyncTaskExecutor
调度的另一个长时间运行的任务中。将调度程序拆分为不同的线程解决了这个问题。谢谢