【问题标题】:Tips to improve Simple Spring Batch Job Performance提高 Simple Spring Batch 作业性能的技巧
【发布时间】:2015-10-29 12:41:23
【问题描述】:

我是第一次使用 spring 批处理应用程序,由于框架过于灵活,我有一些关于性能和最佳实践的问题,我在 spring 文档中找不到明确的答案。

我的目标:

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

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

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

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

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

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

假设:

  1. 文件是增量文件,因此第三方总是发送之前的文件行(可能有一些值更改)和任何新行(总共约 1.2 亿行)。每 6 个月发送一个新文件。
  2. 我们必须在处理时验证输入文件行(是否存在必需的值?有些可以转换为数字和日期?)
  3. 作业必须是可停止/可重新启动的,因为它旨在在时间窗口上运行。

我打算做什么:

为了获得一些读写性能,我避免使用 Spring 的开箱即用反射 bean 并使用jdbcBatchWriter 将处理后的行写入数据库。

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

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

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

所以关于批处理的真正问题:

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

【问题讨论】:

  • 为了得到一个真正的基线,我会从一个简单的工作开始,它读取模拟文件并写入......什么都没有(无操作),这样你就可以得到文件系统的时间文件操作
  • @MichaelPralow 我尝试了你的建议,步骤的阅读部分花费了总时间的近 80%。这个值实际上是有意义的,因为我在没有主键的数据库表中写入读取行。我阅读了更多关于批处理的内容,由于我需要使作业可重新启动,我认为最好对输入数据进行分区并使用本地从属来处理每个分区。

标签: multithreading performance spring-batch partitioning


【解决方案1】:

【讨论】:

猜你喜欢
  • 2021-06-06
  • 2014-06-17
  • 2011-07-12
  • 1970-01-01
  • 1970-01-01
  • 2017-12-04
  • 1970-01-01
  • 1970-01-01
  • 2013-12-13
相关资源
最近更新 更多