

# 排查 Lambda 中的问题
<a name="lambda-troubleshooting"></a>

以下主题为您在使用 Lambda API、控制台或工具时可能遇到的错误和问题提供故障排除建议。如果您发现某个问题未在此处列出，可以使用此页上的 **Feedback** 按钮来报告。

有关更多故障排除建议和常见支持问题的答案，请访问[AWS知识中心](https://aws.amazon.com/premiumsupport/knowledge-center/#AWS_Lambda)。

有关对 Lambda 应用程序进行调试和故障排除的更多信息，请参阅 Serverless Land 中的 [Debugging](https://serverlessland.com/content/service/lambda/guides/aws-lambda-operator-guide/debugging-ops)。

**Topics**
+ [排查 Lambda 中的配置问题](troubleshooting-configuration.md)
+ [Lambda 中的部署问题疑难解答](troubleshooting-deployment.md)
+ [Lambda 中的调用问题疑难解答](troubleshooting-invocation.md)
+ [Lambda 中的执行问题疑难解答](troubleshooting-execution.md)
+ [排查 Lambda 中的事件源映射问题](troubleshooting-event-source-mapping.md)
+ [Lambda 中的联网问题疑难解答](troubleshooting-networking.md)

# 排查 Lambda 中的配置问题
<a name="troubleshooting-configuration"></a>

您的函数配置设置可能会影响 Lambda 函数的整体性能和行为。这些可能不会导致实际的函数错误，但可能会导致意外的超时和结果。

以下主题为您可能遇到的与 Lambda 函数配置设置相关的常见问题提供问题排查建议。

**Topics**
+ [内存配置](#memory-config)
+ [CPU 受限配置](#cpu-bound-config)
+ [超时](#timeouts)
+ [两次调用之间的内存泄漏](#memory-leakage)
+ [返回给以后调用的异步结果](#asynchronous-results)

## 内存配置
<a name="memory-config"></a>

您可以将 Lambda 函数配置为使用 128 MB 与 10240 MB 之间的内存。默认情况下，为在控制台中创建的任何函数都分配了最小量的内存。在此最低设置下，许多 Lambda 函数的性能都很高。但是，如果您要导入大型代码库或完成内存密集型任务，128 MB 是不够的。

如果函数的运行速度比预期慢得多，则第一步是增加内存设置。对于内存受限函数，这将解决瓶颈问题，且可以提高函数性能。

## CPU 受限配置
<a name="cpu-bound-config"></a>

对于计算密集型操作，如果您的函数性能低于预期，则这可能是由于您的函数受 CPU 限制。在这种情况下，函数的计算能力无法跟上工作进度。

虽然 Lambda 不允许您直接修改 CPU 配置，但 CPU 是通过内存设置间接控制。当您分配更多内存时，Lambda 服务会按比例分配更多虚拟 CPU。内存为 1.8 GB 时，Lambda 函数会分配整个 vCPU，而在此级别以上，它可以访问多个 vCPU 核心。在 10240 MB 时，有 6 个可用的 vCPU。也就是说，即使函数没有使用所有内存，您也可以通过增加内存分配来提高性能。

## 超时
<a name="timeouts"></a>

 Lambda 函数的[超时](https://docs.aws.amazon.com/lambda/latest/dg/configuration-console.html)可以设置为 1 到 900 秒（15 分钟）。默认情况下，Lambda 控制台会将该值设置为 3 秒。超时值是一个安全阀，可确保函数不会无限期运行。达到超时值后，Lambda 会停止函数调用。

如果将超时值设置得接近函数的平均持续时间，则会增加函数意外超时的风险。函数的持续时间可能因数据传输和处理量以及与该函数交互的任何服务的延迟而不同。导致超时的常见原因包括：
+ 从 S3 存储桶或其他数据存储下载数据时，下载量会比平均值更大或花费更长时间。
+ 一个函数向另一项服务发出请求，这需要更长的时间才能响应。
+ 提供给函数的参数要求函数具有更高的计算复杂度，这会导致调用花费更长的时间。

在测试应用程序时，请确保您的测试准确反映数据的大小和数量以及真实的参数值。重要的是，可在您的工作负载合理预期值的上限使用数据集。

此外，在可行的情况下，可对工作负载实施上限限制。在本示例中，应用程序可以对每种文件类型使用最大大小限制。然后，您可以针对一系列的预期文件大小（达到并包括最大限制）来测试应用程序的性能。

## 两次调用之间的内存泄漏
<a name="memory-leakage"></a>

Lambda 调用的 INIT 阶段中存储的全局变量和对象在暖调用之间保留其状态。只有在执行环境首次运行时（也称为“冷启动”），它们才会完全重置。处理程序退出时，存储在处理程序中的任何变量都会销毁。最佳实践是使用 INIT 阶段来设置数据库连接、加载库、创建缓存和加载不可变资产。

在同一执行环境中跨多个调用使用第三方库时，请查看其文档以了解在无服务器计算环境中的使用情况。某些数据库连接和日志记录库可能会保存中间调用结果和其他数据。这会导致这些库的内存使用量随着随后的暖调用而增长。在此情况下，即使您的自定义代码正确处理了变量，您也可能会发现 Lambda 函数的内存不足。

此问题会影响在暖执行环境中发生的调用。例如，以下代码会在两次调用之间产生内存泄漏。Lambda 函数通过增加全局数组的大小，每次调用都会占用额外的内存：

```
let a = []

exports.handler = async (event) => {
    a.push(Array(100000).fill(1))
}
```

配置了 128 MB 内存，在调用此函数 1000 次后，Lambda 函数的**监控**选项卡会显示在发生内存泄漏时调用、持续时间和错误计数的典型变化：

![\[调试操作图 4\]](http://docs.aws.amazon.com/zh_cn/lambda/latest/dg/images/debugging-ops-figure-4.png)


1.  **调用** – 由于调用需要更长时间才能完成，因此会定期中断稳定的事务速率。在稳定状态期间，内存泄漏不会使用函数分配的所有内存。随着性能下降，操作系统会对本地存储进行分页以适应函数所需的不断增长的内存，从而减少要完成的事务量。

1.  **持续时间** – 在函数的内存不足之前，它会以稳定的两位数毫秒速率完成调用。随着分页的发生，持续时间会延长一个数量级。

1.  **错误计数** – 由于内存泄漏超出分配的内存，最终函数因计算超出超时值而出错，或者执行环境停止该函数。

错误发生后，Lambda 会重新启动执行环境，这解释了为什么所有三个图表都显示恢复到原始状态。扩展 CloudWatch 持续时间指标可提供最短、最大和平均持续时间统计数据的更多详细信息：

![\[调试操作图 5\]](http://docs.aws.amazon.com/zh_cn/lambda/latest/dg/images/debugging-ops-figure-5.png)


要查找在 1000 次调用中所生成的错误，您可以使用 CloudWatch Insights 查询语言。以下查询排除信息日志，以仅报告错误：

```
fields @timestamp, @message
| sort @timestamp desc
| filter @message not like 'EXTENSION'
| filter @message not like 'Lambda Insights'
| filter @message not like 'INFO' 
| filter @message not like 'REPORT'
| filter @message not like 'END'
| filter @message not like 'START'
```

针对此函数的日志组运行时，这表明超时是造成周期性错误的原因：

![\[调试操作图 6\]](http://docs.aws.amazon.com/zh_cn/lambda/latest/dg/images/debugging-ops-figure-6.png)


## 返回给以后调用的异步结果
<a name="asynchronous-results"></a>

对于使用异步模式的函数代码，一次调用的回调结果可能会在未来调用中返回。此示例使用 Node.js，但相同逻辑可以应用于使用异步模式的其他运行时。该函数使用 JavaScript 中传统的回调语法。它调用一个带有增量计数器的异步函数，用于跟踪调用次数：

```
let seqId = 0

exports.handler = async (event, context) => {
    console.log(`Starting: sequence Id=${++seqId}`)
    doWork(seqId, function(id) {
        console.log(`Work done: sequence Id=${id}`)
    })
}

function doWork(id, callback) {
    setTimeout(() => callback(id), 3000)
}
```

连续多次调用时，回调的结果会出现在后续调用中：

![\[调试操作图 7\]](http://docs.aws.amazon.com/zh_cn/lambda/latest/dg/images/debugging-ops-figure-7.png)


1. 代码调用 `doWork` 函数，提供回调函数作为最后一个参数。

1. 在调用回调之前，`doWork` 函数需要一段时间来完成。

1. 该函数的日志记录表明调用将在 `doWork` 函数完成执行之前结束。此外，在开始迭代之后，将处理先前迭代的回调，如日志所示。

在 JavaScript 中，异步回调通过[事件循环](https://developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop)处理。其他运行时使用不同的机制来处理并发。函数的执行环境结束时，Lambda 会冻结环境，直到下次调用。恢复后，JavaScript 会继续处理事件循环，在这种情况下包括来自先前调用的异步回调。如果没有此上下文，则该函数可能会无缘无故地运行代码，并返回任意数据。事实上，它实际上是运行时并发和执行环境如何交互的构件。

这使得前一次调用的私有数据有可能出现在后续调用中。有两种方法可防止或检测此行为。首先，JavaScript 提供了 [async 和 await 关键字](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function)来简化异步开发，还强制代码执行等待异步调用完成。可以使用此方法重写上面的函数，如下所示：

```
let seqId = 0
exports.handler = async (event) => {
    console.log(`Starting: sequence Id=${++seqId}`)
    const result = await doWork(seqId)
    console.log(`Work done: sequence Id=${result}`)
}

function doWork(id) {
  return new Promise(resolve => {
    setTimeout(() => resolve(id), 4000)
  })
}
```

使用此语法可防止处理程序在异步函数完成之前退出。在这种情况下，如果回调的时间超过 Lambda 函数的超时时间，则该函数将引发错误，而不是在以后的调用中返回回调结果：

![\[调试操作图 8\]](http://docs.aws.amazon.com/zh_cn/lambda/latest/dg/images/debugging-ops-figure-8.png)


1. 该代码在处理程序中使用 await 关键字调用异步 `doWork` 函数。

1. 在解析 promise 之前，`doWork` 函数需要一段时间才能完成。

1. 该函数超时，因为 `doWork` 花费的时间超过了超时限制允许的时间，并且在以后的调用中不会返回回调结果。

通常，您应确保代码中的任何后台进程或回调在代码退出前已完成。如果在您的使用案例中无法做到这一点，您可以使用标识符来确保回调属于当前调用。为此，您可以使用上下文对象所提供的 *awsRequestId*。通过将此值传递给异步回调，您可以将传递的值与当前值进行比较，以检测回调是否来自另一个调用：

```
let currentContext

exports.handler = async (event, context) => {
    console.log(`Starting: request id=$\{context.awsRequestId}`)
    currentContext = context

    doWork(context.awsRequestId, function(id) {
        if (id != currentContext.awsRequestId) {
            console.info(`This callback is from another invocation.`)
        }
    })

}

function doWork(id, callback) {
    setTimeout(() => callback(id), 3000)

}
```

![\[调试操作图 9\]](http://docs.aws.amazon.com/zh_cn/lambda/latest/dg/images/debugging-ops-figure-9.png)


1. Lambda 函数处理程序取用上下文参数，该参数提供对唯一调用请求 ID 的访问权限。

1. 将 `awsRequestId` 传递给 doWork 函数。在回调中，将 ID 与当前调用的 `awsRequestId` 进行比较。如果这些值不同，则代码可以相应地采取行动。

# Lambda 中的部署问题疑难解答
<a name="troubleshooting-deployment"></a>

更新函数时，Lambda 使用更新的代码或设置来启动函数的新实例，从而部署更改。部署错误会阻止新版本的使用，并可能由于部署程序包、代码、权限或工具中的问题而引起。

当您使用 Lambda API 或客户端（如 AWS CLI）将更新直接部署到函数时，您可以直接在输出中查看 Lambda 中的错误。如果您使用 AWS CloudFormation、AWS CodeDeploy 或 AWS CodePipeline 等服务，请在该服务的日志或事件流中查找来自 Lambda 的响应。

以下主题为您在使用 Lambda API、控制台或工具时可能遇到的错误和问题提供故障排除建议。如果您发现某个问题未在此处列出，可以使用此页上的 **Feedback** 按钮来报告。

有关更多故障排除建议和常见支持问题的答案，请访问[AWS知识中心](https://aws.amazon.com/premiumsupport/knowledge-center/#AWS_Lambda)。

有关对 Lambda 应用程序进行调试和故障排除的更多信息，请参阅 Serverless Land 中的 [Debugging](https://serverlessland.com/content/service/lambda/guides/aws-lambda-operator-guide/debugging-ops)。

**Topics**
+ [常规：权限被拒绝/无法加载此类文件](#troubleshooting-deployment-denied)
+ [常规：调用 UpdateFunctionCode 时出错](#troubleshooting-deployment-updatefunctioncode)
+ [Amazon S3：错误代码 PermanentRedirect。](#troubleshooting-deployment-PermanentRedirect)
+ [常规：找不到、无法加载、无法导入、找不到类、没有此类文件或目录](#troubleshooting-deployment-functionHandler1)
+ [常规：未定义的方法处理程序](#troubleshooting-deployment-functionHandler2)
+ [常规：超出 Lambda 代码存储限制](#troubleshooting-deployment-CodeStorageExceeded)
+ [Lambda：图层转换失败](#troubleshooting-deployment-LayerConversionFailed)
+ [Lambda：InvalidParameterValueException or RequestEntityTooLargeException](#troubleshooting-deployment-InvalidParameterValueException1)
+ [Lambda：InvalidParameterValueException](#troubleshooting-deployment-InvalidParameterValueException2)
+ [Lambda：并发和内存限额](#troubleshooting-deployment-quotas)
+ [Lambda：预置并发的别名配置无效](#troubleshooting-deployment-provisioned-concurrency)

## 常规：权限被拒绝/无法加载此类文件
<a name="troubleshooting-deployment-denied"></a>

**错误：***EACCES: permission denied, open '/var/task/index.js'*（EACCES: 权限被拒绝，打开“/var/task/index.js”）

**错误：***cannot load such file -- function*（无法加载此文件 – 函数）

**错误：***[Errno 13] Permission denied: '/var/task/function.py'*（[Errno 13] 权限被拒绝:“/var/task/function.py”）

Lambda 运行时需要权限才能读取部署包中的文件。在 Linux 权限八进制表示法中，Lambda 对于不可执行文件（rw-r--r--）需要 644 个权限，对于目录和可执行文件需要 755 个权限（rwxr-xr-x）。

在 Linux 和 MacOS 中，使用 `chmod` 命令更改部署包中文件和目录的文件权限。例如，要为不可执行文件提供正确的权限，请运行以下命令。

```
chmod 644 <filepath>
```

要在 Windows 中更改文件权限，请参阅 Microsoft Windows 文档中的 [Set, View, Change, or Remove Permissions on an Object](https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2008-R2-and-2008/cc731667(v=ws.10))。

**注意**  
如果您不向 Lambda 授予访问部署包中目录所需的权限，Lambda 会将这些目录的权限设置为 755（rwxr-xr-x）。

## 常规：调用 UpdateFunctionCode 时出错
<a name="troubleshooting-deployment-updatefunctioncode"></a>

**错误：***An error occurred (RequestEntityTooLargeException) when calling the UpdateFunctionCode operation*（在调用 UpdateFunctionCode 操作时出错 (RequestEntityTooLargeException)）

在将部署包或层归档直接上载到 Lambda 时，ZIP 文件的大小最多为 50 MB。要上载一个较大的文件，请将此文件存储在 Amazon S3 中并使用 S3Bucket 和 S3Key 参数。

**注意**  
当您直接使用 AWS CLI、AWS 开发工具包或通过其他方式上传文件时，二进制 ZIP 文件将转换为 base64，其大小将增加约 30%。为了支持这一点以及请求中其他参数的大小，Lambda 应用的实际请求大小限制会更大。因此，50 MB 的限制是近似值。

## Amazon S3：错误代码 PermanentRedirect。
<a name="troubleshooting-deployment-PermanentRedirect"></a>

**错误：***Error occurred while GetObject.（GetObject 时发生错误。） S3 错误代码：PermanentRedirect。S3 错误消息：存储桶位于此区域中：us-east-2。请使用此区域重试请求*

当您从 Amazon S3 存储桶上载函数的部署包时，存储桶必须与函数位于同一区域。当您在 [UpdateFunctionCode](https://docs.aws.amazon.com/lambda/latest/api/API_UpdateFunctionCode.html) 调用中指定 Amazon S3 对象或在 AWS CLI 或 AWS SAM CLI 中使用程序包并部署命令时，可能会出现此问题。为您在其中开发应用程序的每个区域创建部署构件存储桶。

## 常规：找不到、无法加载、无法导入、找不到类、没有此类文件或目录
<a name="troubleshooting-deployment-functionHandler1"></a>

**错误：***找不到模块“function”*

**错误：***cannot load such file -- function*（无法加载此文件 – 函数）

**错误：***无法导入模块“function”*

**错误：***找不到类：function.Handler*

**错误：***fork/exec/var/task/function：没有这样的文件或目录*

**错误：***无法从程序集“Function”加载类型“Function.Handler”。*

函数处理程序配置中文件或类的名称与您的代码不匹配。有关更多信息，请参阅下文的 部分。

## 常规：未定义的方法处理程序
<a name="troubleshooting-deployment-functionHandler2"></a>

**错误：***index.handler 未定义或未导出*

**错误：***模块“function”上缺少处理程序“handler”*

**错误：***undefined method `handler' for \$1<LambdaHandler:0x000055b76ccebf98>*（\$1<LambdaHandler:0x000055b76ccebf98> 的未定义的方法“handler”）

**错误：***在类 function.Handler 上没有找到具有正确方法签名的名为 handleRequest 的公共方法。*

**错误：***Unable to find method 'handleRequest' in type 'Function.Handler' from assembly 'Function'*（无法从程序集“Function”的类型“Function.Handler”中找到方法“handleRequest”）

函数处理程序配置中的处理程序方法的名称与您的代码不匹配。每个运行时为处理程序定义一个命名约定，例如 *filename*.*methodname*。处理程序是函数代码中的方法，在调用函数时由运行时运行该方法。

对于某些语言，Lambda 提供了包含接口的库，该接口需要具有特定名称的处理程序方法。有关每种语言的处理程序命名的详细信息，请参阅以下主题。
+ [使用 Node.js 构建 Lambda 函数](lambda-nodejs.md)
+ [使用 Python 构建 Lambda 函数](lambda-python.md)
+ [使用 Ruby 构建 Lambda 函数](lambda-ruby.md)
+ [使用 Java 构建 Lambda 函数](lambda-java.md)
+ [使用 Go 构建 Lambda 函数](lambda-golang.md)
+ [使用 C\$1 构建 Lambda 函数](lambda-csharp.md)
+ [使用 PowerShell 构建 Lambda 函数](lambda-powershell.md)

## 常规：超出 Lambda 代码存储限制
<a name="troubleshooting-deployment-CodeStorageExceeded"></a>

**错误：***超出代码存储限制。*

Lambda 将函数代码存储在您账户私有的内部 S3 存储桶中。每个 AWS 账户在每个区域分配 75 GB 存储空间。代码存储包括 Lambda 函数和层使用的总存储空间。如果您达到配额，在尝试部署新函数时会收到 *CodeStorageExceededException*。

通过清理旧版本的函数、删除未使用的代码或使用 Lambda 层来管理可用的存储空间。此外，最好[为单独的工作负载使用单独的 AWS 账户](concepts-application-design.md#multiple-accounts)来帮助管理存储配额。

您可以在 Lambda 控制台的**控制面板**子菜单下查看总存储使用量：

![\[监控可观测性图 26\]](http://docs.aws.amazon.com/zh_cn/lambda/latest/dg/images/monitoring-observability-figure-26.png)




## Lambda：图层转换失败
<a name="troubleshooting-deployment-LayerConversionFailed"></a>

**错误：***Lambda 图层转换失败。有关解决此问题的建议，请参阅《Lambda 用户指南》中的“排查 Lambda 中的部署问题”页面。*

当您使用图层配置 Lambda 函数时，Lambda 会将该层与您的函数代码合并。如果此过程无法完成，Lambda 会返回此错误。如果遭遇此错误，请执行以下步骤：
+ 从图层中删除所有未使用的文件
+ 删除图层中的所有符号链接
+ 重命名任何与函数层中目录同名的文件

## Lambda：InvalidParameterValueException or RequestEntityTooLargeException
<a name="troubleshooting-deployment-InvalidParameterValueException1"></a>

**错误：***InvalidParameterValueException: Lambda was unable to configure your environment variables because the environment variables you have provided exceeded the 4KB limit.（InvalidParameterValueException：Lambda 无法配置您的环境变量，因为您提供的环境变量超过了 4KB 限制。） 测量的字符串：\$1"A1":"uSFeY5cyPiPn7AtnX5BsM...*

**错误：***RequestEntityTooLargeException：对 UpdateFunctionConfiguration 操作的请求必须小于 5120 字节*

存储在函数配置中的变量对象的最大体积不得超过 4096 个字节。这包括密钥名称、值、引号、逗号和括号。HTTP 请求正文的总大小也受到限制。

```
{
    "FunctionName": "my-function",
    "FunctionArn": "arn:aws:lambda:us-east-2:123456789012:function:my-function",
    "Runtime": "nodejs24.x",
    "Role": "arn:aws:iam::123456789012:role/lambda-role",
    "Environment": {
        "Variables": {
            "BUCKET": "amzn-s3-demo-bucket",
            "KEY": "file.txt"
        }
    },
    ...
}
```

在此示例中，对象为 39 个字符，并且它在存储（不含空格）为字符串 `{"BUCKET":"amzn-s3-demo-bucket","KEY":"file.txt"}` 时占用 39 个字节。环境变量值中的每个标准 ASCII 字符使用一个字节。每个扩展 ASCII 和 Unicode 字符可以使用 2 到 4 个字节。

## Lambda：InvalidParameterValueException
<a name="troubleshooting-deployment-InvalidParameterValueException2"></a>

**错误：***InvalidParameterValueException: Lambda 无法配置您的环境变量，因为您提供的环境变量包含目前不支持修改的保留键。*

Lambda 会预留一些环境变量键供内部使用。例如，运行时使用 `AWS_REGION` 来确定当前区域且它不能被覆盖。运行时使用其他变量（如 `PATH`），但这些变量可以在函数配置中扩展。有关完整列表，请参阅[定义运行时环境变量](configuration-envvars.md#configuration-envvars-runtime)。

## Lambda：并发和内存限额
<a name="troubleshooting-deployment-quotas"></a>

**Error:*** Specified ConcurrentExecutions for function decreases account's UnreservedConcurrentExecution below its minimum value*（错误：为函数指定的 ConcurrentExecutions 会导致账户的 UnreservedConcurrentExecution 降至其最小值以下）

**Error:*** 'MemorySize' value failed to satisfy constraint: Member must have value less than or equal to 3008*（错误：“内存大小”值不满足约束条件：成员的值必须小于或等于 3008）

超出您账户的并发或内存[限额](gettingstarted-limits.md)时，就会出现这些错误。新的 AWS 账户减少了并发和内存配额。若要解决与并发相关的错误，您可以[请求增加配额](https://docs.aws.amazon.com/servicequotas/latest/userguide/request-quota-increase.html)。您无法请求增加配额。
+ **并发：**如果您尝试使用预留或预配置并发创建函数，或者如果您的每函数并发请求（[PutFunctionConcurrency](https://docs.aws.amazon.com/lambda/latest/api/API_PutFunctionConcurrency.html)）超出您账户的并发限额，则可能会收到错误。
+ **内存：**如果分配给函数的内存量超过您账户的内存限额，则会出现错误。

## Lambda：预置并发的别名配置无效
<a name="troubleshooting-deployment-provisioned-concurrency"></a>

**错误：***预置并发的别名配置无效*

当您尝试更新 Lambda 函数的代码或配置，而具有预置并发的别名指向存在问题的版本时，就会发生这种错误。Lambda 会预先为预置并发初始化执行环境，如果这些环境由于代码错误、资源限制或受影响的堆栈和别名而无法正确初始化，则部署将失败。如果遭遇此问题，请执行以下步骤：

1. **回滚别名：**临时更新别名指向之前正常工作的版本。

   ```
    aws lambda update-alias \
     --function-name <function-name> \
     --name <alias-name> \
     --function-version <known-good-version>
   ```

1. **修复 Lambda 初始化代码：**确保在处理程序外运行的初始化代码没有任何未捕获的异常，并初始化客户端和连接。

1. **重新部署安全：**部署固定的代码并发布新版本。然后，更新别名指向固定版本。（可选）必要时可重新启用[预置并发](provisioned-concurrency.md)。

如果使用 AWS CloudFormation，请更新堆栈定义 `FunctionVersion:!GetAtt version.Version`，使别名指向正常工作的版本：

```
alias:
 Type: AWS::Lambda::Alias
 Properties:
 FunctionName: !Ref function
FunctionVersion: !GetAtt version.Version
 Name: BLUE
 ProvisionedConcurrencyConfig:
 ProvisionedConcurrentExecutions: 1
```

# Lambda 中的调用问题疑难解答
<a name="troubleshooting-invocation"></a>

当您调用 Lambda 函数时，Lambda 在将事件发送到函数或（对于异步调用）发送到事件队列之前，先验证请求并检查扩展容量。调用错误可能是由请求参数、事件结构、函数设置、用户权限、资源权限或限制中的问题引起的。

如果您直接调用函数，则会在 Lambda 的响应中看到所有调用错误。如果您使用事件源映射或通过其他服务异步调用函数，则可能会在日志、死信队列或失败事件目标中找到错误。错误处理选项和重试行为因调用函数的方式和错误类型而异。

有关 `Invoke` 操作可以返回的错误类型的列表，请参阅 [Invoke](https://docs.aws.amazon.com/lambda/latest/api/API_Invoke.html)（调用）。

**Topics**
+ [Lambda：函数在初始化阶段超时 (Sandbox.Timedout)](#troubleshooting-timeouts)
+ [IAM：lambda:InvokeFunction 未授权](#troubleshooting-invocation-noauth)
+ [Lambda：无法找到有效的引导程序 (Runtime.InvalidEntrypoint)](#troubleshooting-invocation-bootstrap)
+ [Lambda：无法执行操作 ResourceConflictException](#troubleshooting-invocation-ResourceConflictException)
+ [Lambda：函数卡在待处理状态](#troubleshooting-invocation-pending)
+ [Lambda：某个函数正在使用所有并发](#troubleshooting-invocation-allconcurrency)
+ [常规：无法使用其他账户或服务调用函数](#troubleshooting-invocation-cannotinvoke)
+ [常规：函数调用正在循环](#troubleshooting-invocation-loop)
+ [Lambda：预置并发的别名路由](#troubleshooting-invocation-alias)
+ [Lambda：预置并发导致的冷启动](#troubleshooting-invocation-coldstart)
+ [Lambda：新版本的冷启动问题](#troubleshooting-invocation-newversion)
+ [Lambda：运行时出现意外的 Node.js 退出情况（Runtime.NodejsExit）](#troubleshooting-invocation-nodejs-exit)
+ [EFS：函数无法挂载 EFS 文件系统](#troubleshooting-invocation-efsmount)
+ [EFS：函数无法连接到 EFS 文件系统](#troubleshooting-invocation-efsconnect)
+ [EFS：由于超时，函数无法挂载 EFS 文件系统](#troubleshooting-invocation-efstimeout)
+ [Lambda：Lambda 检测到某一 IO 进程耗时过长](#troubleshooting-invocation-ioprocess)
+ [容器：CodeArtifactUserException 错误](#troubleshooting-deployment-container-artifact)
+ [容器：InvalidEntrypoint 错误](#troubleshooting-deployment-container-entrypoint)

## Lambda：函数在初始化阶段超时 (Sandbox.Timedout)
<a name="troubleshooting-timeouts"></a>

 **错误：***任务在 3.00 秒后超时* 

如果 [Init](lambda-runtime-environment.md#runtimes-lifecycle-ib) 阶段超时，Lambda 会在下一个调用请求到达时重新运行 `Init` 阶段，以便再次初始化执行环境。此情况称为[隐藏初始化](lambda-runtime-environment.md#suppressed-init)。不过，如果函数配置了较短的[超时时间](configuration-timeout.md)（通常在 3 秒左右），被抑制的初始化可能无法在分配的超时时间内完成，导致 `Init` 阶段再次超时。另一种情况是，被抑制的初始化已完成，但没有留出足够时间让 [Invoke](lambda-runtime-environment.md#runtimes-lifecycle-invoke) 阶段完成，导致 `Invoke` 阶段超时。

要减少超时错误，请使用下列一项或多项策略：
+ **延长函数超时时间**：延长[超时](configuration-timeout.md)时间，让 `Init` 和`Invoke` 阶段有时间成功完成。
+ **增加函数内存分配**：[内存](configuration-memory.md)越多意味着 CPU 分配也会成比例增加，而这可以加快 `Init` 和 `Invoke` 阶段的完成速度。
+ **优化函数初始化代码**：缩短初始化所需的时间，确保 `Init` 和 `Invoke` 阶段可以在配置的超时时间内完成。

## IAM：lambda:InvokeFunction 未授权
<a name="troubleshooting-invocation-noauth"></a>

 **错误：***User: arn:aws:iam::123456789012:user/developer is not authorized to perform: lambda:InvokeFunction on resource: my-function*（用户: arn:aws:iam::123456789012:user/developer 未获得授权，无法对资源执行 lambda:InvokeFunction: my-function） 

您的用户或您代入的角色必须具有调用函数的权限。此要求还适用于 Lambda 函数以及其他调用函数的计算资源。将 AWS 托管式策略 **AWSLambdaRole** 添加到用户或添加允许对目标函数执行 `lambda:InvokeFunction` 操作的自定义策略。

**注意**  
IAM 操作的名称 (`lambda:InvokeFunction`) 指的是 `Invoke` Lambda API 操作。

有关更多信息，请参阅 [在 AWS Lambda 中管理权限](lambda-permissions.md)。

## Lambda：无法找到有效的引导程序 (Runtime.InvalidEntrypoint)
<a name="troubleshooting-invocation-bootstrap"></a>

 **错误：***无法找到有效的引导程序：[/var/task/bootstrap /opt/bootstrap]* 

当部署包的根目录不包含名为 `bootstrap` 的可执行文件时，通常会发生此错误。例如，如果使用 .zip 文件部署函数 `provided.al2023`，则 `bootstrap` 文件必须位于 .zip 文件的根目录下，而不是目录中。

## Lambda：无法执行操作 ResourceConflictException
<a name="troubleshooting-invocation-ResourceConflictException"></a>

 **错误：***ResourceConflictException: The operation cannot be performed at this time.（ResourceConflictException：此时无法执行该操作。） 该函数目前处于以下状态：待定* 

如果在创建时将函数连接到 Virtual Private Cloud (VPC)，则该函数会在 Lambda 创建弹性网络接口时进入 `Pending` 状态。在此期间，您无法调用或修改函数。如果您在创建后将函数连接到 VPC，则可以在更新处于待处理状态时调用该函数，但无法修改其代码或配置。

有关更多信息，请参阅 [Lambda 函数状态](functions-states.md)。

## Lambda：函数卡在待处理状态
<a name="troubleshooting-invocation-pending"></a>

 **错误：***A function is stuck in the `Pending` state for several minutes.*（一个函数卡在待处理状态达几分钟。） 

如果某个函数卡在 `Pending` 状态超过六分钟，请调用以下 API 操作之一来取消阻止它。
+ [UpdateFunctionCode](https://docs.aws.amazon.com/lambda/latest/api/API_UpdateFunctionCode.html)
+ [UpdateFunctionConfiguration](https://docs.aws.amazon.com/lambda/latest/api/API_UpdateFunctionConfiguration.html)
+ [PublishVersion](https://docs.aws.amazon.com/lambda/latest/api/API_PublishVersion.html)

Lambda 取消处于暂停状态的操作并将函数置于 `Failed` 状态。然后，您可以尝试另一次更新。

## Lambda：某个函数正在使用所有并发
<a name="troubleshooting-invocation-allconcurrency"></a>

 **问题：***一个函数使用了所有可用的并发，导致其他函数被限制。*

要将 AWS 区域中 AWS 账户的可用并发划分为池，请使用[预留并发](configuration-concurrency.md)。预留并发可确保函数始终可以扩展到向其分配的并发，并且不会扩展到向其分配的并发之外。

## 常规：无法使用其他账户或服务调用函数
<a name="troubleshooting-invocation-cannotinvoke"></a>

 **问题：***您可以直接调用您的函数，但是当另一个服务或账户调用它时，它不会运行。*

您向[其他服务](lambda-services.md)和账户授予权限以在函数的[基于资源的策略](access-control-resource-based.md)中调用函数。如果调用方是另一个账户，则该用户还必须具有[函数调用权限](access-control-identity-based.md)。

## 常规：函数调用正在循环
<a name="troubleshooting-invocation-loop"></a>

 **问题：***函数在循环中被连续调用。*

当您的函数在触发它的同一 AWS 服务中管理资源时，通常会发生这种情况。例如，可以创建一个函数来将对象存储在 Amazon Simple Storage Service (Amazon S3) 存储桶中，该存储桶配置了一个[再次调用函数的通知](with-s3.md)。要将函数停止运行，请将可用的[并发](lambda-concurrency.md)减少到零，以限制未来发生的所有调用。然后，确定导致递归调用的代码路径或配置错误。Lambda 会自动检测并停止某些 AWS 服务和 SDK 的递归循环。有关更多信息，请参阅 [使用 Lambda 递归循环检测来防止无限循环](invocation-recursion.md)。

## Lambda：预置并发的别名路由
<a name="troubleshooting-invocation-alias"></a>

 **问题：***在别名路由期间预配置的并发溢出调用。*

Lambda 使用简单的概率模型在两个函数版本之间分发流量。低流量级别情况下，您可能会看到每个版本上配置的流量百分比与实际流量百分比之间的差异很大。如果您的函数使用预置并发，则可以避免[溢出调用](monitoring-metrics-types.md#invocation-metrics)，方法是在别名路由处于活动状态期间配置更多的预置并发实例。

## Lambda：预置并发导致的冷启动
<a name="troubleshooting-invocation-coldstart"></a>

 **问题：***启用预置并发后，会发生冷启动。*

函数上的并发执行次数少于或等于[配置的预置并发级别](provisioned-concurrency.md)时，应该不会发生冷启动。要帮助您确认预置并发是否正常运行，请执行以下操作：
+  [检查是否在函数版本或别名上启用了预置并发](provisioned-concurrency.md)。
**注意**  
未发布[版本的函数](configuration-versions.md)（\$1LATEST）无法配置预置并发。
+ 确保触发器调用了正确的函数版本或别名。例如，如果您正在使用 Amazon API Gateway，检查确认是 API Gateway 在使用预置并发调用函数版本或别名，而非 \$1LATEST。要确认是否使用了预置并发，您可以检查 [ProvisionedConcurrencyInvocations Amazon CloudWatch 指标](monitoring-concurrency.md#provisioned-concurrency-metrics)。非零值表示函数正在初始化的执行环境中处理调用。
+ 通过检查 [ProvisionedConcurrencySpilloverInvocations Amazon CloudWatch](monitoring-concurrency.md#provisioned-concurrency-metrics) 指标来确定您的函数并发是否超出了配置的预置并发级别。非零值表示所有预置并发都处于使用状态，且在冷启动时发生了部分调用。
+ 检查[调用频率](gettingstarted-limits.md#api-requests)（每秒请求数）。具有预置并发的函数每个预置并发的最大速率为每秒 10 个请求。例如，配置了 100 个预置并发的函数可以每秒处理 1000 个请求。如果调用速率超过每秒 1000 个请求，则可能会发生部分冷启动。

## Lambda：新版本的冷启动问题
<a name="troubleshooting-invocation-newversion"></a>

 **问题：***在部署新版本的函数后，会发生冷启动。*

更新函数别名后，Lambda 会根据别名上配置的权重自动将预置并发转移到新版本。

 **错误：***KMSDisabledException: Lambda was unable to decrypt the environment variables because the KMS key used is disabled.（KMSDisabledException：Lambda 无法解密环境变量，因为使用的 KMS 密钥已被禁用。） 请检查功能的 KMS 密钥设置。*

如果您的 AWS Key Management Service (AWS KMS) 密钥被禁用或者撤销了允许 Lambda 使用该密钥的授权，则可能会发生此错误。如果缺少授权，请将函数配置为使用其他密钥。然后，重新分配自定义密钥以重新创建授权。

## Lambda：运行时出现意外的 Node.js 退出情况（Runtime.NodejsExit）
<a name="troubleshooting-invocation-nodejs-exit"></a>

**问题：***Lambda 运行时客户端检测到意外的 Node.js 退出代码。*

这种错误在您的函数在所有 Promise 均已解决之前就退出时出现，例如因代码漏洞导致。当 Node.js 检测到阻止 Promise 被解决的死锁时，也会发生这种情况。此错误仅影响异步样式处理程序，不影响回调样式处理程序。

**受影响的运行时：**Node.js 18 及更高版本。

**要解决此问题，请执行以下操作：**

1. 检查您的函数代码，看看异步处理程序中是否有未解决的 Promise。

1. 在函数完成之前，请确保所有 Promise 都已妥善解决（已解决或拒绝）。

1. 查看您的代码，以了解其中的异步操作是否存在潜在的竞争条件。

有关 Node.js 退出代码和进程终止的更多信息，请参阅 [Node.js 文档](https://nodejs.org/docs/latest/api/process.html#exit-codes)。

## EFS：函数无法挂载 EFS 文件系统
<a name="troubleshooting-invocation-efsmount"></a>

 **错误：***EFSMountFailureException：函数无法使用访问点 arn:aws:elasticfilesystem:us-east-2:123456789012:access-point/fsap-015cxmplb72b405fd 挂载 EFS 文件系统。*

对函数[文件系统](configuration-filesystem.md) 的挂载请求被拒绝。检查函数的权限，并确认其文件系统和访问点存在且可供使用。

## EFS：函数无法连接到 EFS 文件系统
<a name="troubleshooting-invocation-efsconnect"></a>

 **错误：***EFSMountConnectivityException: The function couldn't connect to the Amazon EFS file system with access point arn:aws:elasticfilesystem:us-east-2:123456789012:access-point/fsap-015cxmplb72b405fd.（EFSMountConnectivityException：函数无法使用访问点 arn:aws:elasticfilesystem:us-east-2:123456789012:access-point/fsap-015cxmplb72b405fd 连接到 Amazon EFS 文件系统。） 检查您的网络配置，然后重试。*

函数无法使用 NFS 协议（TCP 端口 2049）与函数的[文件系统](configuration-filesystem.md)建立连接。检查 VPC 子网的[安全组和路由配置](https://docs.aws.amazon.com/efs/latest/ug/network-access.html)。

如果您在更新函数的 VPC 配置设置后出现这些错误，请尝试卸载并重新挂载文件系统。

## EFS：由于超时，函数无法挂载 EFS 文件系统
<a name="troubleshooting-invocation-efstimeout"></a>

 **错误：***EFSMountTimeoutException：由于挂载超时，函数无法使用访问点 \$1arn:aws:elasticfilesystem:us-east-2:123456789012:access-point/fsap-015cxmplb72b405fd\$1 挂载 EFS 文件系统。*

函数能够连接到函数的[文件系统](configuration-filesystem.md)，但挂载操作超时。短时间后再试，并考虑限制函数的[并发](configuration-concurrency.md)以减少文件系统的负载。

## Lambda：Lambda 检测到某一 IO 进程耗时过长
<a name="troubleshooting-invocation-ioprocess"></a>

 *EFSIOException：此函数实例已停止，因为 Lambda 检测到某一 IO 进程花费的时间过长。*

先前的调用超时，且 Lambda 无法终止函数处理程序。当附加的文件系统用完了突发信用并且基准吞吐量不足时，可能会出现此问题。要提高吞吐量，可以增加文件系统的大小或使用预置吞吐量。

## 容器：CodeArtifactUserException 错误
<a name="troubleshooting-deployment-container-artifact"></a>

**错误：***CodeArtifactUserPendingException 错误消息*

CodeArtifact 正在等待优化。当 Lambda 完成优化时，函数将转换为[活动状态](functions-states.md)。HTTP 响应代码：409。

**错误：***CodeArtifactUserDeletedException 错误消息*

计划删除 CodeArtifact。HTTP 响应代码：409。

**错误：***CodeArtifactUserFailedException 错误消息*

Lambda 无法优化代码。您需要更正代码并重新上传。HTTP 响应代码：409。

## 容器：InvalidEntrypoint 错误
<a name="troubleshooting-deployment-container-entrypoint"></a>

**错误：***Runtime.ExitError 或“errorType”：“Runtime.InvalidEntrypoint”*

验证容器映像的 ENTRYPOINT 是否包含作为位置的绝对路径。另外，验证映像不包含作为 ENTRYPOINT 的符号链接。

**错误：** *您正在使用 CloudFormation 模板，并且您的容器 ENTRYPOINT 正被 null 值或空值覆盖。*

查看 CloudFormation 模板中的 [ImageConfig](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-properties-lambda-function-imageconfig.html) 资源。如果在模板中声明 `ImageConfig` 资源，则必须为全部三个属性提供非空值。

# Lambda 中的执行问题疑难解答
<a name="troubleshooting-execution"></a>

当 Lambda 运行时运行函数代码时，可能会在已经处理事件一段时间的函数实例上处理事件，或者可能需要初始化一个新实例。在函数初始化期间、处理程序代码处理事件时或者当函数返回（或无法返回）响应，可能会发生错误。

函数执行错误可能是由您的代码、函数配置、下游资源或权限中的问题引起。如果您直接调用函数，则会在 Lambda 的响应中看到函数错误。如果您使用事件源映射或通过其他服务异步调用函数，则可能会在日志、死信队列或失败时的目标中找到错误。错误处理选项和重试行为因调用函数的方式和错误类型而异。

当您的函数代码或 Lambda 运行时返回错误时，来自 Lambda 的响应中的状态代码为“200 OK”。响应中是否存在错误由名为 `X-Amz-Function-Error` 的标头指示。400 和 500 系列状态代码保留用于[调用错误](troubleshooting-invocation.md)。

**Topics**
+ [Lambda：使用 Visual Studio Code 进行远程调试](#troubleshooting-execution-remote-debugging)
+ [Lambda：执行时间过长](#troubleshooting-execution-toolong)
+ [Lambda：意外的事件有效载荷](#troubleshooting-execution-unexpected-payload)
+ [Lambda：意外的大型有效载荷大小](#troubleshooting-execution-large-payload)
+ [Lambda：JSON 编码和解码错误](#troubleshooting-execution-json-encoding)
+ [Lambda：未显示日志或跟踪](#troubleshooting-execution-logstraces)
+ [Lambda：并非所有我的函数的日志都会出现](#troubleshooting-execution-missinglogs)
+ [Lambda：函数在执行完成之前返回](#troubleshooting-execution-unfinished)
+ [Lambda：运行意外函数版本或别名](#unintended-function)
+ [Lambda：检测无限循环](#infinite-loops)
+ [常规：下游服务不可用](#downstream-unavailability)
+ [AWS 开发工具包：版本和更新](#troubleshooting-execution-versions)
+ [Python：库未正确加载](#troubleshooting-execution-libraries)
+ [Java：从 Java 11 更新到 Java 17 后，函数处理事件所需的时间更长](#troubleshooting-execution-java-perf)
+ [Kafka: 错误处理和重试配置问题](#troubleshooting-kafka-error-handling)

## Lambda：使用 Visual Studio Code 进行远程调试
<a name="troubleshooting-execution-remote-debugging"></a>

**问题：***对实际 AWS 环境中难以复杂的 Lambda 函数行为进行故障排除*

Lambda 通过 AWS Toolkit for Visual Studio Code 提供远程调试功能。有关设置和一般说明，请参阅[使用 Visual Studio Code 远程调试 Lambda 函数](debugging.md)。

有关故障排除、高级使用案例和区域可用性的详细说明，请参阅《AWS Toolkit for Visual Studio Code 用户指南》中的[远程调试 Lambda 函数](https://docs.aws.amazon.com/toolkit-for-vscode/latest/userguide/lambda-remote-debug.html)。

## Lambda：执行时间过长
<a name="troubleshooting-execution-toolong"></a>

**问题：***函数执行时间太长。*

如果您的代码在 Lambda 中运行所花费的时间长于在本地计算机上运行所花费的时间，则可能受到对该函数可用的内存或处理能力的限制。[使用额外内存配置函数](configuration-memory.md)以增加内存和 CPU。

## Lambda：意外的事件有效载荷
<a name="troubleshooting-execution-unexpected-payload"></a>

**问题：***与 JSON 格式错误或数据验证不足相关的函数错误。*

所有 Lambda 函数都会在处理程序的第一个参数中接收事件有效载荷。事件有效载荷是一个 JSON 结构，可能包含数组和嵌套元素。

当上游服务未使用强大的流程检查 JSON 结构时，可能会出现格式错误的 JSON。当服务连接文本字符串或嵌入未经清理的用户输入时，就会发生这种情况。也会经常序列化 JSON，以便在服务之间传递。始终以 JSON 的生产者和使用者的身份解析 JSON 结构，以确保结构有效。

同样，未能检查事件有效载荷中的值范围也可能导致错误。此示例显示了计算预扣税的函数：

```
exports.handler = async (event) => {
    let pct = event.taxPct
    let salary = event.salary

    // Calculate % of paycheck for taxes
    return (salary * pct)
}
```

此函数使用事件有效载荷中的工资和税率来执行计算。但是，该代码未能检查属性是否存在。也未能检查数据类型或确保界限，例如确保税收百分比介于 0 与 1 之间。因此，这些界限以外的值会产生毫无意义的结果。类型不正确或属性缺少会导致运行时错误。

创建测试，以确保您的函数可以处理更大的有效载荷。Lambda 事件有效载荷的最大大小为 1 MB。根据内容，有效载荷越大，可能意味着传递给函数的项目越多，或者 JSON 属性中嵌入的二进制数据越多。在这两种情况下，此项都可能导致对 Lambda 函数进行更多处理。

较大的有效载荷也可能导致超时。例如，Lambda 函数每 100 毫秒处理一条记录，且超时时间为 3 秒。成功处理有效载荷中的 0-29 个项目。但是，一旦有效载荷包含超过 30 个项目，该函数就会超时并引发错误。为避免这种情况，请确保设置超时，以处理预期最大数量的项目所需的额外处理时间。

## Lambda：意外的大型有效载荷大小
<a name="troubleshooting-execution-large-payload"></a>

**问题：***由于有效载荷较大，函数超时或导致错误。*

较大的有效载荷也可能导致超时和错误。我们建议创建测试以确保您的函数能够处理最大预期有效载荷，并确保正确设置函数超时。

此外，某些事件有效载荷可能包含指向其他资源的指针。例如，内存为 128 MB 的 Lambda 函数可以针对作为对象存储在 S3 中的 JPG 文件执行图像处理。对于较小的图像文件，该函数可以按预期运行。但是，当提供较大的 JPG 文件作为输入时，Lambda 函数会因内存不足而引发错误。为避免这种情况，测试案例应包括预期数据大小上限的示例。该代码还应验证有效载荷大小。

## Lambda：JSON 编码和解码错误
<a name="troubleshooting-execution-json-encoding"></a>

**问题：***解析 JSON 输入时出现 NoSuchKey 异常。*

进行检查，确保在正确处理 JSON 属性。例如，对于 S3 生成的事件，`s3.object.key` 属性包含了 URL 编码的对象密钥名称。许多函数将此属性处理为文本，以加载引用的 S3 对象：

**Example**  

```
const originalText = await s3.getObject({
  Bucket: event.Records[0].s3.bucket.name,
  Key: event.Records[0].s3.object.key
}).promise()
```

此代码适用于密钥名称 `james.jpg`，但是当名称为 `james beswick.jpg` 时会引发 `NoSuchKey` 错误。由于 URL 编码会转换密钥名称中的空格和其他字符，因此，您必须确保函数在使用以下数据之前解码了密钥：

**Example**  

```
const originalText = await s3.getObject({
  Bucket: event.Records[0].s3.bucket.name,
  Key: decodeURIComponent(event.Records[0].s3.object.key.replace(/\+/g, " "))
}).promise()
```

## Lambda：未显示日志或跟踪
<a name="troubleshooting-execution-logstraces"></a>

**问题：***日志未显示在 CloudWatch Logs 中。*

**问题：***跟踪未显示在 AWS X-Ray 中。*

您的函数需要权限才能调用 CloudWatch Logs 和 X-Ray。更新函数的[执行角色](lambda-intro-execution-role.md)以向其授予权限。添加以下托管策略以启用日志和跟踪。
+ **AWSLambdaBasicExecutionRole**
+ **AWSXRayDaemonWriteAccess**

向函数添加权限时，请同时简单更新其代码或配置。这会强制停止并替换函数的具有过时凭证的运行实例。

**注意**  
函数调用后，日志可能需要 5 到 10 分钟才能显示。

## Lambda：并非所有我的函数的日志都会出现
<a name="troubleshooting-execution-missinglogs"></a>

**问题：***尽管我拥有正确权限，但 CloudWatch Logs 中缺少函数日志*

如果您的 AWS 账户 达到了其 [CloudWatch Logs 限额限制](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/cloudwatch_limits_cwl.html)，则 CloudWatch 就会对函数日志记录进行节流。发生这种情况时，您函数输出的某些日志可能不会出现在 CloudWatch Logs 中。

如果函数输出日志的速度过快，Lambda 无法对其进行处理，也会导致日志输出无法显示在 CloudWatch Logs 中。当 Lambda 无法按照函数生成日志的速度向 CloudWatch 发送日志时，它会丢弃日志以防止函数的执行速度减慢。单个日志流的日志吞吐量超过 2 MB/s 时，预计会持续观察到删除的日志。

如果函数配置为使用 [JSON 格式的日志](monitoring-cloudwatchlogs-logformat.md)，则 Lambda 会在丢弃日志时尝试向 CloudWatch Logs 发送 [`logsDropped`](telemetry-schema-reference.md#platform-logsDropped) 事件。但是，当 CloudWatch 对函数的日志记录进行节流时，此事件可能无法到达 CloudWatch Logs，因此 Lambda 丢弃日志时您并不始终会看到记录。

要检查 AWS 账户 是否已达到其 CloudWatch Logs 限额限制，请执行以下操作：

1. 打开[服务限额控制台](https://console.aws.amazon.com/servicequotas)。

1. 在导航窗格中，选择 **AWS 服务**。

1. 从 **AWS 服务**列表中，搜索 Amazon CloudWatch Logs。

1. 在**服务限额**列表中，选择 `CreateLogGroup throttle limit in transactions per second`、`CreateLogStream throttle limit in transactions per second` 和 `PutLogEvents throttle limit in transactions per second` 限额以查看利用率。

您还可以设置 CloudWatch 警报，以便在账户利用率超过您为这些限额指定的限制时提醒您。请参阅[根据静态阈值创建 CloudWatch 告警](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/ConsoleAlarms.html)以了解更多信息。

如果 CloudWatch Logs 的默认限额限制不足以满足您的用例，则可以[请求增加限额](https://docs.aws.amazon.com/servicequotas/latest/userguide/request-quota-increase.html)。

## Lambda：函数在执行完成之前返回
<a name="troubleshooting-execution-unfinished"></a>

**问题：(Node.js)** *函数在代码完成执行之前返回*

许多库（包括 AWS 开发工具包）都是异步操作。当您进行网络调用或执行其他需要等待响应的操作时，库返回一个名为 promise 的对象，该对象在后台跟踪操作的进度。

要等待 promise 解析为响应，请使用 `await` 关键字。这会阻止您的处理程序代码执行，直到将 promise 解析为包含响应的对象。如果您不需要在代码中使用来自响应的数据，则可以直接将 promise 返回到运行时。

一些库不返回 promise，但可以包装到返回 promise 的代码中。有关更多信息，请参阅 [定义采用 Node.js 的 Lambda 函数处理程序](nodejs-handler.md)。

## Lambda：运行意外函数版本或别名
<a name="unintended-function"></a>

**问题：***未调用函数版本或别名*

当您在控制台中或使用 AWS SAM 发布新的 Lambda 函数时，最新的代码版本由 `$LATEST` 表示。默认情况下，未指定版本或别名的调用会自动将函数代码的 `$LATEST` 版本作为目标。

如果您使用特定的函数版本或别名，则这些版本或别名是除 `$LATEST` 之外函数的不可变已发布版本。对这些函数进行问题排查时，首先确定调用方是否调用了预期的版本或别名。可以通过检查函数日志来做到这一点。被调用的函数的版本始终显示在 START 日志行中：

![\[调试操作图 1\]](http://docs.aws.amazon.com/zh_cn/lambda/latest/dg/images/debugging-ops-figure-1.png)


## Lambda：检测无限循环
<a name="infinite-loops"></a>

**问题：***与 Lambda 函数相关的无限循环模式*

Lambda 函数中有两种类型的无限循环。第一个发生于函数自身内部，是由一个永不退出的循环所致。只有函数超时，调用才会结束。您可以通过监控超时然后修复循环行为来发现这些问题。

第二种循环是 Lambda 函数与其他 AWS 资源之间的循环。当来自 S3 存储桶等资源的事件调用 Lambda 函数时，就会发生此情况，然后该函数与相同的源资源交互以触发另一个事件。这会再次调用该函数，进而创建与同一 S3 存储桶的另一个交互，依此类推。这些类型的循环可能由多种不同的 AWS 事件源引起，包括 Amazon SQS 队列和 DynamoDB 表。可以使用[递归循环检测](invocation-recursion.md)来识别这些模式。

![\[调试操作图 2\]](http://docs.aws.amazon.com/zh_cn/lambda/latest/dg/images/debugging-ops-figure-2.png)


您可以确保 Lambda 函数写入与使用资源不同的资源，从而避免这些循环。如果您必须将数据发布回使用的资源，则请确保新数据不会触发相同的事件。或者，使用[事件筛选](invocation-eventfiltering.md)。例如，以下是针对使用 S3 和 DynamoDB 资源的无限循环提出的两个解决方案：
+ 如果您回写到同一 S3 存储桶，请使用与事件触发器不同的前缀或后缀。
+ 如果您将项目写入同一 DynamoDB 表，则请包含使用的 Lambda 函数可以筛选的属性。如果 Lambda 找到该属性，则不会导致再次调用。

## 常规：下游服务不可用
<a name="downstream-unavailability"></a>

**问题：***您的 Lambda 函数所依赖的下游服务不可用*

对于调用第三方端点或其他下游资源的 Lambda 函数，请确保它们能够处理服务错误和超时。这些下游资源可能具有可变的响应时间，或者可能由于服务中断而变得不可用。根据实施，如果服务的错误响应未在函数代码中处理，则这些下游错误可能会显示为 Lambda 函数超时或异常。

每当函数依赖于下游服务（例如 API 调用）时，应实施适当的错误处理和重试逻辑。对于关键服务，Lambda 函数应将指标或日志发布到 CloudWatch。例如，如果第三方支付 API 不可用，则 Lambda 函数可以记录此信息。然后，您可以设置 CloudWatch 警报来发送与这些错误相关的通知。

由于 Lambda 可以快速扩展，非无服务器下游服务可能难以应对流量激增。有三种常见的方法可处理此问题：
+  **缓存** – 如果第三方服务返回的值不经常更改，可以考虑缓存这些值的结果。您可以将这些值存储在函数或其他服务的全局变量中。例如，可以将来自 Amazon RDS 实例的产品列表查询的结果保存在函数内一段时间，以防止冗余查询。
+  **加入队列** – 保存或更新数据时，在 Lambda 函数与资源之间添加 Amazon SQS 队列。在下游服务处理消息时，队列可以持久地保存数据。
+  **代理** – 若通常使用长期连接（例如对于 Amazon RDS 实例），应使用代理层来池化和重复使用这些连接。对于关系数据库，[Amazon RDS 代理](https://github.com/aws-samples/s3-to-lambda-patterns/tree/master/docrepository)是一项旨在帮助提高基于 Lambda 的应用程序的可扩展性和弹性的服务。

## AWS 开发工具包：版本和更新
<a name="troubleshooting-execution-versions"></a>

**问题：***运行时包含的 AWS 开发工具包不是最新版本*

**问题：***运行时中包含的 AWS 开发工具包自动更新*

解释性语言的运行时包括 AWS SDK 的一个版本。Lambda 会定期更新这些运行时，以使用最新的 SDK 版本。要查找运行时中包含的 SDK 版本，请参阅以下部分：
+ [包含运行时的 SDK 版本（Node.js）](lambda-nodejs.md#nodejs-sdk-included)
+ [包含运行时的 SDK 版本（Python）](lambda-python.md#python-sdk-included)
+ [包含运行时的 SDK 版本（Ruby）](lambda-ruby.md#ruby-sdk-included)

要使用较新版本的AWS开发工具包，或将函数锁定为特定版本，您可以将库与函数代码捆绑起来，或[创建 Lambda 层](chapter-layers.md)。有关创建具有依赖项的部署程序包的详细信息，请参阅以下主题：

------
#### [ Node.js ]

[使用 .zip 文件归档部署 Node.js Lambda 函数](nodejs-package.md) 

------
#### [ Python ]

 [将 .zip 文件归档用于 Python Lambda 函数](python-package.md) 

------
#### [ Ruby ]

 [使用 .zip 文件归档部署 Ruby Lambda 函数](ruby-package.md) 

------
#### [ Java ]

 [使用 .zip 或 JAR 文件归档部署 Java Lambda 函数](java-package.md) 

------
#### [ Go ]

 [使用 .zip 文件归档部署 Go Lambda 函数](golang-package.md) 

------
#### [ C\$1 ]

 [使用 .zip 文件归档构建和部署 C\$1 Lambda 函数](csharp-package.md) 

------
#### [ PowerShell ]

 [使用 .zip 文件归档部署 PowerShell Lambda 函数](powershell-package.md) 

------

## Python：库未正确加载
<a name="troubleshooting-execution-libraries"></a>

**问题：**(Python) *无法从部署程序包中正确加载某些库*

具有使用 C 或 C \$1\$1 编写的扩展模块的库，必须在与 Lambda (Amazon Linux) 具有相同处理器架构的环境中进行编译。有关更多信息，请参阅 [将 .zip 文件归档用于 Python Lambda 函数](python-package.md)。

## Java：从 Java 11 更新到 Java 17 后，函数处理事件所需的时间更长
<a name="troubleshooting-execution-java-perf"></a>

**问题：**（Java）*从 Java 11 更新到 Java 17 后，函数处理事件所需的时间更长*

使用 `JAVA_TOOL_OPTIONS` 参数调整编译器。Java 17 及更高 Java 版本的 Lambda 运行时会更改默认的编译器选项。虽然此更改缩短了寿命较短的函数的冷启动时间，但以前的行为更适合计算密集型、运行时间较长的函数。将 `JAVA_TOOL_OPTIONS` 设置为 `-XX:-TieredCompilation` 可恢复到 Java 11 的行为。有关 `JAVA_TOOL_OPTIONS` 参数的更多信息，请参阅 [了解 `JAVA_TOOL_OPTIONS` 环境变量](java-customization.md#java-tool-options)。

## Kafka: 错误处理和重试配置问题
<a name="troubleshooting-kafka-error-handling"></a>

**问题：***Kafka 事件源映射无法配置重试设置或失败时的目标*

Kafka 重试配置和失败时的目标仅适用于启用了预置模式的事件源映射。在尝试设置重试配置之前，请确保已在 `ProvisionedPollerConfig` 中配置了 `MinimumPollers`。

常见配置错误：
+ **采用分批处理的无限次重试**：当 `MaximumRetryAttempts` 被设置为 -1（无限）时，无法启用 `BisectBatchOnFunctionError`。设置有限重试限制或禁用分批处理。
+ **相同的主题递归**：Kafka 失败时的目标主题不能与您的任何源主题相同。为您的死信主题选择不同的主题名称。
+ **无效的 Kafka 目标格式**：在指定 Kafka 主题作为失败时的目标时，请使用 `kafka://<topic-name>` 格式。
+ **kafka:WriteData 权限问题**：确保您的执行角色具有目标主题的 `kafka-cluster:WriteData` 权限。如果出现主题不存在的超时错误或者写入 API 的节流问题，可能需要提高账户的限制。

# 排查 Lambda 中的事件源映射问题
<a name="troubleshooting-event-source-mapping"></a>

Lambda 中与[事件源映射](invocation-eventsourcemapping.md)相关的问题可能更加复杂，因为它们涉及跨多项服务的调试。此外，根据所使用的确切事件源，事件源行为可能会有所不同。本节列出了涉及事件源映射的常见问题，并提供了有关如何发现和解决这些问题的指导。

**注意**  
本节以 Amazon SQS 事件源进行说明，但相关原则适用于为 Lambda 函数对消息进行排队的其他事件源映射。

## 识别和管理节流
<a name="esm-throttling"></a>

在 Lambda 中，当达到函数或账户的并发限制时，就会发生节流。考虑以下示例，有一个 Lambda 函数从某个 Amazon SQS 队列中读取消息。此 Lambda 函数模拟 30 秒的调用，批次大小为 1。这意味着该函数每 30 秒仅处理 1 条消息：

```
const doWork = (ms) => new Promise(resolve => setTimeout(resolve, ms))

exports.handler = async (event) => {
    await doWork(30000)

}
```

由于调用时间如此之长，消息开始进入队列的速度要快于系统处理它们的速度。如果账户的未预留并发数为 100，则 Lambda 最多可扩展到 100 个并发执行，然后就会发生节流。您可以在该函数的 CloudWatch 指标中看到此模式：

![\[调试操作图 10\]](http://docs.aws.amazon.com/zh_cn/lambda/latest/dg/images/debugging-ops-figure-10.png)


该函数的 CloudWatch 指标未显示任何错误，但**并发执行**图表显示已达到最大并发数 100。因此，**限制**图表显示了已设置的节流。

您可以使用 CloudWatch 警报检测节流，并设置在函数的节流指标大于 0 时发出警报。发现节流问题后，可以选择以下几种解决方法：
+ 向此区域的 AWS Support 请求增加并发。
+ 确定函数中的性能问题，以提高处理速度，从而提高吞吐量。
+ 增加函数的批次大小，以便每次调用都能处理更多消息。

## 处理函数中的错误
<a name="esm-processing-function"></a>

如果处理函数引发错误，则 Lambda 会将消息返回到 SQS 队列。Lambda 可防止您的函数扩展，从而防止大规模出现错误。CloudWatch 中的以下 SQS 指标表明队列处理存在问题：

![\[调试操作图 11\]](http://docs.aws.amazon.com/zh_cn/lambda/latest/dg/images/debugging-ops-figure-11.png)


特别是，最早消息的期限和可见消息的数量都在增加，但没有消息被删除。队列继续增长，但没有处理消息。处理 Lambda 函数的 CloudWatch 指标也表明存在问题：

![\[调试操作图 12\]](http://docs.aws.amazon.com/zh_cn/lambda/latest/dg/images/debugging-ops-figure-12.png)


**错误计数**指标不为零且不断增长，而**并发执行**次数减少了，且节流已停止。这表明由于错误，Lambda 已停止纵向扩展函数。该函数的 CloudWatch 日志提供了错误类型的详细信息。

您可以通过识别导致错误的函数，然后找到并解决错误，以解决此问题。修复错误并部署新函数代码之后，CloudWatch 指标应显示处理的恢复情况：

![\[调试操作图 13\]](http://docs.aws.amazon.com/zh_cn/lambda/latest/dg/images/debugging-ops-figure-13.png)


在这里，**错误计数**指标降为零，**成功率**指标恢复为 100%。Lambda 再次开始纵向扩展函数，如**并发执行**图中所示。

## 识别和处理反向压力
<a name="esm-backpressure"></a>

如果事件产生器为 SQS 队列生成消息的速度始终高于 Lambda 函数处理消息的速度，则会出现反向压力。在这种情况下，SQS 监控应显示最早消息的期限线性增长，以及可见消息的大致数量。您可以使用 CloudWatch 警报检测队列中的反向压力。

解决反向压力的步骤取决于您的工作负载。如果主要目标是通过 Lambda 函数提升处理能力和吞吐量，您有以下几种选择：
+ 向 AWS Support 请求增加特定区域的并发。
+ 增加函数的批次大小，以便每次调用都能处理更多消息。

# Lambda 中的联网问题疑难解答
<a name="troubleshooting-networking"></a>

默认情况下，Lambda 在与AWS服务和互联网连接的内部 Virtual Private Cloud (VPC) 中运行您的函数。要访问本地网络资源，您可以将[函数配置为连接到您账户中的 VPC](configuration-vpc.md)。使用此功能时，您可以管理函数的互联网访问以及与 Amazon Virtual Private Cloud（Amazon VPC）资源的网络连接。

网络连接错误可能是由于 VPC 的路由配置、安全组规则、AWS Identity and Access Management（IAM）角色权限、网络地址转换（NAT）或资源可用性（例如 IP 地址或网络接口）中的问题造成。根据具体问题的不同，如果请求无法到达目标，则可能会看到特定错误或超时。

**Topics**
+ [VPC：函数无法访问互联网或超时](#troubleshooting-networking-cfn)
+ [VPC：TCP 或 UDP 连接间歇性失败](#troubleshooting-networking-tcp-udp)
+ [VPC：函数需要在不使用互联网的情况下访问 AWS 服务](#troubleshooting-networking-access)
+ [VPC：已达到弹性网络接口限制](#troubleshooting-networking-limit)
+ [EC2：类型为“lambda”的弹性网络接口](#troubleshooting-networking-eni)
+ [DNS：UNKNOWNHOSTEXCEPTION，无法连接到主机](#troubleshooting-networking-dns-tcp)

## VPC：函数无法访问互联网或超时
<a name="troubleshooting-networking-cfn"></a>

**问题：***连接到 VPC 后，您的 Lambda 函数失去互联网访问权限。*

**错误：***错误：连接 ETIMEDOUT 176.32.98.189:443*

**错误：***错误：任务在 10.00 秒后超时*

**错误：***ReadTimeoutError: Read timed out. (read timeout=15)*

当您将函数连接到某个 VPC 时，所有出站请求都会通过该 VPC。要连接到互联网，请将 VPC 配置为将出站流量从函数的子网发送到公有子网中的 NAT 网关。有关更多信息和示例 VPC 配置，请参阅 [为连接到 VPC 的 Lambda 函数启用互联网访问权限](configuration-vpc-internet.md)。

如果某些 TCP 连接超时，且您的子网使用网络访问控制列表（NACL），则请参阅[VPC：TCP 或 UDP 连接间歇性失败](#troubleshooting-networking-tcp-udp)。否则，这可能是由于数据包碎片造成的。Lambda 函数无法处理传入的碎片 TCP 请求，因为 Lambda 不支持 TCP 或 ICMP 的 IP 碎片化。

## VPC：TCP 或 UDP 连接间歇性失败
<a name="troubleshooting-networking-tcp-udp"></a>

**注意**  
仅当子网使用[网络访问控制列表（ACL）](https://docs.aws.amazon.com//vpc/latest/userguide/vpc-network-acls.html#nacl-basics)，此问题才适用。Lambda 不需要网络 ACL 即可连接到您的子网。

**问题：***Lambda 间歇性地失去与 VPC 子网的连接，而您已为这些子网配置了网络访问控制列表（ACL）*。

对于支持 VPC 的 Lambda 函数，AWS 在客户的账户中创建 [Hyperplane ENI](configuration-vpc.md#configuration-vpc-enis)，并使用临时端口 `1024` 至 `65535` 将 Lambda 连接到客户的 VPC。如果在目标子网中使用网络 ACL，则必须允许 TCP 和 UDP 的端口范围为 `1024` 至 `65535`。不允许此完整端口范围可能会导致间歇性连接失败。

## VPC：函数需要在不使用互联网的情况下访问 AWS 服务
<a name="troubleshooting-networking-access"></a>

**问题：***您的 Lambda 函数需要在不使用互联网的情况下访问 AWS 服务。*

要在不能访问互联网的情况下从私有子网将函数连接到 AWS 服务，请使用 VPC 端点。

## VPC：已达到弹性网络接口限制
<a name="troubleshooting-networking-limit"></a>

**错误：***ENILimitReachedException：函数的 VPC 已达到弹性网络接口限制。*

当您将一个 Lambda 函数连接到某个 VPC 时，Lambda 将为该函数所附加的每个子网和安全组组合创建一个弹性网络接口。原定设置服务配额为每个 VPC 250 个网络接口。要请求增加配额，您可以使用 [Service Quotas 控制台](https://console.aws.amazon.com/servicequotas/home/services/lambda/quotas/L-9FEE3D26)。

## EC2：类型为“lambda”的弹性网络接口
<a name="troubleshooting-networking-eni"></a>

 **错误代码：***Client.OperationNotPermitted*

 **错误消息：***无法修改此类接口的安全组*

如果您尝试修改由 Lambda 管理的弹性网络接口（ENI），则会收到此错误。`ModifyNetworkInterfaceAttribute` 不包含在用于更新由 Lambda 创建的弹性网络接口上的操作的 Lambda API 中。

## DNS：UNKNOWNHOSTEXCEPTION，无法连接到主机
<a name="troubleshooting-networking-dns-tcp"></a>

 **错误消息：***UNKNOWNHOSTEXCEPTION*

Lambda 函数最多支持 20 个并发 TCP 连接进行 DNS 解析。函数可能正要耗尽此限制。大多数常见的 DNS 请求都是通过 UDP 完成的。如果函数只建立 UDP DNS 连接，那么此问题与您无关。该错误通常是由配置错误或基础设施降级引发的，因此在深入检查 DNS 流量之前，请确认 DNS 基础设施是否配置正确且运行正常，并且 Lambda 函数是否引用 DNS 中指定的主机。

请注意，如果诊断出问题与 TCP 连接最大值有关，您不能请求提高此限制。如果 Lambda 函数因 DNS 有效负载较大而回退到 TCP DNS，请确认解决方案是否正在使用支持 EDNS 的库。有关 EDNS 的更多信息，请参阅 [RFC 6891 standard](https://datatracker.ietf.org/doc/html/rfc6891)。如果 DNS 有效负载持续超过 EDNS 最大限制，则解决方案仍可能会耗尽 TCP DNS 限制。