随着时间的流逝,每隔2分钟运行一次Nodejs函数

use*_*987 12 javascript node.js typescript

这是很难描述的问题。我有一个koajs具有功能的应用程序,该功能每2分钟在多个实例(10-1000范围)中创建。此计划的作业是在应用启动时创建的。我使用它koajs是因为我需要为此应用程序提供一些简单的api端点。在开始的3-5个小时中,它运行良好,然后创建的实例数开始减少,并且某些日志输出消失了。

这是基于实际代码的最小示例:

server.ts

const bootstrap = async () => {
    process.setMaxListeners(0); //(node:7310) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 uncaughtException listeners added to [process]. Use emitter.setMaxListeners() to increase limit
                                //appears on app startup (however seems like this setMaxListeners(0) doesnt affect anything since the warning persist)
    const app = new Koa();
    app.use(async ctx => {
        ctx.body = "Welcome to my Server!";
    });
    app.listen(port);
    new Main().run();
};

bootstrap(); 
Run Code Online (Sandbox Code Playgroud)

main.ts(尝试:cronNPM包,node-schedulersetInterval,递归setTimeout)来运行scheduledJobWrapper

    isStarting: boolean = false;

    async run() {
        logger.info(`running the app, every 2 minutes`);

        //let that = this;
        // new CronJob(`*/2 * * * *`, function () {
        //     that.scheduledJobWrapper();
        // }, null, true, 'America/Los_Angeles');

        const interval = 2 * 60 * 1000;
        setInterval(() => {
            this.scheduledJobWrapper();
        }, interval);
    }

    async scheduledJobWrapper() {
        logger.info("here scheduledJobWrapper");

        let args = {};
        //some irrelevant logic to set the arguments
        await this.scheduledJob(args);
    }

    async scheduledJob(args) {
        try {
            logger.info("starting");
            if (!this.isStarting) {
                this.isStarting = true;

                const runningCount = Executor.tasks.length; //Executor.tasks is a singleton containing some info about tasks. details are irrelevant. the point is it contains the active tasks.
                const tasksLimit = 100;

                if (runningCount < tasksLimit) {
                    for await (const i of Array(tasksLimit - runningCount).keys()) {
                        if (Executor.tasks.length > 20)
                            await global.sleep(5 * 1000);

                        this.startWrapper(args); //calling main task here
                    }
                }
                this.isStarting = false;

                logger.info(`Started: ${Executor.tasks.length - runningCount}`);
            }
        } catch (e) {
            logger.error("Error running scheduled job: " + e.toString());
        }
    }
Run Code Online (Sandbox Code Playgroud)

在此示例中,问题表现如下:预期的所有工作在最初的3-5个小时内进行,之后每次执行计划的函数调用时:

  1. logger.info("here scheduledJobWrapper"); 现在不会显示任何输出。
  2. logger.info("starting"); 不在输出中
  3. this.startWrapper 确实在运行,并且其中的代码正在执行。

尽管其中的代码this.startWrapper仍在运行,但是新创建的作业的数量正在缓慢减少。硬件(RAM / CPU)负载不大(CPU低于10%,RAM低于20%)

关于可能原因的任何线索?

nodejs: 12.6.0

谢谢!

更新 似乎与使用setInterval该应用程序的运行时间更长(6-24小时),但此后问题仍然开始。

xar*_*rgr 0

首先,最好将 Main() 的实例移动到监听范围内:

app.listen(port, () => {
   new Main().run();
});
Run Code Online (Sandbox Code Playgroud)

我不知道在后端运行 setInterval 函数有多好。最好提取这个逻辑并将其移动到 cron 作业中。

我们确定机器可以运行 100 个任务吗?请按顺序计算任务并查看问题何时开始。也许您无法安排 100 个任务并且在某处存在一个限制