Spring Batch 2.0 新特性概览

工程 | Dave Syer | 2008年10月21日 | ...

本文概述了Spring Batch 2.0的主要主题,并重点介绍了与1.x版本的区别。新版本的开发工作正在顺利进行,上周发布了M2版本,我们收到了很多关注,因此现在似乎是提供一些提示的好时机。

Spring Batch 2.0 主题

新版本的主要四个主题是

  • Java 5 和 Spring 3.0
  • 非顺序执行
  • 可扩展性
  • 配置:注解和 XML 命名空间
因此,我们将分别介绍这些方面,并描述它们的含义以及更改对现有 Spring Batch 用户的影响。下面将详细介绍已实现的功能,这些功能主要属于第一类,其他领域也有一些启用功能。

Spring Batch 2.0.0.M2 中项目的物理布局没有变化(相同的旧下载,相同的 Java 包基本布局)。我们没有删除任何功能,但我们借此机会修改了一些 API,并且对于从 1.x 升级项目的用户来说,有一些细微的更改。Spring Batch 还处于发展初期,我们正在添加一些非常重要的功能,因此我们认为进行主要版本更改是进行一些清理的好机会。我们预计任何人都不会遇到升级困难,如果您是现有用户,本文将帮助您了解这些更改。

Java 5 和 Spring 3.0

您可能知道,Spring 3.0 将是第一个专门针对 Java 5 的 Spring 主要版本(我将留给 Juergen 和 Arjen 详细说明)。现在 Sun 已在 JDK 1.4 上加盖了“服务生命周期结束”的印章,这似乎是合适的,并且 Spring 3.0 有些很棒的新功能,我们希望利用这些功能。

类型安全

Spring Batch 2.0.0.M1 版本的大部分工作都用于将现有代码转换为 Java 5,并在可能的情况下利用泛型和参数化类型。这为框架用户提供了更好的编程体验,允许编译时进行类型安全检查,并最终降低使用 Spring Batch 的项目的维护成本。例如,在ItemReader中,它是 Spring Batch 中的核心接口和用户扩展点之一,我们现在拥有类型安全的read方法

public interface ItemReader<S> {
    S read();
}

这里需要进一步注意的是,旧的 (1.x) 框架回调mark()reset()已从该接口中移除,使之更易于最终用户使用,并避免对框架要求和何时要求的误解。相同的关注点(或标记和重置)现在在框架提供的Step实现中内部处理。

面向块的处理

类似的更改,以及一个稍微激进的更改,也发生在合作伙伴ItemWriter接口中,框架使用该接口写入数据


public interface ItemWriter<T> {
    void write(List<? extends T> items);
}

旧的框架回调flush()clear()也已从该接口中移除,为了弥补这一点,write()方法具有新的签名。这里的底线是我们已转向框架内部的面向块的处理范式。这实际上在批处理框架中比旧的面向项目的做法更自然,因为出于性能原因,我们通常需要缓冲和刷新,而旧的接口使得用户操作起来很笨拙。现在您可以在write()方法内执行所有需要的批处理。

Step 工厂 Bean 更改

面向块的处理方法的一个副作用是步骤工厂 Bean 实现的更改。旧的SkipLimitStepFactoryBean已重命名为FaultTolerantStepFactoryBean,它仍然可以作为旧工厂 Bean 的替代品用于大多数常见用例。默认情况下,它会创建一个在回滚期间缓冲输入项目的步骤实现,以便新的ItemReaderItemWriter接口能够与非事务性输入源(如文件)正常工作。对于在回滚后重新呈现项目的输入源,客户端必须在工厂 Bean 中设置一个标志(isReaderTransactional是 M2 中标志的名称)-JmsItemReader是框架中唯一相关的读取器,并且没有多少项目使用它,因此这不是一个很大的变化。

业务处理

一个相关的新功能是,出现了一个名为ItemProcessor:

public interface ItemProcessor<S,T> {
    T process(S item);
}

的新成员。在 1.x 中,类型为S的输入项与类型为T的输出项之间的转换必须隐藏在其他参与者之一(通常是ItemWriter)内部。现在,我们已经将此问题泛化,并将其置于与同类框架同等重要的位置,ItemReaderItemWriter。1.x 用户可能会在这里识别出旧的ItemTransformer接口的痕迹,该接口现已移除。

更有用的 Tasklet 接口

许多人查看 Spring Batch 1.x 时都会问:“如果我的业务逻辑不是读取和写入怎么办?”为了更令人满意地回答这个问题,我们修改了Tasklet接口。在 Spring Batch 1.x 中,它相当简单——实际上只不过是一个Callable,但在 2.0 中,我们为其提供了更多灵活性,并将其更好地融入框架的主流(例如,现在将中央面向块的步骤实现实现为Tasklet)。以下是新的接口


public interface Tasklet {
    ExitStatus execute(StepContribution contribution, 
        AttributeAccessor attributes);
}

其思想是,tasklet 现在可以更多地反馈给封闭的步骤,这使其成为一个更灵活的平台来实现业务逻辑。该StepContribution已经是 1.x API 的一部分,但它没有公开曝光。它的作用是在不使程序员担心另一个线程中的并发修改的情况下,收集对当前StepExecution的更新。这也告诉我们,Tasklet将被重复调用(而不是在 1.x 框架中每个步骤只调用一次),因此它可以用于执行更广泛的业务处理任务。该AttributeAccessor是键值对的块范围的存储。tasklet 可以使用它来存储在回滚中将保留的中间结果。

作业和步骤属性的延迟绑定

到目前为止(到 M2 为止),我们无法利用任何新的 Spring 3.0 功能,因为还没有发布 Spring 3.0。但从下一个里程碑 (M3) 开始,我们将使用新的 Spring EL(表达式语言)功能来启用JobParametersExecutionContext属性到步骤组件的延迟绑定。这是一个经常被请求的功能,并且我们在 1.x 中有一些针对特殊情况的解决方法,例如StepExecutionResourceProxy用于将文件名绑定到作业的输入参数。Spring Batch 2.0 中可用的更通用的解决方案是允许将这些步骤属性绑定到任意组件,方法是在适当的 Spring 范围内定义它们,例如

<bean id="step1" parent="simpleStep">
  <property name="itemReader">
    <bean class="org.springframework.batch.item.file.FlatFileItemReader" scope="step">
        <property value="#{jobParameters[inputFile]}" />
        ...
    </bean>
  </property>
  ...
</bean>

项目读取器需要绑定到仅在运行时可用的文件名。为此,我们将其声明为 scope="step" 并使用了 Spring EL 绑定模式#{...}将作业参数绑定进来。相同的模式将适用于步骤和作业级别的执行上下文属性。

StepScope在每晚快照中可用,但我们仍在使用 Spring 2.5.5,因此 EL 绑定尚不可用。步骤范围的 Bean 也是解决旧的 Spring Batch 问题(如何使步骤线程安全)的一个好方法。如果步骤依赖于有状态的组件(如FlatFileItemReader),则它只需要将该组件定义为 scope="step",框架将为其创建一个延迟初始化代理,并且将在每个步骤执行时根据需要创建一次。为每个作业执行创建一个新的ApplicationContext仍然没有问题,这是 1.x 中防止线程在作业之间发生冲突的当前最佳实践。但现在步骤范围为您提供了另一种选择,对于大多数 Spring 用户来说,这可能更容易掌握。

非顺序执行

在 1.x 中,作业的模型始终是步骤的线性序列,如果一个步骤失败,则作业失败。尽管许多作业仍然符合此模式,因此它还没有消失,但在 2.0 中,我们通过引入一些新功能来解除此限制。这些功能计划在 M3 版本中发布,因此实现细节可能会更改,但其理念是支持三个功能

  • 条件执行:根据ExitStatus分支到不同的步骤。这包括能够根据 FAILED 状态进行分支的能力,这意味着步骤失败不再对作业致命。
  • 暂停执行并等待明确的指令继续。例如,在业务规则强制手动干预以检查业务关键数据有效性的情况下,这非常有用。
  • 并行执行多个步骤。如果步骤是独立的,用户可以指定哪些分支可以并行执行。
截至本文撰写之时,每晚快照包含一个ConditionalJob,它支持上述第一个用例。

可扩展性

Spring Batch 1.x 始终旨在作为单个 VM,可能是多线程模型,但我们在其中构建了许多支持在多个进程中并行执行的功能。许多项目已成功实施了可扩展的解决方案,依靠 Spring Batch 的服务质量功能来确保处理仅按正确的顺序进行。在 2.0 中,我们计划更明确地公开这些功能。可扩展性有两种方法,我们将同时支持:远程分块和分区。

远程分块

远程分块是一种无需了解数据结构即可划分步骤工作的方法。任何输入源都可以通过在单个进程中读取(如 1.x 中的正常操作)并将项目作为块发送到远程工作进程来动态拆分。远程进程实现监听器模式,响应请求,处理数据并发送异步回复。请求和回复的传输必须具有持久性、保证交付和单一消费者,并且任何 JMS 实现都已具备这些功能。但 Spring Batch 是在 Spring One Americas

配置:注解和 XML 命名空间

使用注解实现批处理逻辑的想法类似于 Spring @MVC。最终效果是,无需实现并可能注册一堆接口(读取器、写入器、处理器、监听器等),而只需注释一个 POJO 并将其插入步骤。有对应于各种接口的方法级注解,以及对应于作业、步骤和块级属性的参数级注解和工厂方法(有点像@ModelParameter@RequestParameter在 Spring @MVC 中。

Spring Batch 的 XML 命名空间使常见事物的配置更加容易。例如,上面提到的ConditionalJob具有 XML 配置选项,因此简单的条件执行可能如下所示


<job>
  <step name="gamesLoad" next="playerLoad"/>
  <step name="playerLoad">
    <next on="*" to="summarize"/>
    <next on="FAILED" to="compensate"/>
  </step>
  <step name="compensate"/>
  <step name="summarize"/>
</job>

第一步(“gamesLoad”)紧随其后的是“playerLoad”,但如果失败,则可以转到替代步骤(“compensate”),而不是正常地使用“summarize”步骤完成作业。XML 中的<step元素的 name= 属性是一个 bean 引用,因此Step的实现在其他地方定义(可能通过注解)。

数据库模式更改

元数据模式中有一些整理任务和对数据模型的扩展。我们将为任何从 1.x 迁移到 2.0 的人提供更新脚本,因此它们不应该引起任何问题,并且肯定会使元数据的导航和交互更容易。对于那些刚接触 Spring Batch 的人来说,该框架的一些主要优势是诸如可恢复性和幂等性(仅处理一次业务数据)之类的服务质量特性。我们通过关系数据库中的共享状态(在大多数用例中)实现这些功能,并且此数据库中数据模型的定义在 2.0 中略有更改。

主要更改与ExecutionContext的存储有关,它过去集中在一个表中,即使上下文可以与StepExecutionJobExecution关联。新的模型将更受 DBA 欢迎,因为它使 DDL 中的关系更加透明。我们还开始以 JSON 格式存储上下文值,以便人类用户更容易阅读和跟踪(单个实体的上下文都存储在一个表的一行中,而不是多行)。

我们还添加了一些其他统计信息,用于统计和核算已执行和跳过的项目,在每个阶段拆分读取、处理和写入的总项目计数。对于未将其执行拆分为读取、处理、写入的步骤(或任务),这比需要的更全面,但对于大多数用例,它比仅存储总项目计数更合适。

结束语

希望本文能激发您对 Spring Batch 2.0 的兴趣,并且您将有时间下载快照或里程碑并试用它。我们从社区获得了如此好的反馈,如果没有您的帮助和支持,该产品就不会像现在这样好。如果我错过了您感兴趣的内容,或者没有提供足够的细节,我深感抱歉,但我需要将其压缩成合理的博客大小格式。如果有人感兴趣,我可以写更多内容 - 只需提问即可。

如果您确实想了解更多信息,有一个绝佳的机会可以从今年的 Spring One Americas 团队那里了解 Spring Batch 2.0 和所有其他 SpringSource 活动。Lucas Ward 将在一个会议上介绍 Spring Batch 2.0 功能,我将更详细地展示可扩展性功能。还可以查看 论坛 上的讨论,或访问主页 此处

获取 Spring 新闻通讯

与 Spring 新闻通讯保持联系

订阅

领先一步

VMware 提供培训和认证,以加速您的进步。

了解更多

获得支持

Tanzu Spring 在一个简单的订阅中提供 OpenJDK™、Spring 和 Apache Tomcat® 的支持和二进制文件。

了解更多

即将举行的活动

查看 Spring 社区中所有即将举行的活动。

查看全部