如何解决node.js 和 redis 集群:处理断开连接
TL;DR 将ioredis 与redis 集群一起使用,如果redis 无法访问,然后尝试重新连接,正确的获取错误的方法是什么?
更多详情:
我正在使用 ioredis 从 node.js 连接到 redis 集群,并尝试为断开连接创建一个相当可靠的解决方案。我想要实现的一方面是在对 redis 的请求失败时收到错误,另一方面,尝试在后台和下一个请求中重新连接。 Ioredis 似乎没有很好地记录这一点,我能够实现这一点的唯一方法是组合 enableOfflineQueue=true
,添加一个返回 false 的 clusterRetryStrategy
,并在捕获连接错误时,创建通过使用 new Redis.Cluster(...)
重新实例化 ioredis 的新连接。
请注意,我尝试过的其他配置都没有实现这种行为:要么永远重试而不抛出错误(如果 clusterRetryStrategy
未定义),要么立即抛出错误并且永远不会再次尝试重新连接(如果enableOfflineQueue
为假),无论我为 reconnectOnError
定义了什么。
-
我的主要问题是,这是一个好策略吗?我是否在之前的 Redis.Cluster 实例中留下了未清理的资源(即,这会造成内存泄漏)吗? 有没有更好的方法来实现这种行为(例如,明确告诉ioredis重新连接,而不重新实例化)?
-
另一个问题,如果此技术实际上是推荐的策略,则是:似乎需要很长时间才能收到错误(针对本地集群运行 5-10 秒)-是否存在一种缩短连接错误的时间的方法?有没有办法配置这个时间(比如~2 秒)?
为了清楚起见,下面是我用来测试的代码。代码中真正相关的部分只是
if (redis.status === 'end') {
redis = connectToCluster();
}
问题的真正含义是什么。
以下是我与 local redis cluster (on windows WSL) 结合运行的代码,我在测试运行时启动和停止该代码以观察行为。
const Promise = require('bluebird');
const Redis = require('ioredis');
function connectToCluster() {
return new Redis.Cluster([
{ host: 'localhost',port: 30001 },{ host: 'localhost',port: 30002 },port: 30003 },port: 30004 },port: 30005 },port: 30006 },],{
enableOfflineQueue: true,clusterRetryStrategy: times => false
});
}
let redis = connectToCluster();
describe('Redis client: ',function () {
it('should error when redis fails and return correct connection state when connected or not',async function () {
this.timeout(300000);
try {
await wait(500);
try {
for (let i = 0; i < 100; i++) {
await redis.set(i,i);
}
} catch (e) {
console.log(`======================================= Failed to insert test data =======================================`);
}
let succeeded = 0,Failed = 0;
for (let i = 0; i < 300000; i++) {
let start = Date.Now();
try {
if (redis.status === 'end') {
console.log(`======================================= RECONNECTING TO CLUSTER (redis.status = "${redis.status}") =======================================`);
redis = connectToCluster();
}
await redis.get(i % 100);
succeeded++;
} catch (e) {
console.log(`======================================= request ${i} Failed in ${Date.Now() - start}ms =======================================`);
Failed++;
}
if (i % 1000 === 0) {
console.log(`=============================== retrieved ${i} times,succeeded: ${succeeded},Failed: ${Failed} ===============================`);
global.gc();
}
}
} catch (e) {
console.log(`========== caught error: ${e.stack}`);
}
});
});
async function wait(ms = 10) {
await Promise.resolve().delay(ms);
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。