帮忙分析下这段 nodejs 代码的内存泄漏原因 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
msmmbl
V2EX    Node.js

帮忙分析下这段 nodejs 代码的内存泄漏原因

  •  
  •   msmmbl 2021-11-22 17:44:44 +08:00 4537 次点击
    这是一个创建于 1417 天前的主题,其中的信息可能已经有所发展或是发生改变。

    有一个实时应用,使用 nodejs 编写,会每隔一段时间调用远程 grpc ,大概每秒 1 、2 次这样的调用。上线一个月后发现服务器内存占用越来越大。大概占用了 14GB 的内存吧。用 iotop 发现 node 内存炸了。

    使用了 alinode dump heap 了,发现了有一个 promisifyCall 占用了大量内存,疑似泄露。

    调用链是

    自身大小(字节) 总大小(字节) 函数 0 524600 processTicksAndRejections internal/process/task_queues.js 0 524600 updateStatus 我自己的文件 0 524600 publish 这里调用了 grpc 导出的函数 524600 524600 promisifyCall 这里应该就是泄露的函数了 

    promisifyCall 来自于 https://github.com/bojand/promisify-call ,看了下是被 grpcCaller 引用的 https://github.com/bojand/grpc-caller 。项目中使用了 grpcCaller 去调用 grpc 方法。

    const res = await grpcCallerInstance.publish(req); 

    接着这个 publish 操作就走到promisifyCall中去了

    promisifyCall 的定义看了下,https://github.com/bojand/promisify-call/blob/master/index.js

    const wc = require('with-callback') /** * Promisifies the call to <code>fn</code> if appropriate given the arguments. * Calls the function <code>fn</code> either using callback style if last argument is a function. * If last argument is not a function, <code>fn</code> is called returning a promise. * This lets you create API that can be called in either fashions. * @param {Object} ctx context / this * @param {Function} fn The function to call * @param {arguments} args Arguments * @return {undefined|*|Promise} Promise if promisified */ function promisifyCall (ctx, fn) { const args = [] args.push.apply(args, arguments) args.splice(0, 2) // check if last (callback) argument is being pased in explicitly // as it might be undefined or null, in which case we'll replace it const same = fn.length && args.length === fn.length const lastIndex = same ? fn.length - 1 : args.length - 1 const lastArg = args && args.length > 0 ? args[lastIndex] : null const cb = typeof lastArg === 'function' ? lastArg : null if (cb) { return fn.apply(ctx, args) } return wc(callback => { same ? args[lastIndex] = callback : args.push(callback) fn.apply(ctx, args) }) } 

    隐约感觉里面的 args 变量可能会导致泄露。但还是没想明白怎样才会发生这个泄露。

    第 1 条附言    2021-11-23 08:49:33 +08:00
    重启应用后内存不涨了,先再跑一个月看看
    msmmbl
        1
    msmmbl  
    OP
       2021-11-22 18:04:12 +08:00
    我可能搞错了,524600 字节并不大。再抓一晚上数据看看。
    zhzbql
        2
    zhzbql  
       2021-11-22 18:07:24 +08:00
    Node.js 不用 buffer 不是最大内存 1.4GB 吗,兄弟你这 14GB 怎么搞出来的
    msmmbl
        3
    msmmbl  
    OP
       2021-11-22 18:14:29 +08:00
    @zhzbql 同时起了多个进程
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     1110 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 27ms UTC 23:17 PVG 07:17 LAX 16:17 JFK 19:17
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86