【发布时间】:2020-04-08 19:29:39
【问题描述】:
我对这个问题有点绝望:我们正在为我们的 API 运行 AWS Lambda,它与 MongoDB Atlas (M20) 上的 MongoDB 集群通信。为了防止在每次 Lambda 调用时创建新连接,我们遵循以下模式:https://docs.atlas.mongodb.com/best-practices-connecting-to-aws-lambda/ 在 Lambda 容器的生命周期内缓存连接。我们有一些细微的变化:
async function getProdDB() {
const url = `mongodb+srv://${process.env.DB_USER}:${process.env.DB_PASSWORD}@xxxxx-yyyy.zzzzz.net?retryWrites=true`
if (!cachedDb || !cachedDb.serverConfig.isConnected()) {
cachedClient = await MongoClient.connect(
url,
{ useNewUrlParser: true, useUnifiedTopology: true }
)
cachedDb = cachedClient.db(process.env.DB_NAME)
}
return cachedDb
}
这也检查我们是否已连接。现在这在 98% 的时间内都有效,但我们的 Lambda 调用有时会超时。我们试着诊断了一下:
- 我们将 Lambda 的超时限制从 6 秒更改为 30 秒/60 秒,而 Lambda 函数仍会不时超时。 Mongo 从来没有抛出错误,由于 TimeoutError,它总是 Lambda 完成调用
- 如果调用成功和不成功,
cachedDB.serverConfig.isConnected()返回 rue` - 导致超时的业务逻辑部分是对 MongoDB 本身的查询,常见的 MongoDB 操作,如在非常小的集合(前 100 个文档)上的
findOne或updateOne - 我们尝试在 https://github.com/Automattic/mongoose/issues/8180 之后将 NodeJS 上的 MongoDB 驱动程序从
3.3.1升级到3.3.5(虽然我们没有使用 mongoose,只是使用了官方的 mongodb NodeJS 驱动程序),但问题仍然存在 - 我们尝试通过使用相同版本驱动程序的 NodeJS 脚本直接查询我们的 MongoDB 集群,在数千个查询中,没有一个超时问题发生。所以我们得出结论,问题不在于我们的集群本身,而在于连接。
- 频繁调用的函数不会比定期调用但频率较低的函数更频繁地超时。看起来,即使在调用
isConnected()时返回true,我们与 MongoDB 的缓存连接也在某种程度上变得陈旧,并且在 Lambda 容器在没有调用的情况下保持打开一段时间后无法重用。我们使用默认超时:https://scalegrid.io/blog/understanding-mongodb-client-timeout-options/ - 检查了 Atlas 上的 MongoDB 日志条目 - 没有任何可疑之处
- 停止 chaching 数据库连接解决了这个问题,但使大多数 API 调用慢了 2-3 倍,我们仍然想了解问题的根源
有没有人遇到过类似的问题,或者可以建议我们如何有效地调试这个问题?
【问题讨论】:
-
如果我这个语句 ::
In case of successful and unsuccessful invocations是关于 lambda 调用 - 那么你的意思是不管 lambda 超时或成功 - DB 调用正在发生吗?另外我会说将这个(!cachedDb || !cachedDb.serverConfig.isConnected())更改为(!cachedDb && !cachedDb.serverConfig.isConnected()),请尝试测试是否每次都创建连接或者它是否正在使用缓存连接。同样的代码或不同的代码也会发生超时 - 当callback()未正确调用时,可能会发生通常的 lambda 超时。 -
续:在您的情况下,如果使用客户端或通用代码执行的相同查询确实在更少的毫秒内执行,则不会花费太多时间导致 lambda 超时!通常的 lambda 超时时间最长为 15 分钟,但理想的是 15-30 秒,具体取决于操作 - 你的情况已经足够好了..
-
关于您的第一条评论:是的,
true是从cachedDb.serverConfig.isConnected()返回的情况下,数据库将查询结果返回给 lambda,也没有,导致 lmabda 调用卡在对数据库的调用中并在 lambda 设置的超时限制后超时 -
建议更改为条件对我来说没有意义。我们想检查他们是否还没有缓存连接,或者我们有一个,但它没有连接。在这里使用 AND 是行不通的,例如当你有一个
cachedDB但它没有连接时,条件将是虚假的,不会发生创建新连接的尝试。 -
是的,完全相同的代码有时会正确执行,有时会超时。当代码在 lambda 上执行良好时,lambda 调用平均需要 20-30 毫秒才能执行。无论我们在 Lambda 中设置多高的超时限制,有时相同的函数都会超时。
标签: node.js mongodb amazon-web-services aws-lambda