常见问题解答

是否可以在多个线程或多个进程中执行作业?

有三种方法可以解决这个问题 - 但我们建议在分析此类需求时谨慎行事(真的有必要吗?)。

  • 在步骤中添加一个 TaskExecutor。用于配置步骤的 StepBuilder 提供了一个可以设置的“taskExecutor”属性。只要步骤本身是可重启的(实际上是幂等的),这就可以工作。并行作业示例展示了它在实践中的工作方式 - 这使用“进程指示器”模式来标记输入记录在业务事务中的完成情况。

  • 使用 PartitionStep 将步骤执行显式地拆分到多个步骤实例中。Spring Batch 对此主要策略有一个本地多线程实现(PartitionHandler),这使其成为 IO 密集型作业的绝佳选择。请记住,对于以这种方式执行的步骤中的有状态组件,使用 scope="step",以便为每个步骤执行创建单独的实例,并且线程之间没有交叉对话。

  • 使用在 spring-batch-integration 模块中实现的远程分块方法。这需要一些持久中间件(例如 JMS)来实现驱动步骤和远程工作者之间的可靠通信。基本思想是在驱动进程中使用一个特殊的 ItemWriter,并在工作者进程中使用一个监听器模式(通过 ChunkProcessor)。

如何使项读取器线程安全?

您可以同步 read() 方法(例如,通过将其包装在一个执行同步的委托器中)。请记住,您将失去可恢复性,因此最佳实践是将步骤标记为不可恢复,为了安全(和效率),您还可以将读取器的 saveState=false 设置。

Spring Batch 在使用灵活策略和默认实现方面的理念是什么?您能为这个或那个属性添加一个公共 getter 吗?

Spring Batch 中有许多扩展点供框架开发人员(而不是业务逻辑实现者)使用。我们希望客户创建他们自己的更具体的策略,这些策略可以插入以控制诸如提交间隔(CompletionPolicy)、关于如何处理异常的规则(ExceptionHandler)以及许多其他内容。

一般来说,我们试图劝阻用户扩展框架类。Java 语言没有给我们足够的灵活性来将类和接口标记为内部。通常,您可以期望在源树顶层的 org.springframework.batch.* 包中找到任何内容都是公开的,但不一定可子类化。我们不鼓励扩展大多数策略的具体实现,而是建议使用组合或分叉方法。如果您的代码只能使用来自 Spring Batch 的接口,那么这将为您提供最大的可移植性。

Spring Batch 与 Quartz 有什么区别?它们在解决方案中都有用武之地吗?

Spring Batch 和 Quartz 的目标不同。Spring Batch 提供了处理大量数据的功能,而 Quartz 提供了调度任务的功能。因此,Quartz 可以补充 Spring Batch,但不是排斥技术。常见的组合是使用 Quartz 作为 Spring Batch 作业的触发器,使用 Cron 表达式和 Spring Core 方便的 SchedulerFactoryBean

如何使用 Spring Batch 调度作业?

使用调度工具。市场上有许多调度工具。例如:Quartz、Control-M、Autosys。Quartz 没有 Control-M 或 Autosys 的所有功能,它被认为是轻量级的。如果你想要更轻量级的工具,你可以直接使用操作系统(cronat 等)。

可以使用 Spring Batch 的作业步骤模型和 Spring Batch 中的非顺序功能来实现简单的顺序依赖关系。我们认为这很常见。事实上,它使纠正调度程序的常见误用变得更容易 - 配置了数百个作业,其中许多作业不是独立的,而是仅依赖于另一个作业。

Spring Batch 如何允许项目通过并行处理或其他方式优化性能和可扩展性?

我们认为这是 JobStep 的作用之一。Step 的特定实现处理将业务逻辑分解并将其在并行进程或处理器之间高效共享的问题(参见 PartitionStep)。这里有很多技术可以发挥作用。本质上只是一组对分布式代理的并发远程调用,这些代理可以处理一些业务处理。由于业务处理通常已经模块化 - 例如输入一个项目,处理它 - Spring Batch 可以通过多种方式制定分布策略。我们有一些经验的一种实现是一组处理业务处理的远程 Web 服务。我们将特定范围的主键发送到多个远程调用中的每一个。相同的基本策略适用于任何 Spring 远程协议(普通 RMI、HttpInvoker、JMS、Hessian 等),只需在执行层配置中更改几行代码。

如何使用消息传递来扩展批处理架构?

来自现有项目的许多实际证据表明,批处理的管道方法非常有利,可以提高弹性和吞吐量。我们经常面临着需要审计跟踪和保证处理的关键任务应用程序,但在负载下对性能有非常严格的限制,或者高吞吐量具有竞争优势。

Matt Welsh 的工作表明,分阶段事件驱动架构 (SEDA) 比更严格的处理架构具有巨大的优势,而面向消息的中间件 (JMS、AQ、MQ、Tibco 等) 为我们提供了许多开箱即用的弹性。在系统中,下游和上游阶段之间存在反馈,因此可以根据需求量调整消费者数量,这尤其有利。那么这如何融入 Spring Batch 呢?spring-batch-integration 项目在 Spring Integration 中实现了这种模式,可用于扩展对具有大量处理项的任何步骤的远程处理。特别是请参见“chunk”包,以及其中的ItemWriterChunkHandler实现。