docker - 防止在 docker 上的 nest.js 中运行多个 cron

在 docker 中,我们为我们的微服务使用了 deploy: replicas: 3。我们有一些 Cronjob,问题是运行所有 cronjob 的系统被调用了 3 次,这不是我们想要的。我们只想运行一次。 nest.js 中的 cron 示例:

  @Cron(CronExpression.EVERY_5_MINUTES)
  async runBiEventProcessor() {
    const calculationDate = new Date()
    Logger.log(`Bi Event Processor started at ${calculationDate}`)

如何在不将副本更改为 1 的情况下仅运行此 cron 一次?

最佳答案

当 cron 或后台作业是同时运行多个实例的应用程序的一部分时,这是一个非常普遍的问题。

有多种方法可以处理这种情况。如果您没有具体的解决方案,以下是一些解决方法:

  1. 仅为后台处理创建一个单独的服务,并确保一次只有一个实例在运行。

  2. 将 cron 作业公开为 API 并触发 API 以启动后台处理。在这种场景下,负载均衡器只会将请求交给一个实例。这种方法将确保只有一个实例可以处理该作业。您仍然需要一个外部实体来访问 API,它可以是内部的或第三方的。

  3. 使用 Bull Queue 或提供类似功能的任何其他工具或库中的可重复作业功能。 Bull 会将工作移交给任何活跃的处理器。这样,它可以确保作业仅由一个事件处理器处理一次。 Nest.js 有 wrapper对于相同的。阅读有关 Bull 队列可重复作业的更多信息 here .

  4. 实现自定义锁定机制 听起来并不难。其他框架中的许多其他调度程序都采用类似的原则来处理并发。

    • 如果您使用 RDBMS,请使用事务和锁定。在数据库中创建 cron 记录。第一个 cron 进入并处理后立即获取锁。其他并发作业将失败或超时,因为它们将无法获取锁。但是您需要在这种方法中处理一些情况,以使其无错误且完美无缺。
    • 如果您使用的是 MongoDB 或任何支持 TTL(生存时间)设置和唯一索引的类似数据库。将文档插入数据库,其中文档中的一个字段具有唯一约束,以确保另一作业无法再插入一个文档,因为它会因数据库级唯一约束而失败。另外,确保文档上有 TTL(Time-to-live index);这样,文档将在配置的时间后被删除。

如果您没有任何其他具体选项,这些是解决方法。

https://stackoverflow.com/questions/70168350/

相关文章:

c# - 如何在 C# 中创建 JSON 对象

svelte - svelte.config.js 错误语法错误 : Cannot use impo

vue.js - 有没有可能把它变成 '<script setup>' ?我尝试了很多方法但可

maven - 如何找到 Log4j 的深层用法

r - 忽略 R 中某些值的行求和值

next.js - 单击链接后如何关闭模态窗口

r - 如何将一列添加到由其他列的最小值组成的数据框中?

r - 缩短 R 中的长向量

c++ - 访问元组 vector 中的元素 C++

python - 在 python 的列表列表中查找唯一的单词