redis 从上个月左右开始,我们的Lambda NodeJS 12.x上的AUTH出现NR_CLOSED错误

qjp7pelc  于 2023-03-17  发布在  Redis
关注(0)|答案(1)|浏览(173)

我们正在使用Redis节点模块让Redis客户端与Redis服务器通信。从上个月左右开始,我们在Lambda上遇到了NR_CLOSED错误。我们正在使用node redis库和redis-labs作为我们的Redis服务器,详细信息将在下面提到。

2021-05-25T08:47:00.034Z    ed14111b-3ce2-4354-b46e-3101c27b6efa    ERROR   Uncaught Exception  
{
    "errorType": "AbortError",
    "errorMessage": "Stream connection ended and command aborted. It might have been processed.",
    "code": "NR_CLOSED",
    "command": "AUTH",
    "args": [
        "*******"
    ],
    "origin": {
        "errorType": "Error",
        "errorMessage": "Redis Error",
        "stack": [
            "Error: Redis Error",
            "    at Object.retry_strategy (/var/task/services/CacheService.js:15:20)",
            "    at RedisClient.connection_gone (/var/task/node_modules/redis/index.js:618:41)",
            "    at RedisClient.on_error (/var/task/node_modules/redis/index.js:410:10)",
            "    at Socket.<anonymous> (/var/task/node_modules/redis/index.js:279:14)",
            "    at Socket.emit (events.js:314:20)",
            "    at Socket.EventEmitter.emit (domain.js:483:12)",
            "    at emitErrorNT (internal/streams/destroy.js:92:8)",
            "    at emitErrorAndCloseNT (internal/streams/destroy.js:60:3)",
            "    at processTicksAndRejections (internal/process/task_queues.js:84:21)"
        ]
    },
    "stack": [
        "AbortError: Stream connection ended and command aborted. It might have been processed.",
        "    at RedisClient.flush_and_error (/var/task/node_modules/redis/index.js:362:23)",
        "    at RedisClient.connection_gone (/var/task/node_modules/redis/index.js:624:18)",
        "    at RedisClient.on_error (/var/task/node_modules/redis/index.js:410:10)",
        "    at Socket.<anonymous> (/var/task/node_modules/redis/index.js:279:14)",
        "    at Socket.emit (events.js:314:20)",
        "    at Socket.EventEmitter.emit (domain.js:483:12)",
        "    at emitErrorNT (internal/streams/destroy.js:92:8)",
        "    at emitErrorAndCloseNT (internal/streams/destroy.js:60:3)",
        "    at processTicksAndRejections (internal/process/task_queues.js:84:21)"
    ]
}

在2个月之前,我们从来没有遇到过这个redis错误。这就是我们在Lambda代码中使用它的方式。

缓存服务.js

var redis = require("redis");
var await = require('asyncawait/await');
var async = require('asyncawait/async');
const { promisify } = require('util');

module.exports = function (config) {
    this.client = redis.createClient({
    host: config['redis']['host'],
    port: config['redis']['port'],
    password:config['redis']['password'],
    retry_strategy: function (options) {

        if (options.error) {
            console.log("RedisError: ", options.error);
            return new Error('Redis Error');  //line 15 for error stack reference
            }
        return 100;
        }
        });
    
    this.getCachedData = async function getCachedData(key) {
        const getAsync = promisify(this.client.get).bind(this.client);
        var data =  await getAsync(key);
        return data
    }
    
    this.closeConnection = function closeConnection() {
        // close the redis connection
        this.client.quit();
    }
}

这是使用此服务的方式

module.exports = {
    resetConfig: async function (paramConfigData, falconConfigData) {
        if (paramConfigData !== "" && paramConfigData.fetched_at < Date.now()) {
            paramConfigData = ""
        }

        if (paramConfigData === "") {
           

>         try {
>                 var configCacheHandler = new CacheService(falconConfigData)
>                 var cachedConfig = await(configCacheHandler.getCachedData(this.client+":config"));
                 paramConfigData = JSON.parse(cachedConfig);
                 paramConfigData.fetched_at = Date.now() + 10000;
                configCacheHandler.closeConnection();

            } catch (e) {
                console.log("Cached config RedisError:", e)
            }
        }
        return paramConfigData;
    }

}

环境

*Node.js版本12.x
*Redis库版本2.8.0
*Redis版本6.0.6
*平台Node JS(Lambda)

fnvucqvd

fnvucqvd1#

如果客户端连接断开,Node-redis会返回一个NR_CLOSED错误代码。但是,node-redis无法重新连接到2.8.0版本的Redis,因为这个问题It will never reconnect when the connection has closed
这里是我们使用的一个解决方案,尝试在node-redis客户端的error事件监听器上重新连接Redis服务器
样本代码

redisClient = redis.createClient({
      port: this.cacheOptions.port,
      host: this.cacheOptions.host,
      connect_timeout: 5000
    });

    redisClient.on('error', (err) => {
      return this.checkErrAndReconnect(err);
    });

  checkErrAndReconnect: function(err) {
    var errorCode, isAbortError, isAggregateError, isRedisError;
    isRedisError = err instanceof redis.RedisError ? true : false;
    isAbortError = err.constructor.name === 'AbortError' ? true : false;
    isAggregateError = err.constructor.name === 'AggregateError' ? true : false;
    errorCode = err.code;
    if ((isRedisError || isAbortError || isAggregateError) && errorCode === 'CONNECTION_BROKEN') {
      return this.timeOutId = setTimeout(() => {
        return this.reconnect();
      }, 30000);
    }
  },

  reconnect: function() {
    if (redisClient.connected) {
      clearTimeout(this.timeOutId);
      return;
    }
    if (!redisClient.closing) {
      return;
    }

    // reconnect to redis
    try {
      redisClient = redis.createClient({
        port: this.cacheOptions.port,
        host: this.cacheOptions.host
      });
    } catch (error) {
      logger.error('Failed to recreate redis client');
    }
  }

相关问题