nodejs:在什么情况下,Settimeout无法运行功能? CPU悬挂?
我的基于Settimeout Recells的Hight加载脚本。经过几天不间断的操作后,有时序列有一个断裂。
代码示例:
function someFnc(threadNum) {
try {
console.log(`[${threadNum}] Execution...`);
// a lot of code...
console.log(`[${threadNum}] Going to sleep 30s...`);
setTimeout(() => someFnc(threadNum), 30 * 1000);
} catch(e) {
console.error(e);
setTimeout(() => someFnc(threadNum), 1000);
}
}
// run threads
someFnc(0);
someFnc(1);
someFnc(2);
在控制台中我看到了:
[0] Execution...
[1] Execution...
[2] Execution...
...other logs...
[0] Going to sleep 30s...
[1] Going to sleep 30s...
[2] Going to sleep 30s...
[0] Execution...
[1] Execution...
[2] Execution...
...other logs...
[0] Going to sleep 30s...
[1] Going to sleep 30s...
[2] Going to sleep 30s...
[0] Execution...
[1] Execution...
[2] Execution...
...other logs...
[0] Going to sleep 30s...
[1] Going to sleep 30s...
[2] Going to sleep 30s...
它有效1-2天,一些线程(例如2)在[2]上冻结30s ...
因此,其他线程正常工作正常但是一些线程也可以冻结。
我的想法:
- 我在功能开始时有一个
console.log
,我一定会查看该功能是否运行。因此,我可以得出结论,该功能在挂起后再也不会被调用。 - 我看到的最后一条消息是
[n]进入30s ...
,其次是settimeout
,而没有其他。 - 由于这个两个原因,我可以得出结论,
settimeout
的问题。 - 我有一个高度加载的系统,每天数百万
settimeout
执行,有时我的CPU已100%加载,并且冻结了几秒钟。我认为这可能是计时器失败的原因,我没有其他想法。
有人知道如何跟踪计时器是否启动?如何调试?
在内核级别的工作方式?
谁知道settimeout 系统记住我的代码应在06/26/2022 10:01:54.123上执行。 但是,如果CPU冻结了2秒钟,则下一个tick稍后发生,计时器只是输掉/忽略了此任务,而拒绝启动它,因为它很旧?
尽管在我看来,所有任务必须在一段时间(超时/间隔)形成队列后完成,如果一个任务未完成,那么另一个任务也不会启动。在这种情况下,整个程序将冻结,但我看到其余的计时器毫无问题地工作。
就我而言,计时器“按时”的准确性不是很重要,但必须执行。如果我的假设是正确的,并且Nodejs跳过了“陈旧”计时器,是否有可能避免这种情况并强迫他们运行?
我使用了nodejs 12.x,但决定更新,现在我有v14.18.2
。
I have hight loaded script based on setTimeout recalls. After several days of uninterrupted operation, sometimes there is a break in the sequence.
Code example:
function someFnc(threadNum) {
try {
console.log(`[${threadNum}] Execution...`);
// a lot of code...
console.log(`[${threadNum}] Going to sleep 30s...`);
setTimeout(() => someFnc(threadNum), 30 * 1000);
} catch(e) {
console.error(e);
setTimeout(() => someFnc(threadNum), 1000);
}
}
// run threads
someFnc(0);
someFnc(1);
someFnc(2);
In console I see this:
[0] Execution...
[1] Execution...
[2] Execution...
...other logs...
[0] Going to sleep 30s...
[1] Going to sleep 30s...
[2] Going to sleep 30s...
[0] Execution...
[1] Execution...
[2] Execution...
...other logs...
[0] Going to sleep 30s...
[1] Going to sleep 30s...
[2] Going to sleep 30s...
[0] Execution...
[1] Execution...
[2] Execution...
...other logs...
[0] Going to sleep 30s...
[1] Going to sleep 30s...
[2] Going to sleep 30s...
it works 1-2 day and some thread (for example 2) freeze on [2] Going to sleep 30s...
as a result, other threads works fine but some thread can freeze too.
My thoughts:
- I have a
console.log
at the very beginning of the function, I will definitely see if the function is run. Therefore, I can conclude that the function was never called again after the hangup. - The last message I see is
[n] Going to sleep 30s...
followed bysetTimeout
and nothing else. - For this 2 reasons, I can conclude that the problem with
setTimeout
. - I have a highly loaded system, millions of
setTimeout
executions per day, sometimes my CPU is 100% loaded and has freezes for a few seconds. I think that this may be the reason for the failure of the timer, I have no other ideas.
Does anyone know how to track if the timer has been started? How can this be debugged?
Who knows how setTimeout works at the kernel level?
Perhaps when I do setTimeout(..., 30 * 1000)
, the system remembers that my code should be executed for example on 06/26/2022 10:01:54.123, checks every 17 milliseconds for example the current system time and if it finds a time match (+- 50ms for example), it run it.
But, if the CPU freezes for 2 seconds, the next tick occurs later and the timer simply loses/ignores this task, refuses to start it because it is very old?
although it seems to me that all tasks that must be completed after a period of time (timeout/interval) form a queue, and if one was not completed, then the other would not be started either. In this case, the whole program would freeze, but I see that the rest of the timers work without problems.
In my case, the accuracy of the timer "on time" is not very important, but it must be executed. If my assumptions are correct and nodejs is skipping "stale" timers, is it possible to avoid this and force them to run?
I used nodejs 12.x, but decided to update and now I have v14.18.2
.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我知道的一种情况是将其设置为约24.855天。
它只是失败。
其次,JS时间不准确,IE 1000ms有时为988ms有时1002ms,依此类推...
因此,如果您有很多超时(不建议它消耗大量资源),那么他们肯定会重叠。
如果您需要订单,只需使用队列或消息传播。
另外可能还有内存问题 - 是否有任何限制?
,我将其更改为:
One case I know is setting it to wait for more that about 24.855 days.
It just fails.
Second, the JS time is not accurate, i.e. 1000ms are sometimes 988ms sometimes 1002ms and so on...
So there's a big chance that if you have many timeouts (which is not recommended as it consumes a ton of resources) they can definitely overlap.
If you need an order, just use a Queue or a Message-broker.
Also there might be memory issues - Is there any limit to setTimeout?
And lastly, I'd change it to: