在生产中使用MemoryStore

Mil*_*kov 114 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.
Run Code Online (Sandbox Code Playgroud)

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

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

Mil*_*kov 80

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

  1. JSON解析的问题已在最近的版本中修复
  2. 如果用户从不访问它们,则没有过期会话的清理(即唯一的清理是访问时)

解决方案似乎相当简单,至少这是我打算做的事情:使用setInterval定期清理过期的会话.MemoryStore提供了all()来获取列表,我们可以使用get()来强制读取,从而使它们到期.伪代码:

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

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

  • 他们把这个信息放在那里,这真是一件蠢事.这就像"我们可以做得对,但我们只会把它弄错,然后你就会在互联网上玩一个猜谜游戏.哈哈!失败者!" (56认同)
  • sessionStore?那是一个node.js全局变量吗?如果没有,我如何在node.js中获得对会话存储的引用? (4认同)
  • 我发现你也可以使用Redis和Mongo作为后备存储并让db清理它.对于Mongo,您可以在确保索引的同时设置到期日期. (3认同)
  • var sessionStore的值是什么? (2认同)

ign*_*aur 45

因此,接受的答案是[编辑:几乎是一个黑客攻击,其他人只是建议使用我认为有点过分的数据库.

我遇到了同样的问题,只是用cookie-session替换了express -session.

要做到这一点,只需安装cookie-session:

npm install cookie-session
Run Code Online (Sandbox Code Playgroud)

然后在你的app.js,找到express-session正在使用和替换的地方cookie-session.

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

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

  • 区别在于,“ cookie-session”将数据存储在客户端上,而“ express-session”将数据存储在服务器上。 (3认同)
  • 你是怎么做到的. (2认同)
  • 这实际上是一个有用的答案.感谢名单. (2认同)

ale*_*lex 27

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

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

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


Dov*_*etz 11

该模块旨在处理内存泄漏问题. https://www.npmjs.com/package/session-memory-store

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


Kri*_*ian 7

我认为网络上的共识是,正确的方法是确实使用数据库,但如果你是积极的,你不想这样做,那么压制警告 - 警告不是法律.

但是,既然你和我都同意内存泄漏是一个真正的问题,那么很难说redis是矫枉过正,因为它可以解决你的问题.

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

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

  • MemoryStore不包含在Node中,它包含在Express/Connect中 (7认同)
  • 抑制警告不会使内存泄漏消失. (2认同)
  • 我感觉到你的痛苦,但节点现在已经非常流行了......它有点属于领土 (2认同)

hug*_*gie 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 } )
Run Code Online (Sandbox Code Playgroud)

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

编辑:您似乎需要拥有自己的"lastAccess"字段.当您访问它时,您自己更新该字段.检查MongoDB文档过期数据 http://docs.mongodb.org/manual/tutorial/expire-data/

编辑2:

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

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