Spring Batch重新启动崩溃的作业

嗨 Spring 批用户,

关于文档http://docs.spring.io/spring-batch/reference/htmlsingle/#d5e1320

“如果进程死亡(”kill -9“或服务器故障),该作业当然没有运行,但是JobRepository无法知道,因为在进程死亡之前没有人告诉它 . ”

我试图通过使用找到并重新启动陈旧的作业执行

Set<JobExecution> jobExecutions = jobExplorer.findRunningJobExecutions(jobName);
...
jobExecution.setStatus(FAILED);
jobExecution.setEndTime(new Date());
jobRepository.update(jobExecution);
jobOperator.restart(jobExecution.getId());

但这似乎非常不方便 . 1)我必须在其他(新)工作开始之前这样做 . 2)我必须处理运行服务器的多个实例,因此findRunningJobExecutions将无法解决问题 .

您可以找到有关此主题的其他问题:https://jira.spring.io/browse/BATCH-2433?jql=project%20%3D%20BATCH%20AND%20status%20%3D%20Open%20ORDER%20BY%20priority%20DESC Spring Batch after JVM crash

我很想看到一个解决方案来注册“启动干净的工作听众” . 这仍然无法解决多服务器环境引起的问题,因为Spring批处理不知道STARTED标记的JobExecution是否未在另一个实例上运行 .

感谢Alex的任何建议

回答(1)

2 years ago

您的工作不能也不应该从 kill -9 方案中恢复"automatically" . kill -9 的处理方式与应用程序抛出一个被捕获的 Exception 的方式截然不同 . 这样做的原因是您已经有效地从应用程序下拉出地毯,而没有给它机会与数据库达到同步点,以便向 ExecutionContext 提交任何必要的信息或更新作业/步骤状态 . 因此,数据库的最后一个状态接触点将保留,作业仍将显示为 STARTED .

"OK, fine"你说,“但是如果我开始另一次执行,我希望它能够找到 STARTED 执行,然后从它停止的地方继续 . ”这里的问题是,应用程序没有干净的方法来区分正在运行的作业与已失败但无法启动数据库的作业 . 这里的框架在谨慎方面正确地犯了错误并阻止您启动已经运行的作业,这是一件好事 .

为什么?因为我们假设您的工作实际上仍在运行,并且您意外重新启动 . 编码后,框架将开始旋转,查看正在运行的执行并失败,并显示以下消息 A job execution for this job is already running . 由于有人意外地发起了两次工作,我已经被这个保存了!

如果你要实现你建议的监听器,那么第二次执行将被允许启动,你将有两个不同的JVM重复相同的工作,可能写入相同的文件/表并导致巨大的数据混乱,这是不可能的清理 .

相信我,如果Linux终端因为与数据库的连接被切断而终止您的工作或您的工作死亡,那么在您尝试重新启动之前,您需要注意这些执行状态 .

最后,在您实际想要杀死工作的机会中,您可以利用其他几种标准模式来停止工作:

Stop via throw Exception

Stop via JobOperator.stop()