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

Nodejs中使用ioredis调用hnormalget时报Connection is Closed错误如何解决

问题根因与修复方案

问题定位

  • 错误触发的核心是ioredis连接被主动销毁后没有自动重建,调用hnormalget时无可用连接触发报错
  • 具体错误点:
    1. 你在error事件回调和select操作失败时主动调用了clientRead.end(true),该方法会强制终止连接,且不会触发内置的重连逻辑,和你代码备注的「触发重连」完全相反
    2. 初始化客户端时已经指定了db:10,后续在connect事件中再次执行select DBNUM属于冗余操作,若两个库号不一致还会触发不必要的错误
    3. ioredis原生支持Promise,不需要额外使用Promise.promisifyAll封装,多余封装可能引入异步逻辑异常
    4. retryStrategy中判断times不是数字时返回错误,会直接终止所有重连尝试,后续所有请求都会直接抛出连接关闭错误

修复方案

  • 移除所有主动调用clientRead.end(true)的逻辑,ioredis内置的重连机制会在连接异常时自动触发重连,不需要手动销毁
  • 移除冗余的connect事件中select操作,直接在初始化客户端的db参数中填写正确的库号即可
  • 移除Promise.promisifyAll封装,直接使用ioredis原生的Promise方法
  • 调整retryStrategy逻辑,不要直接返回错误终止重连,仅在重试次数超过阈值时再终止

修复后代码

var redis = require('ioredis');
var config = require('./../../config');
var DBNUM = config.redis.GPDatabaseNum;

var clientRead = new redis({
    port: config.database.redisPort,
    host: config.database.redisHost,
    prefix: config.database.redisPrefix,
    password: config.database.redisPassword,
    connectionName: 'redisDB-gpRedisCacheRead',
    db: DBNUM, // 直接使用正确的库号,不需要后续select
    readOnly: true,
    keepAlive: 1,
    retryStrategy : function retryStrategy(times) {
        log.error("Redis retry strategy called for gpRedisCache.js...44")
        // 最多重试20次,超过后再终止重连
        if (times > 20) {
            log.error('Redis 重连次数超过上限,停止重连');
            return new Error('Redis Retry time exhausted');
        }
        const delay = Math.min(times * 50, 2000);
        return delay;
    }
});

// 只做错误日志上报,不要主动销毁连接
clientRead.on('error', function(err) {
    log.error(`Error in redis connection on file gpRedisCache.js:95: ${err}`);
});

// 连接成功日志可根据需求添加
clientRead.on('connect', function() {
    log.info('redis读连接建立成功');
});

var redisCacheSeparateReadWritePooledConn = {
    hnormalget: async (hashKey, key) => {
        try {
            const data = await clientRead.hget(hashKey, key);
            return { err: null, data };
        } catch (err) {
            // 可额外增加连接状态判断,若连接断开可等待重连完成后重试一次
            return { err };
        }
    },
}

module.exports = redisCacheSeparateReadWritePooledConn;

可选优化

  • 可以在hnormalget中调用clientRead.status检查连接状态,如果是end或者close状态,可以先等待1-2秒让重连完成后再重试一次请求
  • 如果对可用性要求高,可以引入连接池,避免单连接故障导致所有请求失败

内容的提问来源于stack exchange,提问作者Yogendra Singh

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.13 04:00:00