提高简单弹簧批处理作业性能的技巧

时间:2015-10-29 12:41:23

标签: multithreading performance spring-batch partitioning

我第一次使用Spring批处理应用程序,由于框架太灵活,我对实现工作的性能和最佳实践有一些问题,我在春季文档中找不到明确的答案。 / p>

我的目标:

  1. 读取具有固定列长度值的ASCII文件,该文件由具有先前指定布局的第三方发送(步骤1阅读器)

  2. 验证读取值并注册(日志文件)错误(自定义消息)

  3. 在处理器上应用一些业务逻辑以过滤任何不需要的行(STEP 1处理器)

  4. 在oracle数据库(STEP 1 writer)上编写有效行

  5. 执行上一步后,使用步骤1完成时间戳(步骤2 tasklet)更新数据库上的表

  6. 在作业停止时发送电子邮件,其中包含已处理数量的摘要,错误和书写行,开始时间和结束时间(这些信息是jobRepository元数据吗?)< / p>

  7. 假设:

    1. 该文件是递增的,因此第三方总是发送先前的文件行(可能有一些值更改)和任何新行(总共~120万行)。每6个月发送一个新文件。
    2. 我们必须在处理时验证输入文件行是否存在(是否存在必需值?有些可以转换为数字和日期吗?)
    3. 作业必须是可停止/可重新启动的,因为它打算在时间窗口上运行。
    4. 我打算做什么:

      为了在读写方面取得一些成绩,我避免使用Spring的开箱即用反射bean,并使用jdbcBatchWriter将处理过的行写入数据库。

      FileReader使用自定义FieldSetMapper读取行,使用FieldSet.readString方法转换所有列(这意味着读取时没有ParseException)。在处理器上注入的Bean执行解析和验证,因此这样我们可以避免在读取过程中跳过异常,这似乎是一项昂贵的操作,并且可以计算无效行以通过将来的步骤,从而在步骤/作业执行上下文中保存信息。 / p>

      处理器bean应该转换对象读取返回包含原始对象的Wrapper,解析后的值(即Dates和Longs),解析引发的第一个最终异常以及指示验证是否成功的布尔值或不。在解析另一个CustomProcessor之后,通过查询已经插入的相似或相同的寄存器来检查是否应该在数据库中插入寄存器。在最糟糕的情况下,此业务规则可能意味着在每个有效行的数据库中进行查询。

      A jdbcItemWriter会丢弃处理器返回的空值,并将有效寄存器写入数据库。

      关于批处理的真正问题:

      我可以使用哪些性能提示来改善批处理性能?在初步尝试中,将完美有效的模拟输入文件加载到数据库中导致15个小时的处理,而不查询数据库以验证是否应插入已处理的寄存器。什么是本地处理最简单的解决方案?