NodeJS Redis - 在后台重新连接
NodeJS Redis - Reconnect In Background
我的情况是 - 我正在尝试通过 REDIS 密钥检索资源。如果密钥不存在,则从 API.
获取它
运行 遇到以下问题:如果 Redis 连接断开或者我无法从启动时连接到 Redis,则 nodejs 库 ('redis') 将继续尝试重新连接。它阻止我通过 API 获取我需要的信息,因为重试逻辑将接管并且不会继续获取所需信息。
我想在后台使用此功能 运行 - 可以吗?
意思是,如果 Redis down/cannot 从 NodeJs 连接到 REDIS,那么它将尝试重新连接。然而,当它关闭并且应用程序将尝试定期重新连接时,我希望能够通过备份计划获取数据,即通过 API,如上所述。
任何关于这种情况的指示都将不胜感激 - 提前致谢。
您可以在 redis-connection 周围创建一个 wrapper/proxy,确保所有 redis 操作都已连接到 redis。如果不是,你可以抛出一个错误(你可以在调用者中处理)或者 return undefined.
基本上,您可以监听 ready
和 error
事件并更新包装器内的 status
标志,以便始终了解当前连接状态。
现在,这肯定会涵盖初始连接不成功或呼叫之间发生断开连接的情况。问题是在您成功检查 status
标志后断开连接的罕见情况。要解决这个问题,您可以为 redis 调用定义一个最大等待时间,如果达到超时则 return/throw 一个错误并忽略 redis 结果。下面是一些可以帮助您入门的基本代码:
class RedisService {
isConnected = false;
client;
constructor() {
this.client = redis.createClient();
this.client.get = promisify(this.client.get).bind(this.client);
this.client.set = promisify(this.client.set).bind(this.client);
this.attachHandlers();
}
attachHandlers() {
this.client.on("ready", () => {
this.isConnected = true;
});
this.client.on("error", (err) => {
this.isConnected = false;
console.log(err);
});
}
async tryGet(key) {
if (!this.isConnected) {
return undefined; // or throw an error
}
return Promise.race([this.client.get(key), this.wait()]);
}
async trySet(key, val) {
if (!this.isConnected) {
return undefined; // or throw an error
}
return Promise.race([this.client.set(key, val), this.wait()]);
}
wait(ms = 200) {
return new Promise(resolve => {
setTimeout(resolve, ms);
})
}
}
然后在你的来电者中你可以这样做:
async someMethodThatCallsRedisOrApi() {
let result;
try {
result = await redisService.tryGet('testkey');
} catch (e) {
console.log(e);
}
if (!result) {
result = apiService.get(...); // call the actual api to get the result
await redisService.trySet('testkey', result);
}
res.json(result)
});
我的情况是 - 我正在尝试通过 REDIS 密钥检索资源。如果密钥不存在,则从 API.
获取它运行 遇到以下问题:如果 Redis 连接断开或者我无法从启动时连接到 Redis,则 nodejs 库 ('redis') 将继续尝试重新连接。它阻止我通过 API 获取我需要的信息,因为重试逻辑将接管并且不会继续获取所需信息。
我想在后台使用此功能 运行 - 可以吗?
意思是,如果 Redis down/cannot 从 NodeJs 连接到 REDIS,那么它将尝试重新连接。然而,当它关闭并且应用程序将尝试定期重新连接时,我希望能够通过备份计划获取数据,即通过 API,如上所述。
任何关于这种情况的指示都将不胜感激 - 提前致谢。
您可以在 redis-connection 周围创建一个 wrapper/proxy,确保所有 redis 操作都已连接到 redis。如果不是,你可以抛出一个错误(你可以在调用者中处理)或者 return undefined.
基本上,您可以监听 ready
和 error
事件并更新包装器内的 status
标志,以便始终了解当前连接状态。
现在,这肯定会涵盖初始连接不成功或呼叫之间发生断开连接的情况。问题是在您成功检查 status
标志后断开连接的罕见情况。要解决这个问题,您可以为 redis 调用定义一个最大等待时间,如果达到超时则 return/throw 一个错误并忽略 redis 结果。下面是一些可以帮助您入门的基本代码:
class RedisService {
isConnected = false;
client;
constructor() {
this.client = redis.createClient();
this.client.get = promisify(this.client.get).bind(this.client);
this.client.set = promisify(this.client.set).bind(this.client);
this.attachHandlers();
}
attachHandlers() {
this.client.on("ready", () => {
this.isConnected = true;
});
this.client.on("error", (err) => {
this.isConnected = false;
console.log(err);
});
}
async tryGet(key) {
if (!this.isConnected) {
return undefined; // or throw an error
}
return Promise.race([this.client.get(key), this.wait()]);
}
async trySet(key, val) {
if (!this.isConnected) {
return undefined; // or throw an error
}
return Promise.race([this.client.set(key, val), this.wait()]);
}
wait(ms = 200) {
return new Promise(resolve => {
setTimeout(resolve, ms);
})
}
}
然后在你的来电者中你可以这样做:
async someMethodThatCallsRedisOrApi() {
let result;
try {
result = await redisService.tryGet('testkey');
} catch (e) {
console.log(e);
}
if (!result) {
result = apiService.get(...); // call the actual api to get the result
await redisService.trySet('testkey', result);
}
res.json(result)
});