【问题标题】:Node.js seems to be collecting private variables even though they're neededNode.js 似乎正在收集私有变量,即使它们是必需的
【发布时间】:2013-12-21 17:55:59
【问题描述】:

我有几个模块从数据库中提取数据并将它们存储在本地内存中。然后,我具有从对象中提取数据的功能,因为不同的页面需要它们。它工作得很好,除了在我的登台服务器上每天一两次,对象是空的,我必须重新启动服务器才能再次填写数据。

我已经消除了这里的一些复杂性,但这就是想法,几个小时后,道路是空的,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 小时左右后停止响应的任何原因,我将不胜感激:)。

【问题讨论】:

  • “复杂性”中的某些东西可能是问题所在——我没有看到任何会导致您描述的问题的东西(除非数据库驱动程序在几个小时后再次调用回调)。
  • 有趣,我会在 db 回调中添加一个 console.log 以确保。这个模块并不复杂,但其他一些模块更复杂。
  • 您是否真的检查了roads 以确定它是否为空,或者您是否从您观察到的行为中推断出它?我能想到你会得到所有null 结果的其他原因。例如,如果调用 getRoad 的代码在某个时候出现问题并开始使用无效的 id 值调用它。

标签: node.js garbage-collection


【解决方案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/等),这将为您提供灵活性。比如:

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]);
            }
        });
    }
};

【讨论】:

  • 没有看到任何错误日志正在输出。是的,我一直在考虑重构整个事情以使用回调,我喜欢不使用它们的简单性,但它们可能只是必需的。
  • 我将其标记为答案,因为这是首先编写这些内容的正确方法,我希望它能对其他人有所帮助。但我的问题似乎出在 mysql-simple-pool
猜你喜欢
  • 1970-01-01
  • 2020-10-16
  • 1970-01-01
  • 2015-04-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-28
相关资源
最近更新 更多