【问题标题】:long loop in node.js leak memorynode.js 中的长循环泄漏内存
【发布时间】: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://stackoverflow.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...')
);

【问题讨论】:

    标签: node.js express nodes node-modules node-webkit


    【解决方案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);
    

    【讨论】:

      猜你喜欢
      • 2014-05-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-04-08
      • 2012-03-11
      • 2016-01-01
      相关资源
      最近更新 更多