

# 了解 Lambda 函数调用方法
<a name="lambda-invocation"></a>

部署 Lambda 函数后，可以通过多种方式调用函数：
+ [Lambda 控制台](testing-functions.md)：使用 Lambda 控制台快速创建测试事件来调用函数。
+ [AWS SDK](https://aws.amazon.com/developer/tools/)：使用 AWS SDK 以编程方式调用函数。
+ [调用](https://docs.aws.amazon.com/lambda/latest/api/API_Invoke.html) API – 使用 Lambda 调用 API 直接调用函数。
+ [AWS Command Line Interface（AWS CLI）](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/invoke.html)：使用 `aws lambda invoke` AWS CLI 命令从命令行直接调用函数。
+ [函数 URL HTTP(S) 端点](urls-configuration.md)：使用函数 URL 创建可用于调用函数的专用 HTTP(S) 端点。

这些全部都是*直接*调用函数的方法。在 Lambda 中，常见用例是根据应用程序中其他地方发生的事件调用函数。某些服务可以利用每个新事件调用 Lambda 函数。这称为[触发器](lambda-services.md)。对基于流和队列的服务，Lambda 使用批量记录调用该函数。这称为[事件源映射](invocation-eventsourcemapping.md)。

调用函数时，您可以选择同步或异步调用。使用[同步调用](invocation-sync.md)时，您将等待函数处理该事件并返回响应。使用[异步调用](invocation-async.md)时，Lambda 会将事件排队等待处理并立即返回响应。[调用 API 中的 `InvocationType` 请求参数](https://docs.aws.amazon.com/lambda/latest/api/API_Invoke.html#API_Invoke_RequestParameters)会决定 Lambda 如何调用函数。`RequestResponse` 的值表示同步调用，`Event` 的值则表示异步调用。

要通过 IPv6 调用您的函数，请使用 Lambda 的公共[双堆栈端点](https://docs.aws.amazon.com/general/latest/gr/rande.html#dual-stack-endpoints)。双堆栈端点同时支持 IPv4 和 IPv6。Lambda 双堆栈端点使用以下语法：

```
protocol://lambda.us-east-1.api.aws
```

您也可以使用 [Lambda 函数 URL](urls-configuration.md) 通过 IPv6 调用函数。函数 URL 的端点具有以下格式：

```
https://url-id.lambda-url.us-east-1.on.aws
```

如果函数调用出现错误，对于同步调用，则查看响应中的错误消息并手动重试调用。对于异步调用，Lambda 会自动处理重试并将调用记录发送到[目标](invocation-async-retain-records.md#invocation-async-destinations)。

# 同步调用 Lambda 函数
<a name="invocation-sync"></a>

当您同步调用某个函数时，Lambda 会运行该函数并等待响应。当函数完成时，Lambda 返回来自函数代码的响应以及其他数据，例如已调用函数的版本。要使用 AWS CLI 同步调用函数，请使用 `invoke` 命令。

```
aws lambda invoke --function-name my-function \
    --cli-binary-format raw-in-base64-out \
    --payload '{ "key": "value" }' response.json
```

如果使用 **cli-binary-format** 版本 2，则 AWS CLI 选项是必需的。要将其设为默认设置，请运行 `aws configure set cli-binary-format raw-in-base64-out`。有关更多信息，请参阅*版本 2 的 AWS Command Line Interface 用户指南*中的 [AWS CLI 支持的全局命令行选项](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-options.html#cli-configure-options-list)。

您应看到以下输出：

```
{
    "ExecutedVersion": "$LATEST",
    "StatusCode": 200
}
```

下图显示了同步调用 Lambda 函数的客户端。Lambda 将事件直接发送给函数，并将函数的响应发送回调用方。

![\[\]](http://docs.aws.amazon.com/zh_cn/lambda/latest/dg/images/invocation-sync.png)


`payload` 是一个包含 JSON 格式事件的字符串。AWS CLI 用来写入函数响应的文件的名称为 `response.json`。如果函数返回对象或错误，则响应正文是 JSON 格式的对象或错误。如果函数退出时没有错误，则响应正文为 `null`。

**注意**  
Lambda 在发送响应之前不会等待外部扩展完成。Lambda 扩展作为独立进程在执行环境中运行，并可以在完成函数调用后继续运行。有关更多信息，请参阅 [使用 Lambda 扩展增强 Lambda 函数](lambda-extensions.md)。

该命令的输出（显示在终端中）包含来自 Lambda 响应中的标头的信息。这包括处理事件的版本（在使用[别名](configuration-aliases.md)时非常有用），以及 Lambda 返回的状态代码。如果 Lambda 能够运行该函数，则状态代码为 200，即使该函数返回错误也是如此。

**注意**  
对于超时很长的函数，在等待响应的同步调用期间，客户端可能会断开连接。配置您的 HTTP 客户端、软件开发工具包、防火墙、代理或操作系统，以允许针对超时或保持活动设置保持长时间的连接。

如果 Lambda 无法运行该函数，则将在输出中显示错误。

```
aws lambda invoke --function-name my-function \
    --cli-binary-format raw-in-base64-out \
    --payload value response.json
```

您应看到以下输出：

```
An error occurred (InvalidRequestContentException) when calling the Invoke operation: Could not parse request body into json: Unrecognized token 'value': was expecting ('true', 'false' or 'null')
 at [Source: (byte[])"value"; line: 1, column: 11]
```

AWS CLI 是一种开源工具，让您能够在命令行 Shell 中使用命令与 AWS 服务进行交互。要完成本节中的步骤，您必须拥有 [AWS CLI 版本 2](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html)。

您可以通过 [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-welcome.html)，使用 `--log-type` 命令选项检索调用的日志。响应包含一个 `LogResult` 字段，其中包含多达 4KB 来自调用的 base64 编码日志。

**Example 检索日志 ID**  
以下示例说明如何从 `LogResult` 字段中检索名为 `my-function` 的函数的*日志 ID*。  

```
aws lambda invoke --function-name my-function out --log-type Tail
```
您应看到以下输出：  

```
{
    "StatusCode": 200,
    "LogResult": "U1RBUlQgUmVxdWVzdElkOiA4N2QwNDRiOC1mMTU0LTExZTgtOGNkYS0yOTc0YzVlNGZiMjEgVmVyc2lvb...",
    "ExecutedVersion": "$LATEST"
}
```

**Example 解码日志**  
在同一命令提示符下，使用 `base64` 实用程序解码日志。以下示例说明如何为 `my-function` 检索 base64 编码的日志。  

```
aws lambda invoke --function-name my-function out --log-type Tail \
--query 'LogResult' --output text --cli-binary-format raw-in-base64-out | base64 --decode
```
如果使用 **cli-binary-format** 版本 2，则 AWS CLI 选项是必需的。要将其设为默认设置，请运行 `aws configure set cli-binary-format raw-in-base64-out`。有关更多信息，请参阅*版本 2 的 AWS Command Line Interface 用户指南*中的 [AWS CLI 支持的全局命令行选项](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-options.html#cli-configure-options-list)。  
您应看到以下输出：  

```
START RequestId: 57f231fb-1730-4395-85cb-4f71bd2b87b8 Version: $LATEST
"AWS_SESSION_TOKEN": "AgoJb3JpZ2luX2VjELj...", "_X_AMZN_TRACE_ID": "Root=1-5d02e5ca-f5792818b6fe8368e5b51d50;Parent=191db58857df8395;Sampled=0"",ask/lib:/opt/lib",
END RequestId: 57f231fb-1730-4395-85cb-4f71bd2b87b8
REPORT RequestId: 57f231fb-1730-4395-85cb-4f71bd2b87b8  Duration: 79.67 ms      Billed Duration: 80 ms         Memory Size: 128 MB     Max Memory Used: 73 MB
```
`base64` 实用程序在 Linux、macOS 和 [Ubuntu on Windows](https://docs.microsoft.com/en-us/windows/wsl/install-win10) 上可用。macOS 用户可能需要使用 `base64 -D`。

有关 `Invoke` API 的更多信息（包括参数、标头和错误的完整列表），请参阅[调用](https://docs.aws.amazon.com/lambda/latest/api/API_Invoke.html)。

当您直接调用函数时，可以检查错误的响应并重试。在出现客户端超时、节流和服务错误时，AWS CLI 和AWS开发工具包也会自动重试。有关更多信息，请参阅[了解 Lambda 中的重试行为](invocation-retries.md)。

# 异步调用 Lambda 函数
<a name="invocation-async"></a>

多个 AWS 服务（如 Amazon Simple Storage Service（Amazon S3）和 Amazon Simple Notiﬁcation Service（Amazon SNS）将异步调用函数以处理事件。您也可以使用 AWS Command Line Interface（AWS CLI）或一种 AWS SDK 来异步调用 Lambda 函数。在异步调用函数时，您不会等待函数代码的响应。您将事件交给 Lambda，Lambda 处理其余部分。您可以配置 Lambda 处理错误的方式，并将调用记录发送到下游资源，例如 Amazon Simple Queue Service（Amazon SQS）或 Amazon EventBridge（EventBridge），以将应用程序的组件链接在一起。

下图显示了异步调用 Lambda 函数的客户端。Lambda 在将事件发送到函数之前对事件排队。

![\[\]](http://docs.aws.amazon.com/zh_cn/lambda/latest/dg/images/features-async.png)


对于异步调用，Lambda 将事件置于队列中并返回成功响应，而不返回其他信息。一个单独的进程会从队列中读取事件并将其发送到函数。

 要使用 AWS Command Line Interface（AWS CLI）或一种 AWS SDK 来异步调用 Lambda 函数，请将 [InvocationType](https://docs.aws.amazon.com/lambda/latest/api/API_Invoke.html#lambda-Invoke-request-InvocationType) 参数设置为 `Event`。以下示例显示了调用函数的 AWS CLI 命令。

```
aws lambda invoke \
  --function-name my-function  \
  --invocation-type Event \
  --cli-binary-format raw-in-base64-out \
  --payload '{ "key": "value" }' response.json
```

您应看到以下输出：

```
{
    "StatusCode": 202
}
```

如果使用 **cli-binary-format** 版本 2，则 AWS CLI 选项是必需的。要将其设为默认设置，请运行 `aws configure set cli-binary-format raw-in-base64-out`。有关更多信息，请参阅*版本 2 的 AWS Command Line Interface 用户指南*中的 [AWS CLI 支持的全局命令行选项](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-options.html#cli-configure-options-list)。

输出文件 (`response.json`) 不包含任何信息，但运行此命令时仍会创建该文件。如果 Lambda 无法将事件添加到队列，则命令输出中将显示错误消息。

# Lambda 如何处理异步调用的错误和重试
<a name="invocation-async-error-handling"></a>

Lambda 管理函数的异步事件队列以及在出错时重试的尝试次数。如果函数返回错误，Lambda 默认会尝试再运行两次，前两次尝试之间等待一分钟，第二次与第三次尝试之间等待两分钟。函数错误包括函数代码返回的错误，以及函数运行时返回的错误，例如超时。

如果该函数没有足够的并发性可用于处理所有事件，则其他请求将受到限制。对于节流错误（429）和系统错误（500 系列），Lambda 会将事件返回到队列并尝试再次运行该函数，默认最长运行 6 小时。在第一次尝试后，重试间隔从 1 秒以指数级增加到最多 5 分钟。如果队列包含多个条目，Lambda 将增加重试间隔并降低从队列中读取事件的速率。

即使您的函数没有返回错误，它也可能多次从 Lambda 接收相同的事件，因为队列本身具有最终一致性。如果函数无法跟上传入事件，则也可能从队列中删除事件而不将其发送到函数。确保您的函数代码正常处理重复事件，并且您有足够的并发可用于处理所有调用。

当队列很长时，新事件可能会在 Lambda 有机会将它们发送到您的函数之前过期。当事件过期或所有处理尝试都失败时，Lambda 将放弃该事件。您可为函数[配置错误处理](invocation-async-configuring.md)以减少 Lambda 执行的重试次数，或者更快地放弃未处理的事件。要捕获丢弃的事件，请为函数[配置死信队列](invocation-async-retain-records.md#invocation-dlq)。要捕获失败调用的记录（例如超时或运行时错误），[请创建失败时目标](invocation-async-retain-records.md#invocation-async-destinations)。

# 配置 Lambda 异步调用的错误处理设置
<a name="invocation-async-configuring"></a>

使用以下设置来配置 Lambda 如何处理异步函数调用的错误和重试：
+ [MaximumEventAgeInSeconds](https://docs.aws.amazon.com/lambda/latest/api/API_PutFunctionEventInvokeConfig.html#lambda-PutFunctionEventInvokeConfig-request-MaximumEventAgeInSeconds)：Lambda 在异步事件队列中保留事件的最长时间（以秒为单位），此后将丢弃事件。
+ [MaximumRetryAttempts](https://docs.aws.amazon.com/lambda/latest/api/API_PutFunctionEventInvokeConfig.html#lambda-PutFunctionEventInvokeConfig-request-MaximumRetryAttempts)：函数返回错误时 Lambda 重试事件的最大次数。

使用 Lambda 控制台或 AWS CLI 配置有关函数、版本或别名的错误处理设置。

------
#### [ Console ]

**配置错误处理**

1. 打开 Lamba 控制台的 [Functions](https://console.aws.amazon.com/lambda/home#/functions)（函数）页面。

1. 选择函数。

1. 选择 **Configuration（配置）**，然后选择 **Asynchronous invocation（异步调用）**。

1. 在 **Asynchronous invocation (异步调用)** 下，选择 **Edit (编辑)**。

1. 配置以下设置。
   + **Maximum age of event**（事件的最长期限）– Lambda 在异步事件队列中保留事件的最长时间（最长 6 小时）。
   + **Retry attempts**（重试次数）– 函数返回错误时 Lambda 重试的次数（0 到 2 之间）。

1. 选择**保存**。

------
#### [ AWS CLI ]

要通过 AWS CLI 配置异步调用，请使用 [put-function-event-invoke-config](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/put-function-event-invoke-config.html) 命令。以下示例配置一个最长事件期限为 1 小时且无重试的函数。

```
aws lambda put-function-event-invoke-config \ 
  --function-name error \
  --maximum-event-age-in-seconds 3600 \
  --maximum-retry-attempts 0
```

`put-function-event-invoke-config` 命令覆盖函数、版本或别名上的任何现有配置。要配置某个选项而不重置其他选项，请使用 [update-function-event-invoke-config](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/update-function-event-invoke-config.html)。以下示例配置 Lambda，以便在无法处理事件时将记录发送到名为 `destination` 的标准 SQS 队列。

```
aws lambda update-function-event-invoke-config \
  --function-name my-function \
  --destination-config '{"OnFailure":{"Destination": "arn:aws:sqs:us-east-1:123456789012:destination"}}'
```

------

您应看到以下输出：

```
{
    "LastModified": 1573686021.479,
    "FunctionArn": "arn:aws:lambda:us-east-1:123456789012:function:my-function:$LATEST",
    "MaximumRetryAttempts": 0,
    "MaximumEventAgeInSeconds": 3600,
    "DestinationConfig": {
        "OnSuccess": {},
        "OnFailure": {}
    }
}
```

当调用事件超过最长期限或所有重试均失败时，Lambda 会丢弃该事件。要保留已丢弃事件的副本，请配置失败事件[目标](invocation-async-retain-records.md#invocation-async-destinations)。

# 获取 Lambda 异步调用记录
<a name="invocation-async-retain-records"></a>

Lambda 可以将异步调用记录发送给以下某个 AWS 服务。
+ **Amazon SQS** – 标准 SQS 队列
+ **Amazon SNS** – 标准 SNS 主题
+ **Amazon S3** – Amazon S3 存储桶（仅限失败时）
+ **AWS Lambda** – Lambda 函数
+ **Amazon EventBridge** – EventBridge 事件总线

调用记录包含有关 JSON 格式的请求和响应的详细信息。您可为成功处理的事件以及处理尝试失败的事件配置单独的目标。或者，您可以将标准 Amazon SQS 队列或标准 Amazon SNS 主题配置为丢弃事件的死信队列。对于死信队列，Lambda 只发送事件的内容，不包含有关响应的详细信息。

如果 Lambda 无法向您配置的目的地发送记录，它会向 Amazon CloudWatch 发送 `DestinationDeliveryFailures` 指标。如果您的配置包含不支持的目标类型，例如 Amazon SQS FIFO 队列或 Amazon SNS FIFO 主题，则可能会发生这种情况。权限误配和大小限制可能会导致发生传输错误。有关 Lambda 调用指标的更多信息，请参阅 [调用指标](monitoring-metrics-types.md#invocation-metrics)。

**注意**  
要防止触发函数，可以将函数的预留并发设置为零。当您将异步调用函数的预留并发设置为零时，Lambda 会开始将新事件发送到已配置的[死信队列](#invocation-dlq)或失败时的[事件目标](#invocation-async-destinations)，且不会做出任何重试。要处理在预留并发设置为零时发送的事件，您必须使用死信队列或失败时事件目标中的事件。

## 添加目标
<a name="invocation-async-destinations"></a>

要保留异步调用的记录，请向函数添加目标。您可以选择将成功或失败的调用发送到目标。每个函数可以有多个目标，因此您可以为成功和失败的事件配置不同的目标。发送到目标的每条记录都是一个 JSON 文档，其中包含有关调用的详细信息。与错误处理设置一样，您可以在函数版本或别名上配置目标。

**提示**  
您还可以保留以下事件源映射类型的失败调用记录：[Amazon Kinesis](kinesis-on-failure-destination.md#kinesis-on-failure-destination-console)、[Amazon DynamoDB](services-dynamodb-errors.md) 和 [Apache Kafka（Amazon MSK 和自托管式 Apache Kafka）](kafka-on-failure.md#kafka-onfailure-destination)。<a name="destinations-permissions"></a>

下表列出了 Lambda 支持的异步调用记录目标。要让 Lambda 成功将记录发送到您选择的目标，请确保函数的[执行角色](lambda-intro-execution-role.md)也包含相关权限。该表还描述了每种目标类型如何接收 JSON 调用记录。


| 目标类型 | 所需的权限 | 特定于目标的 JSON 格式 | 
| --- | --- | --- | 
|  Amazon SQS 队列  |  [sqs:SendMessage](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_SendMessage.html)  |  Lambda 将调用记录作为 `Message` 传递到目标。  | 
|  Amazon SNS 主题  |  [sns:Publish](https://docs.aws.amazon.com/sns/latest/api/API_Publish.html)  |  Lambda 将调用记录作为 `Message` 传递到目标。  | 
|  Amazon S3 存储桶（仅限失败时）  |  [s3:PutObject](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObject.html) [s3:ListBucket](https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListObjectsV2.html)  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/lambda/latest/dg/invocation-async-retain-records.html)  | 
|  Lambda 函数  |  [lambda:InvokeFunction](https://docs.aws.amazon.com/lambda/latest/api/API_Invoke.html)  |  Lambda 将调用记录作为有效负载传递给函数。  | 
|  EventBridge  |  [events:PutEvents](https://docs.aws.amazon.com/eventbridge/latest/APIReference/API_PutEvents.html)  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/lambda/latest/dg/invocation-async-retain-records.html)  | 

**注意**  
对于 Amazon S3 目标，如果您已使用 KMS 密钥对存储桶启用加密，则您的函数还需要 [kms:GenerateDataKey](https://docs.aws.amazon.com/kms/latest/APIReference/API_GenerateDataKey.html) 权限。

**重要**  
使用 Amazon SNS 作为目的地时，请注意，Amazon SNS 的最大消息大小限为 256 KB。如果异步调用有效载荷接近 1 MB，则调用记录（包括原始有效载荷加上其他元数据）可能会超过 Amazon SNS 限制并导致传输失败。对于较大的有效载荷，可考虑使用 Amazon SQS 或 Amazon S3 目的地。

以下步骤介绍如何使用 Lambda 控制台和 AWS CLI 配置函数的目标。

------
#### [ Console ]

1. 打开 Lamba 控制台的[函数](https://console.aws.amazon.com/lambda/home#/functions)页面。

1. 选择函数。

1. 在 **Function overview (函数概览)** 下，选择 **Add destination (添加目标)**。

1. 对于 **Source (源)**，选择 **Asynchronous invocation (异步调用)**。

1. 对于 **Condition (条件)**，请从以下选项中选择：
   + **On failure**（失败时）– 当事件的所有处理尝试均失败或超过最长期限时发送记录。
   + **On success**（成功时）– 函数成功处理异步调用时发送记录。

1. 对于 **Destination type (目标类型)**，请选择接收调用记录的资源类型。

1. 对于 **Destination (目标)**，请选择一个资源。

1. 选择**保存**。

------
#### [ AWS CLI ]

要使用 AWS CLI 配置目标，请运行 [update-function-event-invoke-config](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/update-function-event-invoke-config.html) 命令。以下示例配置 Lambda，以便在无法处理事件时将记录发送到名为 `destination` 的标准 SQS 队列。

```
aws lambda update-function-event-invoke-config \
  --function-name my-function \
  --destination-config '{"OnFailure":{"Destination": "arn:aws:sqs:us-east-1:123456789012:destination"}}'
```

------

### Amazon S3 目标的安全最佳实践
<a name="s3-destination-security"></a>

如果删除配置为目标的 S3 存储桶而不将目标从函数配置中删除，则可能会造成安全风险。如果其他用户知道您的目标存储桶的名称，则他们可以在其 AWS 账户中重新创建存储桶。调用失败的记录将发送到存储桶，这可能会暴露您函数中的数据。

**警告**  
为确保您的函数中的调用记录不会发送到另一个 AWS 账户中的 S3 存储桶，请向函数的执行角色添加条件，以将 `s3:PutObject` 权限限制为您账户中的存储桶。

以下示例显示了一个 IAM 策略，该策略将您函数的 `s3:PutObject` 权限限制为您账户中的存储桶。该策略还为 Lambda 提供了使用 S3 存储桶作为目标所需的 `s3:ListBucket` 权限。

```
{
    "Version": "2012-10-17",		 	 	 
    "Statement": [
        {
            "Sid": "S3BucketResourceAccountWrite",
            "Effect": "Allow",
            "Action": [
                "s3:PutObject",
                "s3:ListBucket"
            ],
            "Resource": [
                "arn:aws:s3:::*/*",
                "arn:aws:s3:::*"
            ],
            "Condition": {
                "StringEquals": {
                    "s3:ResourceAccount": "111122223333"
                }
            }
        }
    ]
}
```

要使用 AWS 管理控制台 或 AWS CLI 向函数的执行角色添加权限策略，请参阅以下程序中的说明：

------
#### [ Console ]

**向函数的执行角色添加权限策略（控制台）**

1. 打开 Lamba 控制台的[函数](https://console.aws.amazon.com/lambda/home#/functions)页面。

1. 选择想要修改其执行角色的 Lambda 函数。

1. 在**配置**选项卡中，选择**权限**。

1. 在**执行角色**选项卡中，选择您的函数的**角色名称**,以打开该角色的 IAM 控制台页面。

1. 通过执行以下操作，向角色添加权限策略：

   1. 在**权限策略**窗格中，选择**添加权限**，然后选择**创建内联策略**。

   1. 在**策略编辑器**中，选择 **JSON**。

   1. 将要添加的策略粘贴到编辑器中（替换现有 JSON），然后选择**下一步**。

   1. 在**策略详细信息**下，输入**策略名称**。

   1. 选择**创建策略**。

------
#### [ AWS CLI ]

**向函数的执行角色添加权限策略（CLI）**

1. 创建具有所需权限的 JSON 策略文档并将其保存在本地目录中。

1. 使用 IAM `put-role-policy` CLI 命令向您函数的执行角色添加权限。在您保存 JSON 策略文档的目录中运行以下命令，并用您自己的值替换角色名称、策略名称和策略文档。

   ```
   aws iam put-role-policy \
   --role-name my_lambda_role \
   --policy-name LambdaS3DestinationPolicy \
   --policy-document file://my_policy.json
   ```

------

### 调用记录的示例
<a name="destination-example-record"></a>

当调用与条件匹配时，Lambda 会向目标发送包含调用详细信息的 [JSON 文档](#destinations-permissions)。以下示例显示了由于函数错误而导致三次处理尝试失败的事件的调用记录。

**Example**  

```
{
    "version": "1.0",
    "timestamp": "2019-11-14T18:16:05.568Z",
    "requestContext": {
        "requestId": "e4b46cbf-b738-xmpl-8880-a18cdf61200e",
        "functionArn": "arn:aws:lambda:us-east-1:123456789012:function:my-function:$LATEST",
        "condition": "RetriesExhausted",
        "approximateInvokeCount": 3
    },
    "requestPayload": {
        "ORDER_IDS": [
            "9e07af03-ce31-4ff3-xmpl-36dce652cb4f",
            "637de236-e7b2-464e-xmpl-baf57f86bb53",
            "a81ddca6-2c35-45c7-xmpl-c3a03a31ed15"
        ]
    },
    "responseContext": {
        "statusCode": 200,
        "executedVersion": "$LATEST",
        "functionError": "Unhandled"
    },
    "responsePayload": {
        "errorMessage": "RequestId: e4b46cbf-b738-xmpl-8880-a18cdf61200e Process exited before completing request"
    }
}
```

调用记录包含有关事件、响应和记录发送原因的详细信息。

### 追踪发往目的地的请求
<a name="destinations-tracing"></a>

在每个请求排队、由 Lambda 函数处理并传递到目标服务时，您可以使用 AWS X-Ray 查看每个请求的连接视图。当您为调用函数的函数或服务激活 X-Ray 跟踪时，Lambda 会向请求添加 X-Ray 标头并将标头传递给目标服务。来自上游服务的跟踪会自动链接到下游 Lambda 函数的跟踪，从而创建整个应用程序的端到端视图。有关跟踪的更多信息，请参阅 [使用 AWS X-Ray 可视化 Lambda 函数调用](services-xray.md)。

## 添加死信队列
<a name="invocation-dlq"></a>

作为[失败时的目标](#invocation-async-destinations)的替代，您可以使用死信队列配置函数，以保存丢弃的事件供进一步处理。死信队列的作用与失败时的目标相同，在某个事件的所有处理尝试都失败或者已过期而未处理时使用。但是，您只能在函数级别添加或删除死信队列。函数版本使用与未发布的版本（\$1LATEST）相同的死信队列设置。失败时的目标还支持其他目标，并在调用记录中包含有关函数响应的详细信息。

要重新处理死信队列中的事件，您可以将其设置为 Lambda 函数的[事件源](invocation-eventsourcemapping.md)。或者，您也可以手动检索事件。

您可以为死信队列选择 Amazon SQS 标准队列或 Amazon SNS 标准主题。不支持 FIFO 队列和 Amazon SNS FIFO 主题。
+ [Amazon SQS 队列](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-create-queue.html) – 队列会保存失败的事件，直到检索这些事件为止。如果您希望单个实体（例如 Lambda 函数或 CloudWatch 告警）来处理失败事件，请选择 Amazon SQS 标准队列。有关更多信息，请参阅 [将 Lambda 与 Amazon SQS 结合使用](with-sqs.md)。
+ [Amazon SNS 主题](https://docs.aws.amazon.com/sns/latest/gsg/CreateTopic.html) – 主题将失败的事件中继到一个或多个目标。如果您希望多个实体对失败事件采取行动，请选择 Amazon SNS 标准主题。例如，您可以配置主题以将事件发送到电子邮件地址、Lambda 函数或 HTTP 端点。有关更多信息，请参阅 [使用 Amazon SNS 通知调用 Lambda 函数](with-sns.md)。

要将事件发送到队列或主题，您的函数需要其他权限。添加具有函数[执行角色](lambda-intro-execution-role.md)[所需权限](#destinations-permissions)的策略。如果已使用客户自主管理型 AWS KMS 密钥加密目标队列或主题，则请确保您的函数的执行角色和密钥[基于资源的策略](https://docs.aws.amazon.com/kms/latest/developerguide/key-policies.html)都包含相关权限。

创建目标并更新函数的执行角色后，将死信队列添加到函数中。您可以配置多个函数，以便将事件发送到同一目标。

------
#### [ Console ]

1. 打开 Lamba 控制台的[函数](https://console.aws.amazon.com/lambda/home#/functions)页面。

1. 选择函数。

1. 选择 **Configuration（配置）**，然后选择 **Asynchronous invocation（异步调用）**。

1. 在 **Asynchronous invocation (异步调用)** 下，选择 **Edit (编辑)**。

1. 将**死信队列服务**设置为 **Amazon SQS** 或 **Amazon SNS**。

1. 选择目标队列或主题。

1. 选择**保存**。

------
#### [ AWS CLI ]

要通过 AWS CLI 配置死信队列，请使用 [update-function-configuration](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/update-function-configuration.html) 命令。

```
aws lambda update-function-configuration \
  --function-name my-function \
  --dead-letter-config TargetArn=arn:aws:sns:us-east-1:123456789012:my-topic
```

------

Lambda 按原样将事件发送到死信队列，并在属性中包含其他信息。您可以使用此信息来标识函数返回的错误，或者将事件与日志或 AWS X-Ray 跟踪相关联。

**死信队列消息属性**
+ **RequestID**（字符串）– 调用请求的 ID。请求 ID 显示在函数日志中。您还可以使用 X-Ray 开发工具包，在跟踪中的属性上记录请求 ID。然后，可以在 X-Ray 控制台中按请求 ID 搜索跟踪。
+ **ErrorCode**（数字）– HTTP 状态代码。
+ **ErrorMessage**（字符串）– 错误消息的第一个 1 KB 文本块。

如果 Lambda 无法向死信队列发送消息，则会删除该事件并发出 [DeadLetterErrors](monitoring-metrics-types.md) 指标。之所以发生这种情况，可能是由于缺少权限，或者消息的总大小超过目标队列或主题的限制。例如，假设正文大小接近 1 MB 的 Amazon SNS 通知触发了一个导致错误的函数。在这种情况下，Amazon SNS 添加的事件数据加上 Lambda 添加的属性，可能会导致消息超过死信队列中允许的最大大小。

如果您正在使用 Amazon SQS 作为事件源，请在 Amazon SQS 队列本身而不是 Lambda 函数上配置死信队列。有关更多信息，请参阅 [将 Lambda 与 Amazon SQS 结合使用](with-sqs.md)。

# 调用持久性 Lambda 函数
<a name="durable-invocation"></a>

可以使用与默认 Lambda 函数相同的方法来调用持久性 Lambda 函数，但针对长时间运行的执行有一些重要注意事项。本节介绍持久性函数的调用模式、执行管理和最佳实践。

## 同步调用限制
<a name="synchronous-invocation-limits"></a>

持久性 Lambda 函数的同步调用限制为 15 分钟，这与默认 Lambda 函数相同。如果您的持久性函数需要运行超过 15 分钟，则必须异步调用该函数。

**何时使用同步调用：**适用于那些在 15 分钟内即可完成的持久性函数，以及那些您需要即时结果的情况，例如快速审批流程或短时间的数据处理任务。

## 长时间运行的工作流程的异步调用
<a name="asynchronous-invocation"></a>

对于运行时间可能超过 15 分钟的持久性函数，请使用异步调用。这使得该函数能够在您的客户端接收到即时确认的同时继续运行。

------
#### [ TypeScript ]

```
import { LambdaClient, InvokeCommand } from "@aws-sdk/client-lambda";

const client = new LambdaClient({});

// Asynchronous invocation
const command = new InvokeCommand({
  FunctionName: "my-durable-function",
  InvocationType: "Event", // Asynchronous
  Payload: JSON.stringify({ orderId: "12345" })
});

await client.send(command);
```

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

```
import boto3
import json

client = boto3.client('lambda')

# Asynchronous invocation
response = client.invoke(
    FunctionName='my-durable-function',
    InvocationType='Event',  # Asynchronous
    Payload=json.dumps({'order_id': '12345'})
)
```

------

## 执行管理 API
<a name="execution-management-apis"></a>

Lambda 提供相关 API 来管理和监控持久性函数的执行情况，包括列出执行记录、获取执行状态以及停止正在运行的执行。

------
#### [ TypeScript ]

```
// Get execution status
const statusCommand = new InvokeCommand({
  FunctionName: "my-durable-function",
  InvocationType: "RequestResponse",
  Payload: JSON.stringify({ 
    action: "getStatus", 
    executionId: "exec-123" 
  })
});

const result = await client.send(statusCommand);
```

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

```
# Get execution status
response = client.invoke(
    FunctionName='my-durable-function',
    InvocationType='RequestResponse',
    Payload=json.dumps({
        'action': 'get_status',
        'execution_id': 'exec-123'
    })
)
```

------

# Lambda 如何处理来自基于流和队列的事件源的记录
<a name="invocation-eventsourcemapping"></a>

*事件源映射*是一种 Lambda 资源，它从流或基于队列的服务中读取项目并调用包含批次记录的函数。在事件源映射内，称为*事件轮询器*的资源会主动轮询新消息并调用函数。默认情况下，Lambda 会自动扩展事件轮询器，但对于某些事件源类型，您可以使用[预调配模式](#invocation-eventsourcemapping-provisioned-mode)来控制专用于事件源映射的事件轮询器的最小和最大数量。

以下服务使用事件源映射调用 Lambda 函数：
+ [Amazon DocumentDB（兼容 MongoDB）（Amazon DocumentDB）](with-documentdb.md)
+ [Amazon DynamoDB](with-ddb.md)
+ [Amazon Kinesis](with-kinesis.md)
+ [Amazon MQ](with-mq.md)
+ [Amazon Managed Streaming for Apache Kafka (Amazon MSK)](with-msk.md)
+ [自行管理的 Apache Kafka](with-kafka.md)
+ [Amazon Simple Queue Service (Amazon SQS)](with-sqs.md)

**警告**  
Lambda 事件源映射至少处理每个事件一次，有可能出现重复处理记录的情况。为避免与重复事件相关的潜在问题，我们强烈建议您将函数代码设为幂等性。要了解更多信息，请参阅 AWS 知识中心的[如何让我的 Lambda 函数保持幂等性](https://repost.aws/knowledge-center/lambda-function-idempotent)。

## 事件源映射与直接触发器的区别
<a name="eventsourcemapping-trigger-difference"></a>

某些 AWS 服务可以使用*触发器*直接调用 Lambda 函数。这些服务将事件推送到 Lambda，并在指定事件发生时立即调用该函数。触发器适用于离散事件和实时处理。当您[使用 Lambda 控制台创建触发器](lambda-services.md#lambda-invocation-trigger)时，控制台会与相应的 AWS 服务交互以配置该服务的事件通知。触发器实际上由生成事件的服务而不是 Lambda 存储和管理。以下是一些使用触发器调用 Lambda 函数的服务示例：
+ **Amazon Simple Storage Service（Amazon S3）：**当在存储桶中创建、删除或修改对象时调用函数。有关更多信息，请参阅 [教程：使用 Amazon S3 触发器调用 Lambda 函数](with-s3-example.md)。
+ **Amazon Simple Notiﬁcation Service（Amazon SNS）：**将消息发布到 SNS 主题时调用函数。有关更多信息，请参阅 [教程：将 AWS Lambda 与 Amazon Simple Notification Service 结合使用](with-sns-example.md)。
+ **Amazon API Gateway：**在向特定端点发出 API 请求时调用函数。有关更多信息，请参阅 [使用 Amazon API Gateway 端点调用 Lambda 函数](services-apigateway.md)。

事件源映射是在 Lambda 服务中创建和管理的 Lambda 资源。事件源映射旨在处理来自队列的大量流数据或消息。分批处理来自流或队列的记录比单独处理记录更高效。

## 批处理行为
<a name="invocation-eventsourcemapping-batching"></a>

预设情况下，事件源映射会将记录合并为单个有效载荷进行批处理，并由 Lambda 将其发送到您的函数。要微调批处理行为，您可以配置批处理时段（[MaximumBatchingWindowInSeconds](https://docs.aws.amazon.com/lambda/latest/api/API_CreateEventSourceMapping.html#lambda-CreateEventSourceMapping-request-MaximumBatchingWindowInSeconds)）和批处理大小（[BatchSize](https://docs.aws.amazon.com/lambda/latest/api/API_CreateEventSourceMapping.html#lambda-CreateEventSourceMapping-response-BatchSize)）。批处理时段是将记录收集到单个有效载荷中的最长时间。批处理大小是单个批处理中的最大记录数。满足以下三个条件中的任意一个时，Lambda 会调用您的函数：
+ **批处理时段达到其最大值。**默认的批处理时段行为因特定的事件源而异。
  + **对于 Kinesis、DynamoDB 和 Amazon SQS 事件源：**原定设置的批处理时段是 0 秒。这意味着，一旦记录可用，Lambda 就会调用您的函数。要设置批处理时段，请配置 `MaximumBatchingWindowInSeconds`。您可以将此参数设置为介于 0 秒到 300 秒之间的任意值，以 1 秒为增量。如果您配置了批处理时段，则下一个时段将在上一个函数调用完成后立即开始计算。
  + **对于 Amazon MSK、自托管式 Apache Kafka、Amazon MQ 和 Amazon DocumentDB 事件源：**默认批处理时段为 500 毫秒。您可以将 `MaximumBatchingWindowInSeconds` 配置为介于 0 秒到 300 秒之间的任意值，以秒的整数倍调整。在 Kafka 事件源映射的预置模式中，如果您配置了批处理时段，则下一个时段将在上一批处理完成后立即开始计算。在非预置 Kafka 事件源映射中，如果您配置了批处理时段，则下一个时段将在上一个函数调用完成后立即开始计算。要最大限度地减小在预置模式下使用 Kafka 事件源映射的延迟，请将 `MaximumBatchingWindowInSeconds` 设置为 0。此设置可确保 Lambda 在完成当前函数调用后立即开始处理下一个批次。有关低延迟处理的更多信息，请参阅[低延迟 Apache Kafka](with-kafka-low-latency.md)。
  + **对于 Amazon MQ 和 Amazon DocumentDB 事件源：**默认批处理时段为 500 毫秒。您可以将 `MaximumBatchingWindowInSeconds` 配置为介于 0 秒到 300 秒之间的任意值，以秒的整数倍调整。第一条记录到达后，批处理时段将立即开始计算。
**注意**  
由于您只能以秒的整数倍调整 `MaximumBatchingWindowInSeconds`，因此无法在更改该值后恢复到 500 毫秒的默认批处理时段。要恢复原定设置的批处理时段，必须创建新的事件源映射。
+ **达到批处理大小。**最小批处理大小为 1。原定设置和最大批处理大小取决于事件源。有关这些值的详细信息，请参阅 `CreateEventSourceMapping` API 操作的 [BatchSize](https://docs.aws.amazon.com/lambda/latest/api/API_CreateEventSourceMapping.html#lambda-CreateEventSourceMapping-request-BatchSize) 规范。
+ **有效载荷大小达到 [6MB](https://docs.aws.amazon.com/lambda/latest/dg/gettingstarted-limits.html)。**您不能修改此限制。

下图演示了这三个条件。假设批处理时段从 `t = 7` 秒开始。在第一种场景中，批处理时段累积 5 条记录后在 `t = 47` 秒达到 40 秒的最大值。在第二种场景中，批处理大小在批处理时段到期之前达到 10，因此批处理时段会提前结束。在第三种场景中，在批处理时段到期之前达到最大有效载荷大小，因此批处理时段会提前结束。

![\[\]](http://docs.aws.amazon.com/zh_cn/lambda/latest/dg/images/batching-window.png)


建议您测试不同批处理和记录的大小，这样每个事件源的轮询频率都会根据函数完成任务的速度进行调整。[CreateEventSourceMapping](https://docs.aws.amazon.com/lambda/latest/api/API_CreateEventSourceMapping.html) `BatchSize` 参数控制每次调用可向函数发送记录的最大数量。批处理大小如果较大，通常可以更有效地吸收大量记录的调用开销，从而增加吞吐量。

Lambda 在发送下次批处理之前不会等待任何配置的[扩展](lambda-extensions.md)完成。换句话说，扩展可能会在 Lambda 处理下一批记录时继续运行。如果您违反了账户的任何[并发](lambda-concurrency.md)设置或限制，可能会导致节流问题。要检测这是否是潜在问题，请监控函数并检查所显示的[并发指标](monitoring-concurrency.md#general-concurrency-metrics)是否高于事件源映射的预期。由于调用间隔时间较短，Lambda 可能会短暂报告高于分片数量的并发使用量。即使对于没有扩展名的 Lambda 函数也是如此。

预设情况下，如果函数返回错误，事件源映射会重新处理整个批处理，直到函数成功，或直到批处理中的项目到期。为确保按顺序处理，在错误得到解决之前，事件源映射会暂停处理受影响的分片。对于流源（DynamoDB 和 Kinesis），可以配置 Lambda 在函数返回错误时重试的最大次数。批次未到达您的函数时出现的服务错误或节流，不计入重试次数。您还可以配置事件源映射，以便在丢弃事件批处理时将调用记录发送到[目标](invocation-async-retain-records.md#invocation-async-destinations)。

## 预调配模式
<a name="invocation-eventsourcemapping-provisioned-mode"></a>

Lambda 事件源映射使用事件轮询器对您的事件源进行轮询，以获取新消息。默认情况下，Lambda 根据消息量管理这些轮询器的自动扩缩。当消息流量增加时，Lambda 会自动增加用于处理负载的事件轮询器数量，并在流量减少时减少事件轮询器数量。

在预置模式下，您可以通过定义专用轮询资源的最低和最高限制来微调事件源映射的吞吐量，这些资源始终处于准备状态以应对预期的流量模式。这些资源能够自动扩展 3 倍的速度，以应对事件流量的突然激增，并提供高出 16 倍的容量来处理数百万个事件。这样有助于您构建响应速度快且具有严格性能要求的事件驱动型工作负载。

在 Lambda 中，事件轮询器是一种计算单元，其吞吐能力因事件源类型的不同而有所差异。对于 Amazon MSK 和自行管理的 Apache Kafka，每个事件轮询器最多可以处理 5 MB/秒的吞吐量或最多 5 次并发调用。例如，如果您的事件源平均生成 1MB 的有效载荷，而您的函数平均运行时间为 1 秒，则单一的 Kafka 事件轮询器能够支持每秒 5MB 的吞吐量以及 5 次并发的 Lambda 调用（假设没有有效载荷的转换操作）。对于 Amazon SQS，每个事件轮询器最多可以处理 1 MB/秒的吞吐量或最多 10 次并发调用。使用预置模式会产生额外成本，具体取决于您的事件轮询器使用情况。有关定价的详细信息，请参阅 [AWS Lambda 定价](https://aws.amazon.com/lambda/pricing/)。

预置模式适用于 Amazon MSK、自行管理的 Apache Kafka 和 Amazon SQS 事件源。虽然并发设置允许您控制函数的扩展，但预调配模式允许您控制事件源映射的吞吐量。为确保获得最佳性能，您可能需要分别调整这两个设置。

预置模式非常适合需要稳定的事件处理延迟的实时应用程序，例如金融服务公司处理市场数据源、电子商务平台提供实时个性化推荐以及游戏公司管理实时玩家互动等。

每个事件轮询器均支持不同的吞吐能力：
+ 对于 Amazon MSK 和自行管理的 Apache Kafka：最高可以处理 5 MB/秒的吞吐量或最多 5 次并发调用
+ 对于 Amazon SQS：最多可以处理 1 MB/秒 的吞吐量或最多 10 次并发调用，或者每秒最多进行 10 次 SQS 轮询 API 调用。

对于 Amazon SQS 事件源映射，您可以将轮询器的最小数量设置在 2 到 200 之间，默认值为 2；同时，将最大数量设置在 2 到 2000 之间，默认值为 200。Lambda 会根据您所配置的最小值和最大值来扩展事件轮询器的数量，能够迅速将并发次数提升至最多每分钟 1000 次，从而实现对事件的一致性低延迟处理。

对于 Kafka 事件源映射，您可以将轮询器的最小数量设置在 1 到 200 之间（默认值为 1），同时将最大数量设置在 1 到 2000 之间（默认值为 200）。Lambda 会根据您主题中的事件积压情况，在您配置的最小值和最大值之间扩缩事件轮询器的数量，从而实现对事件的低延迟处理。

请注意，对于 Amazon SQS 事件源，最大并发设置不能与预置模式一起使用。使用预置模式时，您可以通过最大的事件轮询器设置来控制并发性。

有关配置预调配模式的详细信息，请参阅以下各部分：
+ [为 Amazon MSK 事件源映射配置预调配模式](kafka-scaling-modes.md)
+ [为自行管理 Apache Kafka 事件源映射配置预调配模式](kafka-scaling-modes.md#kafka-provisioned-mode)
+ [对 Amazon SQS 事件源映射使用预置模式](with-sqs.md#sqs-provisioned-mode)

要最大限度地降低预置模式下的延迟，请将 `MaximumBatchingWindowInSeconds` 设置为 0。此设置可确保 Lambda 在完成当前函数调用后立即开始处理下一个批次。有关低延迟处理的更多信息，请参阅[低延迟 Apache Kafka](with-kafka-low-latency.md)。

配置预调配模式后，您可以通过监控 `ProvisionedPollers` 指标来观测事件轮询器对您的工作负载的使用情况。有关更多信息，请参阅 [事件源映射指标](monitoring-metrics-types.md#event-source-mapping-metrics)。

## 事件源映射 API
<a name="event-source-mapping-api"></a>

要使用 [AWS Command Line Interface（AWS CLI）](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) 或 [AWS SDK](https://aws.amazon.com/getting-started/tools-sdks/) 来管理事件源，可以使用以下 API 操作：
+ [CreateEventSourceMapping](https://docs.aws.amazon.com/lambda/latest/api/API_CreateEventSourceMapping.html)
+ [ListEventSourceMappings](https://docs.aws.amazon.com/lambda/latest/api/API_ListEventSourceMappings.html)
+ [GetEventSourceMapping](https://docs.aws.amazon.com/lambda/latest/api/API_GetEventSourceMapping.html)
+ [UpdateEventSourceMapping](https://docs.aws.amazon.com/lambda/latest/api/API_UpdateEventSourceMapping.html)
+ [DeleteEventSourceMapping](https://docs.aws.amazon.com/lambda/latest/api/API_DeleteEventSourceMapping.html)

# 在事件源映射上使用标签
<a name="tags-esm"></a>

对事件源映射进行标记可以组织和管理资源。标签是与资源关联的自由格式键值对，在 AWS 服务中受支持。有关标签用例的更多信息，请参阅《Tagging AWS Resources and Tag Editor Guide》**中的 [Common tagging strategies](https://docs.aws.amazon.com//tag-editor/latest/userguide/best-practices-and-strats.html#tag-strategies)。

事件源映射与函数相关联，而函数也可以有自己的标签。事件源映射并不会自动继承函数的标签。可以使用 AWS Lambda API 来查看和更新标签。在 Lambda 控制台中管理特定事件源映射时，还可以查看和更新标签，包括将预置模式用于 Amazon SQS 的那些标签。

## 使用标签所需的权限
<a name="esm-tags-required-permissions"></a>

要允许 AWS Identity and Access Management（IAM）身份（用户、组或角色）读取资源或为其设置标签，请授予该身份相应的权限：
+ **lambda:ListTags** – 当资源有标签时，将此权限授予需要在其上调用 `ListTags` 的任何人。对于带标签的函数，`GetFunction` 也需要此权限。
+ **lambda:TagResource** – 将此权限授予需要调用 `TagResource` 或执行在创建时授予标记的操作的任何人。

或者，也可以考虑授予 **lambda:UntagResource** 权限以允许 `UntagResource` 调用该资源。

有关更多信息，请参阅 [Lambda 的基于身份的 IAM policy](access-control-identity-based.md)。

## 通过 Lambda 控制台使用标签
<a name="tags-esm-console"></a>

您可以使用 Lambda 控制台创建带标签的事件源映射、向现有事件源映射添加标签以及按标签筛选事件源映射，包括在预置模式中为 Amazon SQS 配置的那些映射。

使用 Lambda 控制台为支持的流服务和基于队列的服务添加触发器时，Lambda 会自动创建事件源映射。有关这些事件源的更多信息，请参阅 [Lambda 如何处理来自基于流和队列的事件源的记录](invocation-eventsourcemapping.md)。若要在控制台中创建事件源映射，必须满足以下先决条件：
+ 函数
+ 来自受影响服务的事件源

可在用于创建或更新触发器的同一用户界面中添加标签。

**在创建事件源映射时添加标签**

1. 打开 Lamba 控制台的[函数](https://console.aws.amazon.com/lambda/home#/functions)页面。

1. 选择函数的名称。

1. 在 **Function overview**（函数概览）下，选择 **Add trigger**（添加触发器）。

1. 在**触发器配置**下的下拉列表中，选择事件源所属服务的名称。

1. 为事件源提供核心配置。有关配置事件源的更多信息，请参阅 [使用来自其 AWS 他服务的事件调用 Lambda](lambda-services.md)中相关服务的部分。

1. 在**事件源映射配置**下选择**其他设置**。

1. 在**标签**下选择**添加新标签**。

1. 在**键**字段中输入标签键。有关标记限制的信息，请参阅《Tagging AWS Resources and Tag Editor Guide》中的 [Tag naming limits and requirements](https://docs.aws.amazon.com//tag-editor/latest/userguide/best-practices-and-strats.html#id_tags_naming_best_practices)。**

1. 选择**添加**。

**向现有事件源映射添加标签**

1. 在 Lambda 控制台中打开[事件源映射](https://console.aws.amazon.com/lambda/home#/event-source-mappings)。

1. 在资源列表中，选择与**函数**和**事件源 ARN** 对应的事件源映射的 **UUID**。

1. 从**常规配置**窗格下方的选项卡列表中选择**标签**。

1. 选择**管理标签**。

1. 选择 **Add new tag（添加新标签）**。

1. 在**键**字段中输入标签键。有关标记限制的信息，请参阅《Tagging AWS Resources and Tag Editor Guide》中的 [Tag naming limits and requirements](https://docs.aws.amazon.com//tag-editor/latest/userguide/best-practices-and-strats.html#id_tags_naming_best_practices)。**

1. 选择**保存**。

**按标签筛选事件源映射**

1. 在 Lambda 控制台中打开[事件源映射](https://console.aws.amazon.com/lambda/home#/event-source-mappings)。

1. 选择搜索框。

1. 在下拉列表中，从**标签**副标题下方选择标签键。

1. 选择**使用：“tag-name”**查看所有使用此键标记的事件源映射，或者选择一个**运算符**进一步按值筛选。

1. 选择标签值以按标签键和值的组合进行筛选。

搜索框还支持搜索标签键。输入键名称，即可在列表中查找该键。

## 通过 AWS CLI 使用标签
<a name="tags-esm-cli"></a>

可以使用 Lambda API 在现有 Lambda 资源（包括事件源映射）上添加和删除标签。还可以在创建事件源映射时添加标签，这样就可以在资源的整个生命周期中对其进行标记。

### 使用 Lambda 标签 API 更新标签
<a name="tags-esm-api-config"></a>

可以通过 [TagResource](https://docs.aws.amazon.com/lambda/latest/api/API_TagResource.html) 和 [UntagResource](https://docs.aws.amazon.com/lambda/latest/api/API_UntagResource.html) API 操作，添加和删除受支持 Lambda 资源的标签。

可以使用 AWS CLI 调用这些操作。要向现有资源添加标签，请使用 `tag-resource` 命令。此示例添加了两个标签，一个带有键 *Department*，另一个带有键 *CostCenter*。

```
aws lambda tag-resource \
--resource arn:aws:lambda:us-east-2:123456789012:resource-type:my-resource \
--tags Department=Marketing,CostCenter=1234ABCD
```

要删除标签，请使用 `untag-resource` 命令。此示例删除了键为 *Department* 的标签。

```
aws lambda untag-resource --resource arn:aws:lambda:us-east-1:123456789012:resource-type:resource-identifier \
--tag-keys Department
```

### 在创建事件源映射时添加标签
<a name="tags-esm-on-create"></a>

若要使用标签创建 Lambda 事件源映射，请使用 [CreateEventSourceMapping](https://docs.aws.amazon.com/lambda/latest/api/API_CreateEventSourceMapping.html) API 操作。指定 `Tags` 参数。可以使用 `create-event-source-mapping` AWS CLI 命令和 `--tags` 选项调用此操作。有关使用此 CLI 命令的更多信息，请参阅《AWS CLI Command Reference》中的 [create-event-source-mapping](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/create-event-source-mapping.html)。**

在将 `Tags` 参数与 `CreateEventSourceMapping` 一起使用之前，请确保角色拥有标记资源的权限以及此操作所需的常规权限。有关标记权限的更多信息，请参阅 [使用标签所需的权限](#esm-tags-required-permissions)。

### 使用 Lambda 标签 API 查看标签
<a name="tags-esm-api-view"></a>

要查看应用于特定 Lambda 资源的标签，请使用 `ListTags` API 操作。有关更多信息，请参阅 [ListTags](https://docs.aws.amazon.com/lambda/latest/api/API_ListTags.html)。

可以提供 ARN（Amazon 资源名称），以使用 `list-tags` AWS CLI 命令调用此操作。

```
aws lambda list-tags --resource arn:aws:lambda:us-east-1:123456789012:resource-type:resource-identifier
```

### 按标签筛选资源
<a name="tags-esm-filtering"></a>

您可以使用 AWS Resource Groups Tagging API [GetResources](https://docs.aws.amazon.com/resourcegroupstagging/latest/APIReference/API_GetResources.html) API 操作按标签筛选资源。`GetResources` 操作最多可接收 10 个筛选条件，每个筛选条件包含一个标签键和最多 10 个标签值。提供具有 `ResourceType` 的 `GetResources`，可按特定资源类型进行筛选。

可以使用 `get-resources` AWS CLI 命令调用此操作。有关使用 `get-resources` 的示例，请参阅《AWS CLI Command Reference》**中的 [get-resources](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/resourcegroupstaggingapi/get-resources.html#examples)。

# 控制 Lambda 向您的函数发送的事件
<a name="invocation-eventfiltering"></a>

您可以使用事件筛选，控制 Lambda 将流或队列中的哪些记录发送给函数。例如，您可以添加筛选条件，以便函数仅处理包含特定数据参数的 Amazon SQS 消息。事件筛选仅适用于某些事件源映射。您可以将筛选条件添加到以下 AWS 服务 的事件源映射：
+ Amazon DynamoDB
+ Amazon Kinesis Data Streams
+ Amazon MQ
+ Amazon Managed Streaming for Apache Kafka (Amazon MSK)
+ 自行管理的 Apache Kafka
+ Amazon Simple Queue Service (Amazon SQS)

有关在特定事件源中筛选的具体信息，请参阅 [使用具有不同 AWS 服务 的筛选条件](#filtering-by-service)。Lambda 不支持 Amazon DocumentDB 的事件筛选。

默认情况下，您可以为单个事件源映射定义最多五个不同的筛选条件。筛选条件是使用逻辑运算符 OR 组合起来的。如果来自事件源的记录符合一个或多个筛选条件，则 Lambda 会将该记录包含在发送到函数的下一个事件中。如果不符合任何筛选条件，Lambda 会丢弃该记录。

**注意**  
如果您需要为一个事件源定义 5 个以上的筛选条件，可请求将每个事件源的配额提高到 10 个筛选条件。如果您尝试添加的筛选条件数量超过当前配额允许的数量，则在创建事件源时，Lambda 将会返回错误。

**Topics**
+ [

## 了解事件筛选基础知识
](#filtering-basics)
+ [

## 处理不符合筛选条件的记录
](#filtering-criteria-not-met)
+ [

## 筛选条件规则语法
](#filtering-syntax)
+ [

## 将筛选条件附加到事件源映射（控制台）
](#filtering-console)
+ [

## 将筛选条件附加到事件源映射（AWS CLI）
](#filtering-cli)
+ [

## 将筛选条件附加到事件源映射（AWS SAM）
](#filtering-sam)
+ [

## 筛选条件的加密
](#filter-criteria-encryption)
+ [

## 使用具有不同 AWS 服务 的筛选条件
](#filtering-by-service)

## 了解事件筛选基础知识
<a name="filtering-basics"></a>

筛选条件 (`FilterCriteria`) 对象是一个由筛选条件 (`Filters`) 列表组成的结构。每个筛选条件都是一个用于定义事件筛选模式 (`Pattern`) 的结构。模式是 JSON 筛选条件规则的字符串表示。`FilterCriteria` 对象的结构如下所示。

```
{
   "Filters": [
        {
            "Pattern": "{ \"Metadata1\": [ rule1 ], \"data\": { \"Data1\": [ rule2 ] }}"
        }
    ]
}
```

为了更清楚起见，以下是在纯 JSON 中展开的筛选条件 `Pattern` 的值。

```
{
    "Metadata1": [ rule1 ],
    "data": {
        "Data1": [ rule2 ]
    }
}
```

筛选条件模式可以包括元数据属性和/或数据属性。可用元数据参数和数据参数的格式根据充当事件源的 AWS 服务 而有所不同。例如，假设事件源映射从 Amazon SQS 队列接收到以下记录：

```
{
    "messageId": "059f36b4-87a3-44ab-83d2-661975830a7d",
    "receiptHandle": "AQEBwJnKyrHigUMZj6rYigCgxlaS3SLy0a...",
    "body": "{\\n \"City\": \"Seattle\",\\n \"State\": \"WA\",\\n \"Temperature\": \"46\"\\n}",
    "attributes": {
        "ApproximateReceiveCount": "1",
        "SentTimestamp": "1545082649183",
        "SenderId": "AIDAIENQZJOLO23YVJ4VO",
        "ApproximateFirstReceiveTimestamp": "1545082649185"
    },
    "messageAttributes": {},
    "md5OfBody": "e4e68fb7bd0e697a0ae8f1bb342846b3",
    "eventSource": "aws:sqs",
    "eventSourceARN": "arn:aws:sqs:us-east-2:123456789012:my-queue",
    "awsRegion": "us-east-2"
}
```
+ **元数据属性**是包含有关创建记录的事件的信息的字段。在示例 Amazon SQS 记录中，元数据属性包括 `messageID`、`eventSourceArn` 和 `awsRegion` 等字段。
+ **数据属性**是包含流或队列中数据的记录的字段。在 Amazon SQS 事件示例中，数据字段的键是 `body`，数据属性是字段 `City`、`State` 和 `Temperature`。

不同类型的事件源为其数据字段使用不同的键值。要对数据属性进行筛选，请确保在筛选条件的模式中使用正确的键。如需数据筛选键列表，并查看每个支持的 AWS 服务 的筛选模式示例，请参阅 [使用具有不同 AWS 服务 的筛选条件](#filtering-by-service)。

事件筛选可处理多层 JSON 筛选。例如，考虑以下来自 DynamoDB 流的记录片段：

```
"dynamodb": {
    "Keys": {
        "ID": {
            "S": "ABCD"
        }
        "Number": {
            "N": "1234"
    },
    ...
}
```

假设您只想处理排序键值 `Number` 为 4567 的记录。在这种情况下，您的 `FilterCriteria` 对象与以下类似：

```
{
    "Filters": [
        {
            "Pattern": "{ \"dynamodb\": { \"Keys\": { \"Number\": { \"N\": [ "4567" ] } } } }"
        }
    ]
}
```

为了更清楚起见，以下是在纯 JSON 中展开的筛选条件 `Pattern` 的值。

```
{
    "dynamodb": {
        "Keys": {
            "Number": {
                "N": [ "4567" ]
                }
            }
        }
}
```

## 处理不符合筛选条件的记录
<a name="filtering-criteria-not-met"></a>

Lambda 如何处理不符合筛选条件的记录取决于事件源。
+ 对于 **Amazon SQS**，如果消息不符合筛选条件，Lambda 会自动从队列中删除该消息。您无需在 Amazon SQS 中手动删除这些消息。
+ 对于 **Kinesis** 和 **DynamoDB**，在筛选条件评估记录后，流迭代器会跳过此记录。如果记录不符合筛选条件，您无需从事件源手动删除记录。保留期结束后，Kinesis 和 DynamoDB 会自动删除这些旧记录。如果您希望提前删除记录，请参阅[更改数据保留期](https://docs.aws.amazon.com/streams/latest/dev/kinesis-extended-retention.html)。
+ 对于 **Amazon MSK**、**自行管理的 Apache Kafka** 和 **Amazon MQ** 消息，Lambda 会丢弃与筛选条件中包含的所有字段不匹配的消息。对于 Amazon MSK 和自行管理的 Apache Kafka，Lambda 在成功调用函数后，会为匹配和不匹配的消息提交偏移。对于 Amazon MQ，Lambda 在成功调用函数后确认匹配的消息，并在筛选不匹配的消息时确认此类消息。

## 筛选条件规则语法
<a name="filtering-syntax"></a>

对于筛选条件规则，Lambda 支持 Amazon EventBridge 规则，并使用与 EventBridge 相同的语法。有关更多信息，请参阅 *Amazon EventBridge 用户指南*中的 [Amazon EventBridge 事件模式](https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-event-patterns.html)。

以下是可用于 Lambda 事件筛选的所有比较运算符的汇总。


| 比较运算符 | 示例 | Rule syntax（规则语法） | 
| --- | --- | --- | 
|  Null  |  用户 ID 为空  |  "UserID": [ null ]  | 
|  空  |  姓氏为空  |  "LastName": [""]  | 
|  Equals  |  名字为“Alice”  |  "Name": [ "Alice" ]  | 
|  等于（忽略大小写）  |  名字为“Alice”  |  “Name”：[ \$1 "equals-ignore-case": "alice" \$1 ]  | 
|  And  |  位置为“纽约”，日期为“星期一”  |  "Location": [ "New York" ], "Day": ["Monday"]  | 
|  Or  |  付款类型为“信用卡”或“借记卡”  |  "PaymentType": [ "Credit", "Debit"]  | 
|  或（多个字段）  |  位置为“纽约”，或日期为“星期一”。  |  “\$1or”：[ \$1 "Location": [ "New York" ] \$1, \$1 "Day": [ "Monday" ] \$1 ]   | 
|  非  |  天气是除“下雨”以外的任何天气  |  "Weather": [ \$1 "anything-but": [ "Raining" ] \$1 ]  | 
|  数值（等于）  |  价格为 100  |  "Price": [ \$1 "numeric": [ "=", 100 ] \$1 ]  | 
|  数值（范围）  |  价格大于 10，且小于等于 20  |  "Price": [ \$1 "numeric": [ ">", 10, "<=", 20 ] \$1 ]  | 
|  存在  |  产品名存在  |  "ProductName": [ \$1 "exists": true \$1 ]  | 
|  不存在  |  产品名不存在  |  "ProductName": [ \$1 "exists": false \$1 ]  | 
|  始于  |  地区位于美国  |  "Region": [ \$1"prefix": "us-" \$1 ]  | 
|  结尾为  |  文件名以 .png 扩展名结尾。  |  “FileName”：[ \$1 "suffix": ".png" \$1 ]   | 

**注意**  
与 EventBridge 一样，对于字符串，Lambda 使用精确的逐个字符匹配，而不进行小写化或任何其他字符串标准化。此外，对于数值，Lambda 使用字符串表示。例如，300、300.0 和 3.0e2 不相等。

请注意，Exists 运算符仅适用于事件源 JSON 中的叶节点，与中间节点不匹配。例如，使用以下 JSON，筛选条件模式 `{ "person": { "address": [ { "exists": true } ] } }"` 找不到匹配项，因为 `"address"` 是中间节点。

```
{
  "person": {
    "name": "John Doe",
    "age": 30,
    "address": {
      "street": "123 Main St",
      "city": "Anytown",
      "country": "USA"
    }
  }
}
```

## 将筛选条件附加到事件源映射（控制台）
<a name="filtering-console"></a>

按照以下步骤使用 Lambda 控制台创建包含筛选条件的新事件源映射。

**使用筛选条件创建新事件源映射（控制台）**

1. 打开 Lamba 控制台的[函数](https://console.aws.amazon.com/lambda/home#/functions)页面。

1. 选择要为其创建事件源映射的函数名称。

1. 在 **Function overview**（函数概览）下，选择 **Add trigger**（添加触发器）。

1. 对于 **Trigger configuration**（触发器配置），请选择支持事件筛选的触发器类型。有关受支持的服务列表，请参阅本页开头的列表。

1. 展开**其他设置**。

1. 在 **Filter criteria**（筛选条件）下，选择 **Add**（添加），然后定义并输入筛选条件。例如，您可以输入以下筛选条件。

   ```
   { "Metadata" : [ 1, 2 ] }
   ```

   这指示 Lambda 只处理字段 `Metadata` 等于 1 或 2 的记录。您可以继续选择**添加**，以添加更多筛选条件，但不得超过最大允许数量。

1. 添加完筛选条件后，选择**保存**。

使用控制台输入筛选条件时，只需输入筛选条件模式，无需提供 `Pattern` 键或转义引号。在上述说明的第 6 步中，`{ "Metadata" : [ 1, 2 ] }` 对应于下面的 `FilterCriteria`。

```
{
   "Filters": [
      {
          "Pattern": "{ \"Metadata\" : [ 1, 2 ] }"
      }
   ]
}
```

在控制台中创建事件源映射后，您可以在触发器详细信息中看到格式化后的 `FilterCriteria`。有关使用控制台创建事件筛选条件的更多示例，请参阅 [使用具有不同 AWS 服务 的筛选条件](#filtering-by-service)。

## 将筛选条件附加到事件源映射（AWS CLI）
<a name="filtering-cli"></a>

假设您希望事件源映射具有以下 `FilterCriteria`：

```
{
   "Filters": [
      {
          "Pattern": "{ \"Metadata\" : [ 1, 2 ] }"
      }
   ]
}
```

要使用 AWS Command Line Interface（AWS CLI）创建包含这些筛选条件的新事件源映射，请运行以下命令。

```
aws lambda create-event-source-mapping \
    --function-name my-function \
    --event-source-arn arn:aws:sqs:us-east-2:123456789012:my-queue \
    --filter-criteria '{"Filters": [{"Pattern": "{ \"Metadata\" : [ 1, 2 ]}"}]}'
```

此 [create-event-source-mapping](https://docs.aws.amazon.com/cli/latest/reference/lambda/create-event-source-mapping.html) 命令将为包含指定 `FilterCriteria` 的函数 `my-function` 创建新的 Amazon SQS 事件源映射。

要将这些筛选条件添加到现有事件源映射中，请运行以下命令。

```
aws lambda update-event-source-mapping \
    --uuid "a1b2c3d4-5678-90ab-cdef-11111EXAMPLE" \
    --filter-criteria '{"Filters": [{"Pattern": "{ \"Metadata\" : [ 1, 2 ]}"}]}'
```

请注意，要更新事件源映射，您需要其 UUID。您可以通过 [list-event-source-mappings](https://docs.aws.amazon.com/cli/latest/reference/lambda/list-event-source-mappings.html) 调用获取 UUID。Lambda 还会在 [create-event-source-mapping](https://docs.aws.amazon.com/cli/latest/reference/lambda/create-event-source-mapping.html) CLI 响应中返回 UUID。

要从事件源中删除筛选条件，您可以运行以下包含空 `FilterCriteria` 对象的 [update-event-source-mapping](https://docs.aws.amazon.com/cli/latest/reference/lambda/update-event-source-mapping.html) 命令。

```
aws lambda update-event-source-mapping \
    --uuid "a1b2c3d4-5678-90ab-cdef-11111EXAMPLE" \
    --filter-criteria "{}"
```

有关使用 AWS CLI 创建事件筛选条件的更多示例，请参阅 [使用具有不同 AWS 服务 的筛选条件](#filtering-by-service)。

## 将筛选条件附加到事件源映射（AWS SAM）
<a name="filtering-sam"></a>

 假设您要在 AWS SAM 中配置事件源以使用以下筛选条件：

```
{
   "Filters": [
      {
          "Pattern": "{ \"Metadata\" : [ 1, 2 ] }"
      }
   ]
}
```

 要将这些筛选条件添加到事件源映射中，请将以下代码段插入事件源的 YAML 模板中。

```
FilterCriteria: 
  Filters: 
    - Pattern: '{"Metadata": [1, 2]}'
```

 有关为事件源映射创建和配置 AWS SAM 模板的更多信息，请参阅《AWS SAM 开发人员指南》中的 [ EventSource](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-property-function-eventsource.html) 部分。有关使用 AWS SAM 模板创建事件筛选条件的更多示例，请参阅 [使用具有不同 AWS 服务 的筛选条件](#filtering-by-service)。

## 筛选条件的加密
<a name="filter-criteria-encryption"></a>

默认情况下，Lambda 不会加密您的筛选条件对象。对于可能在筛选条件对象中包含敏感信息的应用场景，您可以使用自己的 [KMS 密钥](https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#kms_keys)对其进行加密。

加密筛选条件对象后，您可以使用 [GetEventSourceMapping](https://docs.aws.amazon.com/lambda/latest/api/API_GetEventSourceMapping.html) API 调用查看其纯文本版本。您必须拥有 `kms:Decrypt` 权限才能成功查看纯文本筛选条件。

**注意**  
如果您的筛选条件对象已加密，Lambda 会在 [ListEventSourceMappings](https://docs.aws.amazon.com/lambda/latest/api/API_ListEventSourceMappings.html) 调用的响应中编辑 `FilterCriteria` 字段的值。相反，此字段显示为 `null`。要查看 `FilterCriteria` 的真实值，请使用 [GetEventSourceMapping](https://docs.aws.amazon.com/lambda/latest/api/API_GetEventSourceMapping.html) API。  
要在控制台中查看 `FilterCriteria` 解密后的值，请确保您的 IAM 角色包含使用 [GetEventSourceMapping](https://docs.aws.amazon.com/lambda/latest/api/API_GetEventSourceMapping.html) 的权限。

您可以通过控制台、API/CLI 或 CloudFormation 指定自己的 KMS 密钥。

**使用客户自有 KMS 密钥加密筛选条件（控制台）**

1. 打开 Lamba 控制台的[函数](https://console.aws.amazon.com/lambda/home#/functions)页面。

1. 选择**添加触发器**。如果您已有触发器，请选择**配置**选项卡，然后选择**触发器**。选择现有触发器，然后选择**编辑**。

1. 选中**使用客户自主管理型 KMS 密钥加密**旁边的复选框。

1. 在**选择客户自主管理型 KMS 加密密钥**中，选择已启用的现有密钥或创建新密钥。根据操作的不同，您需要以下部分或全部权限：`kms:DescribeKey`、`kms:GenerateDataKey` 和 `kms:Decrypt`。使用 KMS 密钥政策授予这些权限。

如果您使用自己的 KMS 密钥，[密钥政策](https://docs.aws.amazon.com/kms/latest/developerguide/key-policies.html)中必须允许以下 API 操作：
+ `kms:Decrypt` – 必须授予区域 Lambda 服务主体 (`lambda.AWS_region.amazonaws.com`)。允许 Lambda 使用此 KMS 密钥解密数据。
  + 为防止[跨服务混淆代理问题](https://docs.aws.amazon.com/IAM/latest/UserGuide/confused-deputy.html)，密钥政策使用 [https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_condition-keys.html#condition-keys-sourcearn](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_condition-keys.html#condition-keys-sourcearn) 全局条件密钥。`aws:SourceArn` 密钥的正确值是您的事件源映射资源的 ARN，因此只有在知道其 ARN 之后，才能将其添加到政策中。在向 KMS 发出解密请求时，Lambda 还会在[加密上下文](https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#encrypt_context)中转发 `aws:lambda:FunctionArn` 和 `aws:lambda:EventSourceArn` 密钥及其各自的值。这些值必须与密钥政策中的指定条件相匹配，解密请求才能成功。您无需为自行管理的 Kafka 事件源添加 EventSourceArn，因为它们没有 EventSourceArn。
+ `kms:Decrypt` – 还必须授予打算使用密钥在 [GetEventSourceMapping](https://docs.aws.amazon.com/lambda/latest/api/API_GetEventSourceMapping.html) 或 [DeleteEventSourceMapping](https://docs.aws.amazon.com/lambda/latest/api/API_DeleteEventSourceMapping.html) API 调用中查看纯文本筛选条件的主体。
+ `kms:DescribeKey` – 提供客户自主管理型密钥详细信息以允许主体使用密钥。
+ `kms:GenerateDataKey` – 为 Lambda 提供代表指定主体生成数据密钥以加密筛选条件的权限（[信封加密](https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#enveloping)）。

您可以使用 AWS CloudTrail 来跟踪 Lambda 代表您发出的 AWS KMS 请求。有关 CloudTrail 事件示例，请参阅[为 Lambda 监控您的加密密钥](security-encryption-at-rest.md#encryption-key-monitoring)。

我们还建议使用 [https://docs.aws.amazon.com/kms/latest/developerguide/conditions-kms.html#conditions-kms-via-service](https://docs.aws.amazon.com/kms/latest/developerguide/conditions-kms.html#conditions-kms-via-service) 条件密钥将 KMS 密钥的使用限制为仅限来自 Lambda 的请求。此密钥的值是区域 Lambda 服务主体 (`lambda.AWS_region.amazonaws.com`)。以下是授予所有相关权限的密钥政策示例：

**Example AWS KMS 密钥政策**    
****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Id": "example-key-policy-1",
    "Statement": [
        {
            "Sid": "Allow Lambda to decrypt using the key",
            "Effect": "Allow",
            "Principal": {
                "Service": "lambda.us-east-1.amazonaws.com"
            },
            "Action": [
                "kms:Decrypt"
            ],
            "Resource": "*",
            "Condition": {
                "ArnEquals" : {
                    "aws:SourceArn": [
                        "arn:aws:lambda:us-east-1:123456789012:event-source-mapping:<esm_uuid>"
                    ]
                },
                "StringEquals": {
                    "kms:EncryptionContext:aws:lambda:FunctionArn": "arn:aws:lambda:us-east-1:123456789012:function:test-function",
                    "kms:EncryptionContext:aws:lambda:EventSourceArn": "arn:aws:sqs:us-east-1:123456789012:test-queue"
                }
            }
        },
        {
            "Sid": "Allow actions by an AWS account on the key",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::123456789012:root"
            },
            "Action": "kms:*",
            "Resource": "*"
        },
        {
            "Sid": "Allow use of the key to specific roles",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::123456789012:role/ExampleRole"
            },
            "Action": [
                "kms:Decrypt",
                "kms:DescribeKey",
                "kms:GenerateDataKey"
            ],
            "Resource": "*",
            "Condition": {
                "StringEquals" : {
                    "kms:ViaService": "lambda.us-east-1.amazonaws.com"
                }
            }
        }
    ]
}
```

要使用自己的 KMS 密钥对筛选条件进行加密，也可以使用以下 [CreateEventSourceMapping](https://docs.aws.amazon.com/lambda/latest/api/API_CreateEventSourceMapping.html) AWS CLI 命令。使用 `--kms-key-arn` 标志指定 KMS 密钥 ARN。

```
aws lambda create-event-source-mapping --function-name my-function \
    --maximum-batching-window-in-seconds 60 \
    --event-source-arn arn:aws:sqs:us-east-1:123456789012:my-queue \
    --filter-criteria "{\"filters\": [{\"pattern\": \"{\"a\": [\"1\", \"2\"]}\" }]}" \
    --kms-key-arn arn:aws:kms:us-east-1:123456789012:key/055efbb4-xmpl-4336-ba9c-538c7d31f599
```

如果您已有事件源映射，请改用 [UpdateEventSourceMapping](https://docs.aws.amazon.com/lambda/latest/api/API_UpdateEventSourceMapping.html) AWS CLI 命令。使用 `--kms-key-arn` 标志指定 KMS 密钥 ARN。

```
aws lambda update-event-source-mapping --function-name my-function \
    --maximum-batching-window-in-seconds 60 \
    --event-source-arn arn:aws:sqs:us-east-1:123456789012:my-queue \
    --filter-criteria "{\"filters\": [{\"pattern\": \"{\"a\": [\"1\", \"2\"]}\" }]}" \
    --kms-key-arn arn:aws:kms:us-east-1:123456789012:key/055efbb4-xmpl-4336-ba9c-538c7d31f599
```

此操作将覆盖先前指定的任何 KMS 密钥。如果您指定 `--kms-key-arn` 标志和空实参，Lambda 将停止使用您的 KMS 密钥来加密筛选条件。相反，Lambda 默认使用 Amazon 拥有的密钥。

要在 CloudFormation 模板中指定您自己的 KMS 密钥，请使用 `AWS::Lambda::EventSourceMapping` 资源类型的 `KMSKeyArn` 属性。例如，您可以将以下代码段插入事件源的 YAML 模板中。

```
MyEventSourceMapping:
  Type: AWS::Lambda::EventSourceMapping
  Properties:
    ...
    FilterCriteria:
      Filters:
        - Pattern: '{"a": [1, 2]}'
    KMSKeyArn: "arn:aws:kms:us-east-1:123456789012:key/055efbb4-xmpl-4336-ba9c-538c7d31f599"
    ...
```

要能够在 [GetEventSourceMapping](https://docs.aws.amazon.com/lambda/latest/api/API_GetEventSourceMapping.html) 或 [DeleteEventSourceMapping](https://docs.aws.amazon.com/lambda/latest/api/API_DeleteEventSourceMapping.html) API 调用中以纯文本形式查看加密的筛选条件，您必须拥有 `kms:Decrypt` 权限。

从 2024 年 8 月 6 日起，如果您的函数不使用事件筛选，`FilterCriteria` 字段将不再显示在 [CreateEventSourceMapping](https://docs.aws.amazon.com/lambda/latest/api/API_CreateEventSourceMapping.html)、[UpdateEventSourceMapping](https://docs.aws.amazon.com/lambda/latest/api/API_UpdateEventSourceMapping.html) 和 [DeleteEventSourceMapping](https://docs.aws.amazon.com/lambda/latest/api/API_DeleteEventSourceMapping.html) API 调用的AWS CloudTrail 日志中。如果您的函数确实使用了事件筛选，则 `FilterCriteria` 字段将显示为空 (`{}`)。如果拥有正确 KMS 密钥的 `kms:Decrypt` 权限，则仍然可以在响应 [GetEventSourceMapping](https://docs.aws.amazon.com/lambda/latest/api/API_GetEventSourceMapping.html) API 调用时以纯文本形式查看筛选条件。

### Create/Update/DeleteEventSourceMapping 调用的 CloudTrail 日志条目示例
<a name="filter-criteria-encryption-cloudtrail"></a>

在以下 CreateEventSourceMapping 调用的 AWS CloudTrail 示例日志条目中，由于该函数使用事件筛选，`FilterCriteria` 显示为空 (`{}`)。即使 `FilterCriteria` 对象包含函数正在使用的有效筛选条件，也是如此。如果该函数不使用事件筛选，则 CloudTrail 根本不会在日志条目中显示 `FilterCriteria` 字段。

```
{
    "eventVersion": "1.08",
    "userIdentity": {
        "type": "AssumedRole",
        "principalId": "AROA123456789EXAMPLE:userid1",
        "arn": "arn:aws:sts::123456789012:assumed-role/Example/example-role",
        "accountId": "123456789012",
        "accessKeyId": "ASIAIOSFODNN7EXAMPLE",
        "sessionContext": {
            "sessionIssuer": {
                "type": "Role",
                "principalId": "AROA987654321EXAMPLE",
                "arn": "arn:aws:iam::123456789012:role/User1",
                "accountId": "123456789012",
                "userName": "User1"
            },
            "webIdFederationData": {},
            "attributes": {
                "creationDate": "2024-05-09T20:35:01Z",
                "mfaAuthenticated": "false"
            }
        },
        "invokedBy": "AWS Internal"
    },
    "eventTime": "2024-05-09T21:05:41Z",
    "eventSource": "lambda.amazonaws.com",
    "eventName": "CreateEventSourceMapping20150331",
    "awsRegion": "us-east-2",
    "sourceIPAddress": "AWS Internal",
    "userAgent": "AWS Internal",
    "requestParameters": {
        "eventSourceArn": "arn:aws:sqs:us-east-2:123456789012:example-queue",
        "functionName": "example-function",
        "enabled": true,
        "batchSize": 10,
        "filterCriteria": {},
        "kMSKeyArn": "arn:aws:kms:us-east-2:123456789012:key/a1b2c3d4-5678-90ab-cdef-EXAMPLE11111",
        "scalingConfig": {},
        "maximumBatchingWindowInSeconds": 0,
        "sourceAccessConfigurations": []
    },
    "responseElements": {
        "uUID": "a1b2c3d4-5678-90ab-cdef-EXAMPLEaaaaa",
        "batchSize": 10,
        "maximumBatchingWindowInSeconds": 0,
        "eventSourceArn": "arn:aws:sqs:us-east-2:123456789012:example-queue",
        "filterCriteria": {},
        "kMSKeyArn": "arn:aws:kms:us-east-2:123456789012:key/a1b2c3d4-5678-90ab-cdef-EXAMPLE11111",
        "functionArn": "arn:aws:lambda:us-east-2:123456789012:function:example-function",
        "lastModified": "May 9, 2024, 9:05:41 PM",
        "state": "Creating",
        "stateTransitionReason": "USER_INITIATED",
        "functionResponseTypes": [],
        "eventSourceMappingArn": "arn:aws:lambda:us-east-2:123456789012:event-source-mapping:a1b2c3d4-5678-90ab-cdef-EXAMPLEbbbbb"
    },
    "requestID": "a1b2c3d4-5678-90ab-cdef-EXAMPLE33333",
    "eventID": "a1b2c3d4-5678-90ab-cdef-EXAMPLE22222",
    "readOnly": false,
    "eventType": "AwsApiCall",
    "managementEvent": true,
    "recipientAccountId": "123456789012",
    "eventCategory": "Management",
    "sessionCredentialFromConsole": "true"
}
```

## 使用具有不同 AWS 服务 的筛选条件
<a name="filtering-by-service"></a>

不同类型的事件源为其数据字段使用不同的键值。要对数据属性进行筛选，请确保在筛选条件的模式中使用正确的键。下表给出了每个受支持 AWS 服务 的筛选键。


| AWS 服务 | 筛选键 | 
| --- | --- | 
| DynamoDB | dynamodb | 
| Kinesis | data | 
| Amazon MQ | data | 
| Amazon MSK | value | 
| 自行管理的 Apache Kafka | value | 
| Amazon SQS | body | 

以下各节介绍了不同类型事件源的筛选条件模式示例。还为每个受支持的服务提供支持的传入数据格式和筛选条件模式正文格式的定义。
+ [对 DynamoDB 事件源使用事件筛选](with-ddb-filtering.md)
+ [对 Kinesis 事件源使用事件筛选](with-kinesis-filtering.md)
+ [筛选来自 Amazon MQ 事件源的事件](with-mq-filtering.md)
+ [从 Amazon MSK 和自托管式 Apache Kafka 事件源中筛选事件](kafka-filtering.md)
+ [对 Amazon SQS 事件源使用事件筛选](with-sqs-filtering.md)

# 在控制台中测试 Lambda 函数
<a name="testing-functions"></a>

您可以在控制台中使用测试事件调用函数，从而测试 Lambda 函数。*测试事件*是函数的一个 JSON 输入。如果函数不需要输入，则事件可以是空文档 `({})`。

在控制台中运行测试时，Lambda 会使用测试事件同步调用您的函数。函数运行时系统将事件 JSON 转换为一个对象，并将该对象传递给代码的处理程序方法以进行处理。

**创建测试事件**  
您需要先创建一个私有或可共享的测试事件，然后才能在控制台中进行测试。

## 使用测试事件调用函数
<a name="invoke-with-event"></a>

**测试函数**

1. 打开 Lamba 控制台的[函数](https://console.aws.amazon.com/lambda/home#/functions)页面。

1. 选择要测试的函数的名称。

1. 选择**测试**选项卡。

1. 在**测试事件**下，选择**创建新事件**或**编辑已保存的事件**，然后选择要使用的已保存事件。

1. 可选：为事件 JSON 选择一个**模板**。

1. 选择**测试**。

1. 在 **Execution result**（执行结果）下，展开 **Details**（详细信息）以查看测试结果。

要在不保存测试事件的情况下调用函数，请在保存之前选择 **Test**（测试）。这将创建一个未保存的测试事件，Lambda 仅会在会话期间内保存该事件。

对于 Node.js、Python 和 Ruby 运行时，您还可以在**代码**选项卡上访问现有已保存和未保存的测试事件。使用**测试事件**部分来创建、编辑和运行测试。

## 创建私有测试事件
<a name="creating-private-events"></a>

私人测试事件仅供事件创建者使用，并且不需要额外的权限即可使用。每个函数最多可以创建和保存 10 个测试事件。

**创建私有测试事件**

1. 打开 Lamba 控制台的[函数](https://console.aws.amazon.com/lambda/home#/functions)页面。

1. 选择要测试的函数的名称。

1. 选择**测试**选项卡。

1. 在 **Test event**（测试事件）下执行以下操作：

   1. 选择一个 **Template**（模板）。

   1. 输入测试的 **Name**（名称）。

   1. 在文本输入框中，输入 JSON 测试事件。

   1. 在 **Event sharing settings**（事件共享设置）下，选择 **Private**（私有）。

1. 选择**保存更改**。

对于 Node.js、Python 和 Ruby 运行时，您还可以在**代码**选项卡上创建测试事件。使用**测试事件**部分来创建、编辑和运行测试。

## 创建可共享测试事件
<a name="creating-shareable-events"></a>

可共享测试事件是您可与同一 AWS 账户中的其他用户共享的测试事件。您可以编辑其他用户的可共享测试事件并使用这些测试事件调用您的函数。

Lambda 将可共享测试事件作为 Schema 保存在一个名为 `lambda-testevent-schemas` 的 [Amazon EventBridge（CloudWatch Events）Schema 注册表](https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-schema-registry.html)中。由于 Lambda 利用此注册表来存储和调用您创建的可共享测试事件，因此我们建议您不要编辑此注册表或使用 `lambda-testevent-schemas` 名称创建注册表。

要查看、共享和编辑可共享测试事件，您必须拥有以下所有 [EventBridge（CloudWatch Events）Schema 注册表 API 操作](https://docs.aws.amazon.com/eventbridge/latest/schema-reference/operations.html)的权限：
+ [https://docs.aws.amazon.com/eventbridge/latest/schema-reference/v1-registries-name-registryname.html#CreateRegistry](https://docs.aws.amazon.com/eventbridge/latest/schema-reference/v1-registries-name-registryname.html#CreateRegistry)
+ [https://docs.aws.amazon.com/eventbridge/latest/schema-reference/v1-registries-name-registryname-schemas-name-schemaname.html#CreateSchema](https://docs.aws.amazon.com/eventbridge/latest/schema-reference/v1-registries-name-registryname-schemas-name-schemaname.html#CreateSchema)
+ [https://docs.aws.amazon.com/eventbridge/latest/schema-reference/v1-registries-name-registryname-schemas-name-schemaname.html#DeleteSchema](https://docs.aws.amazon.com/eventbridge/latest/schema-reference/v1-registries-name-registryname-schemas-name-schemaname.html#DeleteSchema)
+ [https://docs.aws.amazon.com/eventbridge/latest/schema-reference/v1-registries-name-registryname-schemas-name-schemaname-version-schemaversion.html#DeleteSchemaVersion](https://docs.aws.amazon.com/eventbridge/latest/schema-reference/v1-registries-name-registryname-schemas-name-schemaname-version-schemaversion.html#DeleteSchemaVersion)
+ [https://docs.aws.amazon.com/eventbridge/latest/schema-reference/v1-registries-name-registryname.html#DescribeRegistry](https://docs.aws.amazon.com/eventbridge/latest/schema-reference/v1-registries-name-registryname.html#DescribeRegistry)
+ [https://docs.aws.amazon.com/eventbridge/latest/schema-reference/v1-registries-name-registryname-schemas-name-schemaname.html#DescribeSchema](https://docs.aws.amazon.com/eventbridge/latest/schema-reference/v1-registries-name-registryname-schemas-name-schemaname.html#DescribeSchema)
+ [https://docs.aws.amazon.com/eventbridge/latest/schema-reference/v1-discover.html#GetDiscoveredSchema](https://docs.aws.amazon.com/eventbridge/latest/schema-reference/v1-discover.html#GetDiscoveredSchema)
+ [https://docs.aws.amazon.com/eventbridge/latest/schema-reference/v1-registries-name-registryname-schemas-name-schemaname-versions.html#ListSchemaVersions](https://docs.aws.amazon.com/eventbridge/latest/schema-reference/v1-registries-name-registryname-schemas-name-schemaname-versions.html#ListSchemaVersions)
+ [https://docs.aws.amazon.com/eventbridge/latest/schema-reference/v1-registries-name-registryname-schemas-name-schemaname.html#UpdateSchema](https://docs.aws.amazon.com/eventbridge/latest/schema-reference/v1-registries-name-registryname-schemas-name-schemaname.html#UpdateSchema)

请注意，保存对可共享测试事件所做的编辑将覆盖该事件。

如果您无法创建、编辑或查看可共享测试事件，请检查您的账户是否具有这些操作所需的权限。如果您拥有所需的权限但仍然无法访问可共享测试事件，请检查任何[基于资源的策略](access-control-resource-based.md)，因为这些策略可能会限制对 EventBridge（CloudWatch Events）注册表的访问权限。

**创建可共享测试事件**

1. 打开 Lamba 控制台的[函数](https://console.aws.amazon.com/lambda/home#/functions)页面。

1. 选择要测试的函数的名称。

1. 选择**测试**选项卡。

1. 在 **Test event**（测试事件）下执行以下操作：

   1. 选择一个 **Template**（模板）。

   1. 输入测试的 **Name**（名称）。

   1. 在文本输入框中，输入 JSON 测试事件。

   1. 在 **Event sharing settings**（事件共享设置）下，选择 **Shareable**（可共享）。

1. 选择**保存更改**。

**通过 AWS Serverless Application Model 使用可共享的测试事件。**  
您可以使用 AWS SAM 调用可共享的测试事件。请参阅[《AWS Serverless Application Model 开发人员指南》](https://docs.aws.amazon.com//serverless-application-model/latest/developerguide/using-sam-cli-remote-test-event.html)中的 [https://docs.aws.amazon.com//serverless-application-model/latest/developerguide/using-sam-cli-remote-test-event.html](https://docs.aws.amazon.com//serverless-application-model/latest/developerguide/using-sam-cli-remote-test-event.html)。

## 删除可共享测试事件 Schema
<a name="deleting-test-schemas"></a>

当您删除可共享测试事件时，Lambda 会将其从 `lambda-testevent-schemas` 注册表移除。如果您从注册表中移除了最后一个可共享测试事件，Lambda 将删除该注册表。

如果您删除了函数，Lambda 不会删除任何关联的可共享测试事件 Schema。您必须从 [EventBridge（CloudWatch Events）控制台](https://console.aws.amazon.com/events)手动清除这些资源。

# Lambda 函数状态
<a name="functions-states"></a>

Lambda 在所有函数的函数配置中都包含一个[状态](https://docs.aws.amazon.com/lambda/latest/api/API_GetFunctionConfiguration.html#lambda-GetFunctionConfiguration-response-State)字段，以指示您的函数何时可以调用。`State` 提供了有关函数当前状态的信息，包括您是否可以成功调用该函数。函数状态不会改变函数调用的行为或函数运行代码的方式。

**注意**  
[SnapStart](snapstart.md) 函数的函数状态定义略有不同。有关更多信息，请参阅 [Lambda SnapStart 和函数状态](snapstart-activate.md#snapstart-function-states)。

在许多情况下，DynamoDB 表是保留调用之间状态的理想方式，因为它提供低延迟的数据访问，且可以随着 Lambda 服务进行扩展。如果您正在使用此服务，则可以将数据存储在 [Amazon EFS for Lambda](https://aws.amazon.com/blogs/compute/using-amazon-efs-for-aws-lambda-in-your-serverless-applications/) 中，这样可以实现对文件系统存储的低延迟访问。

函数状态包括：
+ `Pending` – Lambda 创建函数后，它将状态设置为待处理。处于待处理状态时，Lambda 会尝试为函数创建或配置资源，例如 VPC 或 EFS 资源。Lambda 在待处理状态期间不调用函数。在函数上运行的任何调用或其他 API 操作都将失败。
+ `Active` – Lambda 完成资源配置和预置后，函数将转换为激活状态。函数只能在激活时成功调用。
+ `Failed` – 表示资源配置或预置遇到错误。当函数创建失败时，Lambda 会将函数状态设置为 failed，您必须删除该函数，然后重新创建它。
+ `Inactive` – 当函数空闲时间足够长，以便 Lambda 回收为其配置的外部资源时，函数变为非激活状态。当您尝试调用非激活函数时，调用会失败，Lambda 将函数设置为待处理状态，直到重新创建函数资源。如果 Lambda 无法重新创建资源，则函数将返回到非激活状态。您可能需要解决错误并重新部署函数以将其恢复到活动状态。

如果您使用基于 SDK 的自动化工作流程或直接调用 Lambda 的服务 API，请确保在调用之前检查函数的状态以验证函数是否处于活动状态。您可以使用 Lambda API 操作 [GetFunction](https://docs.aws.amazon.com/lambda/latest/api/API_GetFunction.html) 来执行此任务，或者使用 [AWS SDK for Java 2.0](https://github.com/aws/aws-sdk-java-v2) 来配置 Waiter。

```
aws lambda get-function --function-name my-function --query 'Configuration.[State, LastUpdateStatus]'
```

您应看到以下输出：

```
[
 "Active",
 "Successful" 
]
```

在函数创建处于挂起状态时，以下操作会失败：
+ [Invoke](https://docs.aws.amazon.com/lambda/latest/api/API_Invoke.html)
+ [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)

## 更新期间的函数状态
<a name="functions-states-updating"></a>

Lambda 有两种更新函数的操作：
+ [UpdateFunctionCode](https://docs.aws.amazon.com/lambda/latest/api/API_UpdateFunctionCode.html)：更新函数的部署包
+ [UpdateFunctionConfiguration](https://docs.aws.amazon.com/lambda/latest/api/API_UpdateFunctionConfiguration.html)：更新函数的配置

Lambda 使用 [LastUpdateStatus](https://docs.aws.amazon.com/lambda/latest/api/API_FunctionConfiguration.html#lambda-Type-FunctionConfiguration-LastUpdateStatus) 属性来跟踪这些更新操作的进度。更新正在进行时（当 `"LastUpdateStatus": "InProgress"` 时）：
+ 函数的[状态](https://docs.aws.amazon.com/lambda/latest/api/API_GetFunctionConfiguration.html#lambda-GetFunctionConfiguration-response-State)保持为 `Active`。
+ 调用将继续使用函数的先前代码和配置，直到更新完成。
+ 以下操作失败：
  + [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)
  + [TagResource](https://docs.aws.amazon.com/lambda/latest/api/API_TagResource.html)

更新失败时（当为 `"LastUpdateStatus": "Failed"` 时）：
+ 函数的[状态](https://docs.aws.amazon.com/lambda/latest/api/API_GetFunctionConfiguration.html#lambda-GetFunctionConfiguration-response-State)保持为 `Active`。
+ 调用将继续使用函数的先前代码和配置。

**Example GetFunctionConfiguration 响应**  
以下示例是针对正在更新的函数的 [GetFunctionConfiguration](https://docs.aws.amazon.com/lambda/latest/api/API_GetFunctionConfiguration.html) 请求的结果。  

```
{
    "FunctionName": "my-function",
    "FunctionArn": "arn:aws:lambda:us-east-1:123456789012:function:my-function",
    "Runtime": "nodejs24.x",
    "VpcConfig": {
        "SubnetIds": [
            "subnet-071f712345678e7c8",
            "subnet-07fd123456788a036",
            "subnet-0804f77612345cacf"
        ],
        "SecurityGroupIds": [
            "sg-085912345678492fb"
        ],
        "VpcId": "vpc-08e1234569e011e83"
    },
    "State": "Active",
    "LastUpdateStatus": "InProgress",
    ...
}
```

# 了解 Lambda 中的重试行为
<a name="invocation-retries"></a>

直接调用函数时，您需要确定处理与函数代码相关的错误的策略。Lambda 不会自动代表您重试这些类型的错误。要进行重试，您可以说动重新调用函数，将事件发送到队列以进行调试，或者忽略该错误。您的函数代码可能已完全、部分或根本不运行。如要重试，请确保您的函数代码可以多次处理相同的事件，而不会导致重复的事务或其他不必要的副作用。

间接调用函数时，您需要了解调用者的重试行为以及请求在此过程中遇到的任何服务。这包括以下场景。
+ **异步调用** – Lambda 会针对函数错误重试两次。如果该函数没有足够的容量来处理所有传入请求，则事件可能会在队列中等待数小时才能发送到该函数。您可以在函数上配置死信队列以捕获未成功处理的事件。有关更多信息，请参阅 [添加死信队列](invocation-async-retain-records.md#invocation-dlq)。
+ **事件源映射** – 从流中读取的事件源映射将重试整个批次的项。重复错误会阻止受影响的分片的处理，直到错误得到解决或项失效为止。要检测停顿的分片，您可以监控[迭代器期限](monitoring-metrics.md)指标。

  对于从队列中读取的事件源映射，您可以通过在源队列上配置可见性超时和重新驱动策略来确定失败事件的重试次数以及目标之间的时间长度。有关更多信息，请参阅 [Lambda 如何处理来自基于流和队列的事件源的记录](invocation-eventsourcemapping.md) 以及 [使用来自其 AWS 他服务的事件调用 Lambda](lambda-services.md) 下特定于服务的主题。
+ **AWS服务** – AWS服务可能[同步](invocation-sync.md)或异步调用您的函数。对于同步调用，服务将决定是否重试。例如，如果 Lambda 函数返回 `TemporaryFailure` 响应代码，则 Amazon S3 批处理操作会重试该操作。代理来自上游用户或客户端的请求的服务可能具有重试策略，或者可能将错误响应中继回请求者。例如，API Gateway 始终将错误响应中继回请求者。

  对于异步调用，无论调用源如何，重试逻辑都是相同的。默认情况下，对于失败的异步调用，Lambda 最多会重试两次。有关更多信息，请参阅 [Lambda 如何处理异步调用的错误和重试](invocation-async-error-handling.md)。
+ **其他账户和客户端** – 当您向其他账户授予访问权限时，可以使用[基于资源的策略](access-control-resource-based.md)来限制可配置为调用您的函数的服务或资源。为了保护您的函数不发生过载情况，请考虑使用 [Amazon API Gateway](services-apigateway.md) 在您的函数前面放置一个 API 层。

为了帮助您处理 Lambda 应用程序中的错误，Lambda 集成了 Amazon CloudWatch 和 AWS X-Ray 等服务。您可以结合使用日志、指标、警报和跟踪来快速检测和识别函数代码，API 或支持您的应用程序的其他资源中的问题。有关更多信息，请参阅 [监控、调试 Lambda 函数并进行故障排除](lambda-monitoring.md)。

# 使用 Lambda 递归循环检测来防止无限循环
<a name="invocation-recursion"></a>

当您配置 Lambda 函数输出到调用该函数的同一服务或资源时，就可能会创建无限递归循环。例如，Lambda 函数可能会向 Amazon Simple Queue Service（Amazon SQS）队列写入一条消息，该队列随即调用同一函数。此调用导致该函数向队列写入另一条消息，而队列反过来再次调用该函数。

意外发生的递归循环可能会让您的 AWS 账户 产生意外费用。循环还可能导致 Lambda [扩展](lambda-concurrency.md)并使用您账户的所有可用并发。为了帮助减轻意外循环的影响，Lambda 可以在某些类型的递归循环发生后不久将其检测出。默认情况下，在检测到递归循环时，Lambda 会停止调用函数并向您发送通知。如果您的设计有意使用递归模式，则可以更改函数的默认配置，以允许其以递归方式调用。请参阅[允许 Lambda 函数在递归循环中运行](#invocation-recursion-disable)了解更多信息。

**Topics**
+ [

## 了解递归循环检测
](#invocation-recursion-concepts)
+ [

## 受支持的 AWS 服务 和开发工具包
](#invocation-recursion-supported)
+ [

## 递归循环通知
](#invocation-recursion-monitoring)
+ [

## 响应递归循环检测通知
](#invocation-recursion-responding)
+ [

## 允许 Lambda 函数在递归循环中运行
](#invocation-recursion-disable)
+ [

## 支持 Lambda 递归循环检测的区域
](#invocation-recursion-regions)

## 了解递归循环检测
<a name="invocation-recursion-concepts"></a>

Lambda 中的递归循环检测通过跟踪事件来工作。Lambda 是一种事件驱动型计算服务，可在某些事件发生时运行您的函数代码。例如，将项目添加到 Amazon SQS 队列或 Amazon Simple Notiﬁcation Service（Amazon SNS）主题时，就会如此。Lambda 将事件作为 JSON 对象传递给您的函数，其中包含有关系统状态变化的信息。如果某一事件导致您的函数运行时，这就称为*调用*。

为了检测递归循环，Lambda 会使用 [AWS X-Ray](https://docs.aws.amazon.com/xray/latest/devguide/aws-xray.html) 跟踪标头。当[支持递归循环检测的 AWS 服务](#invocation-recursion-supportedservices) 将事件发送到 Lambda 时，这些事件将自动使用元数据进行注释。当您的 Lambda 函数使用[支持的 AWS 开发工具包版本](#invocation-recursion-supportedsdks)将其中一个事件写入另一个支持的 AWS 服务 时，就会更新此元数据。更新后的元数据包括事件调用该函数的次数计数。

**注意**  
您无需启用 X-Ray 主动追踪，即可使用此功能。默认情况下，所有 AWS 客户都启用递归循环检测。使用该功能不会产生任何费用。

*请求链*是由同一触发事件引起的一系列 Lambda 调用。例如，假设 Amazon SQS 队列调用了您的 Lambda 函数。然后，Lambda 函数将处理过的事件发送回同一 Amazon SQS 队列，该队列将再次调用您的函数。在此示例中，函数的每次调用都属于同一请求链。

如果您的函数在同一请求链中被调用的次数超过 16 次，Lambda 会自动停止该请求链中的下一次函数调用并向您发送通知。如果您的函数配置了多个触发器，来自其他触发器的调用则不会受到影响。

**注意**  
即使在源队列的重新驱动策略的 `maxReceiveCount` 设置高于 16 时，Lambda 递归保护也不会阻止 Amazon SQS 在检测到递归循环并终止后重试消息。当 Lambda 检测到递归循环并丢弃后续调用时，它会向事件源映射返回 `RecursiveInvocationException`。这会增加消息的 `receiveCount` 值。Lambda 会继续重试该消息，并继续阻止函数调用，直到 Amazon SQS 确定已超出 `maxReceiveCount` 并将消息发送到配置的死信队列。

如果您为函数配置了[失败时的目标](invocation-async-retain-records.md#invocation-async-destinations)或[死信队列](invocation-async-retain-records.md#invocation-dlq)，则 Lambda 还会将已停止调用的事件发送到您的目标或死信队列。为函数配置目标或死信队列时，确保不要使用函数也在使用的事件触发器或事件源映射。如果您将事件发送到调用函数的同一资源，则可以创建另一个递归循环，此循环也将终止。如果您选择退出递归循环检测，则不会终止此循环。

## 受支持的 AWS 服务 和开发工具包
<a name="invocation-recursion-supported"></a>

Lambda 只能检测包含某些受支持的 AWS 服务 的递归循环。为了检测到递归循环，您的函数还必须使用一种受支持的 AWS 开发工具包。

### 支持的 AWS 服务
<a name="invocation-recursion-supportedservices"></a>

Lambda 目前可检测您的函数、Amazon SQS、Amazon S3 和 Amazon SNS 之间的递归循环。Lambda 还会检测仅由 Lambda 函数组成的循环，这些函数可以同步或异步地相互调用。下图显示了 Lambda 可以检测的一些循环示例：

![\[Lambda 函数、Amazon SNS、Amazon S3 和 Amazon SQS 队列之间的递归循环图。\]](http://docs.aws.amazon.com/zh_cn/lambda/latest/dg/images/RunawayWorkloadDetected_v3.png)


如果 Amazon DynamoDB 等其他 AWS 服务构成循环的一部分，Lambda 目前无法对其进行检测和阻止。

由于 Lambda 目前仅检测涉及 Amazon SQS、Amazon S3 和 Amazon SNS 的递归循环，因此涉及其他 AWS 服务的循环仍有可能导致您的 Lambda 函数遭意外使用。

为防止 AWS 账户 产生意外费用，我们建议您配置 [Amazon CloudWatch 警报](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/AlarmThatSendsEmail.html)，提醒自己注意异常使用模式。例如，您可以将 CloudWatch 配置为在 Lambda 函数并发或调用出现峰值时向自己发送通知。您还可以配置[账单警报](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/monitor_estimated_charges_with_cloudwatch.html)，以便在账户中的支出超过指定的阈值时通知您。您也可以使用 [AWS Cost Anomaly Detection](https://docs.aws.amazon.com/cost-management/latest/userguide/manage-ad.html) 来提醒自己注意异常的计费模式。

### 受支持的 AWS 开发工具包
<a name="invocation-recursion-supportedsdks"></a>

要让 Lambda 检测递归循环，您的函数必须使用以下开发工具包版本中的一种版本或更高版本：


| 运行时系统 | 所需 AWS 开发工具包的最低版本 | 
| --- | --- | 
|  Node.js  |  2.1147.0（开发工具包版本 2） 3.105.0（开发工具包版本 3）  | 
|  Python  |  1.24.46（boto3） 1.27.46（botocore）  | 
|  Java 8 和 Java 11  |  2.17.135  | 
|  Java 17  |  2.20.81  | 
|  Java 21  |  2.21.24  | 
|  .NET  |  3.7.293.0  | 
|  Ruby  |  3.134.0  | 
|  PHP  |  3.232.0  | 
|  Go  |  V2 SDK 1.57.0  | 

某些 Lambda 运行时系统（例如 Python 和 Node.js）包含 AWS 开发工具包的一个版本。如果函数运行时系统中包含的开发工具包版本低于所需的最低版本，您可以将受支持的开发工具包版本添加到函数的部署包中。您还可以使用 [Lambda 层](chapter-layers.md)将受支持的开发工具包版本添加到自己的函数中。有关每个 Lambda 运行时系统包含的开发工具包的列表，请参阅 [Lambda 运行时](lambda-runtimes.md)。

## 递归循环通知
<a name="invocation-recursion-monitoring"></a>

当 Lambda 停止递归循环时，您会通过 [Health Dashboard](https://aws.amazon.com/premiumsupport/technology/aws-health-dashboard/) 或电子邮件收到通知。您还可以使用 CloudWatch 指标来监控 Lambda 已停止的递归的调用次数。

### Health Dashboard 通知
<a name="invocation-recursion-phd"></a>

当 Lambda 停止递归调用时，Health Dashboard 会在**账户运行状况**页面的[未决问题和近期问题](https://health.aws.amazon.com/health/home#/account/dashboard/open-issues)下显示一条通知。请注意，在 Lambda 停止递归调用后，最多可能需要 3.5 小时才能显示此通知。有关在 Health Dashboard 中查看账户事件的更多信息，请参阅《AWS 运行状况用户指南》**中的 [Getting started with your AWS Health Dashboard – Your account health](https://docs.aws.amazon.com/health/latest/ug/getting-started-health-dashboard.html)。

### 电子邮件警报
<a name="invocation-recursion-email"></a>

在首次停止函数的递归调用时，Lambda 会向您发送电子邮件警报。Lambda 每 24 小时最多为您 AWS 账户 中的每个函数发送一封电子邮件。在 Lambda 发送电子邮件通知后，即使 Lambda 停止对该函数的进一步递归调用，您也不会在接下来的 24 小时内再收到该函数的更多电子邮件。请注意，在 Lambda 停止递归调用后，最多可能需要 3.5 小时您才会收到此通知。

Lambda 会向您 AWS 账户 的主要账户联系人和备用运营联系人发送递归循环电子邮件警报。有关查看或更新账户中电子邮件地址的信息，请参阅《AWS 一般参考》**中的 [Updating contact information](https://docs.aws.amazon.com/accounts/latest/reference/manage-acct-update-contact.html)。

### Amazon CloudWatch 指标
<a name="invocation-recursion-cloudwatch"></a>

[CloudWatch 指标](monitoring-metrics-types.md) `RecursiveInvocationsDropped` 会记录 Lambda 因您的函数在单个请求链中被调用次数超过约 16 次而停止的函数调用次数。Lambda 会在停止递归调用后立即发出此指标。要查看此指标，请按照[在 CloudWatch 控制台上查看指标](https://docs.aws.amazon.com/lambda/latest/dg/monitoring-metrics.html#monitoring-metrics-console)的说明进行操作，然后选择指标 `RecursiveInvocationsDropped`。

## 响应递归循环检测通知
<a name="invocation-recursion-responding"></a>

当同一触发事件调用您的函数超过约 16 次时，Lambda 会停止该事件的下一次函数调用，以便中断递归循环。为防止 Lambda 中断的递归循环再次出现，请执行以下操作：
+ 将函数的可用[并发](lambda-concurrency.md)减少到零，即可限制未来发生的所有调用。
+ 移除或禁用会调用函数的触发器或事件源映射。
+ 识别并修复会将事件写回会调用函数的 AWS 资源的代码缺陷。在使用变量定义函数的事件源和目标时，就会出现常见的缺陷来源。请检查并确认您为两个变量使用的是不同值。

此外，如果您的 Lambda 函数的事件源是 Amazon SQS 队列，则可以考虑在源队列上[配置死信队列](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-configure-dead-letter-queue.html)。

**注意**  
确保在源队列上配置死信队列，而不是在 Lambda 函数上配置。您在函数上配置的死信队列用于函数的[异步调用队列](invocation-async.md)，而不是用于事件源队列。

如果事件源是 Amazon SNS 主题，请考虑为您的函数添加[失败时的目标](invocation-async-retain-records.md#invocation-async-destinations)。

**将函数的可用并发减少到零（控制台）**

1. 打开 Lamba 控制台的[函数](https://console.aws.amazon.com/lambda/home#/functions)页面。

1. 选择函数的名称。

1. 选择**限制**。

1. 在**限制函数**对话框中，选择**确认**。

**删除函数的触发器或事件源映射（控制台）**

1. 打开 Lamba 控制台的[函数](https://console.aws.amazon.com/lambda/home#/functions)页面。

1. 选择函数的名称。

1. 选择**配置**选项卡，然后选择**触发器**。

1. 在**触发器**下，选择要删除的触发器或事件源映射，然后选择**删除**。

1. 在**删除触发器**对话框中，选择**删除**。

**禁用函数的事件源映射（AWS CLI）**

1. 要找到要禁用的事件源映射的 UUID，请运行 AWS Command Line Interface（AWS CLI）[list-event-source-mappings](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/list-event-source-mappings.html) 命令。

   ```
   aws lambda list-event-source-mappings
   ```

1. 要禁用事件源映射，请运行以下 AWS CLI [update-event-source-mapping](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/update-event-source-mapping.html) 命令。

   ```
   aws lambda update-event-source-mapping --function-name MyFunction \
   --uuid a1b2c3d4-5678-90ab-cdef-EXAMPLE11111 --no-enabled
   ```

## 允许 Lambda 函数在递归循环中运行
<a name="invocation-recursion-disable"></a>

如果您的设计有意使用递归循环，则可以配置 Lambda 函数以允许递归调用该函数。我们建议避免在设计中使用递归循环。实施错误可能导致递归调用使用您 AWS 账户 的所有可用并发量，并向您的账户收取意外费用。

**重要**  
如果您使用递归循环，请谨慎对待。实施最佳实践防护轨道，以最大限度地降低实施错误的风险。要了解使用递归模式的最佳实践的更多信息，请参阅 Serverless Land 中的 [Recursive patterns that cause run-away Lambda functions](https://serverlessland.com/content/service/lambda/guides/aws-lambda-operator-guide/recursive-runaway)。

您可以使用 Lambda 控制台、AWS Command Line Interface（AWS CLI）和 [PutFunctionRecursionConfig](https://docs.aws.amazon.com//lambda/latest/api/API_PutFunctionRecursionConfig.html) API 将函数配置为允许递归循环。您也可以在 AWS SAM 和 CloudFormation 中配置函数的递归循环检测设置。

默认情况下，Lambda 会检测并终止递归循环。除非您的设计有意使用递归循环，否则我们建议您不要更改函数的默认配置。

请注意，当您将函数配置为允许递归循环时，不会发出 [CloudWatch 指标](monitoring-metrics-types.md#invocation-metrics) `RecursiveInvocationsDropped`。

------
#### [ Console ]

**允许函数在递归循环中运行（控制台）**

1. 打开 Lamba 控制台的[函数](https://console.aws.amazon.com/lambda/home#/functions)页面。

1. 选择函数的名称，打开函数详细信息页面。

1. 选择**配置**选项卡，然后选择**并发和递归检测**。

1. 在**递归循环检测**旁边，选择**编辑**。

1. 选择**允许递归循环**。

1. 选择**保存**。

------
#### [ AWS CLI ]

您可以使用 [PutFunctionRecursionConfig](https://docs.aws.amazon.com/lambda/latest/api/API_PutFunctionRecursionConfig.html) API 来允许在递归循环中调用您的函数。为递归循环参数指定 `Allow`。例如，您可以使用 `put-function-recursion-config` AWS CLI 命令调用此 API：

```
aws lambda put-function-recursion-config --function-name yourFunctionName --recursive-loop Allow
```

------

您可以将函数的配置更改回默认设置，以便 Lambda 在检测到递归循环时将其终止。使用 Lambda 控制台或 AWS CLI 编辑函数的配置。

------
#### [ Console ]

**配置函数以终止递归循环（控制台）**

1. 打开 Lamba 控制台的[函数](https://console.aws.amazon.com/lambda/home#/functions)页面。

1. 选择函数的名称，打开函数详细信息页面。

1. 选择**配置**选项卡，然后选择**并发和递归检测**。

1. 在**递归循环检测**旁边，选择**编辑**。

1. 选择**终止递归循环**。

1. 选择**保存**。

------
#### [ AWS CLI ]

您可以使用 [PutFunctionRecursionConfig](https://docs.aws.amazon.com/lambda/latest/api/API_PutFunctionRecursionConfig.html) API 来配置您的函数，这样 Lambda 在检测到递归循环时将其终止。为递归循环参数指定 `Terminate`。例如，您可以使用 `put-function-recursion-config` AWS CLI 命令调用此 API：

```
aws lambda put-function-recursion-config --function-name yourFunctionName --recursive-loop Terminate
```

------

## 支持 Lambda 递归循环检测的区域
<a name="invocation-recursion-regions"></a>

Lambda 递归循环检测支持在除墨西哥（中部）和亚太地区（新西兰）以外的[所有商业区域](https://docs.aws.amazon.com/general/latest/gr/glos-chap.html#region)使用。

# 创建和管理 Lambda 函数 URL
<a name="urls-configuration"></a>

函数 URL 是 Lambda 函数的专用 HTTP(S) 端点。您可以通过 Lambda 控制台或 Lambda API 创建和配置函数 URL。

**提示**  
Lambda 提供了两种方法来通过 HTTP 端点调用函数：函数 URL 和 Amazon API Gateway。如果您不确定哪种方法最适合您的应用场景，请参阅[选择使用 HTTP 请求调用 Lambda 函数的方法](furls-http-invoke-decision.md)。

创建函数 URL 时，Lambda 会自动为您生成唯一的 URL 端点。创建函数 URL 后，其 URL 端点永远不会改变。函数 URL 的端点具有以下格式：

```
https://<url-id>.lambda-url.<region>.on.aws
```

**注意**  
以下 AWS 区域不支持函数 URL：亚太地区（海得拉巴）(`ap-south-2`)、亚太地区（墨尔本）(`ap-southeast-4`)、亚太地区（马来西亚）(`ap-southeast-5`)、亚太地区（新西兰）(`ap-southeast-6`)、亚太地区（泰国）(`ap-southeast-7`)、亚太地区（台北）(`ap-east-2`)、加拿大西部（卡尔加里）(`ca-west-1`)、欧洲（西班牙）(`eu-south-2`)、欧洲（苏黎世）(`eu-central-2`)、以色列（特拉维夫）(`il-central-1`) 和中东（阿联酋）(`me-central-1`)。

函数 URL 启用了双堆栈，支持 IPv4 和 IPv6。为函数配置函数 URL 后，可以通过 Web 浏览器、curl、Postman 或任何 HTTP 客户端通过其 HTTP（S）端点调用函数。

**注意**  
您只能通过公共 Internet 访问自己的函数 URL。虽然 Lambda 函数确实支持 AWS PrivateLink，但函数 URL 并不支持。

Lambda 函数 URL 使用[基于资源的策略](access-control-resource-based.md)进行安全和访问控制。函数 URL 还支持跨源资源共享 (CORS) 配置选项。

可以将函数 URL 应用于任何函数别名或 `$LATEST` 未发布的函数版本。不能将函数 URL 添加到任何其他函数版本。

以下部分介绍如何使用 Lambda 控制台、AWS CLI 和 CloudFormation 模板创建和管理函数 URL

**Topics**
+ [

## 创建函数 URL（控制台）
](#create-url-console)
+ [

## 创建函数 URL (AWS CLI)
](#create-url-cli)
+ [

## 向 CloudFormation 模板添加函数 URL
](#urls-cfn)
+ [

## 跨源资源共享 (CORS)
](#urls-cors)
+ [

## 节流函数 URL
](#urls-throttling)
+ [

## 停用函数 URL
](#urls-deactivating)
+ [

## 删除函数 URL
](#w2aac39c81c53)
+ [

# 控制对 Lambda 函数 URL 的访问
](urls-auth.md)
+ [

# 调用 Lambda 函数 URL
](urls-invocation.md)
+ [

# 监控 Lambda 函数 URL
](urls-monitoring.md)
+ [

# 选择使用 HTTP 请求调用 Lambda 函数的方法
](furls-http-invoke-decision.md)
+ [

# 教程：使用 Lambda 函数 URL 创建 Webhooook 端点
](urls-webhook-tutorial.md)

## 创建函数 URL（控制台）
<a name="create-url-console"></a>

按照以下步骤，使用控制台创建函数 URL。

### 为现有函数创建函数 URL
<a name="create-url-existing-function"></a>

1. 打开 Lamba 控制台的[函数](https://console.aws.amazon.com/lambda/home#/functions)页面。

1. 选择您要为其创建函数 URL 的函数的名称。

1. 选择 **Configuration**（配置）选项卡，然后选择 **Function URL**（函数 URL）。

1. 选择 **Create function URL**（创建函数 URL）。

1. 对于 **Auth type**（身份验证类型），选择 **AWS\$1IAM** 或 **NONE**。有关函数 URL 身份验证的更多信息，请参阅 [访问控制](urls-auth.md)。

1. （可选）选择 **Configure cross-origin resource sharing (CORS)**（配置跨源资源共享），然后为函数 URL 配置 CORS 设置。有关 CORS 的更多信息，请参阅 [跨源资源共享 (CORS)](#urls-cors)。

1. 选择**保存**。

这将为函数的 `$LATEST` 未发布版本创建函数 URL。函数 URL 将显示在控制台的 **Function overview**（函数概览）部分。

### 为现有别名创建函数 URL
<a name="create-url-existing-alias"></a>

1. 打开 Lamba 控制台的[函数](https://console.aws.amazon.com/lambda/home#/functions)页面。

1. 选择具有您要为其创建函数 URL 的别名的函数的名称。

1. 选择 **Aliases**（别名）选项卡，然后选择要为其创建函数 URL 的别名的名称。

1. 选择 **Configuration**（配置）选项卡，然后选择 **Function URL**（函数 URL）。

1. 选择 **Create function URL**（创建函数 URL）。

1. 对于 **Auth type**（身份验证类型），选择 **AWS\$1IAM** 或 **NONE**。有关函数 URL 身份验证的更多信息，请参阅 [访问控制](urls-auth.md)。

1. （可选）选择 **Configure cross-origin resource sharing (CORS)**（配置跨源资源共享），然后为函数 URL 配置 CORS 设置。有关 CORS 的更多信息，请参阅 [跨源资源共享 (CORS)](#urls-cors)。

1. 选择**保存**。

这将为函数别名创建函数 URL。函数 URL 将显示在控制台中您的别名的 **Function overview**（函数概览）部分。

### 创建具有函数 URL 的新函数
<a name="create-url-new-function"></a>

**创建具有函数 URL 的新函数（控制台）**

1. 打开 Lamba 控制台的 [Functions page](https://console.aws.amazon.com/lambda/home#/functions)（函数页面）。

1. 选择 **Create function**（创建函数）。

1. 在**基本信息**中，执行以下操作：

   1. 在 **Function name**（函数名称）中，输入您的函数的名称，例如 **my-function**。

   1. 对于**运行时**，请选择您首选的语言运行时，例如 **Node.js 24**。

   1. 对于 **Architecture**（架构），请选择 **x86\$164** 或 **arm64**。

   1. 展开 **Permissions**（权限），然后选择是创建新的执行角色还是使用现有的执行角色。

1. 展开 **Advanced settings**（高级设置），然后选择 **Function URL**（函数 URL）。

1. 对于 **Auth type**（身份验证类型），选择 **AWS\$1IAM** 或 **NONE**（无）。有关函数 URL 身份验证的更多信息，请参阅 [访问控制](urls-auth.md)。

1. （可选）选择 **Configure cross-origin resource sharing (CORS)**（配置跨源资源共享）。如果在函数创建过程中选择此选项，则原定设置下，函数 URL 将允许来自所有来源的请求。创建函数后，可以编辑函数 URL 的 CORS 设置。有关 CORS 的更多信息，请参阅 [跨源资源共享 (CORS)](#urls-cors)。

1. 选择**创建函数**。

这将为函数的 `$LATEST` 未发布版本创建一个具有函数 URL 的新函数。函数 URL 将显示在控制台的 **Function overview**（函数概览）部分。

## 创建函数 URL (AWS CLI)
<a name="create-url-cli"></a>

要使用 AWS Command Line Interface (AWS CLI) 为现有 Lambda 函数创建函数 URL，请运行以下命令：

```
aws lambda create-function-url-config \
    --function-name my-function \
    --qualifier prod \ // optional
    --auth-type AWS_IAM
    --cors-config {AllowOrigins="https://example.com"} // optional
```

这会将函数 URL 添加到函数 **my-function** 的 **prod** 限定符中。有关这些配置参数的更多信息，请参阅 API 参考中的[CreateFunctionUrlConfig](https://docs.aws.amazon.com/lambda/latest/api/API_CreateFunctionUrlConfig.html)。

**注意**  
要通过 AWS CLI 创建函数 URL，该函数必须已经存在。

## 向 CloudFormation 模板添加函数 URL
<a name="urls-cfn"></a>

要向 CloudFormation 模板中添加 `AWS::Lambda::Url` 资源，请使用以下语法：

### JSON
<a name="urls-cfn-json"></a>

```
{
  "Type" : "AWS::Lambda::Url",
  "Properties" : {
      "AuthType" : String,
      "Cors" : Cors,
      "Qualifier" : String,
      "TargetFunctionArn" : String
    }
}
```

### YAML
<a name="urls-cfn-yaml"></a>

```
Type: AWS::Lambda::Url
Properties: 
  AuthType: String
  Cors: 
    Cors
  Qualifier: String
  TargetFunctionArn: String
```

### 参数
<a name="urls-cfn-params"></a>
+ （必需）`AuthType` – 定义函数 URL 的身份验证类型。可能的值为 `AWS_IAM` 或 `NONE`。若要将访问权限限制为仅经过身份验证的用户，请设置为 `AWS_IAM`。要绕过 IAM 身份验证并允许任何用户对您的函数发出请求，请设置为 `NONE`。
+ （可选）`Cors` – 定义函数 URL 的 [CORS settings](#urls-cors)（CORS 设置）。要在 CloudFormation 中向 `AWS::Lambda::Url` 资源添加 `Cors`，请使用以下语法。

    
**Example AWS::Lambda::Url.Cors (JSON)**  

  ```
  {
    "AllowCredentials" : Boolean,
    "AllowHeaders" : [ String, ... ],
    "AllowMethods" : [ String, ... ],
    "AllowOrigins" : [ String, ... ],
    "ExposeHeaders" : [ String, ... ],
    "MaxAge" : Integer
  }
  ```  
**Example AWS::Lambda::Url.Cors (YAML)**  

  ```
    AllowCredentials: Boolean
    AllowHeaders: 
      - String
    AllowMethods: 
      - String
    AllowOrigins: 
      - String
    ExposeHeaders: 
      - String
    MaxAge: Integer
  ```
+ （可选）`Qualifier` – 别名。
+ （必需）`TargetFunctionArn` – Lambda 函数的名称或 Amazon 资源名称（ARN）。有效的名称格式包括：
  + **函数名称** – `my-function`
  + **函数 ARN** – `arn:aws:lambda:us-west-2:123456789012:function:my-function`
  + **部分 ARN** – `123456789012:function:my-function`

## 跨源资源共享 (CORS)
<a name="urls-cors"></a>

要定义不同来源如何访问函数 URL，请使用 [跨源资源共享 (CORS)](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS)。如果要从其他域调用函数 URL，建议配置 CORS。Lambda 支持函数 URL 的以下 CORS 标头。


| CORS 标头 | CORS 配置属性 | 示例值 | 
| --- | --- | --- | 
|  [ Access-Control-Allow-Origin](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin)  |  `AllowOrigins`  |  `*`（允许所有源） `https://www.example.com` `http://localhost:60905`  | 
|  [ Access-Control-Allow-Methods](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Methods)  |  `AllowMethods`  |  `GET`, `POST`, `DELETE`, `*`  | 
|  [ Access-Control-Allow-Headers](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Headers)  |  `AllowHeaders`  |  `Date`, `Keep-Alive`, `X-Custom-Header`  | 
|  [ Access-Control-Expose-Headers](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Expose-Headers)  |  `ExposeHeaders`  |  `Date`, `Keep-Alive`, `X-Custom-Header`  | 
|  [ Access-Control-Allow-Credentials](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Credentials)  |  `AllowCredentials`  |  `TRUE`  | 
|  [ Access-Control-Max-Age](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Max-Age)  |  `MaxAge`  |  `5` (默认值)`300`  | 

使用 Lambda 控制台或 AWS CLI 为函数 URL 配置 CORS 时，Lambda 会通过函数 URL 自动将 CORS 标头添加到所有响应中。或者，您也可以手动将 CORS 标头添加到函数响应中。如果存在冲突的标头，则预期行为取决于请求的类型：
+ 对于 OPTIONS 请求之类的预检请求，以函数 URL 上配置的 CORS 标头为准。Lambda 在响应中仅返回这些 CORS 标头。
+ 对于 GET 或 POST 请求之类的非预检请求，Lambda 会同时返回函数 URL 上配置的 CORS 标头以及函数返回的 CORS 标头。这可能会导致响应中出现重复的 CORS 标头。您将看到类似以下的错误：`The 'Access-Control-Allow-Origin' header contains multiple values '*, *', but only one is allowed`。

通常，我们建议在函数 URL 上配置所有 CORS 设置，而不是在函数响应中手动发送 CORS 标头。

## 节流函数 URL
<a name="urls-throttling"></a>

节流限制了函数处理请求的速率。这在很多情况下都很有用，比如防止函数过载下游资源，或者处理请求突然激增的情况。

通过配置预留并发，可以节流 Lambda 函数通过函数 URL 处理请求的速率。预留并发限制了函数的最大并发调用次数。函数的最大每秒请求速率 (RPS) 相当于配置的预留并发的 10 倍。例如，如果将函数配置为预留并发 100，则最大 RPS 为 1,000。

当函数并发超过预留并发时，函数 URL 将返回 HTTP `429` 状态码。如果您的函数收到的请求超过了基于您配置的预留并发的最大 10 倍 RPS，那么您也会收到一个 HTTP `429` 错误。有关预留并发的更多信息，请参阅 [为函数配置预留并发](configuration-concurrency.md)。

## 停用函数 URL
<a name="urls-deactivating"></a>

在紧急情况下，您可能希望拒绝函数 URL 的所有流量。要停用函数 URL，请将预留并发设置为零。这会节流对函数 URL 的所有请求，从而产生 HTTP `429` 状态响应。要重新激活函数 URL，请删除预留的并发配置，或将配置设置为大于零的数量。

## 删除函数 URL
<a name="w2aac39c81c53"></a>

删除函数 URL 后，将无法恢复。创建一个新函数 URL 将导致不同的 URL 地址。

**注意**  
如果您删除身份验证类型为 `NONE` 的函数 URL，Lambda 不会自动删除关联的基于资源的策略。如果要删除此策略，您必须手动执行该操作。

1. 打开 Lamba 控制台的[函数](https://console.aws.amazon.com/lambda/home#/functions)页面。

1. 选择此函数的名称。

1. 选择 **Configuration**（配置）选项卡，然后选择 **Function URL**（函数 URL）。

1. 选择**删除**。

1. 在此字段中输入 *delete*（删除）短语以确认删除。

1. 选择**删除**。

**注意**  
删除具有函数 URL 的函数后，Lambda 会异步删除函数 URL。如果您立即在同一个账户中创建具有相同名称的新函数，则原始函数 URL 可能会被映射到新函数，而不是被删除。

# 控制对 Lambda 函数 URL 的访问
<a name="urls-auth"></a>

**注意**  
从 2025 年 10 月开始，新的函数 URL 将同时需要 `lambda:InvokeFunctionUrl` 和 `lambda:InvokeFunction` 权限。

您可以使用 [AuthType](https://docs.aws.amazon.com/lambda/latest/api/API_CreateFunctionUrlConfig.html#lambda-CreateFunctionUrlConfig-request-AuthType) 参数和附上特定函数的[基于资源的策略](access-control-resource-based.md)来控制对 Lambda 函数 URL 的访问。这两个组件的配置决定了谁可以对函数 URL 调用或执行其他管理操作。

`AuthType` 参数确定了 Lambda 如何对函数 URL 的请求进行身份验证或授权。配置函数 URL 时，必须指定以下 `AuthType` 选项之一：
+ `AWS_IAM` – Lambda 根据 IAM 主体的身份策略和函数基于资源的策略使用 AWS Identity and Access Management (IAM) 对请求进行身份验证和授权。如果只希望经过身份验证的用户和角色使用函数 URL 调用函数，请选择此选项。
+ `NONE` – Lambda 在调用函数之前不会执行任何身份验证。但是，函数基于资源的策略始终有效，并且必须在函数 URL 接收请求之前授予公有访问权限。选择此选项可允许对函数 URL 进行未经身份验证的公有访问。

要了解更多关于安全性的洞察，可以使用 AWS Identity and Access Management Access Analyzer 获取对函数 URL 的外部访问的全面分析。IAM Access Analyzer 还可以监控 Lambda 函数的新权限或更新权限，以帮助您识别授予公有和跨账户访问的权限。可免费使用 IAM Access Analyzer。要开始使用 IAM Access Analyzer，请参阅[使用 AWS IAM Access Analyzer](https://docs.aws.amazon.com/IAM/latest/UserGuide/what-is-access-analyzer.html)。

该页面包含两种身份验证类型的基于资源的策略示例，以及如何使用 [AddPermission](https://docs.aws.amazon.com/lambda/latest/api/API_AddPermission.html) API 操作或 Lambda 控制台创建这些策略。有关设置权限后如何调用函数 URL 的信息，请参阅[调用 Lambda 函数 URL](urls-invocation.md)。

**Topics**
+ [

## 使用 `AWS_IAM` 身份验证类型
](#urls-auth-iam)
+ [

## 使用 `NONE` 身份验证类型
](#urls-auth-none)
+ [

## 治理和访问控制
](#urls-governance)

## 使用 `AWS_IAM` 身份验证类型
<a name="urls-auth-iam"></a>

如果选择 `AWS_IAM` 身份验证类型，则需要调用 Lambda 函数 URL 的用户必须具有 `lambda:InvokeFunctionUrl` 和 `lambda:InvokeFunction` 权限。根据发出调用请求的人员，您可能需要使用[基于资源的策略](access-control-resource-based.md)授予此权限。

如果发出请求的主体与函数 URL 的 AWS 账户 相同，则主体必须****在其[基于身份的策略](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_identity-vs-resource.html)中拥有 `lambda:InvokeFunctionUrl` 和 `lambda:InvokeFunction` 权限，**或者**在函数基于资源的策略中获授权限。换句话说，如果用户已经在其基于身份的策略中拥有 `lambda:InvokeFunctionUrl` 和 `lambda:InvokeFunction` 权限，则基于资源的策略为可选。策略评估遵循[策略评估逻辑](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_evaluation-logic.html)中概述的规则。

如果发出请求的主体位于不同的账户中，则主体必须**同时**具有基于身份的策略（该策略为其提供 `lambda:InvokeFunctionUrl` 和 `lambda:InvokeFunction` 权限）**和**基于资源的策略（基于其尝试调用的函数）中授予的权限。策略评估遵循[确定是否允许跨账户请求](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_evaluation-logic-cross-account.html#policy-eval-cross-account)中概述的规则。

以下基于资源的策略允许 AWS 账户 `444455556666` 中的 `example` 角色调用与函数 `my-function` 关联的函数 URL：[lambda:InvokedViaFunctionUrl](https://docs.aws.amazon.com/lambda/latest/api/API_AddPermission.html#lambda-AddPermission-request-InvokedViaFunctionUrl) 上下文键将操作 `lambda:InvokeFunction` 限制为函数 URL 的调用。这意味着主体必须使用函数 URL 来调用该函数。如果不包含 `lambda:InvokedViaFunctionUrl`，则除了函数 URL 之外，主体还可以通过其他调用方法调用函数。

**Example — 基于跨账户资源的策略**    
****  

```
{
  "Version":"2012-10-17",		 	 	 
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::444455556666:role/example"
      },
      "Action": "lambda:InvokeFunctionUrl",
      "Resource": "arn:aws:lambda:us-east-1:123456789012:function:my-function",
      "Condition": {
        "StringEquals": {
          "lambda:FunctionUrlAuthType": "AWS_IAM"
        }
      }
    },
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::444455556666:role/example"
      },
      "Action": "lambda:InvokeFunction",
      "Resource": "arn:aws:lambda:us-east-1:123456789012:function:my-function",
      "Condition": {
        "Bool": {
          "lambda:InvokedViaFunctionUrl": "true"
        }
      }
    }
  ]
}
```

您可以按照以下步骤通过控制台创建这一基于资源的策略：

**将 URL 调用权限授予另一个账户（控制台）**

1. 打开 Lamba 控制台的[函数](https://console.aws.amazon.com/lambda/home#/functions)页面。

1. 选择要为其授予 URL 调用权限的函数的名称。

1. 选择 **Configuration**（配置）选项卡，然后选择 **Permissions**（权限）。

1. 在 **Resource-based policy**（基于资源的策略）下，选择 **Add permissions**（添加权限）。

1. 选择 **Function URL**（函数 URL）。

1. 对于 **Auth type**（身份验证类型），选择 **AWS\$1IAM**。

1. 输入策略语句的**语句 ID**。

1. 对于**主体**，请输入要向其授予权限的用户或角色的 Amazon 资源名称（ARN）。例如：**444455556666**。

1. 选择**保存**。

或者，也可以使用以下 [add-permission](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/add-permission.html) AWS Command Line Interface (AWS CLI) 命令创建此策略：使用 AWS CLI 时，必须单独添加 `lambda:InvokeFunctionUrl` 和 `lambda:InvokeFunction` 语句。例如：

```
aws lambda add-permission --function-name my-function \
  --statement-id UrlPolicyInvokeURL \
  --action lambda:InvokeFunctionUrl \
  --principal 444455556666 \
  --function-url-auth-type AWS_IAM
```

```
aws lambda add-permission --function-name my-function \
  --statement-id UrlPolicyInvokeFunction \
  --action lambda:InvokeFunction \
  --principal 444455556666 \
  --invoked-via-function-url
```

## 使用 `NONE` 身份验证类型
<a name="urls-auth-none"></a>

**重要**  
当您的函数 URL 身份验证类型为 `NONE` 且您有[基于资源的策略](access-control-resource-based.md)授予公有访问权限时，任何使用您函数 URL 的未经身份验证的用户都可以调用您的函数。

在某些情况下，您可能希望函数 URL 为公有。例如，您可能希望处理直接从 Web 浏览器发出的请求。要允许函数 URL 公有访问权限，请选择 `NONE` 身份验证类型。

如果选择 `NONE` 身份验证类型，Lambda 不会使用 IAM 对函数 URL 的请求进行身份验证。但是，函数必须拥有允许 `lambda:InvokeFunctionUrl` 和 `lambda:InvokeFunction` 的基于资源的策略。使用控制台或 AWS Serverless Application Model (AWS SAM) 创建具有身份验证类型 `NONE` 的函数 URL 时，Lambda 会自动创建基于资源的策略。如果直接使用 AWS CLI、AWS CloudFormation 或 Lambda API，则必须[自己添加策略](#policy-cli)。

我们建议在使用 `NONE` 身份验证类型时，在基于资源的策略中包含 [lambda:InvokedViaFunctionUrl](https://docs.aws.amazon.com/lambda/latest/api/API_AddPermission.html#lambda-AddPermission-request-InvokedViaFunctionUrl) 上下文键。此上下文键可确保只能通过函数 URL 调用函数，而不能通过其他调用方法进行调用。

请注意有关该策略的以下信息：
+ 所有实体均可调用 `lambda:InvokeFunctionUrl` 和 `lambda:InvokeFunction`。这意味着拥有函数 URL 的任何人都可以调用函数。
+ `lambda:FunctionUrlAuthType` 条件键值为 `NONE`。这意味着，此策略仅在函数 URL 的身份验证类型也为 `NONE` 时允许访问。
+ 该 `lambda:InvokedViaFunctionUrl` 条件可确保只能通过函数 URL 调用该函数，而不能通过其他调用方法进行调用。

**Example — NONE 身份验证类型默认基于资源的策略**    
****  

```
{
  "Version":"2012-10-17",		 	 	 
  "Statement": [
    {
      "Sid": "FunctionURLAllowPublicAccess",
      "Effect": "Allow",
      "Principal": "*",
      "Action": "lambda:InvokeFunctionUrl",
      "Resource": "arn:aws:lambda:us-east-2:123456789012:function:my-function",
      "Condition": {
        "StringEquals": {
          "lambda:FunctionUrlAuthType": "NONE"
        }
      }
    },
    {
      "Sid": "FunctionURLInvokeAllowPublicAccess",
      "Effect": "Allow",
      "Principal": "*",
      "Action": "lambda:InvokeFunction",
      "Resource": "arn:aws:lambda:us-east-2:123456789012:function:my-function",
      "Condition": {
        "Bool": {
          "lambda:InvokedViaFunctionUrl": "true"
        }
      }
    }
  ]
}
```

**使用 AWS CLI 创建基于资源的策略**  
除非使用控制台或 AWS SAM 创建身份验证类型为 `NONE` 的函数 URL，否则必须自己添加基于资源的策略。使用以下命令，创建 `lambda:InvokeFunctionUrl` 和 `lambda:InvokeFunction` 权限的语句。每条语句都必须添加到单独的命令中。

```
aws lambda add-permission \
  --function-name UrlTestFunction \
  --statement-id UrlPolicyInvokeURL \
  --action lambda:InvokeFunctionUrl \
  --principal * \
  --function-url-auth-type NONE
```

```
aws lambda add-permission \
  --function-name UrlTestFunction \
  --statement-id UrlPolicyInvokeFunction \
  --action lambda:InvokeFunction \
  --principal * \
  --invoked-via-function-url
```

**注意**  
如果您删除身份验证类型为 `NONE` 的函数 URL，Lambda 不会自动删除关联的基于资源的策略。如果要删除此策略，您必须手动执行该操作。

如果函数基于资源的策略未授予 `lambda:invokeFunctionUrl` 和 `lambda:InvokeFunction` 权限，则用户在尝试调用函数 URL 时，将收到 403 禁止的错误代码。即使函数 URL 使用 `NONE` 身份验证类型，也会发生这种情况。

## 治理和访问控制
<a name="urls-governance"></a>

除了函数 URL 调用权限外，还可以控制对用于配置函数 URL 的操作的访问。Lambda 支持以下针对函数 URL 的 IAM policy 操作：
+ `lambda:InvokeFunctionUrl` – 使用函数 URL 调用 Lambda 函数。
+ `lambda:CreateFunctionUrlConfig` – 创建函数 URL 并设置其 `AuthType`。
+ `lambda:UpdateFunctionUrlConfig` – 更新函数 URL 配置及其 `AuthType`。
+ `lambda:GetFunctionUrlConfig` – 查看函数 URL 的详细信息。
+ `lambda:ListFunctionUrlConfigs` – 列出函数 URL 配置。
+ `lambda:DeleteFunctionUrlConfig` – 删除函数 URL。

要允许或拒绝对其他 AWS 实体的函数 URL 访问，请在 IAM policy 中包含这些操作。例如，以下策略授予 AWS 账户 `444455556666` 中的 `example` 角色在账户 `123456789012` 中更新函数 **my-function** 的函数 URL 的权限。

**Example 跨账户函数 URL 策略**    
****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": { 
                "AWS": "arn:aws:iam::444455556666:role/example"
            },
            "Action": "lambda:UpdateFunctionUrlConfig",
            "Resource": "arn:aws:lambda:us-east-2:123456789012:function:my-function"
        }
    ]
}
```

### 条件键
<a name="urls-condition-keys"></a>

要对函数 URL 进行精细访问控制，请使用条件上下文键。Lambda 支持函数 URL 的以下上下文键：
+ `lambda:FunctionUrlAuthType` – 定义了一个枚举值，描述函数 URL 使用的身份验证类型。该值可以是 `AWS_IAM` 或 `NONE`。
+ `lambda:InvokedViaFunctionUrl` — 将 `lambda:InvokeFunction` 操作限制为通过函数 URL 进行调用。这可以确保只能使用函数 URL 调用该函数，而不能通过其他调用方法进行调用。有关使用 `lambda:InvokedViaFunctionUrl` 上下文键的基于资源的策略示例，请参阅[使用 `AWS_IAM` 身份验证类型](#urls-auth-iam)和[使用 `NONE` 身份验证类型](#urls-auth-none)中的示例。

可以在与函数关联的策略中使用这些上下文键。例如，您可能希望限制谁可以对函数 URL 进行配置更改。要拒绝对 URL 身份验证类型 `NONE` 的任何函数的所有 `UpdateFunctionUrlConfig` 请求，可以定义以下策略：

**Example 带有显式拒绝的函数 URL 策略**    
****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Deny",
            "Principal": "*",
            "Action":[
                "lambda:UpdateFunctionUrlConfig"
            ],
            "Resource": "arn:aws:lambda:us-east-1:123456789012:function:*",
            "Condition": {
                "StringEquals": {
                    "lambda:FunctionUrlAuthType": "NONE"
                }
            }
        }
    ]
}
```

要授予 AWS 账户 `444455556666` 中的 `example` 角色对 URL 身份验证类型 `AWS_IAM` 的函数进行 `CreateFunctionUrlConfig` 和 `UpdateFunctionUrlConfig` 请求的权限，可以定义以下策略：

**Example 带有显式允许的函数 URL 策略**    
****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": { 
                "AWS": "arn:aws:iam::444455556666:role/example"
            },
            "Action":[
                "lambda:CreateFunctionUrlConfig",
                "lambda:UpdateFunctionUrlConfig"
            ],
            "Resource": "arn:aws:lambda:us-east-1:123456789012:function:*",
            "Condition": {
                "StringEquals": {
                    "lambda:FunctionUrlAuthType": "AWS_IAM"
                }
            }
        }
    ]
}
```

您还可以在[服务控制策略](https://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_policies_scps.html)（SCP）中使用此条件键。使用 SCP 在 AWS Organizations 中管理整个企业的权限。例如，要拒绝用户创建或更新使用除 `AWS_IAM` 身份验证类型以外的任何身份验证类型的函数 URL，请使用以下服务控制策略：

**Example 带有显式拒绝的函数 URL SCP**    
****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Deny",
            "Action":[
                "lambda:CreateFunctionUrlConfig",
                "lambda:UpdateFunctionUrlConfig"
            ],
            "Resource": "arn:aws:lambda:*:123456789012:function:*",
            "Condition": {
                "StringNotEquals": {
                    "lambda:FunctionUrlAuthType": "AWS_IAM"
                }
            }
        }
    ]
}
```

# 调用 Lambda 函数 URL
<a name="urls-invocation"></a>

函数 URL 是 Lambda 函数的专用 HTTP(S) 端点。您可以通过 Lambda 控制台或 Lambda API 创建和配置函数 URL。

**提示**  
Lambda 提供了两种方法来通过 HTTP 端点调用函数：函数 URL 和 Amazon API Gateway。如果您不确定哪种方法最适合您的应用场景，请参阅[选择使用 HTTP 请求调用 Lambda 函数的方法](furls-http-invoke-decision.md)。

创建函数 URL 时，Lambda 会自动为您生成唯一的 URL 端点。创建函数 URL 后，其 URL 端点永远不会改变。函数 URL 的端点具有以下格式：

```
https://<url-id>.lambda-url.<region>.on.aws
```

**注意**  
以下 AWS 区域不支持函数 URL：亚太地区（海得拉巴）(`ap-south-2`)、亚太地区（墨尔本）(`ap-southeast-4`)、亚太地区（马来西亚）(`ap-southeast-5`)、亚太地区（新西兰）(`ap-southeast-6`)、亚太地区（泰国）(`ap-southeast-7`)、亚太地区（台北）(`ap-east-2`)、加拿大西部（卡尔加里）(`ca-west-1`)、欧洲（西班牙）(`eu-south-2`)、欧洲（苏黎世）(`eu-central-2`)、以色列（特拉维夫）(`il-central-1`) 和中东（阿联酋）(`me-central-1`)。

函数 URL 启用了双堆栈，支持 IPv4 和 IPv6。配置函数 URL 后，可以通过 Web 浏览器、curl、Postman 或任何 HTTP 客户端通过其 HTTP(S) 端点调用函数。要调用函数 URL，您必须具有 `lambda:InvokeFunctionUrl` 和 `lambda:InvokeFunction` 权限。有关更多信息，请参阅[访问控制](urls-auth.md)。

**Topics**
+ [

## 函数 URL 调用基础
](#urls-invocation-basics)
+ [

## 请求和响应有效负载
](#urls-payloads)

## 函数 URL 调用基础
<a name="urls-invocation-basics"></a>

如果函数 URL 使用 `AWS_IAM` 身份验证类型，则必须使用 [AWS 签名版本 4 (SigV4)](https://docs.aws.amazon.com/general/latest/gr/signature-version-4.html) 对每个 HTTP 请求进行签名。[Postman](https://quickstarts.postman.com/guide/aws/index.html?index=..%2F..index#2) 等工具提供了内置的方法使用 SigV4 对请求进行签名。

如果不使用工具向函数 URL 对 HTTP 请求进行签名，则必须使用 SigV4 手动对每个请求进行签名。当函数 URL 收到请求时，Lambda 还会计算 SigV4 签名。Lambda 仅在签名匹配时处理请求。有关如何使用 SigV4 手动对请求进行签名的说明，请参阅*《Amazon Web Services 一般参考 指南》*中的[利用签名版本 4 对 AWS 请求进行签名](https://docs.aws.amazon.com/general/latest/gr/sigv4_signing.html)。

如果函数 URL 使用 `NONE` 身份验证类型，则不必使用 SigV4 对请求进行签名。您可以使用 Web 浏览器、curl、Postman 或任何 HTTP 客户端来调用函数。

要测试对函数的简单 `GET` 请求，请使用 Web 浏览器。例如，如果您的函数 URL 为 `https://abcdefg.lambda-url.us-east-1.on.aws`，并且包含一个字符串参数 `message`，那么您的请求 URL 可能如下所示：

```
https://abcdefg.lambda-url.us-east-1.on.aws/?message=HelloWorld
```

要测试其他 HTTP 请求，例如 `POST` 请求，可以使用 curl 之类的工具。例如，如果希望在对函数 URL 的 `POST` 请求中包含一些 JSON 数据，可以使用以下 curl 命令：

```
curl -v 'https://abcdefg.lambda-url.us-east-1.on.aws/?message=HelloWorld' \
-H 'content-type: application/json' \
-d '{ "example": "test" }'
```

## 请求和响应有效负载
<a name="urls-payloads"></a>

当客户端调用函数 URL 时，Lambda 会将请求映射到事件对象，然后再将其传递给函数。然后，函数的响应将映射到一个 HTTP 响应，Lambda 会通过函数 URL 将该响应发送回客户端。

请求和响应事件格式遵循与 [Amazon API Gateway 有效负载格式版本 2.0](https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-develop-integrations-lambda.html#http-api-develop-integrations-lambda.proxy-format) 相同的模式。

### 请求有效负载格式
<a name="urls-request-payload"></a>

请求有效负载具有以下结构：

```
{
  "version": "2.0",
  "routeKey": "$default",
  "rawPath": "/my/path",
  "rawQueryString": "parameter1=value1&parameter1=value2&parameter2=value",
  "cookies": [
    "cookie1",
    "cookie2"
  ],
  "headers": {
    "header1": "value1",
    "header2": "value1,value2"
  },
  "queryStringParameters": {
    "parameter1": "value1,value2",
    "parameter2": "value"
  },
  "requestContext": {
    "accountId": "123456789012",
    "apiId": "<urlid>",
    "authentication": null,
    "authorizer": {
        "iam": {
                "accessKey": "AKIA...",
                "accountId": "111122223333",
                "callerId": "AIDA...",
                "cognitoIdentity": null,
                "principalOrgId": null,
                "userArn": "arn:aws:iam::111122223333:user/example-user",
                "userId": "AIDA..."
        }
    },
    "domainName": "<url-id>.lambda-url.us-west-2.on.aws",
    "domainPrefix": "<url-id>",
    "http": {
      "method": "POST",
      "path": "/my/path",
      "protocol": "HTTP/1.1",
      "sourceIp": "123.123.123.123",
      "userAgent": "agent"
    },
    "requestId": "id",
    "routeKey": "$default",
    "stage": "$default",
    "time": "12/Mar/2020:19:03:58 +0000",
    "timeEpoch": 1583348638390
  },
  "body": "Hello from client!",
  "pathParameters": null,
  "isBase64Encoded": false,
  "stageVariables": null
}
```


| 参数 | 描述 | 示例 | 
| --- | --- | --- | 
|  `version`  |  此事件的有效负载格式版本。Lambda 函数 URL 目前支持[有效负载格式版本 2.0](https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-develop-integrations-lambda.html#http-api-develop-integrations-lambda.proxy-format)。  |  `2.0`  | 
|  `routeKey`  |  函数 URL 不使用此参数。Lambda 将其设置为 `$default`，作为占位符。  |  `$default`  | 
|  `rawPath`  |  请求路径。例如，如果请求 URL 为 `https://{url-id}.lambda-url.{region}.on.aws/example/test/demo`，则原始路径值为 `/example/test/demo`。  |  `/example/test/demo`  | 
|  `rawQueryString`  |  包含请求的查询字符串参数的原始字符串。支持的字符包括 `a-z`、`A-Z`、`0-9`、`.`、`_`、`-`、`%`、`&`、`=` 和 `+`。  |  `"?parameter1=value1&parameter2=value2"`  | 
|  `cookies`  |  数组包含发送的部分请求的所有 Cookie。  |  `["Cookie_1=Value_1", "Cookie_2=Value_2"]`  | 
|  `headers`  |  请求标头的列表，以键值对的形式显示。  |  `{"header1": "value1", "header2": "value2"}`  | 
|  `queryStringParameters`  |  请求的查询参数。例如，如果请求 URL 为 `https://{url-id}.lambda-url.{region}.on.aws/example?name=Jane`，则 `queryStringParameters` 值是一个 JSON 对象，其键为 `name`，值为 `Jane`。  |  `{"name": "Jane"}`  | 
|  `requestContext`  |  一个包含有关请求的附加信息的对象，例如 `requestId`、请求的时间以及通过 AWS Identity and Access Management (IAM) 授权的调用者身份。  |   | 
|  `requestContext.accountId`  |  函数拥有者的 AWS 账户 ID。  |  `"123456789012"`  | 
|  `requestContext.apiId`  |  函数 URL 的 ID。  |  `"33anwqw8fj"`  | 
|  `requestContext.authentication`  |  函数 URL 不使用此参数。Lambda 会将其设置为 `null`。  |  `null`  | 
|  `requestContext.authorizer`  |  对象包含有关调用者身份的信息（如果函数 URL 使用 `AWS_IAM` 身份验证类型）。否则，Lambda 会将其设置为 `null`。  |   | 
|  `requestContext.authorizer.iam.accessKey`  |  调用者身份的访问密钥。  |  `"AKIAIOSFODNN7EXAMPLE"`  | 
|  `requestContext.authorizer.iam.accountId`  |  调用者身份的 AWS 账户 ID。  |  `"111122223333"`  | 
|  `requestContext.authorizer.iam.callerId`  |  调用者的 ID（用户 ID）。  |  `"AIDACKCEVSQ6C2EXAMPLE"`  | 
|  `requestContext.authorizer.iam.cognitoIdentity`  |  函数 URL 不使用此参数。Lambda 会将其设置为 `null`，或将其从 JSON 中排除。  |  `null`  | 
|  `requestContext.authorizer.iam.principalOrgId`  |  与调用者身份关联的主体企业 ID。  |  `"AIDACKCEVSQORGEXAMPLE"`  | 
|  `requestContext.authorizer.iam.userArn`  |  调用者身份的用户 Amazon 资源名称（ARN）。  |  `"arn:aws:iam::111122223333:user/example-user"`  | 
|  `requestContext.authorizer.iam.userId`  |  调用者身份的用户 ID。  |  `"AIDACOSFODNN7EXAMPLE2"`  | 
|  `requestContext.domainName`  |  函数 URL 的域名。  |  `"<url-id>.lambda-url.us-west-2.on.aws"`  | 
|  `requestContext.domainPrefix`  |  函数 URL 的域前缀。  |  `"<url-id>"`  | 
|  `requestContext.http`  |  包含有关 HTTP 请求的详细信息的对象。  |   | 
|  `requestContext.http.method`  |  此请求中使用的 HTTP 方法。有效值包括 `GET`、`POST`、`PUT`、`HEAD`、`OPTIONS`、`PATCH` 和 `DELETE`。  |  `GET`  | 
|  `requestContext.http.path`  |  请求路径。例如，如果请求 URL 为 `https://{url-id}.lambda-url.{region}.on.aws/example/test/demo`，则路径值为 `/example/test/demo`。  |  `/example/test/demo`  | 
|  `requestContext.http.protocol`  |  请求的协议。  |  `HTTP/1.1`  | 
|  `requestContext.http.sourceIp`  |  发出请求的即时 TCP 连接的源 IP 地址。  |  `123.123.123.123`  | 
|  `requestContext.http.userAgent`  |  用户代理请求标头值。  |  `Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) Gecko/20100101 Firefox/42.0`  | 
|  `requestContext.requestId`  |  调用请求的 ID。可以使用此 ID 跟踪与函数相关的调用日志。  |  `e1506fd5-9e7b-434f-bd42-4f8fa224b599`  | 
|  `requestContext.routeKey`  |  函数 URL 不使用此参数。Lambda 将其设置为 `$default`，作为占位符。  |  `$default`  | 
|  `requestContext.stage`  |  函数 URL 不使用此参数。Lambda 将其设置为 `$default`，作为占位符。  |  `$default`  | 
|  `requestContext.time`  |  请求的时间戳。  |  `"07/Sep/2021:22:50:22 +0000"`  | 
|  `requestContext.timeEpoch`  |  请求的时间戳，用 Unix epoch 时间表示。  |  `"1631055022677"`  | 
|  `body`  |  请求的正文。如果请求的内容类型为二进制，则正文为 base64 编码。  |  `{"key1": "value1", "key2": "value2"}`  | 
|  `pathParameters`  |  函数 URL 不使用此参数。Lambda 会将其设置为 `null`，或将其从 JSON 中排除。  |  `null`  | 
|  `isBase64Encoded`  |  如果正文为二进制有效负载，并且为 base64 编码，则为 `TRUE`。否则为 `FALSE`。  |  `FALSE`  | 
|  `stageVariables`  |  函数 URL 不使用此参数。Lambda 会将其设置为 `null`，或将其从 JSON 中排除。  |  `null`  | 

### 响应有效负载格式
<a name="urls-response-payload"></a>

当函数返回响应时，Lambda 会解析响应并将其转换为 HTTP 响应。函数响应有效负载的格式如下：

```
{
   "statusCode": 201,
    "headers": {
        "Content-Type": "application/json",
        "My-Custom-Header": "Custom Value"
    },
    "body": "{ \"message\": \"Hello, world!\" }",
    "cookies": [
        "Cookie_1=Value1; Expires=21 Oct 2021 07:48 GMT",
        "Cookie_2=Value2; Max-Age=78000"
    ],
    "isBase64Encoded": false
}
```

Lambda 会为您推断响应格式。如果您的函数返回有效的 JSON 并且没有返回 `statusCode`，Lambda 会做出以下假设：
+ `statusCode`is(`200` )
**注意**  
有效的 `statusCode` 在 100 至 599 范围内。
+ `content-type`is(`application/json` )
+ `body` 是函数响应。
+ `isBase64Encoded`is(`false` )

以下示例显示了 Lambda 函数的输出如何映射到响应有效负载，以及响应有效负载如何映射到最终 HTTP 响应。当客户端调用函数 URL 时，就会看到 HTTP 响应。

**字符串响应的输出示例**


| Lambda 函数输出 | 解释响应输出 | HTTP 响应（客户端看到的内容） | 
| --- | --- | --- | 
|  <pre>"Hello, world!"</pre>  |  <pre>{<br />  "statusCode": 200,<br />  "body": "Hello, world!",<br />  "headers": {<br />    "content-type": "application/json"<br />  },<br />  "isBase64Encoded": false<br />}</pre>  |  <pre>HTTP/2 200<br />date: Wed, 08 Sep 2021 18:02:24 GMT<br />content-type: application/json<br />content-length: 15<br /><br />"Hello, world!"</pre>  | 

**JSON 响应的输出示例**


| Lambda 函数输出 | 解释响应输出 | HTTP 响应（客户端看到的内容） | 
| --- | --- | --- | 
|  <pre>{<br />  "message": "Hello, world!"<br />}</pre>  |  <pre>{<br />  "statusCode": 200,<br />  "body": {<br />    "message": "Hello, world!"<br />  },<br />  "headers": {<br />    "content-type": "application/json"<br />  },<br />  "isBase64Encoded": false<br />}</pre>  |  <pre>HTTP/2 200<br />date: Wed, 08 Sep 2021 18:02:24 GMT<br />content-type: application/json<br />content-length: 34<br /><br />{<br />  "message": "Hello, world!"<br />}</pre>  | 

**自定义响应的输出示例**


| Lambda 函数输出 | 解释响应输出 | HTTP 响应（客户端看到的内容） | 
| --- | --- | --- | 
|  <pre>{<br />   "statusCode": 201,<br />    "headers": {<br />        "Content-Type": "application/json",<br />        "My-Custom-Header": "Custom Value"<br />    },<br />    "body": JSON.stringify({<br />        "message": "Hello, world!"<br />    }),<br />    "isBase64Encoded": false<br />}</pre>  |  <pre>{<br />   "statusCode": 201,<br />    "headers": {<br />        "Content-Type": "application/json",<br />        "My-Custom-Header": "Custom Value"<br />    },<br />    "body": JSON.stringify({<br />        "message": "Hello, world!"<br />    }),<br />    "isBase64Encoded": false<br />}</pre>  |  <pre>HTTP/2 201<br />date: Wed, 08 Sep 2021 18:02:24 GMT<br />content-type: application/json<br />content-length: 27<br />my-custom-header: Custom Value<br /><br />{<br />  "message": "Hello, world!"<br />}</pre>  | 

### Cookie
<a name="urls-cookies"></a>

要从函数返回 Cookie，请不要手动添加 `set-cookie` 标头。相反，请在响应有效负载对象中包含 Cookie。Lambda 会自动进行解释，并将其作为 `set-cookie` 标头添加到 HTTP 响应中，如下例所示。


| Lambda 函数输出 | HTTP 响应（客户端看到的内容） | 
| --- | --- | 
|  <pre>{<br />   "statusCode": 201,<br />    "headers": {<br />        "Content-Type": "application/json",<br />        "My-Custom-Header": "Custom Value"<br />    },<br />    "body": JSON.stringify({<br />        "message": "Hello, world!"<br />    }),<br />    "cookies": [<br />        "Cookie_1=Value1; Expires=21 Oct 2021 07:48 GMT",<br />        "Cookie_2=Value2; Max-Age=78000"<br />    ],<br />    "isBase64Encoded": false<br />}</pre>  |  <pre>HTTP/2 201<br />date: Wed, 08 Sep 2021 18:02:24 GMT<br />content-type: application/json<br />content-length: 27<br />my-custom-header: Custom Value<br />set-cookie: Cookie_1=Value2; Expires=21 Oct 2021 07:48 GMT<br />set-cookie: Cookie_2=Value2; Max-Age=78000<br /><br />{<br />  "message": "Hello, world!"<br />}</pre>  | 

# 监控 Lambda 函数 URL
<a name="urls-monitoring"></a>

您可以使用 AWS CloudTrail 和 Amazon CloudWatch 来监控您的函数 URL。

**Topics**
+ [

## 使用 CloudTrail 监控函数 URL
](#urls-cloudtrail)
+ [

## 函数 URL 的 CloudWatch 指标
](#urls-cloudwatch)

## 使用 CloudTrail 监控函数 URL
<a name="urls-cloudtrail"></a>

对于函数 URL，Lambda 自动支持将以下 API 操作记录为 CloudTrail 日志文件中的事件：
+ [CreateFunctionUrlConfig](https://docs.aws.amazon.com/lambda/latest/api/API_CreateFunctionUrlConfig.html)
+ [UpdateFunctionUrlConfig](https://docs.aws.amazon.com/lambda/latest/api/API_UpdateFunctionUrlConfig.html)
+ [DeleteFunctionUrlConfig](https://docs.aws.amazon.com/lambda/latest/api/API_DeleteFunctionUrlConfig.html)
+ [GetFunctionUrlConfig](https://docs.aws.amazon.com/lambda/latest/api/API_GetFunctionUrlConfig.html)
+ [ListFunctionUrlConfigs](https://docs.aws.amazon.com/lambda/latest/api/API_ListFunctionUrlConfigs.html)

每个日志条目都包含有关调用者身份、发出请求的时间以及其他详细信息的信息。通过查看 CloudTrail **Event history**（事件历史记录），可以看到过去 90 天内的所有事件。要保留过去 90 天的记录，可以创建跟踪记录。

原定设置下，CloudTrail 不会录入 `InvokeFunctionUrl` 请求，这些请求将被视为数据事件。但是，您可以在 CloudTrail 中打开数据事件日志记录。有关更多信息，请参阅 *AWS CloudTrail 用户指南*中的[记录数据事件以便跟踪](https://docs.aws.amazon.com/awscloudtrail/latest/userguide/logging-data-events-with-cloudtrail.html)。

## 函数 URL 的 CloudWatch 指标
<a name="urls-cloudwatch"></a>

Lambda 会向 CloudWatch 发送关于函数 URL 请求的聚合指标。借助这些指标，您可以在 CloudWatch 控制台中监控函数 URL、构建控制面板和配置告警。

函数 URL 支持以下调用指标。我们建议使用 `Sum` 统计数据查看这些指标。
+ `UrlRequestCount` – 向该函数 URL 发出的请求数。
+ `Url4xxCount` – 返回 4XX HTTP 状态码的请求数。4XX 系列代码表示客户端错误，例如错误请求。
+ `Url5xxCount` – 返回 5XX HTTP 状态码的请求数。5XX 系列代码表示服务器端错误，例如函数错误和超时。

函数 URL 还支持以下性能指标。我们建议使用 `Average` 或 `Max` 统计数据查看此指标。
+ `UrlRequestLatency` – 函数 URL 收到请求和函数 URL 返回响应之间的时间。

每个调用和性能指标都支持以下维度：
+ `FunctionName` – 查看分配给函数 `$LATEST` 未发布版本或任何函数别名的函数 URL 的聚合指标。例如，`hello-world-function`。
+ `Resource` – 查看特定函数 URL 的指标。其由函数名称、函数的 `$LATEST` 未发布版本或函数的别名之一定义。例如，`hello-world-function:$LATEST`。
+ `ExecutedVersion` – 根据执行的版本查看特定函数 URL 的指标。您可以主要使用此维度跟踪分配给 `$LATEST` 未发布版本的函数 URL。

# 选择使用 HTTP 请求调用 Lambda 函数的方法
<a name="furls-http-invoke-decision"></a>

Lambda 的许多常见使用案例都涉及使用 HTTP 请求调用函数。例如，您可能希望 Web 应用程序通过浏览器请求调用函数。Lambda 函数还可用于创建完整的 REST API、处理来自移动应用程序的用户交互、通过 HTTP 调用处理来自外部服务的数据，或者创建自定义 Webhook。

以下几节介绍了通过 HTTP 调用 Lambda 的选择，并提供了有助于您针对特定使用案例做出正确决策的信息。

## 在选择 HTTP 调用方法时，您有什么选择？
<a name="w2aac39c81c73b9"></a>

Lambda 提供了两种使用 HTTP 请求调用函数的主要方法：[函数 URL](urls-configuration.md) 和 [API Gateway](services-apigateway.md)。这两个选项之间的主要差异如下所示：
+ **Lambda 函数 URL** 为 Lambda 函数提供了简单、直接的 HTTP 端点。它们针对简单性和成本效益进行了优化，且提供了通过 HTTP 公开 Lambda 函数的最快路径。
+ **API Gateway** 是用于构建功能齐全的 API 的更高级服务。API Gateway 针对大规模构建和管理生产 API 进行了优化，并提供了用于安全、监控和流量管理的全面工具。

## 在已经知道自己要求的情况下的建议
<a name="w2aac39c81c73c11"></a>

如果您已经明确自己的要求，则以下是我们的基本建议：

建议在简单的应用程序或原型设计中使用**[函数 URL](urls-configuration.md)**，其中您只需要基本身份验证方法和请求/响应处理，并且希望将成本和复杂性降至最低。

**[API Gateway](services-apigateway.md)** 是大规模生产应用程序或需要更高级功能的情况下的更好选择，例如 [OpenAPI 描述](https://www.openapis.org/)支持、身份验证选项选择、自定义域名或丰富的请求/响应处理（包括节流、缓存和请求/响应转换）。

## 选择用于调用 Lambda 函数的方法时要考虑的事项
<a name="w2aac39c81c73c13"></a>

在函数 URL 与 API Gateway 之间进行选择时，您需要考虑以下因素：
+ 您的身份验证需求，例如您需要 OAuth 还是 Amazon Cognito 来对用户进行身份验证
+ 您的扩展要求和要实施的 API 的复杂性
+ 您是否需要请求验证和请求/响应格式等高级功能
+ 您的监控要求
+ 您的成本目标

通过了解这些因素，您可以选择能平衡安全性、复杂性和成本要求的最佳选项。

以下信息汇总了两个选项之间的主要差异。

### 身份验证
<a name="w2aac39c81c73c13c11b1"></a>
+ **函数 URL** 通过 AWS Identity and Access Management（IAM）提供基本身份验证选项。您可以将端点配置为公有（无身份验证）或要求 IAM 身份验证。通过 IAM 身份验证，您可以使用标准 AWS 凭证或 IAM 角色来控制访问权限。虽然设置起来很简单，但与其他身份验证方法相比，此方法提供的选项有限。
+ **API Gateway** 提供对更全面的身份验证选项的访问权限。除了 IAM 身份验证外，您还可以使用 [Lambda 授权方](https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-use-lambda-authorizer.html)（自定义身份验证逻辑）、[Amazon Cognito](https://docs.aws.amazon.com/cognito/latest/developerguide/what-is-amazon-cognito.html) 用户池和 OAuth 2.0 流。这种灵活性使您能够实施复杂的身份验证方案，包括第三方身份验证提供商、基于令牌的身份验证和多重身份验证。

### 请求/响应处理
<a name="w2aac39c81c73c13c11b3"></a>
+ **函数 URL** 提供了基本的 HTTP 请求和响应处理。它们支持标准 HTTP 方法，并包括内置的跨源资源共享（CORS）支持。虽然它们可以自然地处理 JSON 有效载荷和查询参数，但不提供请求转换或验证功能。响应处理同样简单 – 客户端从您的 Lambda 函数接收的响应与 Lambda 返回的响应完全相同。
+ **API Gateway** 提供了高级的请求和响应处理功能。您可以定义请求验证器、使用映射模板转换请求和响应、设置请求/响应标头，以及实施响应缓存。API Gateway 还支持二进制有效载荷和自定义域名，并且可以在响应到达客户端之前对其修改。您可以通过使用 JSON 架构来为请求/响应验证和转换设置模型。

### 扩展
<a name="w2aac39c81c73c13c11b5"></a>
+ **函数 URL** 可直接根据您的 Lambda 函数的并发限制进行扩展，并通过将函数扩展到其配置的最大并发限制来处理流量激增。达到该限制后，Lambda 将使用 HTTP 429 响应来响应其他请求。由于没有内置的队列机制，因此处理扩展完全取决于您的 Lambda 函数的配置。默认情况下，Lambda 函数每个 AWS 区域的并发执行限制为 1000 次。
+ **API Gateway** 在 Lambda 自己的扩展基础上提供了额外的扩展功能。其中包括内置的请求队列和节流控制，使您可以更妥善地管理流量激增。默认情况下，API Gateway 每个区域每秒最多可以处理 1 万个请求，容量爆增为每秒 5000 个请求。还提供了在不同级别（API、阶段或方法）限制请求的工具，以保护您的后端。

### 监控
<a name="w2aac39c81c73c13c11b7"></a>
+ **函数 URL** 通过 Amazon CloudWatch 指标来提供基本监控，包括请求计数、延迟和错误率。您可以访问标准 Lambda 指标和日志，它们显示了进入函数的原始请求。虽然这提供了基本的运营可见性，但这些指标主要侧重于函数执行。
+ **API Gateway** 提供全面的监控功能，其中包括详细的指标、日志记录和跟踪选项。您可以通过 CloudWatch 监控 API 调用、延迟、错误率和缓存命中/未命中率。API Gateway 还与 AWS X-Ray 集成，用于分布式跟踪，并提供可自定义的日志记录格式。

### 成本
<a name="w2aac39c81c73c13c11b9"></a>
+ **函数 URL** 遵循标准 Lambda 定价模型 – 您只需按函数调用和计算时间付费。URL 端点本身不收取额外费用。如果您不需要 API Gateway 的其他功能，则会使其成为简单 API 或低流量应用程序的经济实惠之选。
+ **API Gateway** 提供[免费套餐](https://aws.amazon.com/api-gateway/pricing/#Free_Tier)，其中包括为 REST API 接收的一百万次 API 调用和为 HTTP API 接收的一百万次 API 调用。此后，API Gateway 将对 API 调用、数据传输和缓存（如果已启用）收费。请参阅 API Gateway [定价页面](https://aws.amazon.com/api-gateway/pricing/)，了解您自己的使用案例的成本。

### 其他功能
<a name="w2aac39c81c73c13c11c11"></a>
+ **函数 URL** 旨在实现简单性以及 Lambda 直接集成。它们同时支持 HTTP 和 HTTPS 端点，提供内置的 CORS 支持，并提供双堆栈（IPv4 和 IPv6）端点。虽然它们缺乏高级功能，但在需要以快速、直接的方式通过 HTTP 公开 Lambda 函数的场景中，它们表现出色。
+ **API Gateway** 包括许多其他功能，例如 API 版本控制、阶段管理、使用计划的 API 密钥、通过 Swagger/OpenAPI 提供的 API 文档、WebSocket API、VPC 内的私有 API，以及用于提高安全性的 WAF 集成。它还支持金丝雀部署、用于测试的模拟集成以及与 Lambda 之外的其他 AWS 服务的集成。

## 选择调用 Lambda 函数的方法
<a name="w2aac39c81c73c15"></a>

现在，您已经了解了在 Lambda 函数 URL 与 API Gateway 之间进行选择的标准以及它们之间的主要区别，您可以选择最符合您需求的选项，并使用以下资源来帮助您开始使用它。

------
#### [ Function URLs ]

**通过以下资源开始使用函数 URL**
+ 按照[使用函数 URL 创建 Lambda 函数](urls-webhook-tutorial.md)教程进行操作
+ 在本指南的[创建和管理 Lambda 函数 URL](urls-configuration.md) 章节中了解有关函数 URL 的更多信息
+ 通过执行以下操作，尝试控制台内指导教程**创建简单的 Web 应用程序**：

1. 打开 Lamba 控制台的[函数页面](https://console.aws.amazon.com/lambda/home#/functions)。

1. 选择屏幕右上角的图标打开帮助面板。  
![\[\]](http://docs.aws.amazon.com/zh_cn/lambda/latest/dg/images/console_help_screenshot.png)

1. 选择**教程**。

1. 在**创建简单的 Web 应用程序**中，选择**开始教程**。

------
#### [ API Gateway ]

**通过以下资源开始使用 Lambda 和 API Gateway**
+ 按照[利用 API Gateway 使用 Lambda](services-apigateway-tutorial.md) 教程，创建与后端 Lambda 函数集成的 REST API。
+ 要详细了解 API Gateway 提供的不同类型 API，请参阅《Amazon API Gateway 开发人员指南》**的以下部分：
  + [API Gateway REST API](https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-rest-api.html)
  + [API Gateway HTTP API](https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api.html)
  + [API Gateway WebSocket API](https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-websocket-api.html)
+ 试用《Amazon API Gateway 开发人员指南》**的[教程和研讨会](https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-tutorials.html)部分中的一个或多个示例。

------

# 教程：使用 Lambda 函数 URL 创建 Webhooook 端点
<a name="urls-webhook-tutorial"></a>

在本教程中，您将创建 Lambda 函数 URL 来实现 Webhooook 端点。Webhook 是一种轻量级、事件驱动的通信，其使用 HTTP 在应用程序之间自动发送数据。您可以使用 Webhook 接收有关在其他系统中发生的事件的即时更新，例如网站上有新客户注册、处理付款或上传文件时。

通过 Lambda，可以使用 Lambda 函数 URL 或 API Gateway 实现网络挂钩。对于不需要高级授权或请求验证等功能的简单 Webhook 来说，函数 URL 是一个不错的选择。

**提示**  
如果您不确定哪种解决方案最适合您的特定用例，请参阅[选择使用 HTTP 请求调用 Lambda 函数的方法](furls-http-invoke-decision.md)。

## 先决条件
<a name="urls-webhook-tutorial-prereqs"></a>

要完成本教程，您必须在本地计算机上安装 Python（版本 3.8 或更高版本）或 Node.js（版本 18 或更高版本）。

为使用 HTTP 请求测试端点，本教程使用了 [curl](https://curl.se/)，这是一种命令行工具，您可以使用它来通过各种网络协议传输数据。如果您还没有安装该工具，则请参阅 [curl 文档](https://curl.se/docs/install.html)以了解如何安装该工具。

## 创建 Lambda 函数
<a name="urls-webhook-tutorial-function"></a>

首先创建 Lambda 函数，在将 HTTP 请求发送到 Webhooook 端点时会运行该函数。在此示例中，每当提交付款时，发送应用程序都会发送更新，并在 HTTP 请求的正文中指示付款是否成功。Lambda 函数会解析该请求并根据付款状态采取行动。在此示例中，代码仅打印付款的订单 ID，但在实际应用程序中，您可以将订单添加到数据库或发送通知。

该函数还实现了用于 Webhook 的最常见的身份验证方法，即基于哈希的消息身份验证（HMAC）。使用这种方法，发送和接收应用程序共享一个密钥。发送应用程序使用哈希算法将此密钥与消息内容一起生成唯一签名，并将该签名作为 HTTP 标头包含在 Webhook 请求中。然后，接收应用程序会重复此步骤，使用密钥生成签名，并将结果值与请求标头中发送的签名进行比较。如果结果匹配，则该请求被视为合法。

将 Lambda 控制台与 Python 或 Node.js 运行时一起使用创建该函数。

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

**创建 Lambda 函数**

1. 打开 Lamba 控制台的 [Functions](https://console.aws.amazon.com/lambda/home#/functions)（函数）页面。

1. 通过执行以下操作创建基本“Hello world”函数：

   1. 选择**创建函数**。

   1. 选择**从头开始编写**。

   1. 对于**函数名称**，请输入 **myLambdaWebhook**。

   1. 对于**运行时**，选择 **python3.14**。

   1. 选择**创建函数**。

1. 在**代码源**窗格中，通过复制并粘贴以下内容替换现有代码：

   ```
   import json
   import hmac
   import hashlib
   import os
   
   def lambda_handler(event, context):
       
       # Get the webhook secret from environment variables
       webhook_secret = os.environ['WEBHOOK_SECRET']
       
       # Verify the webhook signature
       if not verify_signature(event, webhook_secret):
           return {
               'statusCode': 401,
               'body': json.dumps({'error': 'Invalid signature'})
           }
       
       try:
           # Parse the webhook payload
           payload = json.loads(event['body'])
           
           # Handle different event types
           event_type = payload.get('type')
           
           if event_type == 'payment.success':
               # Handle successful payment
               order_id = payload.get('orderId')
               print(f"Processing successful payment for order {order_id}")
               
               # Add your business logic here
               # For example, update database, send notifications, etc.
               
           elif event_type == 'payment.failed':
               # Handle failed payment
               order_id = payload.get('orderId')
               print(f"Processing failed payment for order {order_id}")
               
               # Add your business logic here
               
           else:
               print(f"Received unhandled event type: {event_type}")
           
           # Return success response
           return {
               'statusCode': 200,
               'body': json.dumps({'received': True})
           }
           
       except json.JSONDecodeError:
           return {
               'statusCode': 400,
               'body': json.dumps({'error': 'Invalid JSON payload'})
           }
       except Exception as e:
           print(f"Error processing webhook: {e}")
           return {
               'statusCode': 500,
               'body': json.dumps({'error': 'Internal server error'})
           }
   
   def verify_signature(event, webhook_secret):
       """
       Verify the webhook signature using HMAC
       """
       try:
           # Get the signature from headers
           signature = event['headers'].get('x-webhook-signature')
   
           if not signature:
               print("Error: Missing webhook signature in headers")
               return False
           
           # Get the raw body (return an empty string if the body key doesn't exist)
           body = event.get('body', '')
           
           # Create HMAC using the secret key
           expected_signature = hmac.new(
               webhook_secret.encode('utf-8'),
               body.encode('utf-8'),
               hashlib.sha256
           ).hexdigest()
           
           # Compare the expected signature with the received signature to authenticate the message
           is_valid = hmac.compare_digest(signature, expected_signature)
           if not is_valid:
               print(f"Error: Invalid signature. Received: {signature}, Expected: {expected_signature}")
               return False
               
           return True
       except Exception as e:
           print(f"Error verifying signature: {e}")
           return False
   ```

1. 在**部署**部分，选择**部署**以更新函数的代码。

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

**创建 Lambda 函数**

1. 打开 Lamba 控制台的[函数](https://console.aws.amazon.com/lambda/home#/functions)页面。

1. 通过执行以下操作创建基本“Hello world”函数：

   1. 选择**创建函数**。

   1. 选择**从头开始编写**。

   1. 对于**函数名称**，请输入 **myLambdaWebhook**。

   1. 对于**运行时**，选择 **nodejs24.x**。

   1. 选择**创建函数**。

1. 在**代码源**窗格中，通过复制并粘贴以下内容替换现有代码：

   ```
   import crypto from 'crypto';
   
   export const handler = async (event, context) => {
       // Get the webhook secret from environment variables
       const webhookSecret = process.env.WEBHOOK_SECRET;
   
       // Verify the webhook signature
       if (!verifySignature(event, webhookSecret)) {
           return {
               statusCode: 401,
               body: JSON.stringify({ error: 'Invalid signature' })
           };
       }
   
       try {
           // Parse the webhook payload
           const payload = JSON.parse(event.body);
   
           // Handle different event types
           const eventType = payload.type;
   
           switch (eventType) {
               case 'payment.success': {
                   // Handle successful payment
                   const orderId = payload.orderId;
                   console.log(`Processing successful payment for order ${orderId}`);
   
                   // Add your business logic here
                   // For example, update database, send notifications, etc.
                   break;
               }
   
               case 'payment.failed': {
                   // Handle failed payment
                   const orderId = payload.orderId;
                   console.log(`Processing failed payment for order ${orderId}`);
   
                   // Add your business logic here
                   break;
               }
   
               default:
                   console.log(`Received unhandled event type: ${eventType}`);
           }
   
           // Return success response
           return {
               statusCode: 200,
               body: JSON.stringify({ received: true })
           };
   
       } catch (error) {
           if (error instanceof SyntaxError) {
               // Handle JSON parsing errors
               return {
                   statusCode: 400,
                   body: JSON.stringify({ error: 'Invalid JSON payload' })
               };
           }
   
           // Handle all other errors
           console.error('Error processing webhook:', error);
           return {
               statusCode: 500,
               body: JSON.stringify({ error: 'Internal server error' })
           };
       }
   };
   
   // Verify the webhook signature using HMAC
   
   const verifySignature = (event, webhookSecret) => {
       try {
           // Get the signature from headers
           const signature = event.headers['x-webhook-signature'];
     
           if (!signature) {
               console.log('No signature found in headers:', event.headers);
               return false;
           }
     
           // Get the raw body (return an empty string if the body key doesn't exist)
           const body = event.body || '';
     
           // Create HMAC using the secret key
           const hmac = crypto.createHmac('sha256', webhookSecret);
           const expectedSignature = hmac.update(body).digest('hex');
     
           // Compare expected and received signatures
           const isValid = signature === expectedSignature;
           if (!isValid) {
               console.log(`Invalid signature. Received: ${signature}, Expected: ${expectedSignature}`);
               return false;
           }
           
           return true;
       } catch (error) {
           console.error('Error during signature verification:', error);
           return false;
       }
     };
   ```

1. 在**部署**部分，选择**部署**以更新函数的代码。

------

## 创建密钥
<a name="urls-webhook-tutorial-key"></a>

为了让 Lambda 函数对 Webhook 请求进行身份验证，其使用与调用应用程序共享的密钥。在此示例中，密钥存储在环境变量中。在生产应用程序中，切勿在函数代码中包含密码等敏感信息。相反，[创建一个 AWS Secrets Manager 密钥](https://docs.aws.amazon.com/secretsmanager/latest/userguide/create_secret.html)，然后[使用 AWS 参数和密钥 Lambda 扩展](with-secrets-manager.md)在 Lambda 函数中检索您的凭证。

**创建并存储 Webhook 密钥**

1. 使用加密安全随机数生成器生成一个随机的长字符串。您可以在 Python 或 Node.js 中使用以下代码片段来生成并打印一个 32 个字符的密钥，也可以使用自己的首选方法。

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

**Example 生成密钥的代码**  

   ```
   import secrets
   webhook_secret = secrets.token_urlsafe(32)
   print(webhook_secret)
   ```

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

**Example 生成密钥的代码（ES 模块格式）**  

   ```
   import crypto from 'crypto';
   let webhookSecret = crypto.randomBytes(32).toString('base64');
   console.log(webhookSecret)
   ```

------

1. 通过执行以下操作，将生成的字符串存储为函数的环境变量：

   1. 在函数的**配置**选项卡中，选择**环境变量**。

   1. 选择**编辑**。

   1. 选择**添加环境变量**。

   1. 在**键**中输入 **WEBHOOK\$1SECRET**，然后在**值**中输入您在上一步生成的密钥。

   1. 选择**保存**。

您将需要在本教程后面的部分中再次使用此密钥来测试函数，因此请现在记下该密钥。

## 创建函数 URL 端点
<a name="urls-webhook-tutorial-furl"></a>

使用 Lambda 函数 URL 为您的 Webhook 创建端点。由于您使用身份验证类型 `NONE` 来创建具有公共访问权限的端点，因此任何人都可以通过该 URL 调用您的函数。要了解有关控制函数 URL 访问权限的更多信息，请参阅[控制对 Lambda 函数 URL 的访问](urls-auth.md)。如果您的 Webhook 需要更多高级身份验证选项，请考虑使用 API Gateway。

**创建函数 URL 端点**

1. 在函数的**配置**选项卡中，选择**函数 URL**。

1. 选择 **Create function URL**（创建函数 URL）。

1. 对于**身份验证类型**，选择**无**。

1. 选择**保存**。

您刚刚创建的函数 URL 的端点将在**函数 URL** 窗格中显示。复制此端点以在本教程后面的部分中使用。

## 在控制台中测试函数
<a name="urls-webhook-tutorial-test-console"></a>

在使用 HTTP 请求通过 URL 端点调用您的函数之前，请在控制台中对其进行测试，以确认您的代码按预期工作。

要在控制台中验证该函数，请首先使用本教程前面的部分中生成的密钥计算一个 Webhook 签名，其中包含以下测试 JSON 有效载荷：

```
{
    "type": "payment.success", 
    "orderId": "1234",
    "amount": "99.99"
}
```

使用以下任一 Python 或 Node.js 代码示例，采用您自己的密钥计算 Webhook 签名。

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

**计算 Webhook 签名**

1. 将以下代码另存为名为 `calculate_signature.py` 的文件。将该代码中的 Webhooook 密钥替换为您自己的值。

   ```
   import secrets
   import hmac
   import json
   import hashlib
   
   webhook_secret = "arlbSDCP86n_1H90s0fL_Qb2NAHBIBQOyGI0X4Zay4M"
   
   body = json.dumps({"type": "payment.success", "orderId": "1234", "amount": "99.99"})
   
   signature = hmac.new(
               webhook_secret.encode('utf-8'),
               body.encode('utf-8'),
               hashlib.sha256
           ).hexdigest()
   
   print(signature)
   ```

1. 通过从保存该代码的同一目录运行以下命令来计算签名。复制该代码输出的签名。

   ```
   python calculate_signature.py
   ```

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

**计算 Webhook 签名**

1. 将以下代码另存为名为 `calculate_signature.mjs` 的文件。将该代码中的 Webhooook 密钥替换为您自己的值。

   ```
   import crypto from 'crypto';
   
   const webhookSecret = "arlbSDCP86n_1H90s0fL_Qb2NAHBIBQOyGI0X4Zay4M"
   const body = "{\"type\": \"payment.success\", \"orderId\": \"1234\", \"amount\": \"99.99\"}";
   
   let hmac = crypto.createHmac('sha256', webhookSecret);
   let signature = hmac.update(body).digest('hex');
   
   console.log(signature);
   ```

1. 通过从保存该代码的同一目录运行以下命令来计算签名。复制该代码输出的签名。

   ```
   node calculate_signature.mjs
   ```

------

现在，您可以在控制台中使用测试 HTTP 请求测试您的函数代码。

**在控制台中测试函数**

1. 为您的函数选择**代码**选项卡。

1. 在**测试事件**部分中，选择**创建新测试事件**。

1. 对于 **Event Name (事件名称)**，输入 **myEvent**。

1. 通过将以下内容复制并粘贴到**事件 JSON** 窗格中来替换现有 JSON。将 Webhooook 签名替换为您在上一步中计算得出的值。

   ```
   {
     "headers": {
       "Content-Type": "application/json",
       "x-webhook-signature": "2d672e7a0423fab740fbc040e801d1241f2df32d2ffd8989617a599486553e2a"
     },
     "body": "{\"type\": \"payment.success\", \"orderId\": \"1234\", \"amount\": \"99.99\"}"
   }
   ```

1. 选择**保存**。

1. 选择**调用**。

   您应该可以看到类似于如下所示的输出内容：

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

   ```
   Status: Succeeded
   Test Event Name: myEvent
   
   Response:
   {
     "statusCode": 200,
     "body": "{\"received\": true}"
   }
   
   Function Logs:
   START RequestId: 50cc0788-d70e-453a-9a22-ceaa210e8ac6 Version: $LATEST
   Processing successful payment for order 1234
   END RequestId: 50cc0788-d70e-453a-9a22-ceaa210e8ac6
   REPORT RequestId: 50cc0788-d70e-453a-9a22-ceaa210e8ac6	Duration: 1.55 ms	Billed Duration: 2 ms	Memory Size: 128 MB	Max Memory Used: 36 MB	Init Duration: 136.32 ms
   ```

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

   ```
   Status: Succeeded
   Test Event Name: myEvent
   
   Response:
   {
     "statusCode": 200,
     "body": "{\"received\":true}"
   }
   
   Function Logs:
   START RequestId: e54fe6c7-1df9-4f05-a4c4-0f71cacd64f4 Version: $LATEST
   2025-01-10T18:05:42.062Z	e54fe6c7-1df9-4f05-a4c4-0f71cacd64f4	INFO	Processing successful payment for order 1234
   END RequestId: e54fe6c7-1df9-4f05-a4c4-0f71cacd64f4
   REPORT RequestId: e54fe6c7-1df9-4f05-a4c4-0f71cacd64f4	Duration: 60.10 ms	Billed Duration: 61 ms	Memory Size: 128 MB	Max Memory Used: 72 MB	Init Duration: 174.46 ms
   
   Request ID: e54fe6c7-1df9-4f05-a4c4-0f71cacd64f4
   ```

------

## 使用 HTTP 请求测试函数
<a name="urls-webhook-tutorial-test-curl"></a>

使用 curl 命令行工具测试您的 Webhook 端点。

**使用 HTTP 请求测试函数**

1. 在终端或 shell 程序中，运行以下 curl 命令。将该 URL 替换为您自己函数 URL 端点的值，并将 Webhook 签名替换为您使用自己的密钥计算得出的签名。

   ```
   curl -X POST https://ryqgmbx5xjzxahif6frvzikpre0bpvpf.lambda-url.us-west-2.on.aws/ \
   -H "Content-Type: application/json" \
   -H "x-webhook-signature: d5f52b76ffba65ff60ea73da67bdf1fc5825d4db56b5d3ffa0b64b7cb85ef48b" \
   -d '{"type": "payment.success", "orderId": "1234", "amount": "99.99"}'
   ```

   您应看到以下输出：

   ```
   {"received": true}
   ```

1. 通过执行以下操作，检查函数的 CloudWatch 日志，确认其是否已正确解析有效载荷：

   1. 在 Amazon CloudWatch 控制台中，打开[日志组](https://console.aws.amazon.com/cloudwatch/home#logsV2:log-groups)页面。

   1. 选择函数的日志组（`/aws/lambda/myLambdaWebhook`）。

   1. 选择最新的日志流。

      您应该可以在函数的日志中看到类似于如下所示的输出内容：

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

      ```
      Processing successful payment for order 1234
      ```

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

      ```
      2025-01-10T18:05:42.062Z e54fe6c7-1df9-4f05-a4c4-0f71cacd64f4 INFO Processing successful payment for order 1234
      ```

------

1. 运行以下 curl 命令，确认您的代码检测到无效的签名。将该 URL 替换为您自己的函数 URL 端点。

   ```
   curl -X POST https://ryqgmbx5xjzxahif6frvzikpre0bpvpf.lambda-url.us-west-2.on.aws/ \
   -H "Content-Type: application/json" \
   -H "x-webhook-signature: abcdefg" \
   -d '{"type": "payment.success", "orderId": "1234", "amount": "99.99"}'
   ```

   您应看到以下输出：

   ```
   {"error": "Invalid signature"}
   ```

## 清除资源
<a name="urls-webhook-tutorial-cleanup"></a>

除非您想要保留为本教程创建的资源，否则可立即将其删除。通过删除您不再使用的 AWS 资源，可防止您的 AWS 账户 产生不必要的费用。

**删除 Lambda 函数**

1. 打开 Lamba 控制台的 [Functions（函数）页面](https://console.aws.amazon.com/lambda/home#/functions)。

1. 选择您创建的函数。

1. 依次选择**操作**和**删除**。

1. 在文本输入字段中键入 **confirm**，然后选择**删除**。

在控制台中创建 Lambda 函数时，Lambda 还会为您的函数创建一个[执行角色](lambda-intro-execution-role.md)。

**删除执行角色**

1. 打开 IAM 控制台的[角色页面](https://console.aws.amazon.com/iam/home#/roles)。

1. 选择 Lambda 创建的执行角色。该角色的名称格式为 `myLambdaWebhook-role-<random string>`。

1. 选择**删除**。

1. 在文本输入字段中输入角色名称，然后选择**删除**。