如今,在多种技术场合下,Serverless架构已经变成了一个神奇的工具。我们正在使用Serverless架构来开发数据处理器,聊天机器人,应用API等等。
今天,我将引导您去使用持久的MongoDB数据存储在AWS Lambda上创建可以随时投入生产的Express API。您可以在AWS Lambda上构建Express应用程序,然后轻松地使用MongoDB。
您可以想象这非常简单——使用 AWS Lambda 很大程度和使用一个小型Node.js运行环境一样,它对除了代码以外的所有事物都进行了一层抽象。
让我们开始吧!
长话短说
您可以直接跳到你感兴趣的部分(但这会狠狠地伤害我的内心),或者按照章节顺序直接开始。
安装工程
工程安装后我们得到的是工程最小化的结构。但是,它仍然拥有继续为未来生产应用程序添加功能所需的一切。为了向您进行介绍,我将工程安装后的最终布局图在下面展示:
正如您所看到的那样,对于带有CRUD逻辑的注解来说,这是一个相当简单的API,但它成功完成了工作。好的,说的够多了,让我们开始运行这个工程吧。
1. 安装Serverless框架
首先你需要安装并配置Serverless架构。 这是一个用于开发的简单命令行工具,可以非常简单地部署项目。
$ npm i -g serverless
你现在已经在你机器的全局环境中安装了Serverless库,它的命令现在在你的终端中随时可用。
提示: 如果你正在使用Linux,那么你可能需要加上sudo。
2. 在你的AWS Console创建一个IAM用户
打开您的AWS Console,然后点击网页左上角的Service下拉菜单,你会看见很多服务。在搜索框输入IAM然后点击搜索结果。
你会被重定向到IAM的主页,继续添加新用户。
给你的IAM用户一个名字,同时选中programmatic access的复选框,点击下一步。
现在你可以授予你的新用户一组权限,因为我们要让Severless在我们的AWS账户上创建和删除各种资源,所以请检查下AdministratorAccess这一项。
继续下去,我们下一步会看到用户被创建。现在,同时也只有这个时候,你拥有用户Access Key ID和私密Access Key的权限。请确保你填写了他们,或者下载页面上的.csv文件。同时,你需要保证这些文件的安全性,并不要让其他人看到。虽然这是一个演示,但我已将它们打上马赛克,以确保您了解保护它们的安全的严重性。
完成这些之后,我们终于可以开始在Serverless的配置里面添加密匙了。
3. 在 Serverless 配置中添加IAM密匙
很好! 保存密钥后,您可以设置Serverless以访问您的AWS账户,我们切换回终端并在一行中键入这些内容:
$ serverless config credentials \
--provider aws \
--key xxxxxxxxxxxxxx \
--secret xxxxxxxxxxxxxx
敲击回车!现在你的Serverless知道在运行任何终端命令时要连接的帐户了,让我们看看它的实际效果。
4. 创建一个服务
新建一个目录去放置你的Serverless应用服务,在那里打开终端,现在你准备好去创建一个新的服务了。
我们所谓的服务,是在名为serverless.yml的文件中定义的AWS Lambda函数,触发它们的事件以及它们所需的任何AWS基础架构资源,都保存在这个文件当中。
回到终端里,输入:
$ serverless create --template aws-nodejs --path sls-express-mongodb
create命令会新建一个新的service。我们需要为这个方法选择一个运行环境。我们称之为template。传入aws-nodejs则将会设置运行环境为 Node.js——这就是我们想要的。path会为服务新建一个文件夹。在这里例子中,我们命名它为sls-express-mongodb。
5. 使用代码编辑器浏览服务目录
使用您最喜欢的代码编辑器打开sls-express-mongodb文件夹。那里应该有三个文件,但是现在我们只关注serverless.yml——它包含此服务的所有配置设置,包括常规配置设置和每个函数的配置。目前您的serverless.yml文件被样板代码和注释所填充,您可以随意将其删除并把这些代码粘贴进去。
functions属性列出了服务中的所有函数。我们只需要一个函数,让我们的整个Express应用程序将被打包到这个单一功能中,其中Handler指出了是哪个函数。我们的最终应用程序将有一个带有run函数的server.js文件(我想这个步骤足够简单)。
现在让我们看一下这些事件,它们正充当着负责路由的代理,这意味着每个命中HTTP端点的请求都将被代理到内部的Express路由器,这很酷。
我们还有一个自定义部分。这个自定义部分可以将环境变量安全地加载到我们的应用程序中。我们可以使用${self:custom.secrets.<环境变量名称>}的格式将这些变量引入,其中变量实际值保存在一个名为secrets.json的简单文件中。
最后,我们还有用于离线测试的serverless-offline插件。
在MongoDB Atlas上面创建数据库
准备好进行更多配置了吗?好吧,没人喜欢这个环节,但我没办法。让我们前往MongoDB Atlas并进行注册.
账户是免费的,而且不需要信用卡,它将成为我们开发所需的沙箱。设置帐户后,请打开帐户页面并添加新组织。
选择一个你喜欢的名字,按“下一步”并继续创建组织。
好的。我们进入了组织页面,请按下New Project按钮。
这将打开一个页面来命名您的工程。只需键入您喜欢的名称,然后点击下一步。
MongoDB非常重视权限和安全性,因此Atlas将向您显示另一个管理权限页面。我们现在可以跳过它,然后创建项目。
好,我们来开始创建实际的集群!按下巨大的绿色“构建新群集”按钮。这将打开一个巨大的集群创建窗口。您可以将所有内容保留为默认值,只需确保选择M0实例大小,然后禁用备份。正如您所看到的,此群集的价格将是免费的。相当不错。就是这样,点击“创建群集”。
创建集群完成之后,为群集添加管理员用户并给他一个复杂度较高的密码。
现在,您只需要从任何地方启用访问权限,我们转到IP白名单。
您的群集将需要几分钟才能部署。部署正在进行的时候 ,让我们开始安装一些依赖项。
安装依赖库
在任何项目,这个步骤都是我最喜欢的的一部分。我们需要确保这一步骤正确完成,这样才能顺利进行。
$ npm init -y
$ npm i --save express mongoose body-parser helmet serverless-http
$ npm i --save-dev serverless-offline
首先,我们正在安装生产依赖项,您肯定了解Express,Mongoose和BodyParser。Helmet是一个微型中间件,用于通过适当的HTTP头保护您的端点。但是,真正的功能在于Serverless的HTTP模块。它将在Express应用程序中创建代理并将其打包到单个lambda函数中。
最后,我们需要Serverless离线来在本地测试我们的应用程序。然后,我们写一些代码怎么样?
编写代码
是时候了!让我们开始吧。
1. 新建 server.js
首先,我们需要将handler.js文件重命名为server.js。这里我们先仅仅使用serverless-http模块运行lambda函数的逻辑。
如您所见,我们需要serverless-http模块,并导出名为run的函数。这将保存serverless-http实例的值,并将我们的app作为参数传递。这就是我们将Express应用程序打包成lambda函数所需的一切!非常简单。
2. 添加私密变量
接下来创建secrets.json文件以保存环境变量。
要获取Atlas群集的连接字符串,请导航到群集仪表板,然后按下 灰色连接按钮。按照说明操作,确保URL看起来像上面的字符串。
3. 创建 Express 应用
现在我们可以开始编写实际的Express应用程序了。
在名为lib的根目录中创建一个新文件夹。在这里,您需要创建一个app.js文件和db.js文件。
安装了mongoose可以显着简化与数据库的连接。这就是我们所需要的。
提示: process.env.DB在secrets.json中被设置,同时被在serverless.yml中被引用。
将db.js切换添加到app.js文件后,粘贴在下面的代码段中。
如果您曾经使用过Express,您会对此感到熟悉。我们需要引入所有模块,使用中间件,引入我们刚才创建的数据库连接以及绑定到/api路径的路由,但我们还没有编写任何路由。所以,让我们开始吧!
4. 添加路由
在lib文件夹中,创建一个名为routes的新文件夹。它将成为应用程序中所有路由的基础。在routes文件夹中创建一个index.js文件并粘贴此代码段。
现在我们可以添加任何其他路由到这个文件,而不会影响其他任何设置,这会让事情简单很多。
5. 编写 CRUD 逻辑
我们已经达到了最有趣的环节。正如您在上面的index.js文件中所看到的,我们需要一个用来定义CRUD操作的notes.controller.js文件,好吧,让我们来创建它。
但是,我们首先需要一个Notes的API模型。在routes文件夹中创建一个notes文件夹,在其中创建另外两个名为note.js和notes.controller.js的文件。在note.js中,我们将定义note的的模型。
有了标题和描述,我们的例子就可以进行展开了。继续下去,我们准备添加CRUD逻辑,打开notes.controller.js并粘贴这些代码。
确保不要忘记引入文件顶部的Note模型。除此之外,一切都相当简单。我们使用Mongoose模型方法来创建CRUD操作,当然,使用async/await语法非常舒服,您还应该考虑在await运算符周围添加try-catch块。但是在这里,这个简单的例子就足够了。
关于代码就是这样。我们准备来进行一些测试!
测试
在部署我的应用程序之前,我更习惯于在本地进行测试。这就是为什么我会快速告诉您如何使用Serverless-offline模块完成测试。因为您已经安装了它并将其添加到serverless.yml中的plugins部分,所以您只需运行一个命令即可在本地计算机上启动API Gateway和AWS Lambda的本地仿真。
$ sls offline start --skipCacheInvalidation
提示: 在你项目的根目录运行sls然后你会看到很多命令。如果你进行了正确的配置,sls offline和sls offline start应该是可用的。
为了使您更容易使用此命令,请将其添加到package.json的npm script中。
添加后,您可以直接运行命令npm run offline,这样更简洁,也更容易记住。回到您的终端并运行它。
您将看到终端告诉您本地服务器已在端口3000上启动。让我们测试一下!
为了测试我的端点,我通常使用Insomnia或Postman,你当然可以随意使用你喜欢的任何工具。首先,通过点击POST端点开始添加一个note。
很好!它的工作方式与预期一致。继续尝试接下来的GET请求。
仍然正确。现在,继续尝试所有其他端点。确保它们都能正常工作,然后,让我们准备好将它部署到AWS。
部署
如果我告诉你,部署这个API仅仅需要运行一个命令,你会相信我吗?嗯,事实就是如此。
$ sls deploy
回到终端,运行上面的命令并耐心等待。您会看到终端上出现了一些端点,这些就是您API的端点。
以同样的方式,正如我在上面展示的那样,再次测试这些已部署的端点,确保它们正常工作。
接下来,您可能会注意到您只将API部署到了开发阶段。所以,我们还需要更改NODE_ENV并部署到生产环境。打开secrets.json文件并将第二行更改为:
"NODE_ENV": "production",
这将设置你Express API的环境为生产环境,并将阶段设置为生产阶段。在我们部属生产环境的API之前,让我们先删除node_modules文件夹,然后加上--production选项重新安装。
$ rm -rf ./node_modules && npm i --production
这将确保仅安装package.json中依赖项列表中指定的依赖项,而不会包括devDependencies列表中的依赖项。
在部署之前,您只需要注释掉serverless.yml中的plugins部分。
继续使用与上面相同的命令进行部署。
$ sls deploy
负载测试
如果我们不进行任何负载测试,这将不是一个建立生产环境API的正确教程。我倾向于使用一个小的npm模块进行负载测试。它被称为loadtest,可以通过简单的命令安装。
$ npm i -g loadtest
提示: Linux 用户可能需要使用sudo指令。
让我们逐步增加负载。我们想要运行的命令是10个并发用户使用GET请求100次命中/api/notes路径。
$ loadtest -n 100 -c 10 https://<id>.execute-api.eu-central-1.amazonaws.com/production/api/notes
回应所有这些请求大约花了5秒钟,没有出现错误。您可以放心,无论您最终拥有它的API规模如何,都会自动扩展到您需要的尺寸,并为您的用户提供服务而不会出现任何问题。以下是此负载测试的日志概述。
这个监控工具叫做Dashbird。 让我们对它进行设置,以便您也可以正确地监控API。
监控
对于Serverless架构而言,工程概述上的存在的缺陷和对应用程序中发生的情况缺乏足够深入了解是真正的问题。有几种产品可以真正帮助减轻这种麻烦——比如Dashbird,Datadog,Serverless,IOPipe等等。
您已经快速开始使用上面的Serverless框架了,让我们进行Dashbird的设置。您可以访问官方文档并快速入门或者跟随我下面的指导。
1. 注册
按照逻辑,我们应该先进行注册,创建一个帐户即可,不需要信用卡。
注册后,您将被重定向到新手入门页面,您需要在其中添加一个IAM角色的ARN。不过幸运的是,Dashbird开发人员为我们创建了一个CloudFormation栈,这使得创建IAM角色变得非常容易。
2. 为Dashbird创建新的AWS IAM角色
注册后,您将被重定向到新手入门页面。
单击创建新的CloudFormation堆栈的链接,然后按照步骤操作。
您需要做的就是不停点下一步,直到您到达名为我确认AWS CloudFormation可能会创建IAM资源框的复选框,选中并创建栈即可。
创建CloudFormation栈后,您将在控制台中看到它。在这里,您只需复制DashbirdIntegrationRole的ARN即可。
怎么样,是不是很简单?
3. 使用创建的角色设置Dashbird
您需要做的就是粘贴上面复制的角色ARN,然后就可以开始了。Dashbird会检查它是否可以访问您的AWS账户。如果一切设置正确,您将被重定向到该应用程序。日志将在一分钟内开始进行记录。
确保检查您的功能并检查您执行的测试是否在图表上可见。这样,您就已经构建了一个可以随时投入生产的API,可以通过简单的方式部署和监控您的应用程序。给自己鼓鼓掌吧!
总结
这是一次充实的冒险之旅!您已经创建了一个生产就绪的Serverless API。使用Serverless架构可能会让你遇到点困难——特别是那些您不习惯的服务,例如Lambda和API Gateway。
我上面展示的方法是我通常使用的方法。通过我的方法,使用Node.js以及您习惯使用的框架、模块和中间件,您可以更轻松地过渡到Serverless架构。
很幸运我们有Serverless Framework这样的开发工具以及Dashbird这样的观测工具,它们让开发的过程变得很简单。
如果你漏掉了上面的某个步骤,可以看本项目的代码库——包含项目全部的代码。
如果您想阅读我以前一些关于Serverless的思考,请访问我的个人资料或加入我的报刊团队!
或者,来顺便看看我写的一些其它的文章:
-
Solving invisible scaling issues with Serverless and MongoDB
-
How to deploy a Node.js application to AWS Lambda using Serverless
-
A crash course on securing Serverless APIs with JSON web tokens
希望大伙喜欢这篇文章,就像我享受创作这篇文章一样。如果你喜欢它,请点一个赞,那么在Medium上的更多人会看它。最后,让我们保持好奇并享受乐趣。
文章首发于dev.to。