Node.js MongoDB Atlas和AWS Lambda之间的间歇性超时问题

Node.js MongoDB Atlas和AWS Lambda之间的间歇性超时问题,node.js,mongodb,amazon-web-services,aws-lambda,Node.js,Mongodb,Amazon Web Services,Aws Lambda,在这个问题上我有点绝望:我们正在为我们的API运行AWS Lambda,该API与MongoDB Atlas(M20)上的MongoDB集群通信。为了防止在每次Lambda调用时创建新连接,我们遵循以下模式:在Lambda容器的生存期内缓存连接。我们有一个轻微的变化: async function getProdDB() { const url = `mongodb+srv://${process.env.DB_USER}:${process.env.DB_PASSWORD}@xxxxx-y

在这个问题上我有点绝望:我们正在为我们的API运行AWS Lambda,该API与MongoDB Atlas(M20)上的MongoDB集群通信。为了防止在每次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的超时限制从6s更改为30s/60秒,Lambda函数仍会时不时超时。Mongo从未抛出错误,总是Lambda由于TimeoutError完成调用
  • 如果调用成功或失败,
    cachedDB.serverConfig.isConnected()
    返回rue`
  • 导致超时的业务逻辑部分是对MongoDB本身的查询,常见的MongoDB操作,如非常小的集合(最多100个文档)上的
    findOne
    updateOne
  • 我们尝试将NodeJS上的MongoDB驱动程序从
    3.3.1
    升级到
    3.3.5
    (我们没有使用mongoose,只是官方的MongoDB NodeJS驱动程序),问题依然存在
  • 我们尝试通过使用相同版本驱动程序的NodeJS脚本直接查询MongoDB集群,在数千次查询中,没有一次出现超时问题。因此我们得出结论,问题不在于我们的集群本身,而在于它们之间的联系
  • 频繁调用的函数不会比定期调用但频率较低的函数超时更频繁。看起来,我们与MongoDB的缓存连接在某种程度上变得陈旧,即使在调用
    isConnected()
    时返回
    true
    ,并且在Lambda容器保持打开一段时间而没有调用后无法重用。我们使用默认超时:
  • 检查Atlas上的MongoDB日志条目-没有可疑之处
  • 停止更改DB连接解决了问题,但会使大多数API调用的速度降低2-3倍,我们仍然希望了解问题的根源

  • 有没有人遇到过类似的问题,或者可以建议我们如何有效地调试这个问题?

    如果我这样说:
    在调用成功和不成功的情况下
    是关于lambda调用的-那么您的意思是不管lambda超时或成功与否-都会发生DB调用?我还要说,将此
    (!cachedDb | |!cachedDb.serverConfig.isConnected())
    更改为
    (!cachedDb&&!cachedDb.serverConfig.isConnected())
    ,请尝试并测试是否每次都创建了连接,还是使用了缓存连接。在同一代码或不同代码上也会发生超时-通常的lambda超时可能发生在调用
    回调()
    不正确的情况下。续:在您的情况下,如果使用客户端或通用代码执行相同的查询时间执行的毫秒数较少,则不会花费太多时间导致lambda超时!!通常lambda超时最长为15分钟,但理想值为15-30秒,具体取决于操作-您的情况已经足够好了..关于您的第一条评论:是,
    true
    是从
    cachedDb.serverConfig.isConnected()
    返回的,如果数据库将查询结果返回给lambda,或者数据库没有返回结果,导致lmabda调用在对数据库的调用中停滞,并在设置的lambdat超时限制后超时。建议更改为条件对我来说没有意义。我们想检查他们是否没有缓存连接,或者我们有缓存连接,但它没有连接。在此处使用AND将不起作用,例如,当您有一个
    cachedDB
    但未连接时,情况将是错误的,并且不会尝试创建新连接。是的,完全相同的代码有时会正确执行,有时会超时。当代码在lambda上正常执行时,lambda调用平均需要20-30毫秒才能执行。无论我们在Lambda中设置了多高的超时限制,有时相同的函数都会超时。