我试图用Mongoose和AWS Lambda连接MongoDB Atlas,但出现错误MongoNetworkError
同一代码已通过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。
谢谢。
答案 0 :(得分:0)
让lambda调用外部端点需要一些额外的步骤
https://aws.amazon.com/premiumsupport/knowledge-center/internet-access-lambda-function/
您的图集还应将连接Lambda的服务器的IP地址列入白名单。
要考虑的另一种选择-在您的Lambda VPC和Atlas之间使用VPC peering。
答案 1 :(得分:0)
我对您的配置有一些疑问:
您是否在Atlas中将AWS Lambda函数的IP地址列入白名单? SO上的几则帖子表明,如果IP未列入白名单,则用户会收到类似MongoNetworkError的错误。 [1] [4]
您是否阅读过Atlas的最佳做法指南,其中指出mongodb连接应该在lambda处理程序之外启动? [2] [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
答案 2 :(得分:0)
好,谢谢大家。最终,我在mongo支持的帮助下找到了解决方案。 这是需要的人的解决方案
Your cluster > Network Access > IP Whitelist
在列表中,您将看到您的IP。这意味着只有您网络中的人才能连接到您的MongoAtlas。 AWS Lambda不在您的网络中,所以aws lambda永远不会连接到您的Mongo Atlas。这就是为什么我得到错误MongoNetworkError
的原因。修复
Your cluster > Network Access > IP Whitelist
ADD IP ADDRESS
ALLOW ACCESS FROM ANYWHERE
,它将IP 0.0.0.0/0添加到列表中,单击confirm
最后!
您所做的就是告诉Mongo Atlas,来自任何地方的任何人都可以连接到您的mongo Atlas。
当然,这不是一个好习惯。您只需要添加AWS Lambda IP,这就是VPC出现的时间。 创建一个VPC并不复杂,并且有很多陡峭之处,其他评论中都有很好的教程。
但是可以肯定的是,这个小指南MongoNetworkError