【问题标题】:Using MemoryStore in production在生产中使用 MemoryStore
【发布时间】:2012-05-25 19:55:31
【问题描述】:

今天我第一次在“生产”模式下运行我的 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?

【问题讨论】:

    标签: node.js


    【解决方案1】:

    好的,在与 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,您就可以对过期会话进行自动垃圾收集。不再有内存泄漏。

    【讨论】:

    • 我发现你也可以使用 Redis 和 Mongo 作为后备存储并让数据库清理它。在 Mongo 的情况下,您可以在确保索引的同时设置到期日期。
    • 他们把这条消息放在那里真是一件愚蠢的事情。这就像“我们本来可以做对的,但我们只会做错,然后你去网上玩猜谜游戏。哈哈!失败者!”
    • var sessionStore 的值是多少?
    • sessionStore?那是一个 node.js 全局变量吗?如果没有,如何在 node.js 中获取对会话存储的引用?
    • @MilanBabuskov - 你把它放在你的app.js 文件中了吗?是否可以选择在快速会话中发出回调?关于如何实现这一点的更多细节会很棒。
    【解决方案2】:

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

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

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

    【讨论】:

    • 你是怎么做到的。
    • 这实际上是一个有用的答案。谢谢。
    • 区别在于cookie-session将数据存储在客户端,而express-session将数据存储在服务器。
    【解决方案3】:

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

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

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

    【讨论】:

      【解决方案4】:

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

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

      【讨论】:

      • 没有尝试过这个,但它看起来是一个很好的解决方案(如果 OP 可以在应用重启时丢失会话)
      • 来自您的链接:“强烈不建议在生产中使用它!”。问题是关于“在生产中使用 MemoryStore”。
      • 对,但只是因为“你不能与其他进程或其他服务共享会话”。这意味着,还有其他更实用的解决方案。但这确实解决了内存泄漏问题,因此如果您不担心这些问题,那么可以使用并解决问题中的问题。
      【解决方案5】:

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

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

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

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

      【讨论】:

      • 抑制警告不会使内存泄漏消失。
      • 大声笑这就是为什么他们建议不要在生产中使用它。所以另一种选择是使用另一种存储方法,不是吗?
      • 我想我只是不喜欢我目前找到的替代品。我正在寻找一个简单的内存中 javascript 替代方案,而不是数据库系统。我真的不明白他们为什么不修复它。我的意思是,一个简单的内存存储有多难......我只是希望有人已经做到了,所以我不必重新发明轮子。
      • 我能感觉到你的痛苦,但是节点现在非常流行......它有点像领土
      • MemoryStore 不包含在 Node 中,它包含在 Express/Connect 中
      【解决方案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 文档expire-data http://docs.mongodb.org/manual/tutorial/expire-data/

      EDIT2:

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

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

      【讨论】:

        【解决方案7】:

        对于那些在使用 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 
        }));
        

        祝你好运!

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

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

        【讨论】:

          【解决方案8】:

          如果你使用 OSX 使用

          brew install memcached
          

          如果是 linux

          apt install memcached
          

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

          【讨论】:

            【解决方案9】:

            使用

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

            解决我的问题

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2023-03-19
              • 2016-02-24
              • 2011-09-03
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2021-03-22
              • 1970-01-01
              相关资源
              最近更新 更多