Node.js Cluster 模式下实现异步会话共享,需要在 express-session 中间件中配置 Redis 存储适配器,确保所有 Worker 进程连接同一个 Redis 实例。适用场景是多进程部署,风险边界在于 Redis 连接池配置不当可能导致连接耗尽。
先说结论:使用外部存储替代内存存储是 Cluster 模式会话共享的唯一可靠方案。
- 适合:多 Worker 进程需要共享用户登录状态的场景。
- 先准备:安装 express-session 和 connect-redis 包,确保 Redis 服务可用。
- 验收:通过负载均衡请求不同 Worker,验证 Session ID 是否保持一致。
命令速用版
在项目根目录执行以下命令安装依赖,确保 package.json 记录版本信息。
npm install express-session connect-redis redis如果使用的是 CommonJS 模块, require 语句需放在 cluster master 进程之外,确保 Worker 继承配置。
为什么会这样
Node.js Cluster 模块创建的每个 Worker 都是独立的进程,拥有独立的内存空间。
默认情况下,express-session 使用 MemoryStore 将会话数据保存在当前进程内存中。当负载均衡将请求分发到不同 Worker 时,目标进程无法读取其他进程内存中的会话数据,导致用户状态丢失。Redis 作为外部独立服务,所有 Worker 均可通过网络访问同一份数据,从而解决进程隔离带来的状态不一致问题。
分步处理
按照以下顺序配置 Redis 存储,每一步完成后检查控制台无报错。
步骤 1:初始化 Redis 客户端
创建独立的 Redis 连接实例,建议配置连接池参数以避免高并发下连接耗尽。
const redis = require('redis');
const client = redis.createClient({
socket: { host: '127.0.0.1', port: 6379 }
});
client.connect().catch(console.error);步骤 2:配置 Session 中间件
将 Redis 客户端传入 connect-redis 构造函数,并将生成的 store 实例交给 express-session。
const RedisStore = require('connect-redis').default;
const session = require('express-session');
app.use(session({
store: new RedisStore({ client }),
secret: 'your_secret_key',
resave: false,
saveUninitialized: false,
cookie: { secure: false, maxAge: 3600000 }
}));步骤 3:启动 Cluster 集群
确保 session 配置代码在 cluster.fork() 之前执行,或者在所有 Worker 中统一初始化。
const cluster = require('cluster');
if (cluster.isPrimary) {
for (let i = 0; i < numCPUs; i++) cluster.fork();
} else {
// Worker 进程启动 HTTP 服务
}怎么验证是否生效
通过以下方法确认会话数据已写入 Redis 且跨进程可见。
检查 Redis 键值
使用 redis-cli 连接数据库,执行 keys 命令查看是否存在 session 前缀的键。
redis-cli
keys sess:*观察 Worker 日志
在不同 Worker 进程中打印 session ID,连续发起请求,确认 ID 不变且进程 PID 变化。
测试负载均衡
使用 ab 或 curl 并发请求登录接口,验证后续请求无需重新登录。
常见坑
配置过程中容易遇到以下问题,需提前规避。
连接池耗尽
默认 Redis 客户端可能未开启连接池,高并发下会报错。需在 createClient 时明确配置 socket 或 pool 参数。
序列化错误
存入 Redis 的对象包含不可序列化字段(如函数、undefined)会导致写入失败。确保 session 数据仅为纯 JSON 对象。
Cookie 安全标志
生产环境启用 HTTPS 后,需将 cookie 配置中的 secure 设为 true,否则浏览器可能拒绝发送 Session ID。
常见问题
MemoryStore 为什么不能在 Cluster 中使用?
MemoryStore 数据保存在单进程内存中,其他 Worker 进程无法访问。
Redis 连接失败会影响服务启动吗?
取决于错误处理逻辑,建议配置重试机制避免进程崩溃,但会话功能将不可用。
需要配置 Sticky Session 吗?
使用 Redis 存储后不需要 Sticky Session,因为会话数据已集中存储,请求可分发至任意 Worker。
参考来源
- npm: express-session - https://www.npmjs.com/package/express-session
- npm: connect-redis - https://www.npmjs.com/package/connect-redis
- Node.js Documentation: Cluster module - https://nodejs.org/api/cluster.html