【问题标题】:Cron server being delayed by multiple minutes using setTimeout()使用 setTimeout() 将 Cron 服务器延迟数分钟
【发布时间】:2017-12-06 15:26:00
【问题描述】:

我目前有一个正在运行的“cron”服务器。它应该执行所有需要在未来运行的定时命令。 这是服务器唯一做的事情。

什么是有效的:在我自己的笔记本电脑上运行这些功能,一切都会及时执行。

出了什么问题:在服务器上运行多天的函数。

我的代码都放在一个快速项目(节点)中,因此其他服务器可以进行调用以添加更多“crons”

文件夹布局:

app.js
-api/
--crons/
---router.js
---functions.js
--.../

在函数文件中,我保留了添加 cron 并执行它的函数。

const _ = require('lodash');
const Crons = [];
const moment = require('moment');

const functions = {

 addCron: (toExecute, dateTime, id, name) => {
    console.log('Cron', dateTime, name, id);
    const now = new Date().getTime();
    const then = new Date(dateTime).getTime();
    const diff = Math.max(then - now, 0);

    let cronJob;
    if (diff >= Math.pow(2, 31)) {
      if(functions.get(name)) {

      }
      cronJob = setTimeout(() => {
        functions.remove(name);
        functions.addCron(toExecute, dateTime, id, name);
      }, diff);
      Crons.push({
        name: name,
        job: cronJob
      });
    } else {
      if(functions.get(name)) {
        functions.remove(name);
      }
      cronJob = setTimeout(() => {
        console.log(`Started cron: ${name} at ${new Date()}`);
        toExecute(id);
        functions.remove(name);
      }, diff);
      Crons.push({
        name: name,
        job: cronJob
      });
    }

  }
};

module.exports = functions;

目前,当我在本地运行此程序时,我的日志显示所有函数的执行时间都晚了大约 1 毫秒(这很好)。 实时服务器上的日志显示,函数每天运行延迟 7 分钟。

日志

1|cronserver | 2017-06-30 18:00:07.195000000: Cron 2017-07-01T17:00:00.000Z YQkWN6BmX8eqzQHC9startCheck YQkWN6BmX8eqzQHC9
1|cronserver | 2017-06-30 18:00:07.195000000: Cron 2017-07-01T17:30:00.000Z 7c2yPyfjKDuujKQjhstartCheck 7c2yPyfjKDuujKQjh
1|cronserver | 2017-06-30 18:00:07.196000000: Cron 2017-07-02T17:00:00.000Z PQKoboRpSkWeTufSdstartCheck PQKoboRpSkWeTufSd
1|cronserver | 2017-06-30 18:00:07.196000000: Cron 2017-07-02T17:30:00.000Z yLFaAjACB9uNPd4YvstartCheck yLFaAjACB9uNPd4Yv
1|cronserver | 2017-06-30 18:00:07.199000000: Cron 2017-07-01T17:30:00.000Z YQkWN6BmX8eqzQHC9start YQkWN6BmX8eqzQHC9
1|cronserver | 2017-06-30 18:00:07.199000000: Cron 2017-07-01T18:00:00.000Z 7c2yPyfjKDuujKQjhstart 7c2yPyfjKDuujKQjh
1|cronserver | 2017-06-30 18:00:07.199000000: Cron 2017-07-02T17:30:00.000Z PQKoboRpSkWeTufSdstart PQKoboRpSkWeTufSd
1|cronserver | 2017-06-30 18:00:07.199000000: Cron 2017-07-02T18:00:00.000Z yLFaAjACB9uNPd4Yvstart yLFaAjACB9uNPd4Yv
1|cronserver | 2017-07-01 17:07:32.253000000: Started cron: YQkWN6BmX8eqzQHC9startCheck at Sat Jul 01 2017 17:07:32 GMT+0000 (UTC)
1|cronserver | 2017-07-01 17:37:33.160000000: Started cron: 7c2yPyfjKDuujKQjhstartCheck at Sat Jul 01 2017 17:37:33 GMT+0000 (UTC)
1|cronserver | 2017-07-01 17:37:33.161000000: Started cron: YQkWN6BmX8eqzQHC9start at Sat Jul 01 2017 17:37:33 GMT+0000 (UTC)
1|cronserver | 2017-07-01 18:07:34.070000000: Started cron: 7c2yPyfjKDuujKQjhstart at Sat Jul 01 2017 18:07:34 GMT+0000 (UTC)
1|cronserver | 2017-07-02 17:14:24.678000000: Started cron: PQKoboRpSkWeTufSdstartCheck at Sun Jul 02 2017 17:14:24 GMT+0000 (UTC)
1|cronserver | 2017-07-02 17:44:25.587000000: Started cron: yLFaAjACB9uNPd4YvstartCheck at Sun Jul 02 2017 17:44:25 GMT+0000 (UTC)
1|cronserver | 2017-07-02 17:44:25.588000000: Started cron: PQKoboRpSkWeTufSdstart at Sun Jul 02 2017 17:44:25 GMT+0000 (UTC)
1|cronserver | 2017-07-02 18:14:26.496000000: Started cron: yLFaAjACB9uNPd4Yvstart at Sun Jul 02 2017 18:14:26 GMT+0000 (UTC)

这个服务器唯一做的就是运行这些功能。任何帮助将不胜感激。

TL;DR 我的 setTimout 函数运行迟了。我该如何解决这个问题

【问题讨论】:

  • 你使用 node.js 吗?
  • 是的,我愿意,我现在将其添加为标签。
  • 什么是functions.remove?你有没有清理过Crons?您当前的代码无限制地增加它:它会逐渐减慢一切......
  • Functions.remove 是一个停止超时并将其从 crons 数组中删除的函数。这用于取消 crons

标签: javascript node.js express cron settimeout


【解决方案1】:

setTimeout 只执行一次,所以我不会将其视为“cron 作业”,而是您希望在未来某个时间执行一次的作业。撇开这个不谈,setTimeout 并不准确,还有multiple known reasons why your setTimeout timer executes at the wrong timesetTimeout 的工作原理是它在事件队列中创建一个事件,直到队列释放它才会执行您的代码 as explained here。我可以很容易地看到一种情况,如果您运行多个 setTimeout 函数,它将导致它们执行时的延迟。或者更有可能您还有其他一些内存泄漏问题,这只是在这里冒泡。

尽管有许多其他选项可以完成您正在尝试做的事情。我已经将node-cron 用于实际的 cron 工作,而且它非常可爱。还有多种方法可以在自己的队列上运行单个作业,例如 KueRabbitMQ

【讨论】:

  • node cron 在它自己的函数中不使用 setTimeout 吗?那么如何才能更精确呢?
  • 这里有非常相似的讨论 github.com/kelektiv/node-cron/issues/218github.com/node-schedule/node-schedule/issues/368 - 他们讨论了一次运行数千个 setTimeout 以最小的延迟。最有可能在执行的代码中运行阻塞事件循环的同步代码。我建议让你的 cron 作业和实际执行的代码在不同的进程上运行。
猜你喜欢
  • 2021-08-12
  • 1970-01-01
  • 1970-01-01
  • 2022-08-02
  • 1970-01-01
  • 2016-01-04
  • 2021-02-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多