开发者迈向 AWS Lambda 的旅程
由 Mux 主办的 DEV 全球展示挑战赛:展示你的项目!
AWS Lambda 的学习曲线出乎意料地陡峭。你创建一个新函数,编写代码,然后它就能执行。很简单,对吧?但随后你会发现,这背后的奥秘远比你想象的要深得多。面对如此之多的主题,你很难知道下一步该从何入手。
到目前为止,您已经开始使用 Lambda,但现在却遇到了瓶颈。在这篇文章中,我们将为您详细介绍五个步骤,帮助您继续您的 Lambda 之旅。
1)改进你的代码
AWS Lambda 看起来很简单——你可以编写任何代码,它都能运行。没错,但并非所有代码都具有相同的价值,有一些重要的方法可以提升 Lambda 函数中代码的性能。
使用 AWS Lambda 的基础是了解它使用的执行环境,这样我们才能了解冷启动等行为,以及我们的代码如何影响它们。
《AWS Lambda最佳实践》是一本非常值得一读的书,但为了突出代码方面最重要的几点:
从处理程序中移除你的逻辑
保持代码尽可能简洁可以避免很多麻烦。当我们开始编写 Lambda 函数时,它们会变得冗长,我们可能会将它们放在处理函数中。
这使得我们的测试变得复杂,因为单元测试与函数的调用方式密不可分。使用处理函数来控制与其他解决方案组件的交互,而业务逻辑则放在代码中的独立函数中。
import requests
def check_inventory(check):
response = request.get('http://apiurl/inventory')
if check in response.text:
return True
else:
return False
def lambda_handler(event, context):
data = check_inventory(event['itemId'])
return {
'statusCode': 200,
'body': json.dumps(data)
}
在这种情况下,无论库存检查逻辑如何集成到 Lambda 中,都可以轻松测试。同样,我们的处理程序只专注于如何将信息传递给业务逻辑以及如何从业务逻辑接收信息,从而更易于维护。这是一个非常基础的示例,而 AWS 欧洲、中东和非洲地区首席布道师 Danilo Poccia 则提供了一个非常精辟的 gist—— GreetingsAPI.js,展示了一个更复杂的集成。
代码外部的配置
在代码内部处理配置总是会造成一团糟。你写过多少次类似这样的代码?
# apiUrl = "https://prod.my-tenant.customersystem.net/v2/res/item"
apiUrl = "http://127.0.0.1:3000/mock"
甚至更糟……
apiToken = "QmFzZTY0IGlzbid0IHJlYWwgZW5jcnlwdGlvbg=="
好吧,我也是……✋ 好在 AWS 为我们提供了一些使用 Lambda 来解决这个问题的方法。
环境变量对大多数开发人员来说都很熟悉,并且在本地计算机和 AWS 上的工作方式完全相同。但是,对于任何需要安全配置或需要在多个 Lambda 函数中使用的配置,都值得了解一下AWS Systems Manager Parameter Store、AWS Secrets Manager或AWS AppConfig。它们可以避免很多未来的麻烦,让您的安全团队高枕无忧。
利用环境重用
当你的函数创建一个新实例时,该Init阶段将运行函数之外的任何静态代码。
如果在处理请求之前需要执行任何耗时较长的任务,或者在接收请求之前需要实例化某些对象,那么这种方法可以显著提高代码效率。尽可能充分利用这种方法,从而加快最终用户的体验。
import pymysql
try:
connection = pymsql.connect(<DetailsGoHere>)
except pymysql.MySQLError as e:
logger.error(e)
sys.exit()
def lambda_handler(event,context):
with connection.cursor() as cursor:
cursor.execute("SELECT * FROM USERS WHERE userId='" + event['uid'] + "'")
data = connection.fetchone()
return data
处理有状态数据时,务必确保在两次调用之间不会发生数据泄漏。即使某个对象已经实例化,也应该进行检查,特别是数据库连接,以确保它们仍然有效。
AWS 无服务器专家 Jeremy Daly 在 2018 年发表的关于在 Lambda 中重用数据库连接的文章很好地介绍了这一概念,尽管现在数据库连接管理有了新的选择。
2)利用持续集成/持续交付和框架
如果您仍在 AWS 控制台中实时编辑和保存代码,那么您很可能遇到过这种情况:
现在都2023年了,你应该已经明白为什么应该使用CI/CD流水线。但是,你可能要花更多的时间构建和调试流水线,而不是真正编写有价值的代码。而这仅仅是部署一个简单的Lambda函数而已。
幸运的是,我们有很多框架和工具可以帮助我们构建和部署无服务器解决方案。每个框架各有优势,但它们的目标都是减少开发和部署之间的摩擦。
- AWS SAM(无服务器应用程序模型)简化了 AWS 无服务器应用程序的部署。
- Wing围绕云原生原语构建了一整套语言,并将其编译成另一个配置提供程序(目前仅支持Terraform)。
- Serverless Framework是构建无服务器应用程序的原始框架,至今仍然是一个可靠的选择。
- Ampt目前处于内部测试阶段,但正致力于构建一个完全集成的开发者平台。我对这将给开发者体验带来的改变感到非常兴奋!
如果您熟悉 CloudFormation,我建议您以AWS SAM作为起点。Ampt 结束内部测试后,我将开始尝试使用它。
3) 使用 PowerTools 轻松实现可观察性
我们都曾为了调试而使用print('boop')`or`console.log('hi!')命令。但这在生产环境中并不适用。为各种输出实现自定义日志记录,再加上生成和处理自定义指标,需要大量额外的工作。更不用说还要支持分布式追踪了。
Lambda PowerTools应运而生——只需几分钟即可将其安装到您的代码中,让您能够极其轻松地处理日志记录、指标和分布式跟踪,所有这些都可以在您选择的语言中轻松完成。
可观测性决定了你的解决方案是充满生产难题的庞大系统,还是众多组件协同运作、精妙绝伦的交响乐,让你能够主动了解并解决问题。这是你能为 AWS 中的无服务器应用程序带来的最直接、最显著的提升。
强烈推荐大家看看Powertools for Python 的教程,它涵盖了 Powertools 以及一些 AWS SAM 的内容!
4)调整部署
“任何足够先进的科技都与魔法无异”(阿瑟·C·克拉克)。Lambda 是一种先进而强大的科技,而它的魔力也造成了一些常见的误解。
- Lambda 可以无限扩展你的函数。
- Lambda 执行环境将立即启动。
- Lambda 会在您更新代码时立即更改所有内容。
- Lambda 将使用它所需的所有资源。
让我们仔细看看如何配置 Lambda 函数。
使用预留并发进行函数扩展
Lambda 函数确实存在扩展限制。默认情况下,每个账户最多可同时执行 1000 个函数。由于账户中的所有 Lambda 函数共享此并发限制,因此您可以使用“预留并发”功能为每个函数预留最大并发量。
预留并发数还可以用于设置上限,以防止 Lambda 函数向下游服务(例如 API)发送请求时造成过载。毕竟,你家附近的咖啡店,即使只有一个咖啡师,也能处理无限多的订单。前提是你愿意无限期地等待你的咖啡。
您可以申请提高帐户的并发限制配额,但最好先考虑其他限制。
冷启动和预置并发
我们从对执行环境的探索中了解到,Lambda 函数不会立即启动新的执行环境——它们需要时间完成初始化阶段。预置并发机制可以确保随时都有最低数量的实例可供使用。
为了解决冷启动问题,使用预置并发 (Precurring Concurrency) 似乎很诱人,但它有一个巨大的缺点:成本不低。让执行环境处于待机状态会产生大约 25% 的持续开销。这听起来似乎不多,但累积起来却相当可观。
一个配备标准 512MB 内存并运行 10 个预置并发实例的 Lambda 函数,每月费用约为 54 美元。这还不包括每个请求及其运行计算时间的成本。因此,在选择预置并发之前,始终值得先进行优化。
使用版本和别名管理变更
Lambda 的一大优势在于能够快速更新代码并立即反映在生产计算环境中。这固然很好,但通常情况下,您还需要更精细的控制。这时,版本控制和别名就派上用场了。
Lambda 内置了版本控制功能。进行实时编辑时,您实际上是在操作$LATEST版本。创建版本可以让您将代码锁定到特定状态,每个版本都可以通过其唯一的 ARN 独立执行。
别名将这种功能提升到了一个新的层次,它允许您动态引用特定函数版本。例如,如果您为某个函数设置了别名prod,那么它就可以成为 API 网关调用该函数的目标。当您完成新版本的测试后,只需更新别名以指向更新后的版本,而无需更新 API 网关。
调整资源配置
您可能在 Lambda 定价中见过“GB 秒”的概念。简而言之,费用是根据 Lambda 函数的运行时间和分配给它的资源量来计算的;尽管名称是“GB 秒”,但内存占用也与分配的 CPU 和网络资源直接相关。
分配给函数的内存越多,函数运行速度就越快。但分配的内存越多,成本也会越高。因此,找到内存分配和函数运行时间之间的最佳平衡点至关重要。一般来说:
- 如果你要执行大量计算,请分配更多内存。
- 如果您正在等待外部调用,请分配较少的内存。
AWS 文档的“内存和计算能力”页面是一个很好的起点。为了避免手动配置,建议您查看AWS Lambda 性能调优,它可以帮助您找到最佳配置。
5) 无服务器架构设计
到目前为止,您的 AWS Lambda 技能已经非常成熟了。但是,在无服务器计算领域,您仍然有很多东西需要学习。有很多入门途径,所以我建议您观看一些来自 AWS re:Invent 2022 的精彩视频。
- 开始构建你的第一个无服务器、事件驱动型应用程序 (SVS209)作者:Emily Shea
- Eric Johnson 著《使用事件驱动架构构建下一代应用程序 (API311-R)》
- 构建 Serverlesspresso:创建事件驱动架构 (SVS312)作者:James Beswick
这些课程能让你更深入地了解无服务器解决方案的开发和架构。由于你已经熟悉 Lambda,所以重点不再是代码,而是模式和架构。
总结
Lambda 的学习之旅远不止于此。这项服务和开发领域还有许多值得深入探索!您几乎可以在《开发者指南》和《运维人员指南》中找到所有问题的答案。AWS 的文档体系非常完善,让用户能够轻松掌握其服务,Lambda 也不例外。
想要深入了解,不妨看看AWS Events YouTube 频道上的精彩内容,那里有 re:Invent 大会上数十场涵盖所有无服务器主题的精彩演讲。你无需花费数千美元就能向行业领袖学习,这些内容绝对值得一看。
最后,别忘了看看AWS社区成员发布的更多内容!可以肯定的是,无论你在构建什么,之前肯定有人做过类似的事情。
注意安全,祝您观云愉快!
文章来源:https://dev.to/aws-builders/developers-journey-to-aws-lambda-16ag






