我正在尝试春季批次。通过ItemReader和ItemWriter运行作业时,我看到了很多例子。如果作业运行没有错误,则没有问题。 但是,在处理了大量记录后,我还没有找到如何在作业失败时处理状态。
我的情景非常简单。从xml文件(ItemReader)读取记录并调用外部系统进行存储(ItemWriter)。那么,如果外部系统在流程中间不可用,并且一段时间后作业状态设置为FAILED,会发生什么?如果我在第二天手动重新启动作业,当外部系统启动并运行时,我将获得先前加载的记录的重复。
在某种程度上,我必须拥有跳过已加载记录的信息。 我试图通过ExecutionContext存储游标,但是当我重新启动作业时,我得到一个新的JOB_EXECUTION_ID并且游标数据丢失,因为在BATCH_STEP_EXECUTION_CONTEXT.SHORT_CONTEXT中获得了一个新行。重启时也会重置BATCH_STEP_EXECUTION.COMMIT_COUNT和BATCH_STEP_EXECUTION.READ_COUNT。
我使用JobOperator重新启动作业: jobOperator.restart(jobExecutionId);
是否有办法重新启动作业而不获取新的jobExecutionId或获取失败作业状态的交替方式。如果有人发现(可以提供)示例状态和错误处理,我会很高兴。
一个替代解决方案当然是创建我自己的表来保存已处理记录的跟踪,但我希望框架有一个这样的机制。否则,我不会用春季批次来理解这个想法。
此致 垫
答案 0 :(得分:2)
Spring Batch提供的主要功能之一是作业存储库中作业状态的持久性。当作业失败时,重新启动时,默认行为是作业在失败的步骤重新启动(跳过已成功完成的步骤)。在基于块的步骤中,我们的大多数读者(包括StaxEventItemReader
)存储了在作业存储库中处理的记录(特别是在ExecutionContext
内)。默认情况下,当基于块的步骤失败时,它会在上次失败的块上重新启动,跳过成功处理的块。
所有这一切的一个例子就是你有三步工作:
<job id="job1">
<step id="step1" next="step2">
<tasklet>
<chunk reader="reader1" writer="writer1" commit-interval="10"/>
</tasklet>
</step>
<step id="step2" next="step3">
<tasklet>
<chunk reader="reader2" writer="writer2" commit-interval="10"/>
</tasklet>
</step>
<step id="step3">
<tasklet>
<chunk reader="reader3" writer="writer3" commit-interval="10"/>
</tasklet>
</step>
</job>
让我们说这个作业完成step1,然后step2有1000个记录要处理但是在记录507处失败。由记录500-510组成的块将回滚并且作业将被标记为失败。重新启动该作业将跳过步骤1,在步骤2中跳过记录1-499并从步骤2的记录500开始(假设您正在使用有状态项目阅读器)。
关于重启时的jobExecutionId,Spring Batch具有作业实例(逻辑运行)和作业执行(物理运行)的概念。对于每天运行的作业,逻辑运行将是星期一运行,星期二运行等。其中每个都由它们自己的JobInstance
组成。如果作业成功,JobInstance
最终只会与其关联一个JobExecution
。如果失败并重新运行,则会为作业重新启动的每个时间创建一个新的JobExecution
。
您可以在此处的Spring Batch文档中详细了解错误处理和特定方案:http://docs.spring.io/spring-batch/trunk/reference/html/index.html