在本文中,我们将使用 Lambda—Amazon Web Services(AWS)套件中的一个新工具—来启动并运行一个微服务。 我们将使用 Lambda 创建一个 HTTP GET 终端,该终端使用 GitHub 的API 发起请求,从 GitHub 中提取存储库信息并返回一个 JSON 响应。
为方便你可以按本文中的步骤进行操作,你将需要一个自己的 AWS 账户。 如果没有,您可以在 https://aws.amazon.com/ 上创建免费的AWS账户。
Lambda 的口号是:“运行代码不用考虑服务器”。乍一看,这可能让人觉得比较困惑。 代码究竟是在哪里或如何运行的呢?
“无服务器”是一个新的软件基础设施术语,你可能有所耳闻。 它用于描述按需执行代码的解决方案。“无服务器”这个术语可能会误导大家,因为事实上,在程序中仍然有服务器。 更好的描述符是 FaaS 或“函数即服务”。
这两个定义用于描述新的开发和部署经验。 这种新体验被认为是“无服务器”的,因为作为开发人员,不再需要管理,监视或扩展正在运行代码的任何服务器。 您只需将代码上传到 FaaS 提供服务的程序(在本例中为 AWS Lambda),FaaS 提供程序将在后台帮你执行代码并管理所有的基础架构。
鉴于这一“无服务器”架构扩展的定义,让我们来看看用 Lambda 工作的一些利弊。
按需使用定价
传统的服务器托管使用重复计费周期。 你的服务器总是启动和运行使用资源和等待输入。 为了保持服务器正常运行,你按月或按年作为账单周期来支付费用。用按需定价,Lambda 按每个函数的使用进行计费。这意味着你的项目利用 Lambda 的功能是不频繁的,相比传统的托管解决方案,你可以节省大量的金钱。
Lambda 定价如下:
每 100 万个请求 0.20 美元
每 GB 秒的计算时间 0.00001667 美元,每次执行时间接近 100ms
内置的自动伸缩功能
在一个传统的被托管的基础设施中, 你会进入到这样一个时期,你可能需要担心性能和扩展性。随着应用程序使用量和通信量的增加,您可能需要添加更多的托管服务器基础设施来跟上需求。对于你的用户,这可能导致失败,成为瓶颈。 当需要增加或减少额外的开销时,Lambda 会自动完成扩展性。
与本地开发工作流程不一致。
你可以在本地写 Lambda 功能代码,隔离测试,但是在没有创建你的拼装版的 Lambda,你不能在本地模拟生产环境。
Lambda 有两个主要概念:代码和触发器。 代码是不言自明的。 在我们的示例中,就是那些由您编写并上传到 Lambda 以产生你所需行为的 JavaScript 代码。
一旦你上传后,代码不会自行执行。 Lambda 有一个称为“触发器”的附加概念。触发器是由其他 AWS 服务触发的事件,它们将数据传递到 Lambda 函数以供执行。
一些示例触发器:
用指向 AWS API 网关的 HTTP 请求来触发 Lambda 代码。
用轮循的事件触发,例如来源于 CloudWatch 事件的 corn 任务。
用 DynamoDB 表的更新来触发 Lambda 代码。
你可以从与预期的 Lambda 签名相匹配的 JavaScript 中,通过导出一个常规函数来定义一个 Lambda 函数。
exports.myLambdaFunction = (event, context, callback) => { // Use callback() and return }
该函数接收3个参数:
event — Lambda 传递给函数的'触发数据'的键值对字典。
context — AWS 内部信息,例如 AWS 请求ID, Lambda 超时时间, 和日志信息.
更多详细信息请看: http://docs.aws.amazon.com/lambda/latest/dg/nodejs-prog-model-context.html
callback — 一个标准的 JavaScript 异步回调句柄。
更多详细信息请看: http://docs.aws.amazon.com/lambda/latest/dg/nodejs-prog-model-handler.html#nodejs-prog-model-handler-callback
开始创建新的 Lambda 函数。访问 Lambda 仪表盘:
https://console.aws.amazon.com/lambda/home?region=us-east-1#/functions?display=list
然后会看到像这样的界面:
点击蓝色的按钮 创建 Lambda 函数(Create a Lambda function) 来开始。
下一个界面会提示你 选择一个设计图(Select a blueprint) 并提供一个可过滤的设计图列表。点击空函数(Blank Function) 选项,它应该是设计图列表中的第一个选项。这个页面可用于将来参考着使用其它工具。
接下来的界面是 配置触发器(Configure Triggers),显示成这样:
点击下一步(Next) 离开这个界面。我们会在后面,建立起我们的函数之后,再来定义触发器。
在这一部分,需要给 Lambda 函数一个名称。我会使用 GithubGet 这个名称。你也可以填写对这个函数的描述,这是可选的。
默认情况下,Lambda UI 设置为内联编辑代码。 您应该看到一个内联编辑器,编辑器中有一个样本函数,如下所示:
内联编辑器需要很少的开销来获取和运行 lambda 代码,但对于本教程,我们将做一些更进阶的事情。
在大多数真实环境中,你如果要创建更多的复杂函数,常常需要通过npm来安装第三方的库。
让我们创建一个使用 npm 依赖项的自定义函数,并将其上传到Lambda。 您可以按照下面的步骤,或者可随意使用示例代码库 中的代码
让我们为我们的新函数设置一个文件夹,并在文件夹中用默认的 package.json 文件初始化 npm:
npm init -f
接下来,我们将安装 GitHub 客户端:
npm install github
创建 index.js 文件,使用以下代码:
var GitHubApi = require('github'); var github = new GitHubApi(); exports.handler = (event, context, callback) => { github.search.repos({ q: 'sitepoint', sort: 'stars' }, function(err, res){ if(err){ callback(err); } var results = res.items.map((repo) => { return { url: repo.html_url, stars: repo.stargazers_count }; }); callback(null, { statusCode: 200, headers: { "Content-Type": "application/json" }, body: JSON.stringify(results) }); }); };
下面是这段代码的功能细节:
引入并初始化了 GitHubAPI
定义了一个与 Lambda 签名匹配的 handler 函数。
当 handler 函数被调用时,它会发出一个查询请求到 GitHub,对所有符合‘sitepoint’的数据仓库进行查询。
在 Github 的应答格式中,创建了一个 map 数据结构,其中包含了每个数据仓库的网址和星标数。
最后,用 http 响应(如对象)调用 Lambda 的回调函数,好与 API 网关预计集成 相匹配。
任意使用一个你熟悉的 zip 工具,创建一个包含函数文件的 zip 压缩包。我在 OS X 系统上使用 zip 命令行是这样的:
zip -r lambdaupload.zip ./index.js ./node_modules/
要将代码上传到 Lambda, 在内联编辑器的 “代码条目类型” 选项上选择 “ 上传 zip 文件 ”,然后使用弹出的窗口上传您的代码。
在这一部分下,我们要设置几个值。 Handler 是在上传的 JavaScript 文件中 Lambda 函数的引用。 默认情况下,它设置为 index.handler。hander 函数通过查找 index 文件与我们上传的文件相映射,并为我们 hander 函数检索出与我们 export.handler 文件相对应的的导出语句。
使用以下信息填写“Role”字段,为创建 Lambda 函数的基本角色:
Role: 从模板中创建新的 role
Role name: Lambda 获取 Role
Policy templates: 简单的微服务权限
这部分完成后, 单击“Next” 按钮继续。比可以看到 ‘Review’ 界面的概述配置:
如果一切正常,单击“创建函数”按钮继续。
既然我们的函数已经创建并初始化了,我们需要一种方法来调用它。现在是时候为该函数分配触发器了。对于触发器的实现,我们将使用 API 网关。
API 网关是另一种 AWS 服务,它能自动创建可配置响应源的 HTTP 终端。我们将把我们的 Lambda 函数作为 API 网关的响应。
点击‘Triggers’(触发器)
点击‘Add trigger’
点击lambda旁边的空白区域
选择“API Gateway”
在安全性中选择“Open”
点击提交
这些步骤可以在下面动画中看到:
当成功添加触发器之后,你应该可以在 Triggers 标签中看到触发器和你的函数被关联起来。
在 API 网关 ID 中会列出一个 URL。你可以访问在浏览器中这个 URL,然后你赢高可以看到一个 JSON 响应,类似下面的日志:
[{"url":"https://github.com/bodrovis/Sitepoint-source","stars":106}, {"url":"https://github.com/Azzurrio/moviestore","stars":80}, {"url":"https://github.com/bodrovis/SitepointMiniChat","stars":54}, {"url":"https://github.com/upchuk/d8-demo-modules","stars":34},
恭喜!你已经成功在 Lambda 上部署和触发代码了。
希望这个项目能给你在 AWS Lambda 上工作建立一个好的基础。虽然我们在函数代码中整合了第三方客户端(GitHub),但它可以替换为其它客户端 API 或者数据库的客户端链接。
这篇文章中演示了建立起 Lambda 的这个过程。这过程看起来手工操作比较多,时间也不长。还有另外一个配置和初始化 Lambda 的方法,就是通过 AWS API 来完成。
现在,已经有一些框架基于 AWS API 建立起来了,它们有助于简化这个过程。
Serverless 框架是当前最强大的无服务器框架。在写文本的时候,这个框架进行了重大版本更新,从0.5 更新到官方 1.0 发行版。很不幸,这个更新并不向后兼容。大多数流行的插件当前还是 0.5,未能更新到 1.0,还需要等等待一段时间才能使用。
Serverless 以及它的插件,承诺提供一个非常全面的 Lambda 体验。它的本地开发环境提供了快速迭代、自动化的 Lambda 代码开发、多个开发平台环境,以及其它功能。
OpenLambda 试图通过提供一个本地开发体验来模拟 Lambda 环境。它提供工具来让部署 Lambda 代码变得容易,也提供快速迭代。这弥补了上面列出的 Lambda 的一些缺点。
评论删除后,数据将无法恢复
评论(5)
引用来自“极客老鸟”的评论
这样的垃圾国内都玩了好几年了吧?而且没这么复杂,不用新工具,直接搞就行了引用来自“eechen”的评论
还"函数即服务",说得那么高大上,Amazon真行,把虚拟主机换个名字(AWS Lambda),就炒作出新花样.