会话更新在请求之间不持久-node.js / express.js / redis / heroku

Tom*_*m G 5 session heroku redis node.js express

我正在使用redis将会话存储在expressjs中。在本地运行时,它运行良好,甚至在大多数情况下,在heroku上运行时,也可以运行。问题是定期(当部署在heroku上时)我会丢失会话更新。

例如,一个用户登录到我的网站,然后将其用户对象添加到会话中:

req.session.user = user;
Run Code Online (Sandbox Code Playgroud)

但是(有时)当我稍后尝试(在不同的请求中)检索对象时,它不存在

//sometimes this is empty, even though I've just set it
var currentUser = req.session.user;
Run Code Online (Sandbox Code Playgroud)

我初始化会话存储如下

if (process.env.REDISTOGO_URL) {
    console.log('Connecting to redis:' + process.env.REDISTOGO_URL);
    var rtg = require('url').parse(process.env.REDISTOGO_URL);
    var redis = require('redis').createClient(rtg.port, rtg.hostname);
    redis.auth(rtg.auth.split(':')[1]);
} else {
    console.log('Connecting to local redis');
    var redis = require('redis').createClient();
}

//sessions
app.use(express.cookieParser('secret key for cookie monster')); //used by session
var RedisStore = require('connect-redis')(express);
app.use(express.session({
    store: new RedisStore({
        client: redis
    })
}));
Run Code Online (Sandbox Code Playgroud)

有任何想法吗?我是否需要对会话数据进行某种刷新(或显式保存)?

Chr*_*eek 0

我将劫持这个古老的问题,让你们了解我是如何解决这个问题的。

长话短说

您可能不久前已将 REDIS_URL 值从 Heroku 应用程序配置复制到本地 .env 文件。Heroku 随着时间的推移改变了这个值,而现在这已经实际发生了。

解决方案是将新的 REDIS_URL 值从 Heroku 应用程序配置复制到本地 .env 文件,或使用另一个 Redis 实例进行本地开发。

你可能已经尝试过了

也许您的会话几天前就正常工作,并且您尝试并验证了所有常见的嫌疑点,以解决这个突然的问题。

一切都无济于事。最后,当您从会话配置中删除 RedisStore 位时,会话将再次工作。

const session = require('express-session');
const RedisStore = require('connect-redis')(session);
// ...
server.set('trust proxy', 1);
server.use(
    session({
        // store: new RedisStore({
        //     url: process.env.REDIS_URL,
        // }),
        secret: process.env.SESSION_SECRET,
        resave: false,
        saveUninitialized: true,
        cookie: {
            path: '/',
            httpOnly: true,
            secure: false,
            maxAge: null,
        },
    })
);
Run Code Online (Sandbox Code Playgroud)

发生了什么?

一段时间后,我明白了删除 Redis 存储是如何解决问题的。我在本地 .env 文件中使用了 Heroku 应用程序配置提供的 REDIS_URL。我了解到Heroku 应用程序上的 REDIS_URL 可能会随着时间的推移而改变

为了让 Heroku 为您管理此附加组件并响应各种操作情况,REDIS 配置变量可能会随时更改。依赖 Heroku 应用程序外部的配置变量可能会导致您必须重新复制该值(如果该值发生变化)。

(强调我的)

因此,就我而言,这确实发生了,我的本地 .env 文件仍然具有旧的 REDIS_URL 值。实际上,无法创建会话存储,因为它尝试连接到不存在的服务。这就是为什么删除 RedisStore 并回退到默认的 MemoryStore 解决了问题。

防止再次发生

我在 redislabs.com 创建了一个帐户并创建了一个免费的 Redis 实例。我现在在本地 .env 文件中使用该 URL。该网址不会改变(我希望)。