最佳 Spring 批量扩展策略

Posted

技术标签:

【中文标题】最佳 Spring 批量扩展策略【英文标题】:Best Spring batch scaling strategy 【发布时间】:2015-05-20 09:13:24 【问题描述】:

我们有运行良好的简单批处理。最近我们有新的要求来实施新的批处理来生成报告。我们有不同的数据源可供阅读以准备此报告。具体来说,我们可能对每个报告都有一个视图。

现在我们希望以这样一种方式扩展这个过程,使其可以扩展并尽早完成。

我熟悉多线程步骤,但不确定其他策略(远程分块和分区步骤)以及何时使用哪个策略。

在我们的例子中,处理 + 写入文件是比读取更多的资源激励。

在这种情况下,哪种方法最适合。

或者,如果我们发现从 db 读取数据与写入 + 处理到文件是相同的资源激励,那么我们必须改进/扩展这个过程的最佳选择是什么。

【问题讨论】:

【参考方案1】:

TLDR;

根据您的描述,我认为您可以尝试使用 Synchronized Reader 的多线程步骤,因为您提到处理和写入是您步骤中更昂贵的部分。

但是,鉴于您的读者是一个数据库,我认为配置和工作的分区步骤将非常有益。设置需要更多的工作,但从长远来看会更好地扩展。

Multi-threaded Step

用途:

加快单个步骤 读取器可以处理负载平衡时(即 JMS 或 AMQP) 使用手动对正在读取的数据进行分区的自定义读取器时

请勿用于:

有状态的项目阅读器

多线程步骤利用 Spring Batch 使用的chunk-oriented processing。当您对一个步骤进行多线程处理时,它允许 spring 批处理在它自己的线程中执行整个 chunk。请注意,这意味着您的数据块的整个读取过程写入周期将并行发生。这意味着没有保证处理您的数据的顺序。另请注意,这不适用于有状态的 ItemReader(JdbcCursorItemReader 和 JdbcPagingItemReader 都是有状态的)。

带同步阅读器的多线程步骤

用途:

加快单个步骤的处理和写入速度 当读取是有状态的时

请勿用于:

加快阅读速度

有一种方法可以解决不能将多线程步骤与有状态项读取器一起使用的限制。你可以synchronize 他们的read() 方法。这基本上会导致读取串行发生(尽管仍然不能保证顺序),但仍然允许处理和写入并行发生。当读取不是瓶颈但处理或写入是瓶颈时,这可能是一个不错的选择。

Partitioning

用途:

加快单个步骤 当读取是有状态的时 输入数据何时可以分区

请勿用于:

当输入数据无法分区时

对步骤进行分区的行为与多线程步骤略有不同。通过分区步骤,您实际上拥有完全不同的StepExecutions。每个 StepExecution 都在它自己的数据分区上工作。这样,阅读器在读取相同数据时不会遇到问题,因为每个阅读器只查看数据的特定部分。这种方法非常强大,但设置起来也比多线程步骤更复杂。

Remote Chunking

用途:

加快单个步骤的处理和写入速度 有状态的读者

请勿用于:

加快阅读速度

远程分块是非常高级的 Spring Batch 用法。它需要某种形式的持久中间件来发送和接收消息(即 JMS 或 AMQP)。使用远程分块,读取仍然是单线程的,但是当每个块被读取时,它会被发送到另一个 JVM 进行处理。在实践中,这与多线程步骤的工作方式非常相似,但是远程分块可以使用多个进程,而不是多个线程。这意味着远程分块允许您水平 扩展您的应用程序,而不是垂直 扩展它。 (TBH 我认为如果您正在考虑实现远程分块,您应该考虑看看 Hadoop 之类的东西。)

Parallel Step

用途:

加快整体作业执行速度 当存在不相互依赖的独立步骤时

请勿用于:

加速步骤执行 相关步骤

当您有一个或多个可以独立执行的步骤时,并行步骤很有用。 Spring Batch 可以轻松地允许步骤在单独的线程中并行执行。

【讨论】:

是否完全排除了相关步骤的并行步骤方案?在我的情况下,即使依赖,并行步骤也更有意义,因为步骤#1 将数据转储到临时数据库表,而步骤#2 应该从临时表中选择数据并进行处理。步骤#2 阅读器是否可以轮询数据库表?有这样的读者吗?以这种方式工作更有意义,因为第 1 步需要很长时间才能产生输出,但当它完成时,我们希望立即在第 2 步中处理它。由于数据库读写,不愿意在第 1 步处理器中插入第 2 步。 @SabirKhan 对您的问题的简短回答是,没有 OOTB 组件可以处理您所描述的内容。我可以看到开发自定义 DB 阅读器,但您必须想办法“通知”第 2 步,第 1 步已完成。听起来第 2 步应该是一个长时间运行的过程,它正在观察数据库的变化并进行一些处理。也许第 1 步发布到持久主题而不是 DB 更有意义?然后,当有新数据可用时,您可以“推送”通知,而不必进行轮询。有很多选择,但我认为并行步骤不是您的解决方案。

以上是关于最佳 Spring 批量扩展策略的主要内容,如果未能解决你的问题,请参考以下文章

spring中策略模式使用

Spring - 使用休眠和弹簧安全扩展类

Kubernetes 动态作业扩展

策略模式优化过多的IF ELSE

spring batch批量处理框架

5个Kubernetes监控最佳实践