在生产中使用MemoryStore

时间:2012-05-25 19:55:31

标签: node.js

今天我第一次以“生产”模式运行我的Node.js应用程序并收到此警告:

Warning: connection.session() MemoryStore is not
designed for a production environment, as it will leak
memory, and obviously only work within a single process.

我只需要运行一个进程,但我应该使用什么呢?我希望我的会话驻留在RAM中以便快速访问。我还想通过简单地关闭Node应用程序来丢弃所有会话。

为这个简单的任务安装Redis,MongoDB或其他数据库似乎太过分了。我也不明白为什么MemoryStore应该包含在Node中,而不应该真正使用它?

8 个答案:

答案 0 :(得分:78)

好的,在与Connect开发人员交谈之后,我获得了更多信息。这里有两件事被认为是内存泄漏:

  1. JSON解析的问题已在最近版本中修复
  2. 如果用户从未访问过期会话,则没有过期会话的清理(即唯一的清理是访问时)
  3. 解决方案似乎相当简单,至少这是我打算做的事情:使用setInterval定期清理过期的会话。 MemoryStore提供了all()来获取列表,我们可以使用get()来强制读取,从而使它们到期。伪代码:

    function sessionCleanup() {
        sessionStore.all(function(err, sessions) {
            for (var i = 0; i < sessions.length; i++) {
                sessionStore.get(sessions[i], function() {} );
            }
        });
    }
    

    现在只需通过setInterval()定期调用sessionCleanup,就可以自动对已过期的会话进行垃圾回收。没有更多的内存泄漏。

答案 1 :(得分:42)

所以接受的答案是[编辑:是]几乎是一个黑客,而其他人只是建议使用我认为有点过分的数据库。

我遇到了同样的问题,只是用cookie-session替换了快速会话。

为此,只需安装cookie-session

即可
npm install cookie-session

然后在app.js中,找到express-session的使用位置,并替换为cookie-session

app.use(require('cookie-session')({
    // Cookie config, take a look at the docs...
}));

你可能需要改变一些其他的东西,因为对我来说这是一个简单的换掉你的叔叔 - 没有伤害的事情。

答案 2 :(得分:25)

MemoryStore仅适用于(快速)开发模式,因为如果您的应用程序重新启动(进程终止),您将丢失所有会话数据(驻留在该进程的内存中)。

如果您不想使用数据库,请使用加密的cookie存储。

http://www.senchalabs.org/connect/cookieSession.html

答案 3 :(得分:11)

此模块旨在解决内存泄漏问题。 https://www.npmjs.com/package/session-memory-store

接受的答案可能没问题。但是,由于这个问题在搜索结果列表中显示得很高,我认为我会将其包括在内,以防它帮助其他任何人。

答案 4 :(得分:6)

我认为网络上的共识是,正确的方法是确实使用数据库,但如果你是肯定的,你不想这样做,那么就禁止警告 - 警告不是法。

然而,由于你和我都同意内存泄漏是一个真正的问题,因此很难证明redis是过度的,因为它可以解决你的问题。

  

我也不明白为什么MemoryStore包含在Node中   不应该真的使用

这是一个很好的观点 - 但我要说节点iself最近才成为生产就绪。有些人不同意它的概念。

答案 5 :(得分:6)

另一种方法是使用Redis或Mongo作为商店。使用Mongo,您可以使用express-session-mongo模块。

建议使用索引选项删除陈旧会话:

var MongoStore = require('express-session-mongo');
app.use(express.session({ store: new MongoStore() }));

db.sessions.ensureIndex( { "lastAccess": 1 }, { expireAfterSeconds: 3600 } )

由于数据库本身删除了过时会话,因此Express会话不需要自行处理清理。

编辑:您似乎需要拥有自己的&#34; lastAccess&#34;领域。当您访问它时,您自己更新该字段。查看MongoDB文档expire-data http://docs.mongodb.org/manual/tutorial/expire-data/

EDIT2

现在变为db.sessions.createIndex( { "createdAt": 1 }, { expireAfterSeconds: 3600 } )

检查此字段的Mongo后台线程每60秒运行一次。因此删除文档的时机并不准确。

答案 6 :(得分:2)

对于那些遇到Redis问题的人,请尝试以下方法 - 希望这会有所帮助。

我正在使用Redis for DEV和PROD以及针对Express v4。 在Windows上我使用轻量级MSOpenTech Redis v3.0工具集,否则,我只使用Heroku Redis插件。通过Node让它工作并不是太难 - 到目前为止......

var session = require('express-session');

. . .

var RedisStore = require('connect-redis')(session);

var redisClient = require('redis').createClient(process.env.REDIS_URL);

var redisOptions = { 
        client: redisClient, 
        no_ready_check: true,
        ttl: 600,
        logErrors: true
};

var redisSessionStore = new RedisStore(redisOptions);

app.use(session({
    store: redisSessionStore,
    secret: 'Some.Long.Series.of.Crazy.Words.and.Jumbled.letter.etc',
    resave: true,       
    saveUninitialized: true 
}));
祝你好运!

PS。我只是重新阅读原始查询并注意到这一点 - 抱歉!

  

仅为此简单任务安装Redis,MongoDB或其他数据库似乎太过分了。

答案 7 :(得分:0)

如果您使用OSX,请使用

brew install memcached

如果是Linux

apt install memcached

解决会话消息,因为应用程序可以连接到127.0.0.1:11211内存缓存服务。