繁体   English   中英

带有猫鼬的AWS lambda到Atlas-MongoNetworkError

[英]AWS lambda with mongoose to Atlas - MongoNetworkError

我正在尝试将MongoDB Atlas与猫鼬和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安装,添加您的mongo atlas用户,密码并推送到AWS。

谢谢。

让lambda呼叫外部端点需要一些额外的步骤

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

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

要考虑的另一种选择-在lambda VPC和Atlas之间进行VPC对等

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

  1. 您是否在Atlas中将AWS Lambda函数的IP地址列入白名单? 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] 什么是Mongoose(或MongoDB)中的TransientTransactionError?
[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支持的帮助下找到了解决方案。 这是任何需要的解决方案

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

固定

  1. 您需要将AWS Lambda IP添加到Mongo Atlas WhiteListIP
  2. 转到您Your cluster > Network Access > 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并不复杂,并且有很多技巧,其他注释中有很好的教程。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM