奇葩的 bug 经历, nodejs 写了个库存监控工具,运行一段时间后总是卡死

2023-11-23 15:45:17 +08:00
weiwenhao  weiwenhao

每次都是运行 10 多个小时就卡死,不退出执行,也没有错误日志。

所以打了些断点想看看卡死在哪里了,结果在非常奇怪的位置。查看内存溢出,fd 溢出等等都比较正常。stack 追踪太复杂,没找到合适的工具。

查论坛有个解决办法就是限制循环运行的次数,在运行一段时间后主动使用 process.exit 退出然后让 pm2 拉起来。

于是准备去改代码实操了,却发现之前的代码是这样的 👇


let retryCount = 4 * 60 * 60; // 基于库存检测的模式,单次耗时 3s 左右。


(async () => {
 	// ....

    // 循环检测购物车
    for (let i = 0; i < retryCount; i++) {
        // ...

        await sleep(5);
    }
})();

Σ(°ロ°),原来是我自己加了 retryCount ,但是我忘记了!!!原来卡死就是循环次数耗尽了。(另外这一段代码循环次数耗尽并不会退出会阻塞住)

2563 次点击
所在节点   Node.js  Node.js
16 条回复
Belmode
Belmode
2023-11-23 15:56:03 +08:00
不忍直视
coderxy
coderxy
2023-11-23 16:38:17 +08:00
炸裂
Puteulanus
Puteulanus
2023-11-23 16:43:00 +08:00
所以这不是 bug ,这是 feature
flyqie
flyqie
2023-11-23 16:48:19 +08:00
所以。。楼主打算怎么 fix ?
ljtfdt
ljtfdt
2023-11-23 16:51:16 +08:00
循环次数耗尽,为什么会阻塞住呢? for 循环不是不会执行了么
weiwenhao
weiwenhao
2023-11-23 17:03:40 +08:00
@ljtfdt 不执行了,但是程序也不会退出,需要手动写 exit 进行退出,我也不太理解这个机制。
zihuyishi
zihuyishi
2023-11-23 17:04:00 +08:00
八成还是哪里有 bug ,当你不知道他为什么会阻塞住的时候说明还是哪里有问题。你可能只是找到了一个表象的 bug
weiwenhao
weiwenhao
2023-11-23 17:04:27 +08:00
@flyqie 还是要 fix 一下,退出循环之后加上一个 exit(0) 让程序主动退出,然后现在也加上了 pm2 主动拉起。
weiwenhao
weiwenhao
2023-11-23 17:07:21 +08:00
@zihuyishi 好像很有道理,为啥循环结束会阻塞是一个值得深究的问题, 我再去研究一下。
zihuyishi
zihuyishi
2023-11-23 17:12:23 +08:00
@weiwenhao 好久好久没写过 nodejs 了,不过我记得 libuv 应该是 loop 里有 callback 就不会退出循环吧。对应的就是 nodejs 如果有在运行的 Promise 就不会退出?
weiwenhao
weiwenhao
2023-11-23 17:15:59 +08:00
@zihuyishi 对的,我现在测试了一下,就是有没清理的环境,所以整个 async fn 不会退出。

(async () => {
var browser = await firefox.launch();

var context = await browser.newContext();

// await context.close(); // 这里注释就不会退出执行。
// await browser.close();

console.log("done??");
})();
gesse
gesse
2023-11-23 17:23:52 +08:00
@ljtfdt
可能数据库没有关闭,就卡在那里了。
aikilan
aikilan
2023-11-23 17:32:05 +08:00
笑出声来 :D
liuidetmks
2023-11-23 17:33:56 +08:00
数据库连接没关闭吧,
zsj1029
2023-11-23 17:41:18 +08:00
请用 for await ,否则循环不会等待,一次性 100 await sleep(5)
opengg
2023-11-24 03:31:01 +08:00
因为 node 在还持有 fd 或者连接,或者 event loop 未清空,或者监听了某些进程事件的时候,不会自动退出。
我曾经遇到过有个 sdk 存在未清理的 fd ,只能在代码里手动 exit()

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/994554

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX