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

d5vmydt9  于 2023-05-17  发布在  Node.js
关注(0)|答案(8)|浏览(260)

**已关闭。**此问题正在寻求书籍、工具、软件库等的建议。它不符合Stack Overflow guidelines。目前不接受答复。

我们不允许问题寻求书籍,工具,软件库等的建议。您可以编辑问题,以便可以用事实和引用来回答。
11天前关闭
社区在11天前审查了是否重新打开此问题,并将其关闭:
原始关闭原因未解决

锁定,此问题及其答案为locked,因为此问题离题但具有历史意义。它目前不接受新的答案或交互。

我正在使用Node的Express w/ Connect中间件。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是有意义的。
但是,对于生产环境中的单主机应用程序,什么是好的解决方案呢?

8ftvxx2r

8ftvxx2r1#

花了一天时间调查这个。以下是我发现的选择。每秒的请求数通过我的本地机器上的ab -n 100000 -c 1 http://127.0.0.1:9778/执行。

  • 无会话-快速(438请求/秒)
  • cookieSession:不需要外部服务,速度影响较小(311 req/sec)-最快,会话将随cookie过期(由maxAge自定义)
  • connect-redis:需要redis服务器,速度影响大(使用redis 2go和redisgreen时为4请求/秒)-比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
})

以下是我为mongo写的coffeescript:

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数据库会比本地数据库慢。* 我只是不能让本地等价物工作,特别是考虑到安装和维护时间对我来说是远远超过我愿意投资时相比,托管远程替代品,我觉得这是真实的其他人太因此为什么这些托管远程数据库服务存在摆在首位!*
有关本地数据库benhmarks,请参阅@Mustafa的答案。
很高兴有人edit this answer将他们的本地数据库基准添加到混合中。

tkclm6bt

tkclm6bt2#

由于接受的答案是只连接到远程主机,很明显它总是比localhost慢。即使它是您家中的下一台计算机,从该计算机读取也需要毫秒,但本地内存只需要纳秒。您应该使用本地安装的服务器进行比较。
以下是我在本地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'
}));
gv8xihay

gv8xihay3#

另一个不错的选择是memcached。如果重新启动memcached,会话状态将丢失,但实际上没有任何理由这样做。即使重新启动应用服务器,您也可以让该高速缓存一直运行。对会话数据的访问实际上是即时的,memcached将使用您给予的任何(适当的)内存量顺利运行。我从来没有见过memcached崩溃(在Linux上)。
https://github.com/elbart/node-memcache
关于memcached一般要记住的事情:

  • 缓存键中永远不要有空白
  • 请注意,存在最大缓存键长度,包括您可能使用的任何命名空间前缀。如果缓存键太长,请使用它的单向散列。

这些都不应该是会话存储的问题;只是一般化的缓存。

zbq4xfa0

zbq4xfa04#

我使用了一个使用connect-mongo的MongoDB会话存储。
使用npm install connect-mongo安装并将现有MemoryStore替换为
app.use(express.session({ store: new MongoStore({ db: 'some-database' }) }));
它自动管理会话的数据库端。

mkshixfv

mkshixfv5#

我仍然会使用Redis,即使是本地开发。这很有帮助,因为即使在重新启动Node应用程序时,它也会存储会话,从而使浏览器会话保持登录状态。默认情况下,Redis将会话保存在内存中,就像connect的内存存储一样,配置简单(我只是在屏幕上运行它沿着我的节点应用程序),如果你只是在配置中使用不同的数据库或会话值,就可以支持多个应用程序。

fzwojiic

fzwojiic6#

我只是在探索node.js,但如果你不需要在session对象中存储大量信息,你可能想探索安全cookie。
安全cookie将会话信息存储为浏览器存储并随每个请求转发的cookie的一部分。它们被加密以防止用户伪造有效的cookie。
其优点是不必在服务器上维护状态--此解决方案可伸缩性好,实现简单。
缺点是你最多只能存储大约4KB的数据,并且数据会在每次请求时发送到服务器(但是你可以有多个虚拟的域指向你的服务器,这样你就不会把这个包袱强加给公共可见的静态内容)。
在网络上搜索,似乎至少有两种node.js的安全cookie实现。不知道他们的生产准备如何:
https://github.com/benadida/node-client-sessions/blob/master/lib/client-sessions.js
https://github.com/caolan/cookie-sessions

cpjpxq1n

cpjpxq1n7#

我知道这是一个老问题,但我在寻找类似问题的解决方案时遇到了它。我已经决定在Linux上使用memcached进行会话存储(使用connect-memcached),但我还需要能够在Windows上运行。我花了一段时间试图为单进程节点应用程序找到内存中的会话存储。Redis和Memcached在Windows上似乎没有得到很好的支持,我不想增加安装的复杂性。
我在另一个Stack Overflow线程中发现了session-memory-store,它看起来不错,但显著增加了我的依赖项的大小。
最后,我在express-session * 的文档中找到了memorystore *。我最初错过了它,因为它的名称与默认的MemoryStore相似,但它正是我正在寻找的:
express-session全功能MemoryStore模块无泄漏!
我现在在集群中运行时使用connect-memcached(仅在Linux上),在运行单个进程时使用memorystore(在Linux或Windows上)。
我认为值得把这个作为另一个答案贴出来,以防其他人像我最初那样犯了错过记忆库的错误。

iqxoj9l9

iqxoj9l98#

请查看我在https://github.com/llambda/express-session-benchmarks上的基准测试,其中显示了不同会话实现的比较。

相关问题