Node.js似乎正在收集私有变量,即使它们是需要的

时间:2013-12-21 17:55:59

标签: node.js garbage-collection

我有几个模块从数据库中提取数据并将它们存储在本地内存中。然后,我有一些函数可以在不同页面需要时从对象中提取数据。它运行良好,除了我的登台服务器上每天一次或两次对象为空,我必须重新启动到服务器以再次填充数据。

我已经删除了一些复杂性,但这是一个想法,几个小时后,道路为空,getRoad总是返回null;

var db = require('./db.js');

var roads = [];
db.query('select * from road', function(err, rows) {
    if (err) { console.log(err); }
    roads = rows;
});

module.exports.getRoad = function(id) {
    if (roads[id]) {
        return roads[id];
    }
    return null;
};

更新

我正在添加db.js,以便您可以看到其中的内容。我还在每一个都进行了大量的日志记录,所以下次失败时我会有更多细节。

var Pool = require('mysql-simple-pool');

var mysql_pool = new Pool(50, {
    host: process.env.IP || '127.0.0.1',
    user: 'username',
    password: 'password',
    database: 'database'
});

module.exports = mysql_pool;

更新

好吧,我可能会提出一个单独的问题,但似乎唯一突破的是调用数据库。所以它绝对不是垃圾收集的问题。似乎有些错误或与mysql-simple-pool或类似的东西有关。如果有人知道为什么mysql-simple-pool会在12个小时后停止响应,我会很感激:)。

1 个答案:

答案 0 :(得分:1)

从这个简化的代码示例中,我能看到的唯一场景是你的db.query回调函数最终会在几个小时后第二次被调用,这表明db.js中存在某种问题。

您是否检查了日志中的console.log(err)输出?

roads中的数据不会被垃圾回收,因为如果你正在调用getRoad必须是对模块的可访问引用;如果对模块本身有可访问的引用,则您的本地人将无法收集资格。

另外,一些提示:在回调函数中,如果没有错误,你应该只采取行动。换句话说,添加 else

db.query('select * from road', function(err, rows) {
    if (err) { console.log(err); }
    else roads = rows;
});

如果您的回调确实第二次被调用(有错误),这将阻止roads被任何内容覆盖。

最后,我强烈建议让getRoad异步。如果您需要转向更具伸缩性的缓存解决方案(即redis / memcahed / etc),这将为您提供未来的灵活性。类似的东西:

module.exports.getRoad = function(id, cb) {
    if (roads[id]) { // this part could later be easily substituted for some
        cb(null, roads[id]); // other caching mechanism.
    } else {
        db.query('select * from road where id=?', [id], function(err, row) {
            if (err) cb(err);
            else if (row.length == 0) cb('Not found');
            else {
                roads[id] = row[0];
                cb(null, row[0]);
            }
        });
    }
};