Socket.io + MQTT = Memory leak?!
因業務需求而踏入了Node.js這完全陌生的領域。
新手的起手式不外乎參考各前輩的範例,
爬了一堆文後參考超圖解物聯網IoT實作入門的一段範例:
這寫法確實達到了我的需求:收到MQTT訊息後,用Socket.io更新畫面資訊。
但系統運行中總是三不五時就會出現node的抱怨:
接著就會看到記憶體用量不停的暴增,
然後...他就死了。
PM2重開後撐不了幾個小時就會死掉,
嚴重的時候甚至要整台server重啟才行。
這個嚴重的Memory leak困擾了一個月左右,
這一個月真是提心吊膽,
每天睜開眼第一件事就是拿手機開網頁...
找了每個可能發生問題的地方都一無所獲,
原本一直在懷疑是Socket.io,
但它的寫法就這麼簡單,
看起來沒什麼能寫錯的地方,
MQTT的寫法也就這麼簡單,
看起來也沒什麼能寫錯的地方,
所以到底是哪出問題了?
後來我家聰明的PM大人提供了一個可能可以嘗試的方法:把Socket.io和MQTT分開。
因為他在漫長的搜索答案當中看到了不把MQTT包在Socket.io的寫法。
好吧,死馬當做活馬醫了。
(其實我本身是滿懷疑這方法能行嗎? 畢竟人家那本書似乎賣得不錯,這麼寫的人應該也不少,沒看到相關的問題啊?)
於是動手把Code改成這樣:
var sio = io.listen(server);
/*MQTT*/
client.on('message', function (topic, msg) {
sio.emit('mqtt', {'msg': msg.toString()});
});
/*Socket.io*/
sio.on('connection', function(socket){
socket.emit('sio', { 'msg': 'data'});
});
P.S:sio.emit 和 socket.emit 雖然都可以傳送資料,但還是有些微差別,詳細內容請至Socket.io網站研究
就這樣,再也沒有發生記憶體暴增的問題了!
說真的,我到現在還是不知道為什麼這樣就能解掉這問題?
我猜也許是MQTT發送頻率不同造成?
我們的案子中MQTT是一秒發送一次,
可能是因為太密集造成記憶體回收來不及?
如果有大大知道為什麼,
還請不吝指教,謝謝!