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


71

我正在使用带有连接中间件的Node's 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是有意义的。

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


1
我正在使用cookie-sessiosn,但是是否存在sessiosn数据,因为在我的情况下,仅显示当前会话,而不显示以前的会话?
阿曼·维尔玛,2015年

Answers:


87

花了一天的时间对此进行调查。这是我发现的选项。每秒请求数是ab -n 100000 -c 1 http://127.0.0.1:9778/在我的本地计算机上执行的。

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

这是我用于cookieSession的coffeescript:

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

这是我用于redis的coffeescript:

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
})

这是我给蒙哥写的咖啡稿:

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数据库将比其本地等效数据库慢。我只是无法让当地的同类设备正常工作,尤其是考虑到与托管远程替代产品相比,我的安装和维护时间远远超过了我愿意投资的时间,我对其他人也是如此,因此为什么这些托管远程替代产品也是如此数据库服务首先存在!

有关本地数据库的注释,请参见@Mustafa的答案

很高兴有人编辑此答案以将其本地数据库基准添加到组合中。


哇,很高兴看到数字。当然影响了我的决定。谢谢!
Lance Nanek

顺便说一句,很高兴看到MemoryStore使用这些工具进行基准测试-有机会吗?;)
UpTheCreek

13
实际上,您应该在本地主机中使用redis进行基准测试,远程使用redis显然很慢
Tan Nguyen

7
当然,这将变慢,您正在使用外部服务器!这个答案在很大程度上是错误的!您正在将苹果与橙子进行比较。–
穆斯塔法

1
@Mustafa看到我的评论回了一些评论:stackoverflow.com/questions/8749907/…–
balupton

74

由于接受的答案仅连接到远程主机,因此很明显它将始终比本地主机慢。即使它是您家中的下一台计算机,从该计算机读取数据也要花费毫秒,但是本地内存仅需要纳秒的时间。您应该使用本地安装的服务器进行比较。

这是我从本地PC获得的结果:您看到的是,在高负载下,redis的速度几乎与内存一样快。您可以克隆我可以使用以下测试代码的存储库: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存储配置:

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

Mongo商店配置:

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

我正在使用cookie-sessiosn,但是是否存在sessiosn数据,因为在我的情况下,仅显示当前会话,而不显示以前的会话?
阿曼·维尔玛

9

另一个不错的选择是memcached。如果重新启动memcached,会话状态将丢失,但实际上从来没有任何理由这样做。即使重新启动应用程序服务器,也可以使缓存始终保持运行状态。对会话数据的访问实际上是瞬时的,并且memcached将在您为其提供的任何(适当)内存量下愉快地运行。而且我从未见过memcached崩溃(在Linux上)。

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

通常要记住的有关memcached的事情:

  • 缓存键中永远不要有空格
  • 请注意,最大高速缓存密钥长度包括您可能使用的任何名称空间前缀。如果您的缓存键太长,请改用1向哈希。

这些都不是会话存储的问题。只是具有通用缓存。


您知道如何将其插入连接中间件的会话处理程序吗?(我是该地区的n00b人)
Nils 2012年

@Chocohound您发现了..我能够连接到Memcache服务器..但是,如何在环境文件中配置具有memcache的会话存储?
艾伦(Alan)

我正在使用cookie-sessiosn,但是是否存在sessiosn数据,因为在我的情况下,仅显示当前会话,而不显示以前的会话?
阿曼·维尔玛

github.com/expressjs/session所列,现在有一个Memcached会话存储区(connect-memcached)可用:npmjs.com/package/connect-memcached
davidm_uk

6

我已经去过使用connect-mongo的MongoDB会话存储。

安装npm install connect-mongo并使用替换现有的MemoryStore

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

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


5

即使是本地开发,我仍然会使用Redis。这很有用,因为即使您重新启动Node应用程序时,它也会存储会话,并保持浏览器会话登录。默认情况下,Redis将会话保存在内存中,就像connect的内存存储易于配置一样(我只是在屏幕上与如果您在配置中使用其他数据库或会话值,则我的节点应用程序可以支持多个应用程序。


我不会为dev和prod使用不同的商店,以这种方式无疑会遇到未捕获的错误。蒂姆是正确的,对本地和产品使用redis。
chovy

但是,如果您在Windows框上进行开发,则不会带来太多乐趣。
UpTheCreek

我正在使用cookie-sessiosn,但是是否存在sessiosn数据,因为在我的情况下,仅显示当前会话,而不显示以前的会话?
阿曼·维尔玛

3

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

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

优点是您不必维护服务器的状态-此解决方案可以很好地扩展并且易于实现。

缺点是您最多只能存储约4KB的数据,并且每次请求都会将数据发送到服务器(但是您可以将多个虚拟域指向您的服务器,因此您不必将包bag强加给公众可见的静态内容,因为例)。

搜索网络似乎为node.js至少有两种安全cookie的实现。尽管不确定生产准备如何,但是:

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

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


有趣的是,本·阿迪达(Ben Adida)实际上是我的朋友。小世界!
尼尔斯2012年

1
我不是专家,但我认为普遍的共识是安全的cookie并不安全。我会做一些阅读,但我不想做任何还不是主流的事情。
尼尔斯2012年

好吧,您总可以去实现基于文件的简单会话存储-与PHP相似。假设操作系统缓存文件,您将获得合理的性能。或者您可以使用tmpfs,它是内存支持的文件系统。
nimrodm 2012年

4
似乎cookie会话现在已通过cookieSession中间件
balupton 2012年

要考虑的另一个数据点。Ruby on Rails的默认会话存储是基于Cookie的(github.com/rails/rails/blob/master/actionpack/lib/…)。
nimrodm

2

我很欣赏这是一个古老的问题,但是我在寻找类似问题的解决方案时遇到了它。我已经决定将memcached用于Linux上的会话存储(带有connect-memcached),但是我还需要能够在Windows上运行。我花了一段时间尝试为单进程节点应用程序找到内存中的会话存储。Redis和Memcached在Windows上似乎没有得到很好的支持,我也不希望它们的安装更加复杂。

我在另一个Stack Overflow线程中找到了会话内存存储,该线程看上去不错,但显着增加了依赖项的大小。

最后,我express-session的文档中找到了memorystore 。我之所以错过了它,是因为它的名称与default相似,但这正是我想要的:MemoryStore

快速会话全功能MemoryStore模块,无泄漏!

我现在在集群中运行时(仅在Linux上)使用connect-memcached,在运行单个进程时(在Linux或Windows上)使用memorystore。

我认为值得将其作为另一个答案,以防万一其他人像我最初那样犯了丢失存储库的错误。


谢谢!那就是我所需要的
Alex Green,

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.