You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Docker中Node.js连接Redis报"Error: The client is closed"问题求助

Docker中Node.js连接Redis出现"Error: The client is closed"的解决方法

问题背景

在Docker环境中部署Node.js服务和Redis服务时,Node.js代码执行时抛出Error: The client is closed错误,相关配置与代码如下:

docker-compose.yml配置

version : "3"
services:
  irbredis:
    image: redis:7.2.2-alpine
    container_name: irbredis
  irbserver:
    image: node:20.9.0-alpine
    container_name: irbserver
    depends_on:
      - irbredis

Node.js相关代码

redisFunc.js:

const redis = require('redis');
const rclient = redis.createClient({ url: "redis://irbredis:6379" });

module.exports = {
    rclient : rclient
}

sessionMW.js:

const session    = require('express-session');
const RedisStore = require('connect-redis').default;

module.exports = session({
    store: new RedisStore({ client : require('./redisFunc.js').rclient }),
    //...其他session配置
});

index.js:

const express = require('express');
const app     = express();   

app.use(express.urlencoded({ extended: true }));
app.use(express.json());

app.use(require('./sessionMW.js'));
//...其他路由配置

依赖版本

"connect-redis": "^7.1.0",
"express": "^4.18.2",
"express-session": "^1.17.3",
"redis": "^4.6.10",

错误日志

irbserver  | Error: The client is closed
irbserver  |     at Commander._RedisClient_sendCommand (/app/node_modules/@redis/client/dist/lib/client/index.js:494:31)
irbserver  |     at Commander.commandsExecutor (/app/node_modules/@redis/client/dist/lib/client/index.js:189:154)
irbserver  |     at BaseClass.<computed> [as get] (/app/node_modules/@redis/client/dist/lib/commander.js:8:29)
irbserver  |     at Object.get (/app/node_modules/connect-redis/dist/cjs/index.js:20:34)
irbserver  |     at RedisStore.get (/app/node_modules/connect-redis/dist/cjs/index.js:53:42)
irbserver  |     at session (/app/node_modules/express-session/index.js:485:11)
irbserver  |     at Layer.handle [as handle_request] (/app/node_modules/express/lib/router/layer.js:95:5)
irbserver  |     at trim_prefix (/app/node_modules/express/lib/router/index.js:328:13)
irbserver  |     at /app/node_modules/express/lib/router/index.js:286:9
irbserver  |     at Function.process_params (/app/node_modules/express/lib/router/index.js:346:12)

问题原因及解决方法

1. Redis客户端未完成连接就被使用

Redis v4.x版本中,createClient仅创建客户端实例,不会自动建立连接。你的代码直接将未连接的客户端传给connect-redis,导致调用命令时客户端处于关闭状态。

解决方法:
在redisFunc.js中添加连接逻辑,确保连接成功后再导出客户端:

const redis = require('redis');
const rclient = redis.createClient({ url: "redis://irbredis:6379" });

// 监听连接错误
rclient.on('error', (err) => console.error('Redis连接错误:', err));

// 主动建立连接
(async () => {
    await rclient.connect();
})();

module.exports = {
    rclient: rclient
};

也可以在应用启动前确保连接完成,修改index.js:

const express = require('express');
const app     = express();
const redisClient = require('./redisFunc.js').rclient;

// 等待Redis连接成功后启动服务
(async () => {
    await redisClient.connect();
    app.use(express.urlencoded({ extended: true }));
    app.use(express.json());
    app.use(require('./sessionMW.js'));
    
    app.listen(3000, () => {
        console.log('服务已启动');
    });
})();

2. depends_on仅保证容器启动顺序,不保证Redis服务就绪

docker-compose中的depends_on仅控制容器启动顺序,Redis容器启动后需要时间完成服务初始化,此时Node.js服务可能已尝试连接,导致连接失败。

解决方法:

  • 方法一:利用Redis客户端自动重连特性,同时监听connect事件确认连接状态。
  • 方法二:在docker-compose.yml中添加healthcheck,仅当Redis服务就绪后再启动Node.js容器:
version : "3"
services:
  irbredis:
    image: redis:7.2.2-alpine
    container_name: irbredis
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 2s
      timeout: 2s
      retries: 5
  irbserver:
    image: node:20.9.0-alpine
    container_name: irbserver
    depends_on:
      irbredis:
        condition: service_healthy

3. 确认版本兼容性

你的connect-redis@7.1.0与redis@4.6.10版本兼容,后续升级时需注意对应版本匹配,避免兼容性问题。

总结

核心问题是Redis客户端未建立连接就被使用,加上Docker容器启动顺序不代表服务就绪,按上述步骤修改代码和配置即可解决问题。

内容的提问来源于stack exchange,提问作者Robert C. Holland

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 12:52:52