gpt4 book ai didi

node.js - Node/ express : concurrency issues when using session to store state

转载 作者:IT老高 更新时间:2023-10-28 23:13:01 25 4
gpt4 key购买 nike

因此,我为此进行了相当多的搜索,发现了几个有点相似的问题,但没有一个真正解决了这个问题,所以我认为这值得自己提出一个问题。

我有一个快速应用程序,其中包含一组修改 session 以保持状态的路由。问题是,如果有多个并行请求,由于请求之间的竞争条件, session 将不时被覆盖。

通常

...
app.use(express.static('/public'));
app.use(session(...));
app.route('methodA').get(function(req, res, next) {
doSomethingSlow().then(function() {
req.session.a = 'foo';
res.send(...);
}
});
app.route('methodB').get(function(req, res, next) {
doSomethingElseSlow().then(function() {
req.session.b = 'bar';
res.send(...);
}
});

基本上问题很简单,例如this 中描述回答。 Express 将 session 存储在 res.end() 中,但是在处理 methodA 请求时,methodB 请求可能同时修改了 session,因此当 methodA 存储 session 时,它将覆盖 methodB 所做的任何更改。因此,即使 Node 是单线程的,并且所有请求都由同一个线程提供服务,但一旦任何方法执行异步操作,我们最终可能会遇到并发问题,从而同时处理其他请求。

但是,我正在努力决定如何着手解决这个问题。我发现的所有答案都只列出了最小化发生这种情况的概率的方法,例如通过在 session MW 之前注册服务静态 MW,确保静态内容不存储 session 。但这只是在一定程度上有所帮助;如果实际上存在应该并行调用的 API 方法,则需要一些真正的 session 更新并发方法(IMO,当涉及并发问题时,每个“解决方案”都力求将问题发生的可能性降到最低,而不是解决实际问题肯定会出错)。

到目前为止,基本上这些是我正在探索的替代方案:

  1. 通过修改我的客户端以确保它串行调用所有 API 方法,从而完全防止同一 session 中的并行请求。

    这可能是可行的,但会对我的架构产生相当大的影响,并可能影响性能。它还避免而不是解决问题,如果我在客户端中出错或 API 被另一个客户端使用,我可能仍会随机遇到此问题,因此感觉不是很健壮。

  2. 确保每次 session 写入之前都有 session 重新加载,并使整个重新加载-修改-写入操作原子化。

    我不确定如何实现这一点。即使我在修改和存储之前修改 res.end() 以重新加载 session 只是,因为读取和写入 session 是异步 I/O,这似乎有可能发生:

    • 请求 A 重新加载 session
    • 请求 A 修改 session.A = 'foo'
    • 请求 B 重新加载 session (并且不会看到 session.A)
    • 请求 A 存储 session
    • 请求 B 修改 session.B = 'bar'
    • 请求 B 存储 session ,覆盖之前的存储,因此 session.A 丢失

所以本质上我需要使每个 reload-modify-store 原子,这基本上意味着阻塞线程?感觉不对劲,不知道怎么办。

  1. 完全停止以这种方式使用 session ,并将必要的状态作为参数传递给每个请求或通过其他方式。

    这也避免了问题而不是解决问题。它也会对我的项目产生巨大影响。但可以肯定的是,这可能是最好的方法。

  2. ???

有人知道如何以稳健的方式解决这个问题吗?谢谢!

最佳答案

一个可能的解决方案是为 express 创建一个简单的中间件,它将维护所有当前请求的列表并将来自同一 session 的任何请求排队。它不会调用 next(),直到之前对该 session-id 的请求被首先处理。

每次收到请求时,它都可以将其存储在一个对象中,键是 session ID cookie 名称,值是 session ID 的当前请求数组。


{
'session-id1':[...排队的请求...],
' session -id2':...
}

当一个请求完成时,它会从数组中移除它自己并触发数组中的下一个请求被处理。

您还可以在 header 中为每个请求添加一个标志,以允许并发运行不需要排队的请求(例如,它们不写入 session ),从而在不需要排队时提高性能.

您应该能够实现这一点,而无需更改您的应用程序。您还可以将 header 中的 opt-out 选项更改为 opt-in 选项,这意味着它将像通常一样同时处理所有请求,除非另有说明。

关于node.js - Node/ express : concurrency issues when using session to store state,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28602214/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com