常见问题
是否可以在多个线程或多个进程中执行任务?
有三种方法可以处理这个问题——但我们建议在分析此类需求时保持谨慎(这真的是必要的吗?)。
-
在步长中添加一个
TaskExecutor。用于配置 Step 的 `StepBuilder` 提供了一个可设置的 "taskExecutor" 属性。只要该步骤本质上是可重启的(即具有幂等性),此方法就有效。并行作业示例展示了其在实际中的工作方式——它在业务事务内部使用“处理指示器”模式来标记输入记录为已完成。 -
使用
PartitionStep将您的步骤执行显式地拆分到多个 Step 实例中。Spring Batch 为此提供了一套本地多线程的主要策略实现(PartitionHandler),使其成为 I/O 密集型作业的理想选择。请记住,在以这种方式执行的步骤中,对于有状态组件应使用scope="step",以便为每次步骤执行创建独立的实例,从而避免线程间的相互干扰。 -
使用在
spring-batch-integration模块中实现的远程分块(Remote Chunking)方法。这需要一些持久的中间件(例如 JMS),以便在驱动步骤和远程工作节点之间进行可靠通信。基本思路是在驱动进程中使用一个特殊的ItemWriter,并在工作节点进程中通过ChunkProcessor采用监听器模式。
如何使 ItemReader 线程安全?
您可以同步 read() 方法(例如,通过将其包装在一个执行同步的委托器中)。
请注意,这将导致无法重启,因此最佳实践是将该步骤标记为不可重启;为了安全(且高效),您还可以在读取器上设置 saveState=false。
Spring Batch 在使用灵活策略和默认实现方面的理念是什么?您能否为此或彼属性添加一个公共的 getter 方法?
Spring Batch 为框架开发者(相对于业务逻辑的实现者)提供了许多扩展点。
我们期望客户端创建自己更具体的策略,以便插入并控制诸如提交间隔(CompletionPolicy)、
异常处理规则(ExceptionHandler)等诸多方面。
通常,我们不建议用户扩展框架类。Java 语言在将类和接口标记为内部使用方面提供的灵活性有限。
通常,您可以预期源代码树顶层、位于包 org.springframework.batch.* 中的任何内容都是公开的,但不一定支持子类化。
我们不建议扩展大多数策略的具体实现,而推荐采用组合或分支(fork)的方式。
如果您的代码仅使用 Spring Batch 提供的接口,将获得最大程度的可移植性。
Spring Batch 与 Quartz 有何不同?在解决方案中它们是否都有用武之地?
Spring Batch 和 Quartz 的目标不同。Spring Batch 提供处理大量数据的功能,而 Quartz 提供任务调度功能。
因此,Quartz 可以补充 Spring Batch,但它们并非互斥的技术。一种常见的组合是使用 Quartz 作为触发器,通过 Cron 表达式
和 Spring Core 提供的便捷 SchedulerFactoryBean 来触发 Spring Batch 作业。
如何使用 Spring Batch 调度作业?
使用调度工具。市面上有很多这样的工具。例如:Quartz、Control-M、Autosys。
Quartz 并不具备 Control-M 或 Autosys 的所有功能——它旨在保持轻量级。
如果您需要更轻量的解决方案,可以直接使用操作系统(cron、at 等)。
简单的顺序依赖可以使用 Spring Batch 的作业 - 步骤模型以及 Spring Batch 中的非顺序功能来实现。 我们认为这非常常见。事实上,它使得纠正调度器的一个常见误用变得更加容易——配置数百个作业, 其中许多作业并非相互独立,而仅依赖于另一个作业。
Spring Batch 如何允许项目通过并行处理或其他方式优化性能和可扩展性?
我们将此视为Job或Step的角色之一。Step 的特定实现负责将业务逻辑拆分,并在并行进程或处理器之间高效共享(参见 PartitionStep)。有许多技术可以在此发挥作用。其本质只是一组对分布式代理的并发远程调用,这些代理能够处理某些业务逻辑。由于业务处理通常已经模块化 - 例如。g.输入一个项目,对其进行处理 - Spring Batch 可以通过多种方式策略性地分配任务。我们有过一些经验的一种实现是一组处理业务逻辑的远程 Web 服务。我们将特定范围的主键作为输入发送到多个远程调用中的每一个。相同的基本策略适用于任何 Spring 远程协议(普通 RMI、HttpInvoker、JMS、Hessian 等)。) 只需在执行层配置中进行几行更改即可。
如何利用消息机制来扩展批处理架构?
现有项目的大量实践证据表明,采用流水线方式进行批处理非常有益,能够提升系统的韧性和吞吐量。 我们经常面对关键任务型应用,这些应用需要完整的审计轨迹和可靠的处理保证,同时在负载下的性能限制极为严格,或者高吞吐量能带来竞争优势。
Matt Welsh 的工作表明,分段事件驱动架构(SEDA)相比更僵化的处理架构具有巨大的优势,
而面向消息的中间件(如 JMS、AQ、MQ、Tibco 等)则开箱即用地为我们提供了强大的弹性。在下游与上游阶段之间存在反馈的系统里,这种架构尤为有益,因为它可以根据需求量的变化动态调整消费者数量。
那么,这与 Spring Batch 如何结合呢?spring-batch-integration 项目已在 Spring Integration 中实现了该模式,
可用于扩展任何包含大量待处理项的步骤的远程处理能力。
请特别关注其中的 "chunk" 包,以及该包内的 ItemWriter 和 ChunkRequestHandler 实现。