[英]Nodejs Azure Redis Cache hang forever and read ECONNRESET error
[英]nodejs to redis ECONNRESET error
对于 Node.js 到 Redis 的连接,我们使用了 Redis npm 模块。
偶尔,我们会收到以下错误,
message: read ECONNRESET, stack: Error: read ECONNRESET
at exports._errnoException (util.js:1020:11)
at TCP.onread (net.js:568:26)
Redis 设置是,内部网中的 1 个 redis 服务器和 2 个 Node js 服务器,每个服务器都有 8 个 PM2 实例在 DMZ 中运行。 节点服务器和 Redis 服务器之间存在防火墙。
NODE 版本 - 6.11.2 REDIS 版本 - 3.2.9 PM2 版本 - 2.4.6
我们也做了 TCP 转储。 TCP 转储显示一些 RST/ACK 数据包。 TCP转储
在 nodeJS 中,我们正在创建单个 redis 连接并尝试对所有请求使用相同的 redis 连接。
const Redis = require('redis');
const Config = require('../../config');
const Logger = require('../helpers/logger');
const redisClient = (function() {
// Start with a fake client so that we have a client that works
// even when Redis server is down
let client = {
get: function(key, callback) {
callback(null, null);
},
setex: function(key, time, value) {
Logger.info('Value:',value);
// Do nothing in particular
}
};
// Attempt to create a new instance of an actual redis client
const redisConfig = Config.get('/redis');
const tempClient = Redis.createClient(redisConfig.port,redisConfig.host, {
//eslint-disable-next-line
// console.log('[redis]','Creating the retry strategy');
retry_strategy: function(options) { //eslint-disable-line
//eslint-disable-next-line
console.log('[redis]','Creating the retry strategy');
if (options.error && options.error.code === 'ECONNREFUSED') {
// End reconnecting on a specific error and flush all commands with
// a individual error
//eslint-disable-next-line
console.log('[redis,error]','Connection refused error');
return new Error('The server refused the connection');
}
if (options.error && options.error.code === 'NR_CLOSED') {
//eslint-disable-next-line
console.log('[redis,error]','Connection closed error');
return new Error('The server closed the connection');
}
if (options.attempt > 5) {
// End reconnecting with built in error
//eslint-disable-next-line
console.log('Exceeded attempts');
return undefined;
}
if (options.total_retry_time > 1000 * 60 * 60) {
// End reconnecting after a specific timeout and flush all commands
// with a individual error
//eslint-disable-next-line
console.log('Retrial time:' + options.total_retry_time);
return 1000;
}
// reconnect after
return Math.min(options.attempt * 100, 3000);
}
});
// Set the "client" variable to the actual redis client instance
// once a connection is established with the Redis server
tempClient.on('ready', () => {
client = tempClient;
});
tempClient.on('error', (error) => {
Logger.info(['redis','error'],'Redis client error:', error);
if (error.code === 'NR_CLOSED') {
tempClient.end();
client = Redis.createClient(redisConfig.port,redisConfig.host, {
retry_strategy: function(options) { //eslint-disable-line
if (options.error && options.error.code === 'NR_CLOSED') {
Logger.info(['redis','error'],'Connection closed error');
return new Error('The server refused the connection');
}
}
});
}
});
/**
* Get a redis client
* @return {Object} client - eventually a proper redis client object
* (if redis is up) or a fake client object (if redis is down)
*/
const getClient = function() {
Logger.info('Getting the client ' + client);
return client;
};
return {
getClient: getClient
};
}());
module.exports = redisClient;
我们想知道究竟是什么导致了连接问题以及原因和解决方法。
在 /etc/redis/redis.conf 文件中,
将 bind 127.0.0.1 替换为 bind 0.0.0.0 将 protected-mode yes 替换为 protected-mode no
然后使用 ufw allow 6379 和 ufw allow 6379/tcp 允许端口 6379
iptables -A 输入 -p tcp --dport 6379 -j 接受 iptables -A 输入 -p udp --dport 6379 -j 接受
终于
须藤 systemctl 停止 redis 须藤 systemctl 启动 redis
我在使用 Google Firebase Cloud Functions 时遇到了同样的问题。 问题是最新版本的 Redis 使连接永远保持活动状态。 如果调用 Redis 的进程在调用 Redis 后不久结束,就像我们使用 Cloud Functions 的情况一样,您必须将timeout
设置设置为不同于默认值 0 的值。
您可以通过更改名为redis.conf
的 Redis 配置文件中的超时值来完成此redis.conf
该文档说您还可以设置超时设置而无需重新启动实例,如果您的 Redis 实例受到保护,则这是不可能的,因此无法通过 redis-cli 运行类似CONFIG SET timeout 15
的内容,因为您会收到以下错误:
(错误) ERR 未知命令
CONFIG
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.