項目中使用了nuxtjs框架進行開發,在開發測試過程當中均無出現任何異常。部署上線到正式生產環境以後,運行了五六天以後node異常,服務中止響應,pm2管理平臺沒法恢復應用程序。須要進入生產環境進行重啓項目。查閱運行日誌以後發現生產服務器會緩慢堆積tcp連接。在到必定的程度以後,會引起node程序 cpu 100%佔用,中止響應。最初階段覺得是_nuxt下的文件並未經過nginx訪問,而是經過node進行讀取的,形成文件打開過多,從新配置了nginx靜態文件讀取規則以後,問題依舊。在解決這個問題的過程當中發現某個文章中提到,若是node內存泄漏會形成node進程跑滿當前cpu,而且打開文件數飆增。html
安裝node-heapdump。node
npm install node-heapdump --save-dev
打開項目根目錄的nuxt.config.js文件,進行heapdump配置。nginx
// 內存快照代碼 var headpdump = require('heapdump') // setInterval(function () { console.log('st headpdump') headpdump.writeSnapshot(function(err, filename) { console.log('dump written to', filename) }) }, 15000) module.exports = {...// nuxt配置}
我設定了每1.5秒,heapdump進行內存快照一次。
而且在間隔過程當中進行如下操做。chrome
等待快照完成以後,heapdump會將快照文件保存在項目根目錄中。npm
接着,咱們打開chrome開發者工具,切換到memory選項卡,點擊load載入hepdump生成在根目錄的文件。服務器
分別載入第一次頁面快照,跟刷新一次以後的快照。咱們點擊切換右側下拉箭頭的視圖
選項卡類型。點擊切換視圖到Comparison。閉包
在等候Chrome比對兩個文件以後,能夠看到第二個文件的內存快照信息。查看右側# Delta選項。
能夠看到 刷新一次以後,增長了69個閉包未釋放。
展開閉包(closure)能夠看到大量的request請求未釋放。
因而可知,問題出如今項目中服務端請求服務接口上。框架
檢查services文件中的請求方法代碼。frontend
import Urls from './url' import Fetch from './fetch.js' let fn = {} Object.keys(Urls).forEach(key => { fn[key] = (data, headers) => { return new Promise((resolve, reject) => { resolve(Fetch(Urls[key].url, {method: Urls[key].method, data, headers})) }) } }) export default fn
發現了問題,services 經過return請求,可是使用的數據都是經過箭頭方法傳遞到下一層,變量被層層引用,這樣會形成閉包沒法徹底釋放。由於傳入的數據一直都有引用沒法gc,這樣也形成了node打開的tcp連接沒法關閉釋放。tcp
咱們修改了services方法,通過修改的代碼以下:
import Urls from './url' import Fetch from './fetch.js' let fn = {} Object.keys(Urls).forEach(key => { fn[key] = function (data, headers) { return Fetch(Urls[key].url, {method: Urls[key].method, data, headers}) } }) export default fn
再次經過調試流程生成內存快照,發現request閉包都回收完畢。內存泄漏問題初步告一段落,項目更新以後已穩定運行。