120

今天我第一次在“生产”模式下运行我的 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 或其他数据库似乎有点过头了。我也不明白为什么 Node 中不应该真正使用 MemoryStore?

4

9 回答 9

81

好的,在与 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() {} );
        }
    });
}

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

于 2012-05-25T21:22:54.770 回答
49

因此,对此的公认答案是 [edit: was] 几乎是一种 hack,而其他人只是建议使用我认为过于矫枉过正的数据库。

我遇到了同样的问题,只是用cookie-session替换了 express- 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...
}));

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

于 2016-05-04T08:49:25.020 回答
31

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

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

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

于 2012-05-25T20:36:19.323 回答
12

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

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

于 2016-09-22T11:31:44.667 回答
8

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

但是,由于您和我都同意内存泄漏是一个真正的问题,因此很难证明说 redis 是矫枉过正,因为它会解决您的问题。

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

这是一个很好的观点 - 但我会说节点本身只是最近才准备好生产。有些人根本不同意它的概念。

于 2012-05-25T20:06:13.183 回答
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 会话不需要自己处理清理工作。

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

编辑2

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

用于检查此字段的 Mongo 后台线程每 60 秒运行一次。所以删除文件的时间并不准确。

于 2014-09-05T05:45:37.570 回答
2

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

我将 Redis 用于 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 
}));

祝你好运!

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

仅仅为了这个简单的任务安装 Redis、MongoDB 或其他数据库似乎有点过头了。

于 2017-07-25T07:50:18.767 回答
0

如果您使用 OSX,请使用

brew install memcached

如果是Linux

apt install memcached

解决会话消息,因为 de app 可以连接到 127.0.0.1:11211 memcache 服务。

于 2019-05-01T20:45:12.953 回答
0

采用

import createMemoryStore from "memorystore";
...
// Memory store
const MemoryStore = createMemoryStore(session);
app.use(session({
    ...
    store: new MemoryStore({
        checkPeriod: 86400000 // prune expired entries every 24h
    }),
    ...
}))

解决我的问题

于 2021-12-06T04:40:47.010 回答