排查 Lambda 托管实例问题 - Amazon Lambda
Amazon Web Services 文档中描述的 Amazon Web Services 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅 中国的 Amazon Web Services 服务入门 (PDF)

排查 Lambda 托管实例问题

节流和扩缩问题

纵向扩展过程中错误率高

问题:当流量迅速增加时,您会遇到节流错误(HTTP 429)。

原因:Lambda 托管实例根据 CPU 资源利用率和多并发饱和状态进行异步扩展。如果您的流量在 5 分钟内增长超过一倍,您可能会在 Lambda 纵向扩展实例和执行环境以满足需求时看到节流出现。

解决方案:

  • 调整目标资源利用率:如果您的工作负载具有可预测的流量模式,则应设定较低的目标资源利用率,以便为流量突发留出更多的缓冲空间。

  • 预热容量:对于计划中的流量增加,请通过较长时间的逐步增加来实现流量的提升,以使扩展保持同步。

  • 监控扩展指标:跟踪节流错误指标,以了解节流和容量扩展问题的原因。

  • 查看函数配置:确保您的函数内存和 vCPU 设置支持多并发执行。如果需要,请增加函数内存或 vCPU 分配。

减慢缩减

问题:流量减少后,实例的缩减过程会持续很长时间。

原因:Lambda 托管实例会逐渐缩减,以保持可用性并避免可能影响性能的快速容量变化。

解决方案:

这是预料之中的行为。Lambda 会谨慎地缩减实例,以确保稳定性。监控您的 CloudWatch 指标,以跟踪正在运行的实例数量。

并发问题

具有低并发性的执行环境会出现节流情况

问题:尽管有可用容量,但您的函数仍会出现节流情况。

原因:具有极低最大并发量的执行环境可能难以实现有效扩展。Lambda 托管实例专为多并发应用程序而设计。

解决方案:

  • 提高最大并发数:如果您的函数调用所占用的 CPU 极少,可提高最大并发数设置至最高每个 vCPU 64 个。

  • 优化函数代码:查看您的函数代码,以降低每次调用时的 CPU 使用量,从而实现更高的并发性。

  • 调整函数内存和 vCPU:确保您的函数具备足够的资源来处理多个并发调用。

线程安全问题(Java 运行时)

问题:您的 Java 函数生成错误的结果或在负载下遭遇竞争条件。

原因:多个线程同时执行处理程序方法,且共享状态不具有线程安全性。

解决方案:

  • 使用 AtomicIntegerAtomicLong 替代基元类型作为计数器

  • HashMap 替换为 ConcurrentHashMap

  • 使用 Collections.synchronizedList() 来包装 ArrayList

  • ThreadLocal 用于特定于请求的状态

  • 从 Lambda 上下文对象访问跟踪 ID,而不是环境变量

有关详细指导,请参阅 Lambda 托管实例的 Java 运行时文档。

状态隔离问题(Node.js 运行时)

问题:您的 Node.js 函数会从不同的请求中返回数据,或者会出现数据损坏的情况。

原因:全局变量在同一工作线程的并发调用中被共享。当异步操作释放控制权时,其他调用可以修改共享状态。

解决方案:

  • 安装并将 @aws/lambda-invoke-store 用于所有特定于请求的状态

  • 将全局变量替换为 InvokeStore.set()InvokeStore.get()

  • /tmp 中使用带有请求 ID 的唯一文件名

  • 使用 InvokeStore.getXRayTraceId() 访问跟踪 ID,而不是环境变量

有关详细指导,请参阅 Lambda 托管实例的 Node.js 运行时文档。

文件冲突(Python 运行时)

问题:您的 Python 函数从 /tmp 中的文件中读取了错误的数据。

原因:多个进程共享 /tmp 目录。对同一文件进行并发写入操作可能会导致数据损坏。

解决方案:

  • 使用带有请求 ID 的唯一文件名:/tmp/request_{context.request_id}.txt

  • 将文件锁定与 fcntl.flock() 结合用于共享文件

  • 在使用后通过 os.remove() 清理临时文件

有关详细指导,请参阅 Lambda 托管实例的 Python 运行时文档。

性能问题

高内存利用率

问题:您的函数出现内存使用率过高或内存不足的问题。

原因:Python 中的每个并发请求都在单独的进程中运行,且拥有自己的内存空间。总内存使用量等于每个进程的内存占用量乘以并发进程数量。

解决方案:

  • 在 CloudWatch 中监控 MemoryUtilization 指标

  • 如果内存使用量接近函数的内存限制,请降低 MaxConcurrency 设置

  • 增加函数内存分配以支持更高的并发数

  • 通过按需加载数据而非在初始化时加载来优化内存使用情况

不一致的性能

问题:函数性能在不同的调用之间差异很大。

原因:Lambda 可能会根据可用性选择不同的实例类型,或者某些函数可能运行在资源可用性各不相同的实例上。

解决方案:

  • 指定允许的实例类型:如果您有特定的性能要求,请在容量提供程序中配置允许的实例类型,以限制 Lambda 可选择的实例类型。

  • 监控实例级别的指标:在容量提供程序级别进行跟踪 CPUUtilizationMemoryUtilization 以确定资源限制。

  • 查看容量指标:检查 vCPUAvailableMemoryAvailable 以确保您的实例上有足够的可用资源。

容量提供程序问题

函数版本未能变为 ACTIVE 状态

问题:您的函数版本发布后仍处于待处理状态。

原因:Lambda 正在启动托管实例并开启执行环境。此过程需要时间,特别是对于新容量提供程序上的第一个函数版本。

解决方案:

等待 Lambda 完成初始化过程。默认情况下,Lambda 会启动三个实例以实现可用区的容错功能,并在将您的函数版本标记为 ACTIVE 之前启动三个执行环境。这通常需要几分钟时间。

无法删除容量提供程序

问题:您在尝试删除容量提供程序时收到错误。

原因:您无法删除已附加了函数版本的容量提供程序。

解决方案:

  1. 使用 ListFunctionVersionsByCapacityProvider API 识别所有使用该容量提供程序的函数版本。

  2. 删除或更新这些函数版本,以解除容量提供程序的关联。

  3. 重新尝试删除容量提供程序。

发布函数过程中出现的一般错误消息

问题:发布函数时,您会遇到一般错误消息,例如“发布期间出现内部错误”。

解决方案:

  • 检查 IAM 权限:确保您对尝试使用的容量提供程序拥有 lambda:PassCapacityProvider 权限。

  • 验证容量提供程序配置:使用 GetCapacityProvider API 确认您的容量提供程序处于 ACTIVE 状态。

  • 查看 VPC 配置:确保您的容量提供程序中指定的子网和安全组配置正确且可访问。

  • 检查 Amazon CloudTrail 日志:查看 CloudTrail 日志,了解有关失败操作的详细错误信息。

监控和可观测性问题

CloudWatch 指标缺失

问题:您在 CloudWatch 中无法看到您的容量提供程序或函数所对应的预期指标。

原因:这些指标每隔 5 分钟发布一次。新的容量提供程序或函数可能无法立即提供指标。

解决方案:

发布函数版本后,至少等待 5 到 10 分钟,然后才能期望在 CloudWatch 中看到相关指标。请确认您查看的命名空间(AWS/Lambda)和维度(CapacityProviderNameFunctionNameInstanceType)是否正确。

找不到 CloudWatch 日志

问题:您的函数成功执行,但在 CloudWatch Logs 中找不到相关日志。

原因:Lambda 托管实例在您的 VPC 中运行,需要网络连接才能将日志发送至 CloudWatch Logs。如果没有正确的 VPC 连接配置,您的函数将无法连接到 CloudWatch Logs 服务端点。

解决方案:

配置 VPC 连接来让您的函数将日志发送到 CloudWatch Logs。您有三种选择:

选项 1:CloudWatch Logs 的 VPC 端点(建议用于生产环境)

  1. 通过 console.aws.amazon.com/vpc/ 打开 Amazon VPC 控制台。

  2. 在导航窗格中,选择端点

  3. 选择 创建端点

  4. 对于服务类别,选择 Amazon 服务

  5. 服务名称中,选择 com.amazonaws.region.logs(将 region 替换为您的 Amazon 区域)。

  6. 对于 VPC,请选择您的容量提供程序使用的 VPC。

  7. 对于子网,选择要在其中创建端点网络接口的子网。要获得高可用性,在多个可用区中选择子网。

  8. 对于安全组,请选择允许来自您函数安全组的入站 HTTPS 流量(端口 443)的安全组。

  9. 为端点启用私有 DNS

  10. 选择创建端点

选项 2:带有互联网网关的公有子网

如果您的容量提供程序使用公有子网,请确保:

  1. 互联网网关已连接到您的 VPC

  2. 路由表将 0.0.0.0/0 流量路由到互联网网关

  3. 安全组允许端口 443 上的出站 HTTPS 流量

选项 3:具有 NAT 网关的私有子网

如果您的容量提供程序使用私有子网,请确保:

  1. 公有子网中存在 NAT 网关

  2. 私有子网路由表将 0.0.0.0/0 流量路由到 NAT 网关

  3. 公有子网路由表将 0.0.0.0/0 流量路由到互联网网关

  4. 安全组允许端口 443 上的出站 HTTPS 流量

有关 VPC 连接选项的详细指南,请参阅 Lambda 托管实例的 VPC 连接

难以将来自并发请求的日志进行关联

问题:来自不同请求的日志是交错排列的,这使得难以跟踪具体的单个请求。

原因:在多并发系统中,日志的交错排列是预期且标准的行为。

解决方案:

  • 使用采用 JSON 格式的结构化日志记录:在所有日志语句中包含请求 ID

  • Java:将 Log4j 与 ThreadContext 配合使用以自动包含请求 ID

  • Node.js:使用采用 JSON 格式的 console.log() 并包含 InvokeStore.getRequestId()

  • Python:使用采用 JSON 格式的标准日志记录模块并包含 context.request_id

有关详细指导,请参阅特定于运行时的文档页面。

获得更多帮助

如果您在尝试这些解决方案后仍然遇到问题:

  1. 查看 CloudWatch 指标:检查容量提供程序和执行环境指标,以确定资源限制或扩展问题。

  2. 检查 Amazon CloudTrail 日志:查看 CloudTrail 日志,了解有关 API 调用和错误的详细错误信息。

  3. 联系 Amazon Support:如果您无法解决问题,请联系 Amazon Support,提供有关您的容量提供程序配置、函数配置以及您遇到的具体错误消息的详细信息。

后续步骤