如何配置 Node Redis 客户端在连接失败时立即抛出错误? [阅读详情]

How to configure Node Redis client to throw errors immediately, when connection has failed? [READ DETAILS]

我正在使用具有此配置的 Node Redis:

import redis from "redis";
import { promisify } from "util";
import config from "../../appConfig";

const redisUrl = config.REDIS_URL;
const [host, port] = redisUrl.substr(8).split(":");
const RedisClient = redis.createClient({ host: host, port: Number(port) });
RedisClient.on("error", (err) => {
    logger.error(err);
});
const GetAsync = promisify(RedisClient.get).bind(RedisClient);
const SetAsync = promisify(RedisClient.set).bind(RedisClient);

export { RedisClient, GetAsync, SetAsync };

我有一些代码首先尝试从 Redis 读取,如果失败,则尝试从 catch 块内的 MongoDB 读取。像这样:

try {
    userId = await GetAsync(idKeyStr);
} catch(err) {
    userId = await GetFromMongoDB();
}

我的问题是当连接失败时,代码卡在 userId = await GetAsync(idKeyStr)。没有异常被抛出,因此代码进入 catch 块。客户端尝试重新连接的默认时间为 1 小时。如果在这 1 小时内,服务器出现,它将重新连接并且卡住的请求将最终得到处理。如果它没有出现,该请求将只停留 1 小时。

如果我从 error 事件的回调中抛出错误,应用程序就会停止,因为未处理的异常。

我在此处找到 createClient 方法的 retry_strategy 选项:https://github.com/NodeRedis/node-redis 这是该页面上给出的示例:

const client = redis.createClient({
  retry_strategy: function(options) {
    if (options.error && options.error.code === "ECONNREFUSED") {
      // End reconnecting on a specific error and flush all commands with
      // a individual error
      return new Error("The server refused the connection");
    }
    if (options.total_retry_time > 1000 * 60 * 60) {
      // End reconnecting after a specific timeout and flush all commands
      // with a individual error
      return new Error("Retry time exhausted");
    }
    if (options.attempt > 10) {
      // End reconnecting with built in error
      return undefined;
    }
    // reconnect after
    return Math.min(options.attempt * 100, 3000);
  },
});

为了立即抛出错误,我修改为:

const client = redis.createClient({
      retry_strategy: function() {
          return new Error("The server refused the connection");
      },
    });

但这会完全停止重试,因此即使服务器启动,客户端也会停止连接尝试,因此它永远不会重新连接。

我如何配置它以便客户端继续重新连接但任何发出的命令都会快速失败,以便我的其他代码继续执行?

enable_offline_queue 设置为 false 就可以了。发现了很多类似的问题,但 none 提到了这个:

What's the default timeout of ioredis send command for any redis call

How to set read timeout on node redis client?

终于从这里得到了这个解决方案:https://github.com/NodeRedis/node-redis/issues/789#issuecomment-373270272

请记住,将 enable_offline_queue 设置为 false,您在服务器出现连接问题时发出的命令将永远不会执行。