Node JS API 上重复出现 SocketClosedUnexpectedlyError

问题描述 投票:0回答:1

我在 Node JS API 中不断收到此错误:

Redis 客户端错误 SocketClosedUnexpectedlyError: Socket 意外关闭 在 TLSSocket. (.../node_modules/@redis/client/dist/lib/client/socket.js:194:118) 在 Object.onceWrapper (节点:事件:633:26) 在 TLSSocket.emit (节点:事件:530:35) 在节点:网络:337:12 在 TCP.done (节点:_tls_wrap:657:7)

之后重新连接成功。不过,这种情况每小时都会发生几次,因此如果同时命中端点,它可能会中断应用程序。 Redis 服务器托管在 Azure 上。在本地运行 API 和在生产环境中的 Azure 应用服务上运行时的行为是相同的。

下面是我用来在我的应用程序中设置 Redis 的代码。

如有任何帮助,我们将不胜感激。谢谢

const redis = require('redis');

const dbIndex = process.env.REDIS_DB_INDEX || 0; // Default to 0 if no index is set
const DEFAULT_TTL = parseInt(process.env.FACETS_CACHE_TTL, 10) || 1800

const redisClient = redis.createClient({
    url: `rediss://${process.env.REDIS_HOST}:6380`,
    password: process.env.REDIS_PASSWORD,
    socket_keepalive: true,
    socket: {
      tls: {
        servername: process.env.REDIS_HOST
      },
      reconnectStrategy: (retries) => {
        // This is a simple example; you can implement more complex logic.
        // For example, you can increase the delay with each retry or set a max number of retries.
        if (retries < 10) {
          // Wait 2 seconds before reconnecting, with 10 total retries
          return 2000;
        } else {
          // Stop trying after 10 attempts
          return null;
        }
      }
    }
  });
  
redisClient.on('error', (err) => console.log('Redis Client Error', err));
redisClient.on('reconnecting', () => console.log('Reconnecting to Redis...'));
let isFirstConnection = true;

redisClient.on('ready', () => {
  if (isFirstConnection) {
    console.log('\nSuccessfully connected to Redis');
    isFirstConnection = false;
  } else {
    console.log('\nSuccessfully reconnected to Redis');
  }
});
  
(async () => {
try {
    await redisClient.connect();
    // select the appropriate database index
    await redisClient.sendCommand(['SELECT', dbIndex]);
    console.log(`database index: ${dbIndex}`);
    console.log(`DEFAULT_TTL = ${DEFAULT_TTL} seconds\n`);
    // Once connected, you can subscribe to events or start issuing commands as needed.
} catch (err) {
    console.error('Failed to connect to Redis:', err);
}
})();

我已经尝试过

socket_keepalive: true
在客户端初始化中,但它似乎没有做任何事情。我什至不确定它是否是 JS 环境的有效参数,因为我已经看到它被建议用于 Python 中的类似问题。

node.js redis node-redis azure-redis-cache
1个回答
0
投票

我在客户端初始化中尝试了

socket_keepalive: true
,但似乎没有做任何事情。我什至不确定它是否是 JS 环境的有效参数,因为我已经看到它被建议用于 Python 中的类似问题。

  • socket_keepalive
    选项不是有效参数。

  • SO_KEEPALIVE
    是正确的参数,您可以在MS_DOC

    中检查相同的参数
  • 在 Node.js 中,当使用

    redis
    库创建 Redis 客户端时,大多数情况下您不会直接与套接字对象交互。

  • 因此,您可以在创建Redis客户端时通过

    SO_KEEPALIVE
    配置对象来配置
    keepAlive
    选项,而不是使用
    socket
    。它将正确管理底层 Node.js 套接字实现。

  • 即使在不活动期间,它也可以通过定期发送保持活动数据包来帮助保持连接活动。

  • 这里我使用了

    keepalive
    参数,我可以与客户端连接而无需重新连接。

我的

Server.js
文件:

const redis = require('redis');

const dbIndex = process.env.REDIS_DB_INDEX || 0; 
const DEFAULT_TTL = parseInt(process.env.FACETS_CACHE_TTL, 10) || 1800;

const redisClient = redis.createClient({
    url: `rediss://${process.env.REDIS_HOST}:6380`,
    password: process.env.REDIS_PASSWORD,
    socket: {
        keepAlive: true, // Enable keep-alive
        tls: {
            servername: process.env.REDIS_HOST
        },
        reconnectStrategy: (retries) => {
            if (retries < 10) {
               
                return 2000;
            } else {
              
                return null;
            }
        }
    }
});

redisClient.on('error', (err) => console.log('Redis Client Error', err));
redisClient.on('reconnecting', () => console.log('Reconnecting to Redis...'));
let isFirstConnection = true;

redisClient.on('ready', () => {
    if (isFirstConnection) {
        console.log('\nSuccessfully connected to Redis');
        isFirstConnection = false;
    } else {
        console.log('\nSuccessfully reconnected to Redis');
    }
});

(async () => {
    try {
        await redisClient.connect();
        await redisClient.sendCommand(['SELECT', dbIndex]);
        console.log(`database index: ${dbIndex}`);
        console.log(`DEFAULT_TTL = ${DEFAULT_TTL} seconds\n`);
       
    } catch (err) {
        console.error('Failed to connect to Redis:', err);
    }
})();
  • 如果与 Redis 的连接丢失,客户端应尝试使用指数退避策略重新连接。因此,构建重新连接策略以更好地处理瞬态问题并提供渐进的退避机制。

  • 感谢@SimoneSacchito,使用选项

    retryStrategy
    来微调重新连接行为。

enter image description here

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.