node.js 中的长循环泄漏内存
Posted
技术标签:
【中文标题】node.js 中的长循环泄漏内存【英文标题】:long loop in node.js leak memory 【发布时间】:2018-06-12 08:02:43 【问题描述】:请帮助我, 我想让我的脚本同时访问多个 URL 以获取一些资源。该脚本运行正常,但问题是它泄漏内存并且服务器将关闭。请任何人帮助给我更好的解决方案。谢谢! 请帮助检查以下源代码:
var fs = require('fs');
var request = require('request');
var dir = './';
var dateTime = require('node-datetime');
const express = require('express');
const app = express();
var urls = [
'http://www.google.com',
'https://www.bing.com',
'http://www.yahoo.com',
"http://***.com",
"http://github.com",
"http://www.yahoo.co.jp"
];
var urlLength=urls.length;
function remoteControllerPress()
var dt = dateTime.create();
var newCurrentTimeDir = dt.format('Y-m-d-H-M-S').toString();
var dirName = dir+newCurrentTimeDir;
if (!fs.existsSync(dirName))
fs.mkdirSync(dirName);
console.log("==============calling at "+newCurrentTimeDir + '\n');
for(var i = 0; i<urlLength; i++)
(function()
var j = i;
var url = urls[j];
process.nextTick(function()
request(url, function(error, response, body)
console.log("---------URL: "+url);
if (!error && response.statusCode == 200)
console.log("URL: " + url + " statusCode: " + response.statusCode);
fs.writeFile(dirName+"/file_"+j, body.toString(), function(err)
if(err)
return console.log(err);
console.log(dirName+"/file_"+ j +" was saved!\n\n");
);
else if (error)
console.log("error.code:", error.code);
);
);
)();
setTimeout(function()
remoteControllerPress();
,6000);
console.log("==============running...\n ");
remoteControllerPress();
app.post('/', function (req, res)
res.send('hello world');
);
app.listen(
3000,
() => console.log('Server start listening on port 3000...')
);
【问题讨论】:
【参考方案1】:您的 remoteControllerPress 函数似乎有对自身的引用,因为您使用超时递归调用它。因此垃圾收集器无法清理内存。
一个简单(丑陋?)的解决方法应该是使用 setInterval
/*setTimeout(function()
remoteControllerPress();
,6000); <-- remove that */
console.log("==============running...\n ");
setInterval(remoteControllerPress, 6000); // <- change this
【讨论】:
感谢 Pierre Mallet 回复我,但是这个解决方案仍然增加了内存。第一次启动内存为 45Mb,然后在每个循环中增加到 105Mb 每 6 秒增加 60Mb 还是在第一次循环后达到 105 然后保持稳定? 它总是增加直到崩溃【参考方案2】:使用异步操作符做异步循环https://caolan.github.io/async/docs.html
使用 setInterval 和 setImmediate 而不是使用 setTimeout 以便在每次调用时清除上下文
var async = require("async");
function remoteControllerPress()
var dt = dateTime.create();
var newCurrentTimeDir = dt.format('Y-m-d-H-M-S').toString();
var dirName = dir+newCurrentTimeDir;
if (!fs.existsSync(dirName))
fs.mkdirSync(dirName);
console.log("==============calling at "+newCurrentTimeDir + '\n');
// TO do it 5 by 5
async.eachOfLimit(urls, 5, function(url, i, cb)
request(url, function(error, response, body)
console.log("---------URL: "+url);
if (!error && response.statusCode == 200)
console.log("URL: " + url + " statusCode: " + response.statusCode);
fs.writeFile(dirName+"/file_"+j, body.toString(), function(err)
if(err)
console.log(err);
console.log(dirName+"/file_"+ j +" was saved!\n\n");
return cb();
);
else if (error)
console.log("error.code:", error.code);
return cb();
else
return cb();
);
, function(err)
return;
);
console.log("==============running...\n ");
setInterval(function()
setImmediate(remoteControllerPress);
,6000);
【讨论】:
以上是关于node.js 中的长循环泄漏内存的主要内容,如果未能解决你的问题,请参考以下文章