【问题标题】:Spring batch state when steps fails步骤失败时的 Spring 批处理状态
【发布时间】:2014-12-30 12:57:51
【问题描述】:

我正在尝试春季批次。通过 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 的情况下重新启动作业或获取失败作业的状态的替代方法。如果有人找到(可以提供)包含状态和错误处理的示例,我会很高兴。

当然,另一种解决方案是创建我自己的表来跟踪已处理的记录,但我真的希望该框架有一个机制。否则我不理解 spring-batch 的想法。

问候 垫子

【问题讨论】:

    标签: spring-batch


    【解决方案1】:

    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>
    

    假设此作业完成了第 1 步,然后第 2 步有 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

    【讨论】:

    • 感谢支持!我的问题更多是关于将状态保持在一个块内。我的工作只有一步,看起来像这样: 读者读取 xml 而作者更新外部资源。 spring-batch 是否仍然支持块内的状态(如果我重新启动作业,如果作业在前一天的处​​理过程中失败,则跳过一些 xml 记录)?也许替代方案是有两个步骤而不是任何块?
    • 我以JobExecution 为例,但是StepExecution(及其相关的ExecutionContext)在一个步骤中保持状态,包括逐块。在每个 chunk 提交之后,step 的状态(包括已经读取了多少条记录等)被持久化到作业存储库中,这样如果发生故障,重新启动时将跳过已经处理的记录。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-21
    • 2021-10-25
    • 2016-10-11
    • 1970-01-01
    相关资源
    最近更新 更多