配置 Step 以进行重启
在"配置和运行作业"部分中,讨论了重启Job的问题。重启会对步骤产生诸多影响,因此可能需要一些特定的配置。
设置启动限制
在许多场景中,您可能需要控制 Step 可以启动的次数。例如,您可能需要配置特定的 Step,使其仅运行一次,因为它会使某些资源失效,而这些资源必须手动修复后才能再次运行。此配置可在步骤级别进行设置,因为不同的步骤可能有不同的要求。一个只能执行一次的 Step 可以与一个可无限次运行的 Step 作为同一 Job 的一部分共存。
-
Java
-
XML
以下代码片段展示了 Java 中启动限制配置的示例:
@Bean
public Step step1(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
return new StepBuilder("step1", jobRepository)
.<String, String>chunk(10).transactionManager(transactionManager)
.reader(itemReader())
.writer(itemWriter())
.startLimit(1)
.build();
}
以下代码片段展示了 XML 中启动限制配置的示例:
<step id="step1">
<tasklet start-limit="1">
<chunk reader="itemReader" writer="itemWriter" commit-interval="10"/>
</tasklet>
</step>
前一个示例中显示的步骤只能运行一次。尝试再次运行它将导致抛出 StartLimitExceededException。请注意,start-limit 的默认值为 Integer.MAX_VALUE。
重启已完成的Step
对于可重启的作业,可能存在一个或多个步骤,无论它们首次执行是否成功,都必须始终运行。例如,验证步骤或在处理前清理资源的Step。在重启作业的正常处理过程中,任何状态为COMPLETED(表示已成功完成)的步骤将被跳过。将allow-start-if-complete设置为true可覆盖此行为,使该步骤始终运行。
-
Java
-
XML
以下代码片段展示了如何在 Java 中定义可重启的作业:
@Bean
public Step step1(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
return new StepBuilder("step1", jobRepository)
.<String, String>chunk(10).transactionManager(transactionManager)
.reader(itemReader())
.writer(itemWriter())
.allowStartIfComplete(true)
.build();
}
以下代码片段展示了如何在 XML 中定义可重启的作业:
<step id="step1">
<tasklet allow-start-if-complete="true">
<chunk reader="itemReader" writer="itemWriter" commit-interval="10"/>
</tasklet>
</step>
Step重启配置示例
-
Java
-
XML
以下 Java 示例展示了如何配置一个具有可重启步骤的作业:
@Bean
public Job footballJob(JobRepository jobRepository, Step playerLoad, Step gameLoad, Step playerSummarization) {
return new JobBuilder("footballJob", jobRepository)
.start(playerLoad)
.next(gameLoad)
.next(playerSummarization)
.build();
}
@Bean
public Step playerLoad(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
return new StepBuilder("playerLoad", jobRepository)
.<String, String>chunk(10).transactionManager(transactionManager)
.reader(playerFileItemReader())
.writer(playerWriter())
.build();
}
@Bean
public Step gameLoad(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
return new StepBuilder("gameLoad", jobRepository)
.allowStartIfComplete(true)
.<String, String>chunk(10).transactionManager(transactionManager)
.reader(gameFileItemReader())
.writer(gameWriter())
.build();
}
@Bean
public Step playerSummarization(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
return new StepBuilder("playerSummarization", jobRepository)
.startLimit(2)
.<String, String>chunk(10).transactionManager(transactionManager)
.reader(playerSummarizationSource())
.writer(summaryWriter())
.build();
}
以下 XML 示例展示了如何配置一个具有可重启步骤的作业:
<job id="footballJob" restartable="true">
<step id="playerload" next="gameLoad">
<tasklet>
<chunk reader="playerFileItemReader" writer="playerWriter"
commit-interval="10" />
</tasklet>
</step>
<step id="gameLoad" next="playerSummarization">
<tasklet allow-start-if-complete="true">
<chunk reader="gameFileItemReader" writer="gameWriter"
commit-interval="10"/>
</tasklet>
</step>
<step id="playerSummarization">
<tasklet start-limit="2">
<chunk reader="playerSummarizationSource" writer="summaryWriter"
commit-interval="10"/>
</tasklet>
</step>
</job>
前面的示例配置用于一个加载足球比赛信息并进行总结的作业。它包含三个步骤:playerLoad、gameLoad 和
playerSummarization。playerLoad 步骤从平面文件加载玩家信息,
而 gameLoad 步骤对游戏执行相同操作。最后一步,
playerSummarization,然后根据提供的游戏数据总结每位玩家的统计数据。假定由 playerLoad 加载的文件必须仅加载一次,而 gameLoad 可以加载特定目录中找到的任何游戏,并在成功加载到数据库后将其删除。因此,
playerLoad 步骤不包含额外的配置。它可以启动任意次数,如果已完成则跳过。然而,gameLoad 步骤需要每次运行,以防自上次运行以来添加了额外的文件。它已将
allow-start-if-complete 设置为 true 以始终启动。(假设游戏加载到的数据库表上有一个流程指示器,以确保汇总步骤能够正确找到新游戏)。汇总步骤,
这是任务中最重要的部分,被配置为起始限制为 2。这很有用,因为如果步骤持续失败,将会向控制作业执行的操作员返回一个新的退出代码,并且在人工干预之前无法重新启动。
此任务为本文档提供了一个示例,它与示例项目中找到的 footballJob 并不相同。 |
本节的其余部分描述了footballJob示例三次运行中每次发生的情况。
运行 1:
-
playerLoad运行并成功完成,向PLAYERS表中添加了 400 名玩家。 -
gameLoad运行并处理 11 个游戏数据文件,将其内容加载到GAMES表中。 -
playerSummarization开始处理,并在 5 分钟后失败。
运行 2:
-
playerLoad不运行,因为它已成功完成,且allow-start-if-complete为false(默认值)。 -
gameLoad再次运行并处理另外 2 个文件,将它们的内容也加载到GAMES表中(同时显示一个处理指示器,表明这些文件尚未被处理)。 -
playerSummarization开始处理所有剩余的游戏数据(使用处理指示器进行过滤),并在 30 分钟后再次失败。
运行 3:
-
playerLoad不运行,因为它已成功完成,且allow-start-if-complete为false(默认值)。 -
gameLoad再次运行并处理另外 2 个文件,将它们的内容也加载到GAMES表中(同时显示一个处理指示器,表明这些文件尚未被处理)。 -
playerSummarization尚未启动,该作业立即被终止,因为这是playerSummarization的第三次执行,而其限制仅为 2。必须提高限制,或将Job作为新的JobInstance执行。