【问题标题】:Spring Batch - Is it possible to write a custom restart in spring batchSpring Batch - 是否可以在 Spring Batch 中编写自定义重启
【发布时间】:2020-03-10 05:18:25
【问题描述】:

我一直在编写一个春季批处理,其中我必须执行一些错误处理。 我知道 Spring Batch 有自己的处理错误和重启的方式。

但是,当批处理失败并再次重新启动时,我想传递我自己的值、条件和参数(用于重新启动),在开始/执行第一步之前需要遵循这些。

那么,是否可以在spring批处理中编写这样的自定义重启?

UPDATE1:(为上述问题提供更好的解释。)

假设第 1 步中我的阅读器的输入格式如下:

具有以下列的表格:

CompanyName1 -> VehicleId1
CN1 -> VID2
CN1 -> VID3
.
.
CN1 -> VID30
CN2 -> VID1
CN2 -> VID2
.
.
CNn -> VIDn

读取器逐行读取此表,块大小为 1(因此在这种情况下,检索到的行将是 CN -> VID )处理它并将其写入文件对象。 这个过程一直持续到所有 CN1 类型的数据都写入 File 对象。当阅读器发送带有 CN2 类型的公司名称的行时,之前创建的 File 对象(对于 CN1 类型的公司名称)将存储在远程位置。然后CN2的文件对象创建过程将继续,直到遇到CN3,在这种情况下,CN2文件对象将被发送到远程位置进行存储 并且该过程将继续。

现在,一旦你理解了这一点,这里就有一个问题。

假设当前正在写入公司名称 2 (CN2) 的数据,车辆 ID 为 VID20 (CN2 -> VID20) 在文件对象中。然后,由于某种原因,我们不得不停止作业/作业失败。在这种情况下,将保存的实例将是 CN2 -> VID20。因此,下次作业运行时,将从 CN2->VID20

正如您可能已经猜到的,当文件对象被破坏时,CN2->VID20 之前写入文件对象的所有 19 个条目都被永久删除,并且这些条目从未通过文件发送到远程位置。

所以我的问题是这样的:

有没有一种方法可以为批处理编写自定义重启,我可以告诉作业从 CN2->VID1 而不是 CN2->VID20 开始?

如果您能想到任何其他方式来处理这种情况,那么也欢迎您提出此类建议。

【问题讨论】:

  • 当你重新启动失败的作业实例(使用相同的参数)时,Spring Batch 将跳过已成功执行的步骤,并从上次失败的面向块的步骤中停止的地方恢复(如果有)。目前尚不清楚I want to pass my own values, conditions and parameters 是什么意思。你能举一个具体的例子来说明你想要达到的目标吗?
  • 我已经为我的问题添加了解释。请务必查看一下。谢谢..!!
  • all the 19 entries before CN2->VID20 which were written in the File Object were deleted permanently when the file Object got destroyed:为什么?如果作业失败,您是否将文件写入永久磁盘或被删除的位置?如果设置 chunksize=1,这意味着文件写入器将刷新每条记录的数据,因此如果作业在第 20 项失败,则第 19 项应该已保存在文件中。您是否将每个公司数据写入单独的文件中?这对于您的工作设计非常重要。在您的情况下,我认为不需要“自定义重启”。
  • 只有在检索到所有 companyData 时,才会将数据写入永久磁盘。例如,CN1 将被写入一个单独的文件中,并且只有在检索到它的所有 VID 时才会存储到持久存储中。接下来 CN2 将以类似的方式编写。但在那之前,这些数据将存储在一个简单的对象中,如果作业停止,该对象将被销毁。所以,如果我们在 CN2->VID20 并且批处理停止,那么之前存储在一个简单文件对象中的所有数据都将丢失(因为它还没有被写入任何物理位置)

标签: spring spring-boot spring-batch


【解决方案1】:

由于您想将每个公司的数据写入单独的文件中,我将使用公司名称作为工作参数。使用这种方法:

  • 每个作业都会读取单个公司的数据并写入文件
  • 如果作业失败,您可以重新启动它,它会从中断的地方继续(Spring Batch 会在写入新数据之前将文件截断到最后已知的写入偏移量)。所以不需要自定义重启“策略”。
  • 无需将块大小设置为 1,这样效率不高。您可以通过这种方法使用合理的块大小

如果公司数量足够少,您可以手动运行作业。否则,您始终可以使用 select distinct(company_name) from yourTable 之类的方式获取不同的值,并编写脚本/循环来启动具有不同参数的批处理作业。归根结底,让每项工作只做一件事并做好。

【讨论】:

  • 感谢@Mahmoud Ben Hassine 提出这个想法。这是我最初的计划,也是最理想的方法。但是,生成这些报告的处理时间会很长(几个小时)。因此,如果我触发多个这种规模的作业,较小作业的处理将受到影响。因此,我必须触发一项将循环创建这些报告的大工作。此外,我将通过阅读器将公司名称和 VID 一起获取,并且无法通过触发批处理的工作来获取它们。
  • 可扩展性是“每个公司一个工作”方法的另一个论据。您可以并行运行多个作业(在同一个 JVM 中使用多个线程,或者在同一台机器或集群内不同机器上的不同 JVM 中)。扩展/改进多个独立任务的性能总是比单个任务更容易。如果你真的想保持单一作业的方法,请尝试使用分区步骤和按公司分区数据。
  • this is the most ideal approach to follow:如果有帮助,请接受答案:stackoverflow.com/help/someone-answers。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-02-14
  • 2017-07-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-19
  • 1970-01-01
相关资源
最近更新 更多