背景
使用nodejs的request向python的flask rest api放送大量的請求導致的”heap out of memory”。
messages.forEach((message)=>{
request({
url: url,
method: `POST`,
json: true,
body: JSON.stringify(message),
}).on(`end`, ()=>{
server.logger.info(`End`);
}).on(`error`, (err) => {
server.logger.error(`Error:${err.toString()}`);
});
});
分析原因
- node記憶體不足
- message object 沒有儘早釋放
- request沒有結束,body裡面的內容沒有及時釋放
解決辦法
- 嘗試 node –max_old_space_size=4096 main.js 增加記憶體。
經過測試,發現的程式的確可以多佔用一些記憶體,跑的久一點,但是最後還是崩了。 - 嘗試 把JSON.stringify(message)提出來,用temp存放,然後把message設定為null, 希望gc能提前回收message。
經過測試,發現效果不明顯,程式依然崩潰。 - 設定request的timeout到1秒。
經過測試,記憶體能回收了,程式執行了,但是python沒有收到訊息。 - 重構python的flask restful api, 使用tornado和flask混用方式,讓python先返回結果,然後再執行task。
經過測試, 程式記憶體維持穩定, 完美執行。
思考
如果記憶體不是持續的增長,而是某時刻一下需要比較大的記憶體,可以嘗試使用上述解決辦法#1;
如果是記憶體在持續增長,需要分析什麼引起的,是因為沒有及時釋放記憶體還是因為記憶體洩露,比如閉包,定時器等。然後對症下藥。
再想想#3還可能遇到的問題,首先是網路不好的情況,python返回慢了的依然會有問題。若是要解決其實應該用stream把messages整體一起傳給python。但是因為現在我正處於封閉開發的階段,沒有時間去重構。