【问题标题】:spring batch - multiResourceItemReader: how to make job parameters unique and restart jobspring batch - multiResourceItemReader:如何使作业参数唯一并重新启动作业
【发布时间】:2015-06-10 15:20:17
【问题描述】:

我正在使用 spring 批处理模块来处理目录中的 csv 文件。目录可能包含具有特定扩展名的多个文件,我正在使用 MultiResourceItemReader 来读取文件。 作业将接收 3 个作业参数,即 read_from_directory、move_to_directory 和 default_user_id。对于所有作业运行,所有这些参数都将保持不变。 read_from_directory 将包含 多个 csv 文件和作业应该一个接一个地处理这些文件。我面临的问题是,由于作业参数相同,我在第二次运行作业时收到 JobInstanceAlreadyCompleteException。我知道这个问题可以通过使用额外的时间戳参数来使作业参数独一无二来解决。但是由于添加时间戳参数将使每个作业实例都是唯一的,我不希望使用这种方法,因为它会在使我的作业可重新启动时产生问题。 所以我想提出一些建议,

  1. 如何在不使用时间戳参数的情况下使每个作业实例唯一。

  2. 在这种情况下如何使作业可重新启动?添加 'restartable="true"' 就足够了,或者我需要一些额外的配置/编码。我在这里有点困惑,因为作业将从一个目录中读取多个文件。因此,如果作业失败,例如,由于其中一个文件中的记录不正确,我如何从它离开的位置重新启动同一个作业?我已将作业配置为在一定时间间隔后使用调度程序定期运行。因此,如果作业失败,然后我纠正了 csv 文件中的错误,作业会在下次运行时从它停止的地方开始吗?

请从我的配置中找到以下相关部分:

<batch:job id="testJob" restartable="true">
        <batch:step id="step1">
            <batch:tasklet>
                <batch:chunk reader="multiResourceItemReader" writer="fileWriter"
                    commit-interval="1">
                </batch:chunk>
            </batch:tasklet>
        </batch:step>
    </batch:job>

    <bean id="fileWriter" class="com.ivish.TestFileWriter" />
    <bean id="multiResourceItemReader" class="org.springframework.batch.item.file.MultiResourceItemReader" scope="step">
        <property name="resources" value="file:#{jobParameters['read_from_directory']}/*.csv" />
        <property name="delegate" ref="fileReader" />
    </bean>

    <bean id="fileReader" class="com.ivish.TestFileReader" scope="step">
        <property name="delegate" ref="delegateFileReader" />
        <property name="moveToDirectory" value="#{jobParameters['move_to_directory']}" />
    </bean>
    <bean id="delegateFileReader" class="org.springframework.batch.item.file.FlatFileItemReader">
        <property name="lineMapper">
            <bean class="org.springframework.batch.item.file.mapping.DefaultLineMapper">
                <property name="lineTokenizer" ref="fileTokenizer" />
                <property name="fieldSetMapper">
                    <bean
                        class="org.springframework.batch.item.file.mapping.PassThroughFieldSetMapper" />
                </property>
            </bean>
        </property>
    </bean>         

谢谢。

【问题讨论】:

    标签: spring spring-batch


    【解决方案1】:

    Spring Batch 有两个与作业“运行”相关的不同概念,JobInstanceJobExecution

    JobInstance 是逻辑运行的概念。它由一组唯一的标识作业参数来标识。在您的示例中,我希望每个 read_from_directory、move_to_directory 和 default_user_id 组合都有一个 JobInstance

    另一个概念是JobExecution。这代表物理运行。例如,如果您运行 read_from_directory、move_to_directory 和 default_user_id 的组合并且它通过了,JobInstance 将有一个子JobExecution。但是,如果第一次尝试(第一次 JobExecution)失败,您可以重新启动作业。重新启动将在现有的JobInstance 下创建一个新的JobExecution(一个逻辑运行下的两个物理运行)。

    考虑到上述情况,每个JobInstance 将通过 read_from_directory、move_to_directory、default_user_id 和某种运行 id 的组合是唯一的(Spring Batch 提供了一个开箱即用的计数器,或者您可以使用时间戳)。

    您可以在此处的文档中阅读有关JobInstanceJobExecution 概念的更多信息:http://docs.spring.io/spring-batch/trunk/reference/html/domain.html#domainJob

    【讨论】:

      【解决方案2】:

      问题 1: 您可以使用自己的逻辑实现 JobParameterIncrementer,下一个实例对您来说是什么以及您希望如何增加参数。然后,您可以在根据您的逻辑运行下一个实例时运行您的作业的下一个实例,否则只需运行您将重新启动最新的实例。如果您以CommandLineJobRunner 开始工作,您可以传递-next 来运行下一个实例,如果您以编程方式执行此操作,则可以使用JobOperator#startNextInstance(String jobName)。这是example 代表JobParameterIncrementer

      问题 2: 对于可重启性,添加 restartable="true" 应该可以解决问题。 FlatFileItemReader 是读取文件的委托扩展 AbstractItemCountingItemStreamItemReader 在读取文件时保存状态。至于MultiResourceItemReader,您可以在documentation 上看到它说:

      使用 setComparator(Comparator) 对输入资源进行排序,以确保在重新启动场景中的作业运行之间保留资源排序。

      所以这意味着资源列表是有序的,每个资源都被委派给FlatFileItemReader,它保留了运行之间的顺序和计数。

      【讨论】:

        猜你喜欢
        • 2017-11-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-06-15
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多