Node.js如何應對內存泄露?
自己用node.js編了個爬蟲程序,在digital ocean上面搭建了兩個docker容器一個node container和一個mongoDB container。使用docker run --link將兩個容器連接起來,大致的架構是這樣。
剛開始運行時,程序正常,mongoDB裡面也有相應的數據,但是隨著時間的推移,內存佔用逐漸增高,最終 process out of memory,node進程退出。請問,Node.js 有什麼辦法檢測/監測/探測內存使用情況,有沒有相應的工具或者包能完成此功能,來針對內存泄露的情況做出debug?
用bnoordhuis/node-heapdump來debug我一般會這樣做(在我確定是memory leak的前提下)
// 第一個dump
heapdump.writeSnapshot("..../app-start.dump")
// 五分鐘後,第二個dump
setTimeout(function () {
heapdump.writeSnapshot("..../app-5min.dump")
}, 60*5*1000)
然後在chrome devtool =&> profile =&> load進兩個dump進行比較。
這篇文章How to Self Detect a Memory Leak in Node把memwatch和heapdump結合起來用,可能對你有用,我沒用過,我覺得用好heapdump應該夠了。
多數leak是因為代碼沒寫好,用點心思讀代碼是可以排除的。比如某個全局對象上只增不減的某些操作或者事件處理函數引用了closure里比較大的對象。內存泄漏其實歸根結底一定可以通過內存快照分析得出,有興趣的朋友可以看看這個:
輕鬆排查線上Node內存泄漏問題 - CNode技術社區
Walmart Node.js Memory LeakWalmart Node.js Memory Leak Part I (翻牆看視頻)
我一般會用pm2拉起node程序,然後設置超過300m內存自動重啟 個人網站絕對跑的剛剛的
-----------20170425-----
內存泄漏這種問題非常蛋疼,解決泄漏問題的難點有1. 如何快速的重現問題 2. 如何驗證泄漏已經解決 如果你不能很好的回答這兩個問題,請使用上面提到的重啟大法,如果可以清晰的回答,那麼恭喜你,這個bug你已經解決,但是我仍然推薦你使用上面的重啟大法,避免你半夜2點鐘被叫起來重啟服務
推薦一個強大的,不僅僅能查看內存泄露,還能看很多東西
Easy-Monitor 2.0: 開啟你的 Node.js 內核性能監控
今年遇到過兩次 Node.js 內存泄漏的問題了。現在 Node.js 已經內置了 inspect 工具了:Node.js v9.2.0 Documentation 。通過這個工具就能檢查。
要真說如何解決問題。。。我一次是換了 mongodb 庫的版本,一次是換了 Node.js 本身的版本,然後問題就消失了。。。
吐個槽,一般的 web 程序想寫出內存泄漏也挺是 tm 有難度的,很多時候就是各種庫有問題或者是 Node.js 的某個版本有問題。。。
Dump出來,放到chrome dev tool 的profile 裡面看。大部分情況就是流量估算有問題,或者沒做限流導致的。
重啟更方便,也更健康。像php-fpm,一般都會配置運行多少次就回收進程重新創建。爬蟲重啟也關係不大。
首先要分清自己想要什麼,不花力氣解決問題,或者一勞永逸的解決問題。
不花力氣解決問題:
1. 就像 @Ian Liu 所說的用pm2設置一個內存值上限,然後超過,就重啟。自己的網站是沒什麼問題,只要網站沒有過多的依賴內存中的狀態。
2.花錢,阿里的alinode(https://alinode.aliyun.com/)很好用,好像可以免費試用15天。
一勞永逸的解決問題:
怎麼解決了,當然是找到問題的根源,為什麼會發生內存泄露?哪個變數發生了內存泄露?這個如果自己有一個很好的js基礎,寫的時候應該有一個好的感覺,然後針對的調試這些代碼,我一般用vscode打斷點,看內存中變數的快照,因為自己知道相應的代碼塊很快就能定位到問題。
但是如果不能那就沒有辦法嗎?當然不是,這裡有幾個devtool:devtool、heapdump + chrome devTool、memwatch等等,網上一搜一大堆。
ref:
- 如何定位 Node.js 的內存泄漏
- 記一次 Node.js 應用內存暴漲分析
最後定位到問題怎麼解決問題?那就要對node對gc的原理要清楚,推薦看《深入淺出Nodejs》裡面說的很不錯。
貌似阿里即將推出一個nodejs內存泄漏的檢測工具
推薦閱讀:
※怎樣學 MongoDB?
※MongoDB 或者 redis 可以替代 memcached 嗎?
※爬蟲爬下來的數據(100G級別,2000W以上數據量)用mysql還是mongodb存儲好?
TAG:JavaScript | MongoDB | Nodejs | 內存泄露 | 伺服器端開發 |