我在 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 中的类似问题。
我在客户端初始化中尝试了
,但似乎没有做任何事情。我什至不确定它是否是 JS 环境的有效参数,因为我已经看到它被建议用于 Python 中的类似问题。
socket_keepalive: true
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 的连接丢失,客户端应尝试使用指数退避策略重新连接。因此,构建重新连接策略以更好地处理瞬态问题并提供渐进的退避机制。
retryStrategy
来微调重新连接行为。