我正在使用一个 Spring Batch 应用程序,它有大约 30 个作业。一些作业依赖于其他作业(例如,作业 B 仅在作业 A 完成后运行),并且所有作业都针对约 500 个帐户按顺序运行。为了优化,我们将其设置为 StatefulSet 并将帐户分配给特定的 pod(尽管分配并不完美)。
例如: Pod0 -> 50 个帐户
Pod1 -> 50 个帐户 ...
每项作业都必须为所有帐户执行。这意味着,必须为 Pod0 上的所有 50 个帐户执行 JobA,并且在每个 pod 中执行类似的操作。
accountShardService.getAccountIds().forEach(account
-> jobs.stream()
.forEach(job -> runJob(account, job)));
挑战:
某些帐户拥有大量数据,从而减慢了其他作业的速度。长时间运行的作业会消耗大部分资源,导致后续计划作业延迟。例如:Pod0 必须为 50 个帐户执行名为 Job-A 的作业。如果其中一个账户有巨大的数据量需要处理,那么它只会占用大部分时间并延迟其余 49 个账户的执行。 优化这个的最佳方法是什么?
此外,我们正在考虑实现无状态,这样任何 Pod 都可以接手任何工作,以提高灵活性。但我不确定如何有效地设置 HPA,尤其是根据工作负载使用哪些指标来扩大/缩小规模。因为如果一个账户的作业处理时间较长,任何 pod 的 CPU 和内存都不会很高,但会延迟其他账户的作业执行。
我希望得到以下方面的建议:
此设置中 HPA 的良好指标 在不影响作业依赖性的情况下跨 Pod 动态分配帐户的方法
注意: 我们正在使用外部 Postgres 元数据作业存储库。
必须为 Pod0 上的所有 50 个账户执行 JobA
当您决定在 kubernetes 上大规模运行批处理作业时,您不应假定或强制作业必须在特定 pod 上运行。你应该让 kubernetes 选择在哪里运行你的工作。
作业具有依赖性这一事实会损害可扩展性。在删除这些依赖项之前,您不会从真正的可扩展批处理架构中受益(如果不能,您需要一种将逻辑封装在单个工作单元中的方法)。
每个作业必须为所有帐户执行
在这种情况下,我会首先创建一个作业的作业(即使用Spring Batch中的
JobStep
概念创建一个复合作业)来封装串行执行逻辑。然后,循环所有复合作业并为每个帐户提交(到 k8s)一个作业实例。这样,不同帐户的作业可以并行运行,而单个帐户的作业将串行执行。