V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
weiwenhao
V2EX  ›  Node.js

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

  •  
  •   weiwenhao · 2023-11-23 15:45:17 +08:00 · 2434 次点击
    这是一个创建于 377 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

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

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

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

    
    let retryCount = 4 * 60 * 60; // 基于库存检测的模式,单次耗时 3s 左右。
    
    
    (async () => {
     	// ....
    
        // 循环检测购物车
        for (let i = 0; i < retryCount; i++) {
            // ...
    
            await sleep(5);
        }
    })();
    
    

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

    16 条回复    2023-11-24 03:31:01 +08:00
    Belmode
        1
    Belmode  
       2023-11-23 15:56:03 +08:00
    不忍直视
    coderxy
        2
    coderxy  
       2023-11-23 16:38:17 +08:00
    炸裂
    Puteulanus
        3
    Puteulanus  
       2023-11-23 16:43:00 +08:00
    所以这不是 bug ,这是 feature
    flyqie
        4
    flyqie  
       2023-11-23 16:48:19 +08:00 via Android
    所以。。楼主打算怎么 fix ?
    ljtfdt
        5
    ljtfdt  
       2023-11-23 16:51:16 +08:00
    循环次数耗尽,为什么会阻塞住呢? for 循环不是不会执行了么
    weiwenhao
        6
    weiwenhao  
    OP
       2023-11-23 17:03:40 +08:00
    @ljtfdt 不执行了,但是程序也不会退出,需要手动写 exit 进行退出,我也不太理解这个机制。
    zihuyishi
        7
    zihuyishi  
       2023-11-23 17:04:00 +08:00
    八成还是哪里有 bug ,当你不知道他为什么会阻塞住的时候说明还是哪里有问题。你可能只是找到了一个表象的 bug
    weiwenhao
        8
    weiwenhao  
    OP
       2023-11-23 17:04:27 +08:00
    @flyqie 还是要 fix 一下,退出循环之后加上一个 exit(0) 让程序主动退出,然后现在也加上了 pm2 主动拉起。
    weiwenhao
        9
    weiwenhao  
    OP
       2023-11-23 17:07:21 +08:00
    @zihuyishi 好像很有道理,为啥循环结束会阻塞是一个值得深究的问题, 我再去研究一下。
    zihuyishi
        10
    zihuyishi  
       2023-11-23 17:12:23 +08:00
    @weiwenhao 好久好久没写过 nodejs 了,不过我记得 libuv 应该是 loop 里有 callback 就不会退出循环吧。对应的就是 nodejs 如果有在运行的 Promise 就不会退出?
    weiwenhao
        11
    weiwenhao  
    OP
       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
        12
    gesse  
       2023-11-23 17:23:52 +08:00
    @ljtfdt
    可能数据库没有关闭,就卡在那里了。
    aikilan
        13
    aikilan  
       2023-11-23 17:32:05 +08:00
    笑出声来 :D
    liuidetmks
        14
    liuidetmks  
       2023-11-23 17:33:56 +08:00
    数据库连接没关闭吧,
    zsj1029
        15
    zsj1029  
       2023-11-23 17:41:18 +08:00
    请用 for await ,否则循环不会等待,一次性 100 await sleep(5)
    opengg
        16
    opengg  
       2023-11-24 03:31:01 +08:00 via Android
    因为 node 在还持有 fd 或者连接,或者 event loop 未清空,或者监听了某些进程事件的时候,不会自动退出。
    我曾经遇到过有个 sdk 存在未清理的 fd ,只能在代码里手动 exit()
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1006 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 38ms · UTC 21:20 · PVG 05:20 · LAX 13:20 · JFK 16:20
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.