这是泄漏记忆吗?

时间:2013-02-05 14:46:13

标签: node.js memory-leaks kue

我的代码泄漏了内存。几个小时后,它会填满整个内存并崩溃。我在这里简化了我的代码,是否有人能够判断它是否泄漏?谢谢。

var request = require('request').forever(), // as per [1]
    async = require('async'),
    kue = require('kue'),
    jobs = kue.createQueue(),
    pool = { maxSockets: 1 };



function main (job, done) {
    async.series(
        [function (callback) {
            var req = request({url: job.data.URL1, pool: pool}, function (err, resp, body) {
                //stuff...
                callback(err);
            });
        },
        function (callback) {
            var req = request({url: job.data.URL2}, function (err, resp, body) {
                //stuff...
                callback(err);
            });
        }
        ],
        function (err) {
            //stuff...
            done();
        }
    );

}

jobs.process('job_name', function (job, done) {  //many jobs with 'job_name' in the queue
    main (job, done);
});

[1] https://groups.google.com/d/msg/nodejs/ZI6WnDgwwV0/sFm4QKK7ODEJ

2 个答案:

答案 0 :(得分:1)

我认为你的代码不应该受到指责。我使用kue时遇到了同样的问题,为了确保我没有做错任何事我做了一个像这样的超级简单工作者:

var Redis       = require('redis'),
    kue         = require('kue'),
    config      = require("../../config/local.js"),
    redisClient = Redis.createClient(config.redis),
    jobs        = kue.createQueue({ redis : config.redis });

jobs.process('testjobs', function processJob(job, done, error) {
    console.log(job.data, error);
    done();
});

运行此代码让我意识到kue是泄漏的那个。解决方法是使用pm2,这个人将运行你的程序并在内存进入屋顶时重新启动它,我使用JSON App Declaration配置之前允许的最大内存量重启过程。

{
  "apps" : [
    {
      "name": "test_worker",
      "script": "test.js",
      "instances": 1,
      "max_restarts": 10,
      "max_memory_restart" : "10M",
      "ignore_watch": [
        "[\\/\\\\]\\./",
        "node_modules"
      ],
      "merge_logs": true,
      "exec_interpreter": "node",
      "exec_mode": "fork_mode"
    }
  ]
}

希望这有帮助。

答案 1 :(得分:1)

如果听起来,作业被添加到队列中的速度比它们被拉出的速度快,你会看到你的内存使用量增长。这不完全是内存泄漏。这是Kue如何提供job-level events的一部分。

默认情况下,Kue挂起到内存中的作业,直到作业完成或失败。它这样做是为了它可以在创建作业的过程中触发作业级事件(例如startprogresscompletefailed)。

这意味着当前队列中的所有作业也存在于创建它们的进程的内存中(假设没有应用程序重新启动)。只要队列没有备份,您就不会看到内存增长。但是,如果队列备份内存增长,有时会令人担忧。

怎么办?如果您关闭作业级事件,Kue将在排队后不会挂起作业。您可以使用jobEvents标志全局执行此操作:

 kue.createQueue({jobEvents: false});

或者您可以使用作业的events方法打开或关闭每个作业的作业级事件:

var job = queue.create('test').events(false).save();

如果您根本不需要回复工作事件,这些工作就可以了。但是,如果您确实需要处理作业的事件,则可以使用queue-level events。由于作业不在内存中,你需要从redis中获取作业以便用它做任何事情:

queue.on('job complete', function(id, result){
  kue.Job.get(id, function(err, job){
    // do something with the job
  });
});