【发布时间】:2020-12-24 23:56:23
【问题描述】:
我正在开发多个 Firebase 云功能(全部托管在同一区域),它们使用 VPC 连接器与同一区域中的 GCP 托管 Redis 实例连接。我正在为 Redis 使用 3.0.2 版的 nodejs 库。在云功能的调试日志中,我看到频繁的连接重置日志,这些日志是针对每个云功能触发的,在连接重置的时间线周围没有固定模式。并且每次在错误事件处理程序中捕获的错误都是 ECONNRESET。在创建 Redis 实例时,我提供了一个 retry_strategy 以在 5 毫秒后重新连接,最多 10 次这样的尝试,同时将 retry_unfulfilled_commands 设置为 true,期望在连接重置时任何未完成的命令都会自动重试(参考代码下面)。
const redisLib = require('redis');
const client = redisLib.createClient(REDIS_PORT, REDIS_HOST, {
enable_offline_queue: true,
retry_unfulfilled_commands: true,
retry_strategy: function(options) {
if (options.error && options.error.code === "ECONNREFUSED") {
// End reconnecting on a specific error and flush all commands with
// a individual error
return new Error("The server refused the connection");
}
if (options.attempt > REDIS_CONNECTION_RETRY_ATTEMPTS) {
// End reconnecting with built in error
console.log('Connection retry count exceeded 10');
return undefined;
}
// reconnect after 5 ms
console.log('Retrying connection after 5 ms');
return 5;
},
});
client.on('connect', () => {
console.log('Redis instance connected');
});
client.on('error', (err) => {
console.error(`Error connecting to Redis instance - ${err}`);
});
exports.getUserDataForId = (userId) => {
console.log('getUserDataForId invoked');
return new Promise((resolve, reject) => {
if(!client.connected) {
console.log('Redis instance not yet connected');
}
client.get(userId, (err, reply) => {
if(err) {
console.error(JSON.stringify(err));
reject(err);
} else {
resolve(reply);
}
});
});
}
// more such exports for different operations
以下是我面临的问题/问题。
- 为什么连接会间歇性重置?
- 我看过日志,即使正在执行云功能,与Redis服务器的连接丢失导致命令失败。
- retry_unfulfilled_commands 设置为 true,我希望它能处理上面第 2 点中提到的场景,但根据调试日志,云功能在这种情况下会超时。这就是我在那种情况下的日志中观察到的。
getUserDataForId invoked
Retrying connection after 5 ms
Redis instance connected
Function execution took 60002 ms, finished with status: 'timeout' --> coming from wrapper cloud function
- 我是否应该尝试在每次这样的 Redis 操作期间创建一个连接,而不是在全局级别创建一个 Redis 连接实例?它可能存在一些性能问题以及有关并发 Redis 连接数量的问题(因为我有多个云功能,并且所有这些功能都会为每个同时调用创建 Redis 连接),对吗?
所以,如何最好地处理它,因为我在开发过程中遇到了所有这些问题,所以不确定是代码相关问题还是一些基础设施配置相关问题。
【问题讨论】:
-
您是使用 Memorystore for Redis 还是您的 Redis 托管在 GCE 实例或 GKE 上?您还可以与我们分享您正在使用的 Redis 版本以及 ECONNRESET 错误的完整日志条目。
-
我正在使用 Memorystore for Redis。版本为 4.0(基本层)。除了记录为 ECONNRESET 的错误外,我在云功能日志中看不到任何其他日志。有没有办法获得增强的 Redis 日志记录?
标签: google-cloud-platform redis google-cloud-functions