块导向处理
Spring Batch 在其最常见的实现中使用了“分块处理”的处理方式。分块处理指的是每次读取一条数据,并在事务边界内创建并写入 'chunks'(数据块)。一旦读取的项目数量等于提交间隔,整个数据块就会由 ItemWriter
写出,然后事务被提交。下图展示了该过程:
图1. 块导向处理
以下伪代码以简化的形式展示了相同的概念:
List items = new Arraylist();
for(int i = 0; i < commitInterval; i++){
Object item = itemReader.read();
if (item != null) {
items.add(item);
}
}
itemWriter.write(items);
你还可以通过可选的 ItemProcessor
配置一个基于块的步骤,在将项目传递给 ItemWriter
之前对其进行处理。下图显示了在步骤中注册 ItemProcessor
时的过程:
图 2. 基于块的处理与项处理器
以下伪代码展示了如何以简化形式实现这一过程:
List items = new Arraylist();
for(int i = 0; i < commitInterval; i++){
Object item = itemReader.read();
if (item != null) {
items.add(item);
}
}
List processedItems = new Arraylist();
for(Object item: items){
Object processedItem = itemProcessor.process(item);
if (processedItem != null) {
processedItems.add(processedItem);
}
}
itemWriter.write(processedItems);
如需了解更多关于项目处理器及其用例的详细信息,请参阅 Item processing 部分。
小节摘要
📄️ 配置步骤
尽管一个 Step 所需的依赖项列表相对较少,但它是一个极其复杂的类,可能包含许多协作者。
📄️ 继承自父级步骤
如果一组步骤共享类似的配置,那么定义一个“父”步骤可能是有帮助的,具体的步骤可以从该父步骤继承属性。类似于 Java 中的类继承,“子”步骤将其元素和属性与父步骤的元素和属性相结合。子步骤还会覆盖父步骤中的任何步骤。
📄️ 提交间隔
如前所述,一个步骤(step)通过提供的 PlatformTransactionManager 读取和写入项目,并定期提交。当 commit-interval 设置为 1 时,它会在写入每个单独的项目后提交。在许多情况下,这种方式并不理想,因为开始和提交事务的成本较高。理想情况下,最好在每次事务中处理尽可能多的项目,而这完全取决于所处理的数据类型以及步骤与之交互的资源。因此,您可以配置每次提交时处理的项目数量。
📄️ 配置步骤以供重新启动
在“配置和运行作业”部分,讨论了重启作业的问题。重启对步骤有诸多影响,因此可能需要一些特定的配置。
📄️ 配置跳过逻辑
在处理过程中,有许多场景下遇到的错误不应导致步骤失败,而是应该被跳过。这通常是一个需要由了解数据本身及其意义的人做出的决定。例如,财务数据可能不可跳过,因为它涉及资金转移,需要完全准确。而加载供应商列表则可能允许跳过。如果某个供应商因格式不正确或缺少必要信息而未被加载,通常不会产生问题。通常,这些错误记录也会被记录下来,这将在稍后讨论监听器时详细说明。
📄️ 配置重试逻辑
在大多数情况下,您希望异常导致跳过或步骤失败。然而,并非所有异常都是确定性的。如果在读取时遇到 FlatFileParseException,它总会针对该记录抛出。重置 ItemReader 并无帮助。然而,对于其他异常(例如 DeadlockLoserDataAccessException,它表示当前进程尝试更新另一个进程持有锁的记录),等待并重试可能会成功。
📄️ 控制回滚
默认情况下,无论是否重试或跳过,ItemWriter 抛出的任何异常都会导致 Step 控制的事务回滚。如果按照前面描述的方式配置了跳过功能,则 ItemReader 抛出的异常不会导致回滚。然而,在许多情况下,ItemWriter 抛出的异常不应该导致回滚,因为没有任何操作会使得事务无效。因此,您可以配置 Step 的一个异常列表,这些异常不会导致回滚。
📄️ 事务属性
你可以使用事务属性来控制隔离、传播和超时设置。你可以在 Spring 核心文档中找到有关设置事务属性的更多信息。
📄️ 注册 ItemStream 与 Step
该步骤必须在其生命周期的必要阶段处理 ItemStream 回调。 (有关 ItemStream 接口的更多信息,请参见 ItemStream)。 如果一个步骤失败并可能需要重新启动,这是至关重要的,因为 ItemStream 接口是步骤获取其在执行之间需要的持久状态信息的地方。
📄️ 拦截步骤执行
与 Job 一样,在 Step 的执行过程中有许多事件,用户可能需要在这些事件中执行某些功能。例如,对于需要写入尾部信息的平面文件,当 Step 完成时需要通知 ItemWriter,以便写入尾部信息。这可以通过许多作用于 Step 范围的监听器之一来实现。