由node的批量requests引起的”heap out of memory”解決方案

NicolasHe發表於2019-02-16

背景
使用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()}`);
    });
  });

分析原因

  1. node記憶體不足
  2. message object 沒有儘早釋放
  3. request沒有結束,body裡面的內容沒有及時釋放

解決辦法

  1. 嘗試 node –max_old_space_size=4096 main.js 增加記憶體。
    經過測試,發現的程式的確可以多佔用一些記憶體,跑的久一點,但是最後還是崩了。
  2. 嘗試 把JSON.stringify(message)提出來,用temp存放,然後把message設定為null, 希望gc能提前回收message。
    經過測試,發現效果不明顯,程式依然崩潰。
  3. 設定request的timeout到1秒。
    經過測試,記憶體能回收了,程式執行了,但是python沒有收到訊息。
  4. 重構python的flask restful api, 使用tornado和flask混用方式,讓python先返回結果,然後再執行task。
    經過測試, 程式記憶體維持穩定, 完美執行。

思考
如果記憶體不是持續的增長,而是某時刻一下需要比較大的記憶體,可以嘗試使用上述解決辦法#1;
如果是記憶體在持續增長,需要分析什麼引起的,是因為沒有及時釋放記憶體還是因為記憶體洩露,比如閉包,定時器等。然後對症下藥。
再想想#3還可能遇到的問題,首先是網路不好的情況,python返回慢了的依然會有問題。若是要解決其實應該用stream把messages整體一起傳給python。但是因為現在我正處於封閉開發的階段,沒有時間去重構。

相關文章