在 VSCode 里调试 Express 项目,一遇到 Session 持久化(Redis),各种奇奇怪怪的问题就冒出来了。其实说到底,大部分报错都不是什么高深莫测的 Bug,而是几个基础环节没对上。这里把几个最容易踩的坑拆开来讲,从连接失败到 cookie 失效,再到怎么手动验证,一条线捋清楚。
常见错误是 Error: connect ECONNREFUSED 127.0.0.1:6379,说明 Node 进程根本连不上 Redis,根本原因是 Redis 服务未启动,而非配置错误;本地调试时 localhost 可能因 VSCode 运行环境(Docker/WSL/远程容器)指向错误的 loopback,应使用 redis-cli -h 127.0.0.1 -p 6379 ping 验证连通性,并确保 redis-server 已运行且网络命名空间一致。

Redis 连接失败时 redis.createClient() 报什么错
最常见的错误就是 Error: connect ECONNREFUSED 127.0.0.1:6379,这其实是在告诉你:Node 进程根本够不着 Redis。不是配置写错了,是 Redis 压根没跑起来。
本地调试时有一个特别容易忽略的点——别直接写 redis://localhost:6379 或 127.0.0.1。VSCode 的调试环境可能跑在 Docker、WSL 或者远程容器里,localhost 指向的是当前进程所在环境的 loopback,不一定是你本机那个 Redis 实例。正确做法是:
- 先在终端里跑一句
redis-cli -h 127.0.0.1 -p 6379 ping,确认 Redis 能不能连上(注意:这个终端必须和 Node 进程在同一个网络命名空间)。 - VSCode 启动调试前,先检查
redis-server是否已经运行;如果用了 Docker,确保容器把6379端口暴露出来了,并且 network mode 是对的(比如host或者自定义 bridge)。 - 推荐显式传入
socket配置,而不是写 host/port。比如这样:redis.createClient({ socket: { host: 'redis', port: 6379 } }),配合docker-compose.yml里 service 名的解析,能省不少事。
connect-redis 初始化失败导致 session 不写入
典型表现是:每次刷新页面,req.session.id 都在变,但 Redis 里查不到任何 key。问题大概率出在 store 实例没正确创建,或者没传进 session() 里。
connect-redis@6+ 和旧版 API 差别很大。新版必须传 client 实例,而且这个 client 得提前调用 connect();旧版则允许直接传 url 或 host/port。所以:
- 先确认版本:
npm list connect-redis。如果 ≥6.0,那就必须手动await redisClient.connect(),再传给new RedisStore({ client: redisClient })。 - 别漏掉
store字段:app.use(session({ store: new RedisStore({ client: redisClient }), ... }))。缺了它,就会回退到内存存储,Redis 里自然啥也没有。 - 检查 Redis 客户端是否处于 ready 状态:打印
redisClient.isOpen,或者监听'ready'事件,等它准备好了再挂载中间件。
VSCode 调试时 session cookie 不生效的几个硬坑
浏览器发请求了,Node 也收到了,但 req.session 始终为空,或者 Set-Cookie 头根本没出现在响应里——这多半是 Express 中间件顺序或者 cookie 配置出了冲突。
express-session必须放在app.use(express.json())和app.use(express.urlencoded())之后,但要放在所有路由app.use('/api', router)之前,否则 session 解析会被跳过。- 本地开发用 HTTP 协议时,千万别设
cookie.secure: true,否则浏览器会静默丢弃Set-Cookie,cookie 根本存不下来。 - 如果前端是 React/Vue 开发服务器(比如
localhost:3000),后端是localhost:3001,需要配上cookie.sameSite: 'none'+cookie.secure: false(仅限开发环境),否则跨端口请求不会带 cookie。 - VSCode 的调试配置(
launch.json)里如果用了env覆盖了NODE_ENV,可能会导致某些中间件行为变化——比如 production 下默认启用secure,结果本地调试就莫名其妙失效了。
Redis 存的 session key 长什么样,怎么手动查
Redis 里实际存的 key 是 sess:,比如 sess:abc123xyz,value 是序列化后的 JSON 字符串,里面包含 cookie、passport、自定义字段等。调试时想验证 session 是否真的写进去了,别光看代码逻辑,直接连 Redis 查:
- 命令行:
redis-cli keys "sess:*"看看有没有匹配的 key。 - 查具体内容:
redis-cli get "sess:abc123xyz",返回的结果类似{"cookie":{"originalMaxAge":null,"expires":null,"httpOnly":true,"path":"/","sameSite":"lax"},"user":"admin"}。 - 注意 TTL:如果设置了
cookie.maxAge,Redis key 会自动带上过期时间;没设的话默认永不过期(除非 Redis 内存淘汰策略触发)。 - 别用 GUI 工具盲目删 key——
connect-redis默认用SETEX写入,删了就真丢了,没有回收机制。
说到底,Redis 的 session 存储本身很轻量,但连接链路、中间件挂载顺序、cookie 安全策略这三块,最容易在 VSCode 调试中突然失效,而且报错不明显。动手排查前,先确认 client 是否 connect 成功、store 是否真实传入、cookie 是否被浏览器接收——把这些基础捋清楚,再动业务逻辑也不迟。