【问题标题】:AWS lambda with mongoose to Atlas - MongoNetworkErrorAWS lambda 与 mongoose 到 Atlas - MongoNetworkError
【发布时间】:2019-11-14 14:47:56
【问题描述】:

我正在尝试将 MongoDB Atlas 与 mongoose 和 aws lambda 连接,但出现错误 MongoNetworkError

  • AWS Lambda
  • 猫鼬
  • MongoDB 地图集

使用serverless-offline 测试了相同的代码并且运行良好,问题是当我将它部署到 AWS Lambda 时。

这是代码片段

'use strict';
const mongoose = require('mongoose');
const MongoClient = require('mongodb').MongoClient;
let dbuser  = process.env.DB_USER;
let dbpass = process.env.DB_PASSWORD;
let opts = { 
    bufferCommands: false, 
    bufferMaxEntries: 0, 
    socketTimeoutMS: 2000000, 
    keepAlive: true, 
    reconnectTries: 30, 
    reconnectInterval: 500,
    poolSize: 10,
    ssl: true,
 };
const uri = `mongodb+srv://${dbuser}:${dbpass}@carpoolingcluster0-bw91o.mongodb.net/awsmongotest?retryWrites=true&w=majority`;
// simple hello test
module.exports.hello = async (event, context, callback) => {
    const response = {
        body: JSON.stringify({message:'AWS Testing :: '+ `${dbuser} and ${dbpass}`}),
    };
    return response;
};
// connect using mongoose
module.exports.cn1 = async (event, context, callback)  => {
    context.callbackWaitsForEmptyEventLoop = false;
    let conn = await mongoose.createConnection(uri, opts);
    const M = conn.models.Test || conn.model('Test', new mongoose.Schema({ name: String }));
    const doc = await M.find();
    const response = {
        body: JSON.stringify({data:doc}),
    };
    return response;
};
// connect using mongodb
module.exports.cn2 = (event, context, callback) => {
    context.callbackWaitsForEmptyEventLoop = false;
    console.log("Connec to mongo using connectmongo ");
    MongoClient.connect(uri).then(client => {
        console.log("Success connect to mongo DB::::");
        client.db('awsmongotest').collection('tests').find({}).toArray()
            .then((result)=>{
                let response = {
                    body: JSON.stringify({data:result}),
                }
                callback(null, response)
            })
    }).catch(err => {
        console.log('=> an error occurred: ', err);
        callback(err);
    });
};

在 CloudWatch 日志中我看到了这个错误

{
    "errorType": "MongoNetworkError",
    "errorMessage": "failed to connect to server [carpoolingcluster0-shard-00-02-bw91o.mongodb.net:27017] on first connect [MongoNetworkError: connection 5 to carpoolingcluster0-shard-00-02-bw91o.mongodb.net:27017 closed]",
    "stack": [
        "MongoNetworkError: failed to connect to server [carpoolingcluster0-shard-00-02-bw91o.mongodb.net:27017] on first connect [MongoNetworkError: connection 5 to carpoolingcluster0-shard-00-02-bw91o.mongodb.net:27017 closed]",
        "    at Pool.<anonymous> (/var/task/node_modules/mongodb-core/lib/topologies/server.js:431:11)",
        "    at Pool.emit (events.js:189:13)",
        "    at connect (/var/task/node_modules/mongodb-core/lib/connection/pool.js:557:14)",
        "    at callback (/var/task/node_modules/mongodb-core/lib/connection/connect.js:109:5)",
        "    at runCommand (/var/task/node_modules/mongodb-core/lib/connection/connect.js:129:7)",
        "    at Connection.errorHandler (/var/task/node_modules/mongodb-core/lib/connection/connect.js:321:5)",
        "    at Object.onceWrapper (events.js:277:13)",
        "    at Connection.emit (events.js:189:13)",
        "    at TLSSocket.<anonymous> (/var/task/node_modules/mongodb-core/lib/connection/connection.js:350:12)",
        "    at Object.onceWrapper (events.js:277:13)",
        "    at TLSSocket.emit (events.js:189:13)",
        "    at _handle.close (net.js:597:12)",
        "    at TCP.done (_tls_wrap.js:388:7)"
    ],
    "name": "MongoNetworkError",
    "errorLabels": [
        "TransientTransactionError"
    ]
}

这里是 github 上重现错误的示例。

https://github.com/rollrodrig/error-aws-mongo-atlas

只需克隆它,npm install,添加您的 mongo atlas 用户、密码并推送到 AWS。

谢谢。

【问题讨论】:

  • 你的mongodb在vpc吗?
  • 不,它在 Mongo Atlas 上。
  • 我认为 aws lambda 具有默认的 0.0.0.0 出口安全组,所以也许您需要允许来自 carpoolingcluster0 的入口?另外,我不确定 lambda 是否与 VPC 相关,但您可能想看看 mongodb.com/blog/post/introducing-vpc-peering-for-mongodb-atlas
  • 我接受了您的项目,并且能够通过0.0.0.0/0 白名单成功连接到我的 Atlas。您的错误很可能是 IP 白名单原因。您需要使用 NAT Gateway(将 lambda 附加到 VPC)或将 all 您的 AWS 区域公共 IP/CIDR 列入白名单。
  • @Imran 也许这就是问题所在,我没有将 mongo db 上的 aws lambda 列入白名单,你有教程吗?

标签: node.js mongodb amazon-web-services mongoose aws-lambda


【解决方案1】:

好的,谢谢大家。最后我在mongo支持的帮助下找到了解决方案。 这是任何需要的人的解决方案

  1. 当您创建 Mongo Altas 集群时,他们会要求您添加本地 ip,它会自动添加到白名单中。你可以在里面看到 Your cluster &gt; Network Access &gt; IP Whitelist 在列表中您将看到您的 IP。这意味着只有您网络中的人才能连接到您的 MongoAtlas。 AWS Lambda 不在您的网络中,所以 aws lambda 永远不会连接到您的 Mongo Atlas。这就是为什么我收到错误MongoNetworkError

修复

  1. 您需要将 AWS Lambda IP 添加到 Mongo Atlas WhiteListIP
  2. 转到您的Your cluster &gt; Network Access &gt; IP Whitelist
  3. 点击按钮ADD IP ADDRESS
  4. 点击ALLOW ACCESS FROM ANYWHERE它会将ip 0.0.0.0/0添加到列表中,点击confirm
  5. 测试来自 AWS Lambda 的调用,我会工作的。

终于!

您所做的是告诉 Mongo Atlas,任何地方的任何人都可以连接到您的 mongo Atlas。

当然,这不是一个好习惯。您只需要添加 AWS Lambda IP,这就是 VPC 出现的时候。 创建 VPC 不太复杂,而且有很多陡峭的地方,其他 cmets 中有很好的教程。

但可以肯定的是,这个小指南涉及MongoNetworkError

【讨论】:

    【解决方案2】:

    我对您的配置有一些疑问:

    1. 您是否将 AWS Lambda 函数的 IP 地址列入 Atlas 中的白名单? SO 上的几篇文章表明,如果 IP 未列入白名单,用户会收到这样的 MongoNetworkError。 [1][4]

    2. 您是否阅读过 Atlas 的最佳实践指南,其中指出 mongodb 连接应在 lambda 处理程序之外启动? [2][3]

    3. 您在 VPC 中使用公共 lambda 函数还是 lambda 函数?它们之间有很大的不同,后者更容易出错,因为必须考虑 VPC 配置(例如 NAT)。

    我能够 ping Atlas 集群中的实例,并能够在端口 27017 上建立连接。但是,通过 mongo shell 连接时,我收到以下错误:

    无法到达设置 CarpoolingCluster0-shard-0 的主节点。

    无法到达集合 CarpoolingCluster0-shard-0 的任何节点。请检查网络连接和设置的状态。连续 1 次检查都发生这种情况。

    当我使用来自 AWS lambda 的 GitHub 示例时,我收到与问题中描述的完全相同的错误消息。

    由于错误消息与身份验证无关,而是与网络相关,因此我认为某些东西阻止了连接...请仔细检查上面的三个配置问题。

    [1]What is a TransientTransactionError in Mongoose (or MongoDB)?
    [2]https://docs.atlas.mongodb.com/best-practices-connecting-to-aws-lambda/
    [3]https://blog.cloudboost.io/i-wish-i-knew-how-to-use-mongodb-connection-in-aws-lambda-f91cd2694ae5
    [4]https://github.com/Automattic/mongoose/issues/5237

    【讨论】:

    • 我没有在 mongo atlas 中将 AWS ip 列入白名单。我会在谷歌上搜索看看是怎么做的。
    【解决方案3】:

    让 lambda 调用外部端点需要一些额外的步骤

    https://aws.amazon.com/premiumsupport/knowledge-center/internet-access-lambda-function/

    您的地图集还应该将连接 lambda 的服务器的 IP 地址列入白名单。

    另一个需要考虑的选项 - 在您的 lambda VPC 和 Atlas 之间使用 VPC peering

    【讨论】:

    • 您是否在某个项目中建立了联系?
    猜你喜欢
    • 2019-06-11
    • 2020-05-12
    • 2020-03-12
    • 2019-04-26
    • 2018-07-13
    • 2019-08-18
    • 2022-01-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多