Spring 服务器故障后恢复批处理文件
Spring batch file resume after Server failure
我已经配置 Spring 启动批处理来处理固定长度的平面文件。我使用 FlatFileItemReader、FixedLengthTokenizer 读取和拆分列,并使用 ItemWriter、JPA Repository 将数据写入数据库。
我遇到过这样的情况,我的服务器崩溃了或者在文件处理时停止了。此时已经处理了一半的文件(意味着一半的数据写入了DB)。当涉及到下一个作业时(当服务器 运行 启动时)文件必须从它停止的地方开始。
例如,一个文件有 1000 行,服务器在处理 500 行后关闭。在下一个作业中,文件必须从 501 行开始。
我在谷歌上搜索了解决方案,但没有相关内容。任何帮助表示赞赏。
据我所知,您所要求的(在块级别重启)不会自动存在于 Spring 批处理 API 中,并且程序员必须在 [=51] 上实现=] 拥有。
Spring Batch 通过 JobOperator.restart 提供作业重启功能。这是一个作业级别的重启,将为下一个 运行 创建一个新的执行 ID & 整个作业将重新 运行 因为还有其他问题,比如有人放入新文件或将现有文件重命名为代替旧文件进行处理,批处理如何知道其相同的输入文件内容明智或数据库自上次 运行 以来未更改?
由于这些问题,程序员必须通过自定义代码来处理这些情况。
第二个问题是,当服务器出现故障时,作业状态仍将是 STARTED
而不是 FAILED
,因为它突然发生并且框架无法正确更新状态。
您需要执行以下步骤,
1.Implement 一个自定义逻辑来决定上次作业执行是否成功或是否需要重新启动。
2.If 需要重新启动,将之前的作业执行标记为 FAILED
& 然后使用 JobOperator.restart(long executionId)
- 对于非分区作业,唯一有用的影响是标记作业状态与 FAILED
一样正确,但整个作业将从头开始。
有很多场景,例如,
a) 作业状态为 STARTED
但所有步骤都标记为 COMPELTED
etc
b) 对于分区作业,完成的步骤很少,失败的很少,启动的步骤很少等
3.If 不需要重新启动,使用 - JobLauncher.run 启动新作业。
因此,通过上述步骤,您会发现真正的块级作业重启并未实现,但上述步骤是您首先需要了解和实施的主要内容。
下一步是在作业重新启动时更改输入,即您设计一种机制将输入记录标记为 processed 已处理块(即读取、处理和写入)并有一个了解哪些输入记录未被处理的方法 - 然后在下一个作业 运行 中,您提供仍未处理的修改后的输入。所以这一切都将成为您的用例特定的自定义逻辑。
我不知道框架本身有任何内置机制可以实现这一点。对我来说,Job Restart 是一种全新的作业执行,具有修改/减少的输入。
我已经配置 Spring 启动批处理来处理固定长度的平面文件。我使用 FlatFileItemReader、FixedLengthTokenizer 读取和拆分列,并使用 ItemWriter、JPA Repository 将数据写入数据库。
我遇到过这样的情况,我的服务器崩溃了或者在文件处理时停止了。此时已经处理了一半的文件(意味着一半的数据写入了DB)。当涉及到下一个作业时(当服务器 运行 启动时)文件必须从它停止的地方开始。
例如,一个文件有 1000 行,服务器在处理 500 行后关闭。在下一个作业中,文件必须从 501 行开始。
我在谷歌上搜索了解决方案,但没有相关内容。任何帮助表示赞赏。
据我所知,您所要求的(在块级别重启)不会自动存在于 Spring 批处理 API 中,并且程序员必须在 [=51] 上实现=] 拥有。
Spring Batch 通过 JobOperator.restart 提供作业重启功能。这是一个作业级别的重启,将为下一个 运行 创建一个新的执行 ID & 整个作业将重新 运行 因为还有其他问题,比如有人放入新文件或将现有文件重命名为代替旧文件进行处理,批处理如何知道其相同的输入文件内容明智或数据库自上次 运行 以来未更改?
由于这些问题,程序员必须通过自定义代码来处理这些情况。
第二个问题是,当服务器出现故障时,作业状态仍将是 STARTED
而不是 FAILED
,因为它突然发生并且框架无法正确更新状态。
您需要执行以下步骤,
1.Implement 一个自定义逻辑来决定上次作业执行是否成功或是否需要重新启动。
2.If 需要重新启动,将之前的作业执行标记为 FAILED
& 然后使用 JobOperator.restart(long executionId)
- 对于非分区作业,唯一有用的影响是标记作业状态与 FAILED
一样正确,但整个作业将从头开始。
有很多场景,例如,
a) 作业状态为 STARTED
但所有步骤都标记为 COMPELTED
etc
b) 对于分区作业,完成的步骤很少,失败的很少,启动的步骤很少等
3.If 不需要重新启动,使用 - JobLauncher.run 启动新作业。
因此,通过上述步骤,您会发现真正的块级作业重启并未实现,但上述步骤是您首先需要了解和实施的主要内容。
下一步是在作业重新启动时更改输入,即您设计一种机制将输入记录标记为 processed 已处理块(即读取、处理和写入)并有一个了解哪些输入记录未被处理的方法 - 然后在下一个作业 运行 中,您提供仍未处理的修改后的输入。所以这一切都将成为您的用例特定的自定义逻辑。
我不知道框架本身有任何内置机制可以实现这一点。对我来说,Job Restart 是一种全新的作业执行,具有修改/减少的输入。