req.session 集群模式下 运行 pm2 重定向后数据丢失

req.session data lost when after redirect when running pm2 in cluster mode

我们正在 运行使用 express 4.6.1 cookie 解析器 1.3.2 connect-flash 0.1.1 和 express session 1.7.0 创建一个 node.js 应用程序。

我们使用 flash 在重定向后的页面上显示消息,有时将数据存储在 req.session 中,以便在用户出错并需要重新输入时自动填写表单。最近我们开始在集群模式下使用 pm2,大多数事情似乎都运行良好,但我们注意到在重定向后我们丢失了闪存数据和存储在 req.session 中的数据。

这是一个例子:

                req.flash("signup", errorString);
                req.session.storedData = {};
                req.session.storedData.username = "";   
                req.session.storedData.password = req.body.password;
                req.session.storedData.email = req.body.email;
                req.session.storedData.emailConfirm = req.body.emailConfirm;
                res.redirect(problemRedirectPath);

这来自一个端点,该端点在用户尝试注册但出现某种错误后接受请求。如果我们 运行 在没有集群模式的情况下,会话数据和闪存都会正确显示,但如果我们 运行 在集群模式下,它们几乎总是丢失(并不总是 :/)

在集群模式下有更好的方法吗?

除非您使用 Redis、Memcache 或其他一些进程来存储会话数据,否则您将无法使用多个 Node 进程来处理请求。现在您的应用仅使用 express-session 来存储会话数据,默认情况下它仅将会话数据存储在内存中。

https://github.com/expressjs/session#sessionoptions

参见上面的警告部分link。

当您 运行 具有集群模块的应用程序时,它将为每个应用程序实例派生一个不同的进程。如果您不做一些工作,这些进程不能直接共享内存,这意味着当请求循环分发到应用程序实例时,任何不在同一进程中结束的请求将无法将它们的 cookie 与服务器端会话存储。

我建议将您的会话存储更改为更适合生产的存储,例如 Redis 或 Memcache。如果你使用 Redis,你可能想看看使用 connect-redis.

我遇到了同样的问题。从使用内存进行 Express 会话切换到 memcached 后,在 pm2 集群模式下一切正常。

https://github.com/balor/connect-memcached

始终建议应用程序永远不要将状态存储在内存中。通过使用像 pm2 这样的 tool/solution,它是一个负载 balancer/process 管理器,它将根据算法在所有实例中分发请求,一个进程将不会包含与其他进程具有的存储在内存中的相同状态。解决方案是:使用外部存储,所有实例都可以共享和访问,比如 mongo/redis/sql/etc。这样所有进程将从同一个源(不是内存,而是数据库)读取状态,解决问题。