【问题标题】:Node.js global variable property is purgedNode.js 全局变量属性被清除
【发布时间】:2023-03-29 20:34:01
【问题描述】:

我的问题不是关于“内存泄漏”,而是关于 node.js (expressjs) 应用程序的“内存清除”。

我的应用程序应该在内存中维护一些对象,以便在服务期间进行快速查找。启动应用程序后暂时(一两天),一切似乎都很好,直到突然我的网络客户端无法查找该对象,因为它已被清除(未定义)。我怀疑 Javascript GC(垃圾收集)。但是,正如您在 psedu 代码中看到的那样,我将对象分配给 node.js 的“全局”变量属性以防止 GC 清除它们。请给我一些线索是什么导致了这个问题。

非常感谢您的建议~

我的 node.js 环境是 node.js 0.6.12、expressjs 2.5.8 和 VMWare cloudfoundry 节点托管。

这是我的 app.js 伪代码:

var express = require("express");
var app = module.exports = express.createServer();

// myMethods holds a set of methods to be used for handling raw data.
var myMethods = require("myMethods");

// creates node.js global properties referencing objects to prevent GC from purging them
global.myMethods = myMethods();
global.myObjects = {};

// omited the express configurations

// creates objects (data1, data2) inside the global.myObjects for the user by id.
app.post("/createData/:id", function(req, res) {

    // creates an empty object for the user.
    var myObject = global.myObjects[req.prams.id] = {};

    // gets json data.
    var data1 = JSON.parse(req.body.data1);
    var data2 = JSON.parse(req.body.data2);

    // buildData1 & buildData2 functions transform data1 & data2 into the usable objects.
    // these functions return the references to the transformed objects.
    myObject.data1 = global.myMethods.buildData1(data1);
    myObject.data2 = global.myMethods.buildData2(data2);

    res.send("Created new data", 200);
    res.redirect("/");
});

// returns the data1 of the user.
// Problem occurs here : myObject becomes "undefined" after one or two days running the service.
app.get("/getData1/:id", function(req, res) {

    var myObject = global.myObjects[req.params.id];
    if (myObject !== undefined) {
        res.json(myObject.data1);
    } else {
        res.send(500); 
    }
});

// omited other service callback functions.

// VMWare cloudfoundry node.js hosting.
app.listen(process.env.VCAP_APP_PORT || 3000);

【问题讨论】:

  • 是的,Redis 可以解决这个问题,但是,我想保持我的程序简单,没有数据库:)
  • 那么我建议使用文件系统,我认为4KB的开销对你的目标和硬件来说不是什么大问题。
  • 作为一般策略,我建议将数据写入存储并仅保留最近使用对象的缓存。我什至会编写一个小函数,定期从缓存中清除最旧的对象。然后我会重写app.get("/getData1/:id"),在返回 404 之前先查看缓存,然后再查看存储(不是 500 - “未找到”不是错误条件)。
  • 我并没有真正看到 global 的使用。为什么不简单地创建一个普通对象?
  • 感谢大家的宝贵意见 :)

标签: javascript node.js garbage-collection global-variables purge


【解决方案1】:

任何类型的缓存系统(无论是您自己的产品还是第三方产品)都应考虑这种情况。您不应依赖内存缓存中始终可用的数据。有太多的事情会导致内存中的数据消失(机器重启、进程重启等等。)

在您的情况下,您可能需要更新代码以查看数据是否在缓存中。如果它不在缓存中,则从持久存储(数据库、文件)中获取它,缓存它,然后继续。

【讨论】:

  • 是的,你是对的。我还应该考虑您所描述的服务器操作失败,例如机器重启。看来我需要缓存和持久存储。非常感谢您的建议!
【解决方案2】:

就像 Haesung 一样,我想保持我的程序简单,没有数据库。和 Haesung 一样,我对 Node.js(和 express)的第一次体验就是观察这种奇怪的清除。虽然我很困惑,但我真的不接受我需要一个存储解决方案来管理一个几百行的 json 文件。对我来说,灯泡时刻是我读到这篇文章的时候

如果你想让一个模块多次执行代码,那么导出一个函数,然后调用那个函数。

取自http://nodejs.org/api/modules.html#modules_caching。所以我在所需文件中的代码从这里改变了

var foo = [{"some":"stuff"}];
export.foo;

到那个

export.foo = function (bar) {
var foo = [{"some":"stuff"}];
return foo.bar;
}

然后它工作得很好:-)

【讨论】:

    【解决方案3】:

    然后我建议使用文件系统,我认为 4KB 开销对于您的目标和硬件来说并不是什么大问题。如果您熟悉前端 javascript,这可能会有所帮助https://github.com/coolaj86/node-localStorage

    【讨论】:

    • 对象的大小可以很大,Cloudfoundry nodejs托管环境不允许使用文件系统。谢谢你的建议!
    • 然后运行一些单独的线程或事件循环,您将在其中检查数据的持久性,并每时每刻重写它们,看起来像一个黑客,但在有限的 PaaS 上还能做什么? :)
    • 我想我必须使用 node-localtSorage 或 Redis 进行持久存储。非常感谢您的意见和建议。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-07-23
    • 1970-01-01
    • 1970-01-01
    • 2017-06-02
    • 1970-01-01
    相关资源
    最近更新 更多