我是第一次使用Spring批处理应用程序,由于框架太灵活,我有一些关于性能和实现工作的最佳实践的问题,我在 Spring 季文档中找不到明确的答案 .
我的目标:
-
读取具有固定列长度值的ASCII文件,该文件由具有先前指定布局的第三方发送(STEP 1阅读器)
-
验证读取值并注册(日志文件)错误(自定义消息)
-
在处理器上应用一些业务逻辑以过滤任何不需要的行(STEP 1处理器)
-
在oracle数据库上写入有效行(STEP 1 writer)
-
执行上一步后,使用步骤1完成时间戳更新数据库上的表(STEP 2 tasklet)
-
在作业停止时发送电子邮件,其中包含已处理数量的摘要,错误和书写行,开始时间和结束时间(这些信息是否在
jobRepository
元数据上?)
假设:
-
该文件是增量文件,因此第三方总是发送先前的文件行(可能有一些值更改)和任何新行(总共约120万行) . 每6个月发送一个新文件 .
-
我们必须验证处理时是否输入文件行(是否存在必需值?有些可以转换为数字和日期吗?)
-
作业必须是可停止/可重新启动的,因为它打算在时间窗口上运行 .
我打算做什么:
为了在读写方面取得一些性能,我避免使用Spring的开箱即用反射bean,并使用 jdbcBatchWriter
将处理过的行写入数据库 .
FileReader
使用自定义 FieldSetMapper
读取行,使用 FieldSet.readString
方法转换所有列(这意味着读取时没有 ParseException
) . 在处理器上注入的Bean执行解析和验证,因此这样我们可以避免在读取期间跳过异常,这似乎是一项昂贵的操作,并且可以计算无效行以通过将来的步骤,从而在步骤/作业执行上下文中保存信息 .
处理器bean应该将对象读取转换为包含原始对象的Wrapper,解析后的值(即Dates和Longs),解析引发的第一个最终Exception以及指示验证是否成功的布尔值 . 在解析另一个 CustomProcessor
之后,通过查询已经插入的类似或相同的寄存器来检查是否应该在数据库中插入寄存器 . 在最糟糕的情况下,此业务规则可能意味着在每个有效行的数据库中进行查询 .
jdbcItemWriter
丢弃处理器返回的空值,并将有效寄存器写入数据库 .
那么关于批处理的真正问题:
我可以使用哪些性能提示来改善批处理性能?在初步尝试中,将完美有效的模拟输入文件加载到数据库中导致15个小时的处理,而不查询数据库以验证是否应插入已处理的寄存器 . 什么是本地处理最简单的解决方案?
1 回答
你见过分区吗? http://docs.spring.io/spring-batch/reference/html/scalability.html这也许有帮助remote chunking with the control on reader in spring batch