本文介绍了是什么导致AWS Lambda上的Mongodb超时错误?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个节点lambda函数,它使用猫鼬查询mongoDb.

I have a node lambda function that queries mongoDb using mongoose.

大约20%的时间,看似随机,尝试连接时出现以下错误:MongoNetworkTimeoutError:连接超时

About 20% of the time, seemingly randomly, I get the following error upon trying to connect:MongoNetworkTimeoutError: connection timed out

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

While MongoDb seems to recommend using context.callbackWaitsForEmptyEventLoop = false and trying to reuse the same connection between calls, I read other posts that said the fix for this would be to actively re-open a connection every time. I tried that but it's still happening. Does anyone have any ideas?

这是我的代码:

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的完整错误输出:

And here's the full error output from 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)"
    ]
}

推荐答案

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

I had the same issue (I have an express app, but that doesn't matter). The solution was to move the database connection object outside the handler method and cache/reuse it.

'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

You can find more details here: https://www.mongodb.com/blog/post/optimizing-aws-lambda-performance-with-mongodb-atlas-and-nodejs

这篇关于是什么导致AWS Lambda上的Mongodb超时错误?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-20 21:36