aws mongodb
本文最初在mongoDB上发布 。 感谢您支持使SitePoint成为可能的合作伙伴。
近年来,开发人员的状况发生了巨大变化。 对于我们开发人员来说,在我们自己的机器上运行我们的所有工具(数据库,Web服务器,开发IDE…)曾经是相当普遍的事情,但是GitHub , MongoDB Atlas和AWS Lambda等云服务正在极大地改变游戏规则。 它们使开发人员越来越容易地在没有(或很少)依赖的任何地方和任何设备上编写和运行代码。
几年前,如果您崩溃了机器,丢失了机器或者只是断电了,那么可能要花几天的时间才能让新机器恢复正常运行并以正确设置和配置方式进行的所有操作以前是。
借助云中的开发人员工具,您现在可以从一台笔记本电脑切换到另一台笔记本电脑,而干扰最小。 但是,这并不意味着一切都是乐观的。 在云中编写和调试代码仍然充满挑战。 作为开发人员,我们知道拥有本地开发环境虽然更轻巧,但仍然非常有价值。
这正是我将在此博文中向您展示的内容:如何轻松地将AWS Lambda Node.js函数与MongoDB Atlas托管的MongoDB数据库集成,该数据库是MongoDB的DBaaS(数据库即服务)。 更具体地说,我们将编写一个简单的Lambda函数,该函数在MongoDB Atlas数据库中存储的集合中创建单个文档。 我将逐步指导您完成本教程,并且您应该在不到一个小时的时间内完成它。
让我们从必要的要求开始,以使您开始运行:
- 具有对IAM和Lambda服务具有管理访问权的用户可用的Amazon Web Services帐户。 如果您还没有,请注册一个免费的AWS账户 。
- 带有Node.js的本地计算机(我告诉过您,我们不会轻易摆脱本地开发环境…)。 我们将在下面的教程中使用Mac OS X,但是在Windows或Linux上执行相同的任务应该相对容易。
- MongoDB Atlas集群活跃起来。 如果您还没有,请注册一个免费的MongoDB Atlas帐户,然后单击几下即可创建集群 。 您甚至可以尝试我们的M0免费集群层 ,非常适合小型开发项目!)。
现在您已经了解了需求,让我们来谈谈我们编写,测试和部署Lambda函数将要采取的具体步骤:
- 默认情况下, MongoDB Atlas是安全的,但是作为应用程序开发人员,我们应该采取一些步骤来确保我们的应用程序符合最小特权访问最佳实践 。 也就是说,我们将通过创建仅对应用程序数据库具有读/写访问权限的MongoDB Atlas数据库用户来微调权限。
- 我们将在本地计算机上设置一个Node.js项目,并确保在将lambda代码部署到Amazon Web Services之前对其进行端到端本地测试。
- 然后,我们将创建我们的AWS Lambda函数并上传Node.js项目以对其进行初始化。
- 最后但并非最不重要的一点是,我们将对Lambda函数进行一些修改,以加密一些敏感数据(例如MongoDB Atlas连接字符串)并从函数代码中对其解密。
关于VPC对等的简短说明
我没有深入研究在MongoDB Atlas集群和AWS Lambda之间设置VPC对等的细节,原因有两个:1)我们已经拥有详细的VPC对等文档页面和我强烈推荐的Atlas中的VPC对等信息 ,以及2) M0集群(我用来构建该演示的集群) 不支持VPC Peering 。
如果您没有设置VPC对等,则会发生以下情况:
- 您将必须将臭名昭著的0.0.0.0/0 CIDR块添加到MongoDB Atlas群集IP白名单中,因为您将不知道AWS Lambda使用哪个IP地址拨打Atlas数据库。
- 您需要为Lambda函数和Atlas群集之间的带宽使用情况付费。
如果您只想编写此演示代码,则这两个警告可能很好,但是如果您打算部署可用于生产的Lambda-Atlas集成,则强烈建议设置VPC对等是安全性最佳实践。 M0是我们当前的免费产品; 请查看我们的MongoDB Atlas定价页面 ,以获取可用实例大小的所有范围。
提醒一下,对于开发环境和低流量网站,M0,M10和M20实例大小应该合适。 但是,对于支持高流量应用程序或大型数据集的生产环境,建议使用M30或更大的实例大小。
在MongoDB Atlas集群中设置安全性
确保您的应用程序符合最低特权访问策略,对于保护数据免受恶意威胁至关重要。 这就是为什么我们将设置一个特定的数据库用户,该用户仅对我们的旅行数据库具有读/写访问权限。 让我们看看如何在MongoDB Atlas中实现这一点:
在“ 群集”页面上,选择“ 安全性”选项卡,然后按“ 添加新用户”按钮
在“ 用户权限”部分中,选择 链接。 这使我们可以在特定数据库而不是任何数据库上分配读/写。
然后,您可以选择分配更多细粒度的访问控制特权:
免费学习PHP!
全面介绍PHP和MySQL,从而实现服务器端编程的飞跃。
原价$ 11.95 您的完全免费
在“ 选择角色”下拉列表中,选择readWrite并在“ 数据库”字段中填写将用于存储文档的数据库的名称。 我选择将其命名为travel
。
在“ 密码”部分,使用“自动生成安全密码”按钮(并记下生成的密码)或设置您喜欢的密码。 然后按添加用户按钮以确认此用户的创建。
让我们抓住集群连接字符串,因为它需要用Lambda代码连接到我们的MongoDB Atlas数据库:
假设您已经创建了MongoDB Atlas集群 ,请按集群旁边的Connect按钮:
复制URI连接字符串值并将其安全地存储在文本文档中。 我们稍后在代码中将需要它以及您刚设置的密码。
此外,如果您不使用VPC对等网络,请导航到IP白名单选项卡并添加0.0.0.0/0 CIDR块,或按“ 允许从任何地方访问”按钮。 提醒您,强烈不建议将此设置用于生产环境,这可能会使您的MongoDB Atlas群集容易受到恶意攻击。
创建一个本地Node.js项目
虽然LAMBDA功能在多国语言的支持,我已经选择使用Node.js的感谢JavaScript的日益普及,作为一种多用途的编程语言和的巨大成功MEAN和MERN栈(缩写词对于M ongoDB,E xpress.js, Angular / R eact, N ode.js –请查看Andrew Morgan关于该主题的出色的面向开发人员的博客系列 )。 另外,说实话,我喜欢它是一种解释性的,轻量级的语言,不需要大量的开发工具和编译器。
现在该写一些代码了,接下来让我们继续使用Node.js作为Lambda函数的首选语言。
首先创建一个文件夹,例如lambda-atlas-create-doc
mkdir lambda-atlas-create-doc
&& cd lambda-atlas-create-doc
接下来,从终端控制台运行以下命令以使用package.json文件初始化我们的项目
npm init
系统将提示您配置一些字段。 我将让他们发挥自己的创造力,但请注意,我选择将入口点设置为app.js(而不是默认的index.js),因此您可能也希望这样做。
我们将需要使用MongoDB Node.js驱动程序,以便我们可以从Lambda函数连接到Atlas上的MongoDB数据库,因此让我们从项目根目录运行以下命令来进行安装:
npm install mongodb --save
我们还希望在本地编写和测试我们的Lambda函数,以加快开发速度并简化调试,因为在Amazon Web Services中每次实例化一个Lambda函数并不是特别快(并且几乎不存在调试功能,除非您成为console.log()
函数的console.log()
)。 我选择使用lambda-local包,因为它提供了对环境变量的支持(我们将在以后使用):
(sudo) npm install lambda-local -g
创建一个app.js
文件。 这将是包含我们的lambda函数的文件:
touch app.js
现在,您已经导入了所有必需的依赖项并创建了Lambda代码文件,在您选择的代码编辑器(Atom,Sublime Text,Visual Studio Code…)中打开app.js文件,并使用以下代码对其进行初始化:
'use strict'
var MongoClient = require('mongodb').MongoClient;
let atlas_connection_uri;
let cachedDb = null;
exports.handler = (event, context, callback) => {
var uri = process.env['MONGODB_ATLAS_CLUSTER_URI'];
if (atlas_connection_uri != null) {
processEvent(event, context, callback);
}
else {
atlas_connection_uri = uri;
console.log('the Atlas connection string is ' + atlas_connection_uri);
processEvent(event, context, callback);
}
};
function processEvent(event, context, callback) {
console.log('Calling MongoDB Atlas from AWS Lambda with event: ' + JSON.stringify(event));
}
让我们暂停一下并注释上面的代码,因为您可能已经注意到了一些奇特的构造:
- 该文件的编写与Amazon Web Services期望的Lambda代码完全相同(例如,带有“ exports.handler”功能)。 这是因为我们正在使用lambda-local在本地测试我们的lambda函数,这可以方便地使我们完全按照AWS Lambda的期望编写代码。 一分钟内将提供更多信息。
- 我们宣布了MongoDB Node.js驱动程序,它将有助于我们连接和查询MongoDB数据库。
- 还要注意,我们在处理程序函数的外部声明了一个
cachedDb
对象。 顾名思义,这是一个我们计划在AWS Lambda为我们的函数实例化基础容器的持续时间内缓存的对象。 这使我们节省了一些宝贵的毫秒(甚至几秒钟)来在Lambda和MongoDB Atlas之间建立数据库连接。 有关更多信息,请阅读我的后续博客文章, 了解如何使用MongoDB Atlas优化Lambda性能 。 - 我们正在使用名为
MONGODB_ATLAS_CLUSTER_URI
的环境变量来传递Atlas数据库的uri连接字符串,主要出于安全目的:我们显然不想在功能代码中硬编码此uri,以及非常敏感的信息(例如用户名和密码)我们用。 由于AWS Lambda自2016年11月以来就支持环境变量 (就像lambda-local NPM软件包所做的那样),因此我们不使用它们就被遗漏了。 - 该功能代码看起来似乎毫无用处的if-else语句和processEvent函数看起来有些混乱,但是当我们使用AWS Key Management Service(KMS)添加解密例程时,这些功能代码将变得清晰起来。 确实,我们不仅要在环境变量中存储MongoDB Atlas连接字符串,而且还希望对其进行加密(使用AWS KMS),因为它包含高度敏感的数据(请注意,即使使用AWS KMS,您也可能会产生费用)如果您有免费的AWS账户)。
现在我们已经完成了代码注释,让我们在根项目目录中创建一个event.json
文件,并用以下数据填充它:
{
"address" : {
"street" : "2 Avenue",
"zipcode" : "10075",
"building" : "1480",
"coord" : [ -73.9557413, 40.7720266 ]
},
"borough" : "Manhattan",
"cuisine" : "Italian",
"grades" : [
{
"date" : "2014-10-01T00:00:00Z",
"grade" : "A",
"score" : 11
},
{
"date" : "2014-01-16T00:00:00Z",
"grade" : "B",
"score" : 17
}
],
"name" : "Vella",
"restaurant_id" : "41704620"
}
(以防万一,您会将该JSON文件发送给MongoDB Atlas以创建我们的BSON文档)
接下来,通过在终端控制台中运行以下命令来确保设置正确:
lambda-local -l app.js -e event.json -E {\"MONGODB_ATLAS_CLUSTER_URI\":\"mongodb://lambdauser:$PASSWORD@lambdademo-shard-00-00-7xh42.mongodb.net:27017\,lambdademo-shard-00-01-7xh42.mongodb.net:27017\,lambdademo-shard-00-02-7xh42.mongodb.net:27017/$DATABASE?ssl=true\&replicaSet=lambdademo-shard-0\&authSource=admin\"}
如果要使用自己的群集URI连接字符串进行测试(如我确定的那样),请不要忘记在E参数中转义双引号,逗号和&字符,否则lambda-local会抛出错误(您还应该用自己的值替换$ PASSWORD和$ DATABASE关键字)。
在本地运行它之后,应该获得以下控制台输出:
如果出现错误,请检查您的连接字符串以及双引号/逗号/符号和转义符(如上所述)。
现在,通过定制processEvent()
函数并添加createDoc()
函数来深入了解函数代码:
function processEvent(event, context, callback) {
console.log('Calling MongoDB Atlas from AWS Lambda with event: ' + JSON.stringify(event));
var jsonContents = JSON.parse(JSON.stringify(event));
//date conversion for grades array
if(jsonContents.grades != null) {
for(var i = 0, len=jsonContents.grades.length; i connecting to database');
MongoClient.connect(atlas_connection_uri, function (err, db) {
cachedDb = db;
return createDoc(db, jsonContents, callback);
});
}
else {
createDoc(cachedDb, jsonContents, callback);
}
}
catch (err) {
console.error('an error occurred', err);
}
}
function createDoc (db, json, callback) {
db.collection('restaurants').insertOne( json, function(err, result) {
if(err!=null) {
console.error("an error occurred in createDoc", err);
callback(null, JSON.stringify(err));
}
else {
console.log("Kudos! You just created an entry into the restaurants collection with id: " + result.insertedId);
callback(null, "SUCCESS");
}
//we don't need to close the connection thanks to context.callbackWaitsForEmptyEventLoop = false (above)
//this will let our function re-use the connection on the next called (if it can re-use the same Lambda container)
//db.close();
});
};
请注意连接到MongoDB Atlas数据库并插入文档有多么容易,以及我添加的一小段代码将JSON日期(格式化为符合ISO的字符串)转换为MongoDB可以存储为BSON日期的真实JavaScript日期。
您可能还已经注意到我的性能优化注释以及对context.callbackWaitsForEmptyEventLoop = false的调用。 如果您有兴趣了解它们的含义(我想您应该!),请参阅我的后续博客文章,了解如何使用MongoDB Atlas优化Lambda性能。
现在,您可以在本地全面测试Lambda函数了。 使用与以前相同的lambda-local命令,希望您会收到一条不错的“ Kudos”成功消息:
如果在您的本地计算机上一切正常,让我们将本地Node.js项目发布为新的Lambda函数!
创建Lambda函数
我们要采取的第一步是压缩Node.js项目,因为我们不会在Lambda代码编辑器中编写Lambda代码函数。 相反,我们将选择zip上传方法来将代码推送到AWS Lambda。
我已经在终端控制台中使用了zip
命令行工具,但是任何方法都可以工作(只要将文件压缩在顶层文件夹中,而不是顶层文件夹本身中即可!):
zip -r archive.zip node_modules/ app.js package.json
接下来,登录AWS控制台并导航到“ IAM角色”页面,并使用AWSLambdaBasicExecutionRole权限策略创建一个角色(例如LambdaBasicExecRole):
现在让我们导航到AWS Lambda页面。 单击立即开始 (如果您从未创建Lambda函数)或单击“ 创建Lambda函数”按钮。 我们不会使用任何蓝图,也不会配置任何触发器,因此请直接在左侧导航栏中选择“ 配置功能” :
在“ 配置功能”页面中,输入您的功能的名称(例如MongoDB_Atlas_CreateDoc
)。 运行时会自动设置为Node.js 4.3
,这对我们来说是完美的,因为这是我们将使用的语言。 在“ 代码输入类型”列表中,选择“上Upload a .ZIP file
,如下面的屏幕截图所示:
单击上载按钮,然后选择先前创建的压缩的Node.js项目文件。
在Lambda函数处理程序和角色部分中,将Handler字段的值修改为app.handler
(为什么?这是一个提示:我使用了app.js
文件,而不是Lambda函数代码使用index.js
文件…),然后选择我们刚刚创建的现有LambdaBasicExecRole
角色:
在“ 高级设置”部分中,您可能希望将“ 超时”值增加到5或10秒,但始终可以在以后进行调整。 将VPC和KMS密钥字段保留为默认值(除非您想使用VPC和/或KMS密钥),然后按Next 。
最后,查看您的Lambda函数,然后按底部的创建函数 。 恭喜,您的Lambda函数已启用,您应该会看到类似于以下屏幕截图的页面:
但是您还记得我们对环境变量的使用吗? 现在是配置它们并使用AWS Key Management Service保护它们的时候了!
配置和保护Lambda环境变量
在Lambda函数的“代码”选项卡中向下滚动,并创建具有以下属性的环境变量:
名称 | 值 |
---|---|
MONGODB_ATLAS_CLUSTER_URI | YOUR_ATLAS_CLUSTER_URI_VALUE |
此时,您可以按页面顶部的“ 保存并测试”按钮,但是为了提高安全性(并建议使用),我们将加密该连接字符串。
选中“ 启用加密助手”复选框,如果您已经创建了加密密钥,请选择它(否则,您可能必须创建一个密钥-这相当简单):
接下来,为MONGODB_ATLAS_CLUSTER_URI变量选择“ 加密”按钮:
返回内联代码编辑器,在顶部添加以下行:
const AWS = require('aws-sdk');
并使用以下代码替换“ exports.handler”方法中“ else”语句的内容:
const kms = new AWS.KMS();
kms.decrypt({ CiphertextBlob: new Buffer(uri, 'base64') }, (err, data) => {
if (err) {
console.log('Decrypt error:', err);
return callback(err);
}
atlas_connection_uri = data.Plaintext.toString('ascii');
processEvent(event, context, callback);
});
(希望我们最初编写的复杂代码现在变得有意义了!)
如果要检查我使用过的全部功能代码 ,请查看以下Gist 。 对于Git爱好者, 完整的Node.js项目源代码也可以在GitHub上获得 。
现在按下“ 保存并测试”按钮,然后在“ 输入测试事件”文本编辑器中,粘贴我们的event.json文件的内容:
滚动并按保存并测试按钮。
如果正确配置了所有内容,则应在Lambda日志输出中收到以下成功消息:
荣誉! 您可以在几分钟前品尝一下成功的经验。
下一步是什么?
我希望此AWS Lambda-MongoDB Atlas集成教程为您提供第一个Lambda项目入门的正确步骤。 现在,您应该能够在本地编写和测试Lambda函数,并将敏感数据(例如MongoDB Atlas连接字符串)安全地存储在AWS KMS中。
那接下来你该怎么办?
- 如果您还没有MongoDB Atlas帐户,那么创建一个帐户还为时不晚!
- 如果您不熟悉MongoDB Node.js驱动程序 ,请查看我们的Node.js驱动程序文档,以了解如何充分利用MongoDB API。 此外,我们还为MongoDB入门的Node.js开发人员提供了在线Node.js课程 。
- 了解如何形象化使用Lambda函数创建的数据,下载MongoDB Compass并阅读如何使用MongoDB Compass可视化数据,以了解如何将其连接到MongoDB Atlas。
- 计划构建大量Lambda函数? 通过阅读我们的《 将MongoDB Atlas,Twilio和AWS Simple Email Service与AWS Step Functions集成在一起》了解如何使用AWS Step Functions 整理它们 。
- 了解如何在更复杂的场景中集成MongoDB和AWS Lambda,请查看我们更高级的博客文章: 使用AWS Lambda和MongoDB Atlas开发Facebook Chatbot 。
当然,请随时向我们提问或在下面的评论中留下您的反馈。 编码愉快!
喜欢这篇文章吗? 重播我们的网络研讨会,那里有关于使用AWS Lambda的无服务器架构的交互式教程。
翻译自: https://www.sitepoint.com/serverless-development-with-node-js-aws-lambda-and-mongodb-atlas/
aws mongodb