亚马逊云科技精选博客
我们使用机器学习技术将英文博客翻译为简体中文。您可以点击导航栏中的“中文(简体)”切换到英文版本。
缩短 Lambda 冷启动时间:迁移到适用于 JavaScript 的 亚马逊云科技 开发工具包
当我们的客户将其应用程序从 JS SDK v2 迁移到 v3 时,他们一直在要求使用可靠的基准测试来评估 SDK 在常见用例中的性能。为了响应这些请求,JS SDK 团队对 亚马逊云科技 Lambda 的冷启动时间进行了基准测试,因为这是客户的常见用例,也是很好的参考标准。我们的基准测试显示,与大多数常见用例中的 v2 相比,v3 缩短了冷启动时间。尽管这些基准测试侧重于 Lambda 冷启动时间,但无论您使用哪种计算服务,迁移到 v3 通常都能提高应用程序性能。
自发布以来,Lambda 已对其 Node.js 18 运行时进行了多项性能优化,本博客文章中的数据基于最新的运行时版本。如果您对 Lambda 冷启动时间很敏感,我们建议将您的 Lambda 函数捆绑在一起,该函数使用带有命令对象的准系统 SDK 客户端,包括 JS SDK v3。您应该为生产应用程序运行自己的基准测试,并使用这篇博客文章作为参考。您也可以参考之前关于
什么是基准测试?
我们使用 JS SDK v3 和 v2 对示例应用程序的 Lambda 冷启动时间进行了基准测试。很大一部分的 JS SDK 客户从 Lambda 发送请求,许多人对冷启动时间很敏感。
以下 Lambda 函数示例代码从 JS SDK v3 导入 STS 客户端,在函数外部创建客户端实例并返回 getCallerIdentity 的 响应。
import { STS } from "@aws-sdk/client-sts";
const client = new STS();
export const handler = async () => client.getCallerIdentity();
v2 中的代码将从 “aws-sdk” 包中导入,并在 API 调用时调用 promise (),如下所示:
import AWS from "aws-sdk";
const client = new AWS.STS();
export const handler = async () => client.getCallerIdentity().promise();
基准测试是针对三个常见用例获得的:
- 按原样使用 Lambda 提供的软件开发工具包
- 用户上传的 node_modules 中的 SDK 按原样
- 使用 esbuild 捆绑销售
我们使用了
这篇博客文章中分享的基准测试适用于以 ECMAScript 模块格式(又名 ESM)编写的 Lambda 函数。我们还收集了以 CommonJS 模块格式编写的函数的基准测试,它们是相似的。我们使用 ESM,因为它是打包 JavaScript 代码以供重复使用的官方标准格式。
按原样使用 Lambda 提供的软件开发工具包
Lambda 在其设置中提供了 SDK 版本,以方便开发人员构建更简单的函数或使用 Lambda 控制台进行开发。这允许客户跳过在 node_modu
les 文件夹中提供 SDK 工件。虽然这是最方便的用例,但它并不是性能最高的用例。
在此基准测试设置中,应用程序仅使用函数源代码上传到 Lambda。它有两个文件系统节点:
package.json
包含项目清单index.mjs
包含函数源代码
JS SDK v3 是在 Lambda 提供的带有 Lambda Node.js 18 的软件开发工具包中引入的。这就是为什么 v2 基准测试在
nodejs16.x 上运行,而 v3 基准测试在 nodejs18.x
上运行。
使用 Lambda 的 Node Runtime 14 和 16 时,从 NODE_PATH 导入的 ESM 不可用。为了测试 Lambda 在 Node.js 16 中提供的 JS SDK v2,我们在我们的测试设置中创建了一个指向 /v ar/runtime/
node_modules 的符号链接。有关详细信息,请查看 GitHub 讨论
此设置的基准测试表明,使用 Lambda 提供的 SDK 时,使用 v3 的 Lambda 函数的冷启动时间比使用 v2 的函数 少了 100 毫秒以上。
版本 v2.1374.0 和 v3.188.0 是 Lambda 在撰写本文时提供的 SDK 版本。Lambda 提供的软件开发工具包版本会定期更新为最新的开发工具包版本。
用户上传的 node_modules 中的 SDK 按原样
与 Lambda 提供的 SDK 设置相比,我们针对用户上传的 node_modules 的基准测试设置有以下变化:
- node_modules 目录中添加了 SDK 工件。
这两个 Lambda 函数都在 nodejs18.x 上进行了基准测试
/var/runtime/node_modules 的符号链接已删除
。
此设置的基准测试表明,与使用 v2 的函数相比,使用 v3 的 Lambda 函数的冷启动时间 减少了大 约 140 毫秒。Lambda 函数的大小也减少了大 约 10 .8 MB。
对于这种设置,预计所有服务的改进将持续超过100ms。Lambda 函数的大小差异将取决于服务客户端,但在 v3 中会更小,与 v2 相比,v3 是模块化的。
使用 esbuild 捆绑销售
捆绑器是一种将多个模块或文件组合成单个文件的工具,通常用于优化 Web 应用程序的交付和执行。捆绑器通常用于前端开发,特别是基于 JavaScript 的项目,但它们也可以用于后端开发。
我们与 esbuild 捆绑在一起的基准测试设置使用 v2 和 v3 中的命名导入,并使用以下命令捆绑应用程序:
esbuild source.mjs --bundle --platform=node --format=esm --main-fields=module,main
要创建 v2 的 ESM 捆绑包,我们需要使用以下 esbuild 选项为需要提供 polyfill:
有关为什么需要这样做的详细信息,请参阅
此设置的基准测试表明,与 esbuild 捆绑在一起时,使用 v3 的 Lambda 函数的冷启动时间比使用 v2 的函数 少了 400 毫秒以上。Lambda 函数的大小也有 2 MB 的差异。
为了减小 v2 中的函数大小,一些客户使用了 STS 客户端的深度导入,如下所示:
import STS from "aws-sdk/clients/sts.js";
当我们在深度导入 STS 客户端时运行基准测试时,v3 中的冷启动时间仍然缩短了大约 10 毫秒。尽管具有深度导入功能的捆绑v2函数比具有全局导入功能的版本小,但捆绑的v3功能仍几乎是其大小的一半。
通过使用带有命令对象的准系统客户端,也可以进一步减小 v3 中的包大小。在幕后,这将导入一个轻量级客户端,并且仅导入您的应用程序需要调用的操作。此结构甚至可以用于 Lambda 函数之外的案例。
import { STSClient, GetCallerIdentityCommand } from "@aws-sdk/client-sts";
const client = new STSClient();
export const handler = async () => client.send(new GetCallerIdentityCommand({}));
在 v3 中使用 STS 客户端的命令导入运行基准测试时,捆绑的应用程序大小减少了约 2KB。冷启动时间缩短了约 3 毫秒。
我们可以从这些基准测试中学到什么?
就常见用例中的 Lambda 冷启动时间而言,JS SDK v3 比 v2 更快。
您实现应用程序的方式会影响性能。如果您在 Lambda 上使用 JS SDK 并且对冷启动时间很敏感,请使用带有准系统客户端和命令对象的 JS SDK v3,并在部署到 Lambda 之前捆绑您的应用程序。此设置的冷启动时间较短,因为 Node.js 只需要读取一个文件,其中包含应用程序的完整源代码。无需花费时间进行模块解析或读取多个文件。当您的应用程序使用 v3 时,包大小会更小,因为 v3 是模块化的。
JS 开发工具包团队建议使用 dling.externalModules 配置中传递一个空数组,这样它就可以捆绑
开发工具包了。有关详细信息,请查看
反馈
要开始使用 JS SDK v3,请访问我们的