什么是单主机Node.js生产应用程序的良好会话存储?

我正在使用Node的Express连接中间件。 Connect的内存会话存储不适合生产:

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

对于更大的部署,mongo或redis是有意义的。

但是,在生产中的单主机应用程序有什么好的解决scheme?

花了一天的时间来看这个。 这是我发现的选项。 请求/秒是通过本地机器上的ab -n 100000 -c 1 http://127.0.0.1:9778/执行的。

  • 没有会议 – 快(438瑞奇/秒)
  • cookieSession :不需要外部服务,速度影响较小(311 req / sec) – 最快,会话将随着cookie过期(由maxAge定制)
  • connect-redis :需要redis服务器,速度很快(redis2go和redisgreen需要4次req / sec) – 比mongo快,会话会在一段时间后被删除(由ttl定制)
  • connect-mongo – 需要mongodb服务器,速度较大(mongohq需要2个req /秒) – 比redis慢,需要手动clear_interval设置为清理会话

这里是我用于cookieSession的coffeescript:

 server.use express.cookieSession({ secret: appConfig.site.salt cookie: maxAge: 1000*60*60 }) 

这里是我用于redis的咖啡脚本:

 RedisSessionStore ?= require('connect-redis')(express) redisSessionStore ?= new RedisSessionStore( host: appConfig.databaseRedis.host port: appConfig.databaseRedis.port db: appConfig.databaseRedis.username pass: appConfig.databaseRedis.password no_ready_check: true ttl: 60*60 # hour ) server.use express.session({ secret: appConfig.site.salt cookie: maxAge: 1000*60*60 store: redisSessionStore }) 

这是我的mongo的咖啡文字:

 server.use express.session({ secret: appConfig.site.salt cookie: maxAge: 100*60*60 store: new MongoSessionStore({ db: appConfig.database.name host: appConfig.database.host port: appConfig.database.port username: appConfig.database.username password: appConfig.database.password auto_reconnect: appConfig.database.serverOptions.auto_reconnect clear_interval: 60*60 # hour }) }) 

当然,远程redis和mongo数据库将比本地数据库慢。 我只是无法得到本地的等值工作,特别是考虑到我的安装和维护时间远远超过我愿意投资的东西,而不是托pipe的远程替代品,我觉得其他人也是这样,因此为什么这些远程托pipe数据库服务首先存在!

对于本地数据库benhmarks,请参阅@穆斯塔法的答案 。

很高兴有人编辑这个答案 ,将他们的本地数据库基准添加到组合中。

由于接受的答案只是连接到远程主机,显而易见,它总是比本地主机慢。 即使是家中的下一台计算机,从该计算机读取也需要几毫秒的时间,但本地内存只需要几十秒。 您应该使用本地安装的服务器来比较它们。

这里是我的本地电脑的结果:你看,在高负载下,redis几乎和内存一样快。 你可以克隆我的回购,这些testing代码可用: https : //github.com/mustafaakin/express-session-store-benchmark

 Concurrency: 1 none 4484.86 [#/sec] memory 2144.15 [#/sec] redis 1891.96 [#/sec] mongo 710.85 [#/sec] Concurrency: 10 none 5737.21 [#/sec] memory 3336.45 [#/sec] redis 3164.84 [#/sec] mongo 1783.65 [#/sec] Concurrency: 100 none 5500.41 [#/sec] memory 3274.33 [#/sec] redis 3269.49 [#/sec] mongo 2416.72 [#/sec] Concurrency: 500 none 5008.14 [#/sec] memory 3137.93 [#/sec] redis 3122.37 [#/sec] mongo 2258.21 [#/sec] 

会话使用的页面是非常简单的页面;

 app.get("/", function(req,res){ if ( req.session && req.session.no){ req.session.no = req.session.no + 1; } else { req.session.no = 1; } res.send("No: " + req.session.no); }); 

Redis商店configuration:

 app.use(express.session({ store: new RedisStore({ host: 'localhost', port: 6379, db: 2, }), secret: 'hello' })); 

Mongo商店configuration:

 app.use(express.cookieParser()); app.use(express.session({ store: new MongoStore({ url: 'mongodb://localhost/test-session' }), secret: 'hello' })); 

另一个好的select是memcached。 如果memcached被重新启动,会话状态会丢失,但实际上从来没有任何理由这样做。 即使重新启动应用程序服务器,您也可以始终保持caching运行。 访问会话数据实际上是瞬间的,memcached会随着你给它的任何(适当的)内存量而愉快地运行。 我从来没有见过memcached崩溃(在Linux上)。

https://github.com/elbart/node-memcache

一般情况下要记住关于memcached:

  • 切勿在caching键中留有空白
  • 请注意,有一个最大的caching密钥长度,包括您可能使用的任何名称空间前缀。 如果您的caching密钥太长,请使用它的单向散列。

这些都不应该是会话存储的问题。 只是泛化的caching。

我已经用了一个使用connect-mongo的MongoDB会话存储。

使用npm install connect-mongo安装,并用现有的MemoryStorereplace

app.use(express.session({ store: new MongoStore({ db: 'some-database' }) }));

它自动pipe理会话的数据库端。

我甚至还会使用Redis进行本地开发。 这是有帮助的,因为即使在重新启动Node应用程序时,它也会保存会话,从而保持浏览器会话的login。默认情况下,Redis将会话保存在内存中,与connect的内存存储相同,configuration简单(我只是在屏幕上运行它我的节点应用程序)可以支持多个应用程序,如果您只是在configuration中使用不同的数据库或会话值。

我只是自己探索node.js,但是如果不需要在会话对象中存储大量信息 – 您可能需要探索安全的cookie。

安全cookie将会话信息存储为浏览器存储和转发每个请求的cookie的一部分。 它们被encryption以防止用户伪造一个有效的cookie。

优点是您不必在服务器上维护状态 – 此解决scheme可以很好地扩展并且易于实现。

缺点是你最多只能存储大约4KB的数据,并且每次请求都会将数据发送到服务器(但是你可以有多个虚构的域名指向你的服务器,所以你不要将这些行李强加给公开的静态内容,例)。

searchnetworking似乎有至less两个node.js的安全cookie的实现。 不知道他们是如何生产的,

https://github.com/benadida/node-client-sessions/blob/master/lib/client-sessions.js

https://github.com/caolan/cookie-sessions