使用 Python 和 AWS Lambda 创建无服务器函数
入门指南
正如大多数对这个主题有所了解的人都知道的那样,“无服务器函数”这个名称其实并不准确。服务器仍然参与整个过程,只不过,正如Web开发领域长期以来的趋势一样,开发者对服务器的控制权越来越少。
虽然这听起来很糟糕,但对于只想把酷炫的产品推向酷炫用户(任何使用你产品的人都很酷,这是商业的第一法则😁)的开发者来说,部署和运维生产环境应用的大部分工作都是繁琐且永无止境的。云托管和托管软件的发展历程表明,放弃对这些环节的控制权通常会降低许多开发者的入门门槛。“无服务器”函数,或者更准确地说是“函数即服务”,正是这一趋势的必然发展;我们领域的许多 杰出 人士对此都感到非常兴奋。
主要好处在于,当以服务形式运行这些函数时,云托管的“按需付费”理念实际上得到了扩展,因为你无需在项目中添加任何额外开销。你无需运行虚拟服务器(该服务器在空闲时会占用资源,并按分钟计费)。你运行的函数仅在被触发时才使用资源,这意味着你只需在用户实际使用你的代码时付费。是不是很棒?
虽然我个人对将越来越多的生产资料(明白我的意思吗?😁)拱手让给那些号称仁慈的企业巨头感到不安,但我还是觉得,为了自己的技术发展,我应该尝试一下无服务器函数,尤其是有那么多文章都在盛赞这些工具的巨大成本节约优势。所以我试了。
基本设置
如果您之前已经创建过 Serverless 函数,则可以跳到第 3 部分。
1. 安装
首先,你需要安装Serverless框架。虽然不用这个框架也能编写无服务器函数,但据我所知,Serverless 框架能让整个过程变得简单得多。你可以使用以下命令安装它:
npm install -g serverless
请注意,无论您使用哪种语言编写函数,Serverless都是一个 node 模块,必须使用npm.
2. 设置管理员服务帐户
接下来,您需要设置一个可以附加代码的服务。对于Serverless支持的任何提供商,设置过程都应该类似,目前支持的提供商包括:
本文仅介绍如何在 AWS 中实现。如果您使用的是其他服务,我建议您查阅Serverless 的文档;它非常出色。
首先,前往 AWS 并导航至 IAM 服务。
接下来,导航至“添加用户”Users并点击。进入后,为您的服务账户添加一个描述性名称。由于这是一个管理账户,供您的Serverless CLI(为避免混淆,下文简称SLS)安装使用,用于更改您的 AWS 账户,因此您可以为其指定一个通用名称,并在您编写的所有服务中使用同一个服务账户。您也可以使用单独的账户,我最初设置时,因为不太了解相关知识,所以给它取了一个项目特定的名称。使用项目特定的账户有助于确保您创建的所有内容保持清晰和独立,但这并非绝对必要。
请务必勾选“程序化访问”复选框,以便 CLI 自动将更改应用到您的帐户。
在下一页中,授予您的服务帐户AdministratorAccess权限。
准备就绪后,点击“创建用户” ,然后复制您的访问密钥 ID和私钥(或将其下载为 CSV 文件)。如果您已经操作到这里,我假设您知道这些密钥非常重要,应该妥善保管。
你快完成了!你是不是很喜欢这种没完没了的配置过程,明明只是想把什么东西组装起来?
现在您只需运行以下命令,即可授予SLS访问您凭据的权限:
serverless config credentials --provider aws --key <ACCESS KEY ID> --secret <SECRET KEY>
好了,现在你可以开始创建项目了。嘿,谁也没说过这不会有点繁琐。不过你应该庆幸SLS会帮你处理很多事情。
3. 创建您的服务项目
现在您已准备好创建项目,请导航至要创建服务的文件夹并执行以下操作:
serverless create --template aws-python3 --path <PATH>
现在你应该看到一个文件夹,里面装满了 Serverless 相关的东西。在这个文件夹里,你应该能看到一个名为 ` .config` 的serverless.yml文件。这是你新项目的主要配置文件。打开它,你应该会看到类似这样的内容(以及我删除的一些注释):
service: my-service
provider:
name: aws
runtime: python3.6
package:
exclude:
- secrets.yaml
functions:
hello:
handler: handler.hello
你还应该有一个handler.py包含hello()函数的文件。如果你看一下上面的内容,你会发现它已经在服务中注册了(就在最底部),名称是 `<service_name>` hello。这意味着你可以将服务的各个部分拆分到不同的文件中,同时handler.py仍然直接将它们注册到你的服务中。真是太方便了!
我讨厌有些作者在攻略里故意让你尝试一些行不通的方法,只是为了证明自己的观点,我觉得这很烦人,所以我就直接告诉你吧:
虽然您已经定义了一个名为 `function` 的函数,hello并且它链接到了一个函数处理程序,但您目前没有办法触发该函数。这就是为什么我们需要event在 `function` 中定义的函数中添加一个 `get_function` 语句serverless.yml。请按如下方式更新它:
functions:
hello:
handler: handler.hello
events:
- http:
path: hello
method: get
该events集合包含各种类型的触发器,可用于触发您的函数。这些触发器包括定时任务、Alexa 技能、物联网触发器等等。现在,您将使用一个简单的 HTTP 触发器,当您向端点发送GET请求时,它将做出响应/hello。
从这里开始,你可以像处理普通的 Python 项目一样处理它,只有一个例外,我会在最后提到。要安装依赖项,只需env像往常一样创建目录,或者使用 Pipenv。你可能希望serverless-python-requirements从这个仓库在你的服务目录中安装依赖项,这将自动将你的依赖项打包,并通过requirements.txt其.PipfilePYTHONPATH
关于 PipEnv 的说明
PipEnv 是一个相对较新的工具,用于替代全局安装模块或之前的默认方案——虚拟环境。它由 Kenneth Reitz 编写并推荐,Kenneth Reitz 也是requests《Python 编程指南》等热门工具的作者。PipEnv 极大地简化了我的开发流程,然而,在使用 PipEnv 时,我遇到了一些模块问题google-client-api,不得不重新设计我的项目venv。如果您依赖此模块并且正在编写无服务器函数,我建议您不要使用 PipEnv。
4. 部署和测试
最后,您需要部署您的函数:
serverless deploy
获取输出中列出的端点,其格式应类似于:
GET - https://xxxxxxxxxx.execute-api.us-east-1.amazonaws.com/dev/hello
如果您需要在不执行部署的情况下获取有关服务的信息,只需运行命令sls info即可注销端点、函数等。
如果您在浏览器中访问该网址,应该会收到以下响应:
Go Serverless!
您还可以通过以下命令调用您的服务:
sls invoke -f hello
如果由于某种原因您没有收到该响应,您可以运行:
sls logs -f <function_name> —tail
查看服务器上特定函数的连续日志。
耶!我们完成了!对吧?嗯……算是吧……
问题在于,部署到你的服务需要相当长的时间,而且这样的测试过程会变得非常繁琐。此外,如果你有生产服务,那么部署到测试环境……是不可取的。
那么,我们该如何测试我们新开发的函数呢?
有几种不同的方法,包括一些高级库,但就目前而言,我发现只需添加local关键字(如下所示)即可完美解决问题:
sls invoke local --function <FUNCTION> --log
您无需访问远程函数实例,而是访问托管在您自己的机器上的函数实例,这意味着您可以保存文件并进行测试,而无需重新部署。
好了,这些是基础知识,但总有更多东西需要学习。
5. 后续步骤
我在使用无服务器函数时遇到的第一个问题是,对于如何管理密钥值缺乏清晰的说明。我发现这篇指南非常实用且易于理解,建议你也看看。
如果你对无服务器解决方案的理念和架构更感兴趣,我推荐你阅读这篇文章,并建议你了解一下 FaaS 方法和传统 Web 后端在架构方面的差异。
我的用例
那么,我究竟想用这一切建造什么呢?
过去十个月或十一个月里,我一直坚持更频繁地去健身房,幸运的是,我做到了。我每周去健身房三天,从一月到八月底,最多也就错过一天。九月份和几个好朋友进行了一次精彩的旅行,让我有点疲惫,所以休息了两周。有一件事我始终坚持,那就是每次在健身房锻炼后,我都会用谷歌表格记录我做了多少组、多少次,有时还会记录一下我的感受。这一切或许看起来有点多余或毫无意义,但我发现,追踪和回顾这些数据确实能帮助我保持动力,取得进步。
现在我已经有了所有这些数据,我想处理它们(目前有46个电子表格),并以交互式图表的形式在我的网站上展示。既然有了数据,为什么不利用它们呢?
为了实现这个目标,我编写了一个函数,它可以从我的工作表中获取数据,将每个工作表转换为一个对象,然后将该对象提供给一个静态前端,前端再将这些数据导入到 D3 图表中。目前它还在开发中,但我希望很快就能发布。
无服务器函数确实让我的路由配置运行速度比搭建服务器快得多。
局限性
我欢迎对以下任何陈述(以及之前的任何陈述)进行纠正。
无服务器功能看起来很棒,因为从理念上看,它们似乎是云托管理念的最终演进。然而,它们也存在一些缺点。
如果你是自托管,这种架构似乎并非明智之选,因为底层服务器依然存在,处于空闲状态,并且可能为了协调每次函数调用的启动和关闭而消耗更多资源。只有当亚马逊或谷歌承担费用时,这种模式才有意义。此外,如果你有长时间运行的进程或后台任务(不包括可设置为函数触发器的定时任务),这种架构可能并非最佳选择。持久层也带来了挑战,因为它们必须托管在外部服务器上,或者使用 DynamoDB、GCD 等数据存储服务。最后,对于那些将空闲时间视为总体成本中占比极小的项目而言,这种架构带来的收益可能有限。这意味着,如果你的服务经常受到访问且访问量较大,那么 FaaS 可能是一个值得等待的趋势。
结论
无服务器函数似乎能为我提供相当长一段时间的深入学习机会,因为它们既消除了传统开发流程带来的现有问题,也给习惯于搭建服务器的开发者带来了新的挑战。下次当你进行原型设计或创建访问量较低的路由时,我强烈建议你首先了解一下无服务器架构。





