是啥导致 AWS Lambda 上的 Mongodb 超时错误?

Posted

技术标签:

【中文标题】是啥导致 AWS Lambda 上的 Mongodb 超时错误?【英文标题】:What is causing Mongodb timeout error on AWS Lambda?是什么导致 AWS Lambda 上的 Mongodb 超时错误? 【发布时间】:2021-04-19 19:12:32 【问题描述】:

我有一个使用 mongoose 查询 mongoDb 的节点 lambda 函数。

大约 20% 的时间,似乎是随机的,我在尝试连接时收到以下错误: MongoNetworkTimeoutError: 连接超时

虽然 MongoDb 似乎建议使用 context.callbackWaitsForEmptyEventLoop = false 并尝试在调用之间重用相同的连接,但我读到其他帖子说解决此问题的方法是每次都主动重新打开连接。我试过了,但它仍然在发生。有人有什么想法吗?

这是我的代码:

let  conn = mongoose.createConnection(process.env.MONGO_URI, 
        bufferCommands: false, // Disable mongoose buffering
        bufferMaxEntries: 0, // and MongoDB driver buffering
        useNewUrlParser: true,
        useUnifiedTopology: true,
        socketTimeoutMS: 45000,
        keepAlive: true,
        reconnectTries: 10
      )

      try 
        await conn
        console.log('Connected correctly to server')

       catch (err) 
        console.log('Error connecting to DB')
        console.log(err)
        console.log(err.stack)
      

  await conn 

以下是 Cloudwatch 的完整错误输出:


    "errorType": "Runtime.UnhandledPromiseRejection",
    "errorMessage": "MongoNetworkTimeoutError: connection timed out",
    "reason": 
        "errorType": "MongoNetworkTimeoutError",
        "errorMessage": "connection timed out",
        "name": "MongoNetworkTimeoutError",
        "stack": [
            "MongoNetworkTimeoutError: connection timed out",
            "    at connectionFailureError (/var/task/node_modules/mongodb/lib/core/connection/connect.js:342:14)",
            "    at TLSSocket.<anonymous> (/var/task/node_modules/mongodb/lib/core/connection/connect.js:310:16)",
            "    at Object.onceWrapper (events.js:420:28)",
            "    at TLSSocket.emit (events.js:314:20)",
            "    at TLSSocket.EventEmitter.emit (domain.js:483:12)",
            "    at TLSSocket.Socket._onTimeout (net.js:484:8)",
            "    at listOnTimeout (internal/timers.js:554:17)",
            "    at processTimers (internal/timers.js:497:7)"
        ]
    ,
    "promise": ,
    "stack": [
        "Runtime.UnhandledPromiseRejection: MongoNetworkTimeoutError: connection timed out",
        "    at process.<anonymous> (/var/runtime/index.js:35:15)",
        "    at process.emit (events.js:326:22)",
        "    at process.EventEmitter.emit (domain.js:483:12)",
        "    at processPromiseRejections (internal/process/promises.js:209:33)",
        "    at processTicksAndRejections (internal/process/task_queues.js:98:32)",
        "    at runNextTicks (internal/process/task_queues.js:66:3)",
        "    at listOnTimeout (internal/timers.js:523:9)",
        "    at processTimers (internal/timers.js:497:7)"
    ]

【问题讨论】:

错误输出不足以诊断问题。 到现在你有解决办法吗?我陷入了同样的境地。我每次都重新打开和关闭连接,但是这个错误是随机出现的,原因仍然未知。 我也有同样的问题,没想到发生了 【参考方案1】:

我遇到了同样的问题(我有一个快速应用程序,但这没关系)。解决方案是将数据库连接对象移到处理程序方法之外并缓存/重用它。

'use strict'
const serverless = require('serverless-http')
const MongoClient = require('mongodb').MongoClient

const api = require('./modules/api')
const SecureConfig = require('./modules/secureConfig')

let dbObject = null
const getDBConnection = async (event, context) => 
    try 
        if (dbObject && dbObject.serverConfig.isConnected()) return dbObject

        const client = await MongoClient.connect(SecureConfig.mongodb.host, SecureConfig.mongodb.mongoConfig)
        dbObject = client.db(SecureConfig.mongodb.db)
        return dbObject
     catch(err) 
        throw(err)
    


module.exports.handler = async (event, context) => 
  const db = await getDBConnection()
  const server = serverless(api.default(db));
  try 
    /**
     * Lambda’s context object exposes a callbackWaitsForEmptyEventLoop property,
     * that effectively allows a Lambda function to return its result to the caller
     * without requiring that the MongoDB database connection be closed.
     * This allows the Lambda function to reuse a MongoDB connection across calls.
     */
    context.callbackWaitsForEmptyEventLoop = false

    return await server(event, context)
   catch (error) 
    console.error('Lambda handler root error.')
    throw error
  

您可以在此处找到更多详细信息:https://www.mongodb.com/blog/post/optimizing-aws-lambda-performance-with-mongodb-atlas-and-nodejs

【讨论】:

以上是关于是啥导致 AWS Lambda 上的 Mongodb 超时错误?的主要内容,如果未能解决你的问题,请参考以下文章

Lambda 上的 FFmpeg 转码导致无法使用(静态)音频

Lambda AWS PreSignUp 响应的正确格式是啥

AWS Lambda 与 Heroku:主要区别是啥?

使用 Node.JS 调用 AWS 胶水的 lambda 函数不使用 console.log 的原因是啥?

AWS Lambda - 在 CI/CD 管道中版本控制和提升 lambda 的最佳实践是啥

将 Lambda 连接到 AWS MSK 中的 kafka 主题的最经济有效的方法是啥?