AWS Lambda 扩展 API - AWS Lambda
AWS 文档中描述的 AWS 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅中国的 AWS 服务入门

AWS Lambda 扩展 API

您可以使用扩展 API 创建 Lambda 扩展。扩展提供了一种将监控、安全和其他工具与 Lambda 执行环境集成的新方式。有关更多信息,请参阅 AWS Lambda 扩展简介

扩展 API 基于现有的运行时 API 构建,该 API 为自定义运行时提供一个 HTTP API,以便从 Lambda 中接收调用事件。作为扩展作者,您可以使用扩展 API 来注册函数和执行环境生命周期事件。为了响应这些事件,您可以启动新进程或运行逻辑。

Lambda 支持内部和外部扩展。内部扩展 可让您配置运行时环境并修改运行时进程的启动。内部扩展使用特定于语言的环境变量和包装脚本,并在运行时进程中启动和关闭。内部扩展在启动和停止这些扩展的运行时进程中作为单独的线程运行。

外部扩展 作为独立进程在执行环境中运行,并在完全处理函数调用后继续运行。外部扩展必须注册 Shutdown 事件,从而触发扩展关闭。由于外部扩展作为进程运行,因此它们可以用不同于函数的语言编写。

以下 Lambda 运行时支持外部扩展:

  • .NET Core 3.1 (C#/PowerShell) (dotnetcore3.1)

  • 自定义运行时 (provided)

  • Amazon Linux 2 (provided.al2) 上的自定义运行时

  • Java 11 (Corretto) (java11)

  • Java 8 (Corretto) (java8.al2)

  • Node.js 12.x (nodejs12.x)

  • Node.js 10.x (nodejs10.x)

  • Python 3.8 (python3.8)

  • Python 3.7 (python3.7)

  • Ruby 2.7 (ruby2.7)

  • Ruby 2.5 (ruby2.5)

我们建议您使用已编译的语言实现外部扩展。在这种情况下,扩展是一个独立的二进制文件,与所有支持的运行时兼容。如果使用非编译的语言,请确保在扩展中包含兼容的运行时。

您可以将扩展共享为 Lambda 层 ,以便在您的组织或整个 Lambda 开发人员社区中使用该扩展。函数开发人员可以通过层查找、管理和安装扩展。

您可以使用 Lambda 控制台、AWS Command Line Interface (AWS CLI) 或基础设施即代码 (IaC) 服务和工具(如 AWS CloudFormation、AWS 无服务器应用程序模型 (AWS SAM) 和 Terraform)来安装和管理扩展。

注意

示例扩展和包装脚本在 GitHub 示例扩展存储库中提供。

Lambda 执行环境生命周期

执行环境的生命周期包括以下阶段:

  • Init:在此阶段,Lambda 使用配置的资源创建或解除冻结执行环境,下载函数和所有层的代码,初始化任何扩展,初始化运行时,然后运行函数的初始化代码(即主处理程序外的代码)。Init 阶段在第一次调用期间发生,或在函数调用之前(如果已启用预置并发)发生。

    Init 阶段分为三个子阶段:Extension initRuntime initFunction init。这些子阶段确保所有扩展和运行时在函数代码运行之前完成其设置任务。

  • Invoke:在此阶段,Lambda 调用函数处理程序。函数运行到完成后,Lambda 准备处理另一个函数调用。

  • Shutdown:如果 Lambda 函数在一段时间内没有接收任何调用,则会触发此阶段。在 Shutdown 阶段,Lambda 终止运行时,提醒扩展以使其干净停止,然后删除环境。Lambda 向每个扩展发送一个 Shutdown 事件,该事件告诉扩展此环境就要关闭。

每个阶段都以一个从 Lambda 服务到运行时和所有已注册扩展的事件开始。运行时和每个扩展通过发送 Next API 请求指示完成。Lambda 在每个进程结束且没有挂起的事件时冻结执行环境。

Init 阶段

Extension init 阶段,每个扩展都需要注册到 Lambda 才能接收事件。Lambda 使用扩展的完整文件名来验证扩展是否已完成引导序列。因此,每个 Register API 调用都必须包含 Lambda-Extension-Name 标头以及扩展的完整文件名。

您最多可以为一个函数注册 10 个扩展。此限制通过 Register API 调用强制执行。

在每个扩展注册到 Lambda 后,Lambda 将启动 Runtime init 阶段。运行时进程调用 Init 函数以启动函数初始化阶段。

Init 阶段在运行时之后结束,每个注册的扩展通过发送 Next API 请求指示完成。

注意

扩展可以在 Init 阶段的任何时间点完成其初始化。

调用阶段

当调用 Lambda 函数来响应 Next API 请求时,Lambda 向运行时和为 Invoke 事件注册的每个扩展发送一个 Invoke 事件。

在调用过程中,外部扩展与函数并行运行。在函数完成后,它们也会继续运行。这使您能够捕获诊断信息,或将日志、指标和跟踪发送到您选择的位置。

Invoke 阶段在运行时之后结束,所有扩展都通过发送 Next API 请求来指示它们已完成。

事件负载

发送到每个扩展的事件包含描述事件内容的元数据。此生命周期事件包括事件的类型、剩余时间 RequestId、调用的函数 ARN 和跟踪标头。

发送到运行时(和 Lambda 函数)的事件包含整个请求、标头(如 RequestId)和负载。发送到每个扩展的事件包含描述事件内容的元数据。此生命周期事件包括事件的类型、剩余时间 RequestId、调用的函数 ARN 和跟踪标头。

希望访问函数事件主体的扩展可以使用与扩展进行通信的运行时开发工具包。在调用函数时,函数开发人员使用运行时开发工具包将负载发送到扩展。

以下是一个示例负载:

{ "eventType": "INVOKE", "deadlineMs": 676051, "requestId": "3da1f2dc-3222-475e-9205-e2e6c6318895", "invokedFunctionArn": "arn:aws:lambda:us-east-1:123456789012:function:ExtensionTest", "tracing": { "type": "X-Amzn-Trace-Id", "value": "Root=1-5f35ae12-0c0fec141ab77a00bc047aa2;Parent=2be948a625588e32;Sampled=1" } }

持续时间限制:函数的超时设置限制整个 Invoke 阶段的持续时间。例如,如果将函数超时设置为 360 秒,则该函数和所有扩展都需要在 360 秒内完成。请注意,没有独立的调用后阶段。持续时间是所有调用时间(运行时 + 扩展)的总和,直到函数和所有扩展完成执行之后才计算。

性能影响和扩展开销:扩展可能会影响函数性能。作为扩展作者,您可以控制扩展对性能的影响。例如,如果扩展执行计算密集型操作,那么函数的持续时间会增加,这是因为扩展和函数代码共用相同的 CPU 资源。此外,如果扩展在函数调用完成后执行大量操作,则函数持续时间会增加,因为 Invoke 阶段会持续,直到所有扩展指示它们都已完成。

为了帮助识别 Invoke 阶段上的扩展引起的开销,Lambda 输出 PostRuntimeExecutionDuration 指标。此指标衡量在运行时 Next API 请求与上次扩展 Next API 请求之间所花的累积时间。

您可以通过使用 PostRuntimeExecutionDuration 指标来衡量扩展添加到函数执行中的额外时间来评估扩展对性能的影响。要衡量所使用的内存增加量,请使用 MaxMemoryUsed 指标。有关函数指标的更多信息,请参阅使用 AWS Lambda 函数指标

函数开发人员可以并行运行不同版本的函数,以了解特定扩展的影响。我们建议扩展作者发布预期的资源消耗,以便函数开发人员更容易选择合适的扩展。

关闭阶段

当 Lambda 即将终止运行时时,它会向运行时发送 Shutdown 事件,然后将其发送给每个注册的外部扩展。扩展可以使用此时间执行最终清理任务。Shutdown 事件是为了响应 Next API 请求而发送的。

持续时间限制Shutdown 阶段的最长持续时间取决于已注册扩展的配置:

  • 300 毫秒 – 无注册扩展的函数。

  • 500 毫秒 – 带有注册的内部扩展的函数。

  • 2000 毫秒 – 具有一个或多个注册的外部扩展的函数。

对于具有外部扩展的函数,Lambda 为运行时进程保留最多 300 毫秒(对于具有内部扩展的运行时,则为 500 毫秒),以执行正常关闭。Lambda 为要关闭的外部扩展分配 2000 毫秒限制的剩余部分。

如果运行时或扩展没有在限制范围内响应 Shutdown 事件,则 Lambda 使用 SIGKILL 信号终止该进程。

事件负载Shutdown 事件包含关闭原因和剩余时间(以毫秒为单位)。

shutdownReason 包括以下值:

  • 降速 – 正常关机

  • 超时 – 持续时间限制超时

  • 失败 – 错误情况,例如 out-of-memory 事件

{ "eventType": "SHUTDOWN", "shutdownReason": "reason for shutdown", "deadlineMs": "time remaining in milliseconds" }

权限和配置

扩展在与 Lambda 函数相同的执行环境中运行。扩展还与函数共享资源,例如 CPU、内存和 /tmp 磁盘存储。此外,扩展使用与函数相同的 AWS Identity and Access Management (IAM) 角色和安全上下文。

文件系统和网络访问权限:扩展名在与函数运行时相同的文件系统和网络名称命名空间中运行。这意味着扩展需要与关联的操作系统兼容。如果扩展需要任何其他网络出口规则,则必须将这些规则应用于函数配置。

注意

因为函数代码目录是只读的,所以扩展无法修改函数代码。

环境变量:扩展可以访问函数的环境变量,但以下特定于运行时进程的变量除外:

  • AWS_EXECUTION_ENV

  • AWS_LAMBDA_LOG_GROUP_NAME

  • AWS_LAMBDA_LOG_STREAM_NAME

  • AWS_XRAY_CONTEXT_MISSING

  • AWS_XRAY_DAEMON_ADDRESS

  • LAMBDA_RUNTIME_DIR

  • LAMBDA_TASK_ROOT

  • _AWS_XRAY_DAEMON_ADDRESS

  • _AWS_XRAY_DAEMON_PORT

  • _HANDLER

故障处理

初始化失败:如果扩展失败,Lambda 会重新启动执行环境以强制执行一致的行为,并促使扩展快速失败。此外,对于某些客户来说,扩展必须满足日志记录、安全性、监管和遥测收集等关键任务需求。

调用失败 (例如内存不足、函数超时):由于扩展与运行时共享资源,因此它们受到内存耗尽的影响。当运行时失败时,所有扩展和运行时本身都会参与 Shutdown 阶段。此外,运行时可以作为当前调用的一部分自动重新启动,也可以通过延迟的重新初始化机制重新启动。

如果在 Invoke 期间出现故障(例如函数超时或运行时错误),Lambda 服务将执行重置。重置的行为类似于 Shutdown 事件。首先,Lambda 关闭运行时,然后向每个注册的外部扩展发送一个 Shutdown 事件。该事件包括关闭的原因。如果此环境用于新调用,则扩展和运行时将作为下一次调用的一部分重新初始化。

注意

Lambda 不会自动关闭反复失败的扩展。但是,Lambda 通过 Amazon CloudWatch 指标和日志报告这些错误,以便函数开发人员和扩展作者能够了解和诊断此类失败。

扩展日志:Lambda 将扩展的日志输出发送到 CloudWatch Logs。Lambda 还会在 Init 期间为每个扩展生成一个额外的日志事件。日志事件记录成功时的名称和注册首选项(事件、配置)或失败时的失败原因。

扩展故障排除

  • 如果 Register 请求失败,请确保 Register API 调用中的 Lambda-Extension-Name 标头包含扩展的完整文件名。

  • 如果 Register 请求对于内部扩展失败,请确保请求未注册 Shutdown 事件。

扩展 API 参考

扩展 API 版本 2020-01-01 的 OpenAPI 规范在此处提供:extensions-api.zip

您可以从 AWS_LAMBDA_RUNTIME_API 环境变量中检索 API 终端节点的值。要发送 Register 请求,请在每个 API 路径之前使用前缀 2020-01-01/。例如:

http://${AWS_LAMBDA_RUNTIME_API}/2020-01-01/extension/register

注册

Extension init 期间,所有扩展都需要注册到 Lambda 才能接收事件。Lambda 使用扩展的完整文件名来验证扩展是否已完成引导序列。因此,每个 Register API 调用都必须包含 Lambda-Extension-Name 标头以及扩展的完整文件名。

内部扩展由运行时进程启动和停止,因此不允许它们注册 Shutdown 事件。

路径/extension/register

方法POST

标头

Lambda-Extension-Name – 扩展名的完整文件名。必需:是。类型:字符串。

主体参数

events – 要注册的事件数组。必填:否。类型:字符串数组。有效字符串:INVOKESHUTDOWN

响应标头

  • Lambda-Extension-Identifier – 生成所有后续请求所需的唯一代理标识符(UUID 字符串)。

响应代码

  • 200 – 响应正文包含函数名称、函数版本和处理程序名称。

  • 400 – 错误请求

  • 403 – 禁止访问

  • 500 – 容器错误。不可恢复状态。扩展应立即退出。

响应示例

{ "functionName": "helloWorld", "functionVersion": "$LATEST", "handler": "lambda_function.lambda_handler" }

下一页

扩展发送 Next API 请求以接收下一个事件,此事件可以是 Invoke 事件或 Shutdown 事件。响应正文包含负载,该负载是包含事件数据的 JSON 文档。

扩展发送 Next API 请求,以表示它已准备好接收新事件。这是一个阻止性调用。

不要对 GET 调用设置超时,因为扩展可能暂停一段时间,直到存在要返回的事件。

路径/extension/event/next

方法GET

参数

Lambda-Extension-Identifier – 扩展的唯一标识符(UUID 字符串)。必需:是。类型:UUID 字符串。

响应标头

  • Lambda-Extension-Identifier – 唯一代理标识符(UUID 字符串)。

响应代码

  • 200 – 响应包含有关下一个事件(EventInvokeEventShutdown)的信息。

  • 403 – 禁止访问

  • 500 – 容器错误。不可恢复状态。扩展应立即退出。

Init 错误

扩展使用此方法向 Lambda 报告初始化错误。当扩展在注册后无法初始化时调用它。Lambda 收到错误后,没有进一步的 API 调用取得成功。扩展应退出。

路径/extension/init/error

方法POST

标头

Lambda-Extension-Identifier – 扩展名的唯一标识符。必需:是。类型:UUID 字符串。

Lambda-Extension-Function-Error-Type – 错误枚举。必需:是。类型:字符串错误枚举(例如,Fatal.ConnectFailed)。

主体参数

ErrorRequest – 包含错误类型、错误消息和堆栈跟踪的 JSON 对象。

响应正文

  • Lambda-Extension-Identifier – 唯一代理标识符(UUID 字符串)。

响应代码

  • 202 – 已接受

  • 400 – 错误请求

  • 403 – 禁止访问

  • 500 – 容器错误。不可恢复状态。扩展应立即退出。

退出错误

扩展使用此方法在退出前向 Lambda 报告错误。当您遇到意外故障时调用它。Lambda 收到错误后,没有进一步的 API 调用取得成功。扩展应退出。

路径/extension/exit/error

方法POST

标头

Lambda-Extension-Identifier – 扩展名的唯一标识符。必需:是。类型:UUID 字符串。

Lambda-Extension-Function-Error-Type – 错误枚举。必需:是。类型:字符串错误枚举(例如,Fatal.ConnectFailed)。

主体参数

ErrorRequest – 包含错误类型、错误消息和堆栈跟踪的 JSON 对象。

响应正文

  • Lambda-Extension-Identifier – 唯一代理标识符(UUID 字符串)。

响应代码

  • 202 – 已接受

  • 400 – 错误请求

  • 403 – 禁止访问

  • 500 – 容器错误。不可恢复状态。扩展应立即退出。