nodejs服務(wù)內(nèi)存泄露排查過(guò)程和優(yōu)化方法
背景
首先項(xiàng)目最初不是自己寫的,項(xiàng)目接手一段時(shí)間后才發(fā)現(xiàn)了問(wèn)題,往往這種情況不能第一時(shí)間定位到具體代碼,需要根據(jù)用戶反饋以及工具排查。
剛開(kāi)始用戶反饋接口卡頓,影響正常使用,我這邊查看日志發(fā)現(xiàn)沒(méi)有異常報(bào)錯(cuò),就嘗試重啟應(yīng)用,重啟后解決問(wèn)題。
分析問(wèn)題
我嘗試了以下步驟
- 由于是代理服務(wù),我以為是請(qǐng)求過(guò)多,導(dǎo)致服務(wù)日志寫入過(guò)多導(dǎo)致,所以我只保留了嚴(yán)重錯(cuò)誤日志,運(yùn)行一段時(shí)間后發(fā)現(xiàn)無(wú)效
- 由于前不久做過(guò)一次容器化部署,程序跑一段時(shí)間后會(huì)生成
core.42
文件,文件很大,有30G, 該文件是進(jìn)程崩潰的內(nèi)存和寄存器的快照。我又嘗試不使用docker
部署,運(yùn)行一段時(shí)間后發(fā)現(xiàn)無(wú)效 - 使用
pm2 list
發(fā)現(xiàn)進(jìn)程的內(nèi)存使用異常高,高達(dá)3.4GB,這才發(fā)覺(jué)可能是內(nèi)存泄露導(dǎo)致程序崩潰
pm2 list ┌────┬─────────┬─────────────┬─────────┬─────────┬──────────┬────────┬──────┬───────────┬──────────┬──────────┬──────────┬──────────┐ │ id │ name │ namespace │ version │ mode │ pid │ uptime │ ? │ status │ cpu │ mem │ user │ watching │ ├────┼─────────┼─────────────┼─────────┼─────────┼──────────┼────────┼──────┼───────────┼──────────┼──────────┼──────────┼──────────┤ │ 0 │ erra │ default │ 0.6.53 │ cluster │ 30696 │ 2h │ 23 │ online │ 0% │ 3.4gb │ root │ disabled │ └────┴─────────┴─────────────┴─────────┴─────────┴──────────┴────────┴──────┴───────────┴──────────┴──────────┴──────────┴──────────┘
內(nèi)存泄漏分析
- 利用Node.js內(nèi)置工具: Node.js提供了一些內(nèi)置工具來(lái)分析內(nèi)存使用情況,如
--inspect
參數(shù)。啟動(dòng)Node.js應(yīng)用程序時(shí)加上該參數(shù),并使用Chrome開(kāi)發(fā)者工具的Memory選項(xiàng)來(lái)觀察內(nèi)存使用情況。
node --inspect --heapsnapshot-signal=SIGUSR2 ./bin/erra.js start
- 打開(kāi) chrome://inspect/#devices
- 啟動(dòng)項(xiàng)目后,先在Menory中創(chuàng)建一個(gè)初始的快照
- 然后進(jìn)行多次操作(根據(jù)項(xiàng)目流程操作),在創(chuàng)建一個(gè)快照進(jìn)行內(nèi)存對(duì)比,發(fā)現(xiàn)內(nèi)存翻倍的增加
- 通過(guò) Retained Size 排序,展開(kāi)頭幾項(xiàng)看看,展開(kāi)到能看到具體對(duì)象或者方法為止
- 通過(guò)展開(kāi)(closure)也可以定位到文件,到此基本可以確定是 proxy-server.js文 件 與proxyReq 對(duì)象相關(guān)出現(xiàn)了內(nèi)存泄露,由于我是本地調(diào)試,所以可以通過(guò)點(diǎn)擊文件名跳轉(zhuǎn)到源碼處
解決問(wèn)題
通過(guò)代碼發(fā)現(xiàn),確實(shí)存在漏洞, 這種情況屬于事件監(jiān)聽(tīng)器未移除 (由于初版代碼不是自己寫的,不能一眼發(fā)現(xiàn)此處有問(wèn)題。)
雖然這里可以改成監(jiān)聽(tīng)事件處理后釋放就可以解決,但是其實(shí)這里只需監(jiān)聽(tīng)一次就行避免頻繁監(jiān)聽(tīng)并移除
驗(yàn)證結(jié)果
為保證是否還存在其他問(wèn)題,需要重復(fù)上面的步驟,重新驗(yàn)證是否還存在內(nèi)存泄露。經(jīng)過(guò)多次模擬操作之后,內(nèi)存穩(wěn)定在 16.6M 左右,確定沒(méi)問(wèn)題后在發(fā)布
結(jié)論
由于代碼可以在本地復(fù)現(xiàn),所以排查過(guò)程還是比較順利的。如果是盲排重點(diǎn)從:定時(shí)器未清除、事件監(jiān)聽(tīng)器未移除、未釋放資源 方向入手。
以上就是nodejs服務(wù)內(nèi)存泄露排查過(guò)程和優(yōu)化方法的詳細(xì)內(nèi)容,更多關(guān)于nodejs服務(wù)內(nèi)存泄露的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Koa從零搭建到Api實(shí)現(xiàn)項(xiàng)目的搭建方法
這篇文章主要介紹了Koa從零搭建到Api實(shí)現(xiàn)項(xiàng)目的搭建方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-07-07NPM 安裝cordova時(shí)警告:npm WARN deprecated minimatch@2.0.10: Pleas
這篇文章主要介紹了NPM 安裝cordova時(shí)警告:npm WARN deprecated minimatch@2.0.10: Please update to minimatch 3.0.2 or higher to的相關(guān)資料,需要的朋友可以參考下2016-12-12Node.js API詳解之 dns模塊用法實(shí)例分析
這篇文章主要介紹了Node.js API詳解之 dns模塊用法,結(jié)合實(shí)例形式分析了Node.js API中dns模塊基本功能、相關(guān)函數(shù)與使用技巧,需要的朋友可以參考下2020-05-05nodejs實(shí)現(xiàn)遍歷文件夾并統(tǒng)計(jì)文件大小
這篇文章主要介紹了nodejs實(shí)現(xiàn)遍歷文件夾并統(tǒng)計(jì)文件大小,下面使用nodejs的遍歷文件夾文件內(nèi)容,并且讀取所有的文件,并采取排序往大到小的順序進(jìn)行輸出,需要的朋友可以參考下2015-05-05NodeJS模塊與ES6模塊系統(tǒng)語(yǔ)法及注意點(diǎn)詳解
這篇文章主要給大家介紹了關(guān)于NodeJS模塊與ES6模塊系統(tǒng)語(yǔ)法及注意點(diǎn)的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-01-01