【问题标题】:Dynamic Crons are executed many times at the same time动态 Crons 同时执行多次
【发布时间】:2023-01-30 02:54:45
【问题描述】:

我正在创造新的定时作业并安排它们在未来运行,但是当执行时间到来时,同一个作业被触发三次。完成工作后我删除它来自注册表,即使这样也不能避免工作的三倍。

localhost 它只触发一次
发布它被触发了三次

我们有三个豆荚在 kubernetes 后面。我想这与此有关。

 const date = dateFns.addMinutes(new Date(), 10);
 const job = new CronJob({
      cronTime: date,
      start: true,
      onTick: async () => {
      await this.sendEmail(params);
    }
 });
this.schedulerRegistry.addCronJob('job01', job);

【问题讨论】:

  • 您是否使用 pm2 集群运行代码?
  • 你是如何创建这些cronjobs的?
  • @HuthaifaMuayyad 是的,我们正在使用 pm2 集群。
  • @YaronIdan 它是动态 cron,我在它们运行后创建和删除,但我发现这是关于 kubernetes 的,但我不知道如何在代码端处理它

标签: cron nestjs cron-task node-schedule


【解决方案1】:

根据您在评论中的回复,您正在使用集群。因此,对于每个正在运行的实例,都会创建一个 cron。如果集群中有三个实例,您将获得三个 cron。您需要做的是为您的集群分配一个名称。我会给你一个我们的设置的例子。

  • 我们正在运行基于最大 cpu 核心的实例。

  • 我们为这些实例分配了一个名称,并将其中一个命名为primary。并将其设置为在一个核心上运行。

  • 其余实例与您如何命名无关紧要,但我们将计数设置为-1。这样我们就可以利用机器上的所有内核。

这是 ecosystem.config.js 的示例

module.exports = {
  apps: [
    {
      name: 'nest-primary',
      script: './dist/src/main.js',
      instances: '1',
      exec_mode: 'cluster',
      time: true,
      combine_logs: true,
      max_memory_restart: '3500M',
      max_old_space_size: 3000,
      log_date_format: 'HH:mm YYYY-MM-DD Z',
      log_type: 'json',
      merge_logs: true,
      env_local: {
        NODE_ENV: 'local',
        HOST: 'localhost',
        PORT: 3000,
        DATABASE_URL: 'mysql://user:password@localhost:3306/himam',
        DATABASE_URL_PG: 'postgresql://postgres:password@localhost:5432/himam',
      },
      env_development: {
        NODE_ENV: 'development',
        PORT: 3000,
        HOST: '0.0.0.0',
        DATABASE_URL: 'mysql://user:password@localhost:3306/himam',
        DATABASE_URL_PG: 'postgresql://postgres:password@localhost:5432/himam',
      },
  },
  {
      name: 'nest-replica',
      script: './dist/src/main.js',
      instances: '-1',
      exec_mode: 'cluster',
      time: true,
      combine_logs: true,
      max_memory_restart: '3500M',
      max_old_space_size: 3000,
      log_date_format: 'HH:mm YYYY-MM-DD Z',
      log_type: 'json',
      merge_logs: true,
      env_local: {
        NODE_ENV: 'local',
        HOST: 'localhost',
        PORT: 3000,
        DATABASE_URL: 'mysql://user:password@localhost:3306/himam',
        DATABASE_URL_PG: 'postgresql://postgres:password@localhost:5432/himam',
      },
      env_development: {
        NODE_ENV: 'development',
        PORT: 3000,
        HOST: '0.0.0.0',
        DATABASE_URL: 'mysql://user:password@localhost:3306/himam',
        DATABASE_URL_PG: 'postgresql://postgres:password@localhost:5432/himam',
      },
  },

当我启动集群时,我通过--env production

pm2 start ecosystem.config.js --env production

最重要的部分,在您的 cron 中,您需要检查实例的名称。您可以通过将您在上面的配置中使用的名称添加到您的 .env 来完成此操作

PM2_PRIMARY_NAME=nest-primary
PM2_REPLICA_NAME=nest-replica
  • 最后,在您想要运行 cron 的代码中,检查进程的名称,如下所示:
 async handleCron() {
    if (process.env.name !== this.configService.get('PM2_PRIMARY_NAME')) {
      return;
    }
    // do your cron logic here.

这确保您的 cron 将只运行一次,因为您的主实例仅在 1 个核心上运行,并且您不会有重复的触发器。请更新我们。

【讨论】:

    猜你喜欢
    • 2023-03-23
    • 2012-11-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-27
    • 2014-03-01
    • 1970-01-01
    相关资源
    最近更新 更多