

# 使用 AWS Lambda 函数的最佳实践
<a name="best-practices"></a>

以下是推荐使用 AWS Lambda 的最佳实践：

**Topics**
+ [函数代码](#function-code)
+ [函数配置](#function-configuration)
+ [功能可扩展性](#function-scalability)
+ [指标和警报](#alarming-metrics)
+ [处理流](#stream-events)
+ [安全最佳实践](#security-best-practices)

## 函数代码
<a name="function-code"></a>

**利用执行环境重用来提高函数性能。**连接软件开发工具包 (SDK) 客户端和函数处理程序之外的数据库，并在 `/tmp` 目录中本地缓存静态资产。由函数的同一实例处理的后续调用可重用这些资源。这样就可以通过缩短函数运行时间来节省成本。

为了避免调用之间潜在的数据泄露，请不要使用执行环境来存储用户数据、事件或其他具有安全影响的信息。如果您的函数依赖于无法存储在处理程序的内存中的可变状态，请考虑为每个用户创建单独的函数或单独的函数版本。

**使用 keep-alive 指令来维护持久连接。**Lambda 会随着时间的推移清除空闲连接。在调用函数时尝试重用空闲连接会导致连接错误。要维护您的持久连接，请使用与运行时关联的 keep-alive 指令。有关示例，请参阅[在 Node.js 中通过 Keep-Alive 重用连接](https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/node-reusing-connections.html)。

**使用[环境变量](configuration-envvars.md)将操作参数传递给函数。**例如，您在写入 Amazon S3 存储桶时，不应对要写入的存储桶名称进行硬编码，而应将存储桶名称配置为环境变量。

**避免在 Lambda 函数中使用递归调用**，在这种情况下，函数会调用自己或启动可能再次调用该函数的进程。这可能会导致意想不到的函数调用量和升级成本。如果您看到意外的调用量，请立即将函数保留并发设置为 `0` 来限制对函数的所有调用，同时更新代码。

Lambda 函数代码中**不要使用非正式的非公有 API**。对于 AWS Lambda 托管式运行时，Lambda 会定期为 Lambda 的内部 API 应用安全性和功能更新。这些内部 API 更新可能不能向后兼容，会导致意外后果，例如，假设您的函数依赖于这些非公有 API，则调用会失败。请参阅 [API 参考](https://docs.aws.amazon.com/lambda/latest/api/welcome.html)以查看公开发布的 API 列表。

**编写幂等代码。**为您的函数编写幂等代码可确保以相同的方式处理重复事件。您的代码应该正确验证事件并优雅地处理重复事件。有关更多信息，请参阅[如何使我的 Lambda 函数具有幂等性？](https://aws.amazon.com/premiumsupport/knowledge-center/lambda-function-idempotent/)。

**注意**  
可使用 Powertools for AWS Lambda 使函数具有幂等性。有关更多信息，请参阅：  
[Python - 幂等性实用程序](https://docs.aws.amazon.com/powertools/python/latest/utilities/idempotency/)
[TypeScript - 幂等性实用程序](https://docs.aws.amazon.com/powertools/typescript/latest/features/idempotency/)
[Java - 幂等性实用程序](https://docs.aws.amazon.com/powertools/java/latest/utilities/idempotency/)
[.NET - 幂等性实用程序](https://docs.aws.amazon.com/powertools/dotnet/utilities/idempotency/)

有关特定语言的代码最佳实践，请参阅以下章节：
+ [Node.js Lambda 函数的代码最佳实践](nodejs-handler.md#nodejs-best-practices)
+ [TypeScript Lambda 函数的代码最佳实践](typescript-handler.md#typescript-best-practices)
+ [Python Lambda 函数的代码最佳实践](python-handler.md#python-handler-best-practices)
+ [Ruby Lambda 函数的代码最佳实践](ruby-handler.md#ruby-best-practices)
+ [Java Lambda 函数的代码最佳实践](java-handler.md#java-best-practices)
+ [Go Lambda 函数的代码最佳实践](golang-handler.md#go-best-practices)
+ [C\$1 Lambda 函数的代码最佳实践](csharp-handler.md#csharp-best-practices)
+ [Rust Lambda 函数的代码最佳实践](rust-handler.md#rust-best-practices)

## 函数配置
<a name="function-configuration"></a>

**对您的 Lambda 函数进行性能测试**是确保选择最佳内存大小配置的关键环节。增加内存大小会触发函数可用 CPU 的同等水平的增加。函数的内存使用率是根据调用情况确定的，可以在 [Amazon CloudWatch](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/WhatIsCloudWatchLogs.html) 中查看。每次调用都将生成一个 `REPORT:` 条目，如下所示：

```
REPORT RequestId: 3604209a-e9a3-11e6-939a-754dd98c7be3	Duration: 12.34 ms	Billed Duration: 100 ms Memory Size: 128 MB	Max Memory Used: 18 MB
```

分析 `Max Memory Used:` 字段能够确定函数是否需要更多内存，或函数的内存大小是否过度配置。

**要为您的函数查找适合的内存配置，**我们建议使用开源 AWS Lambda 功率调谐项目。有关更多信息，请参阅 GitHub 上的 [AWS Lambda 功率调谐](https://github.com/alexcasalboni/aws-lambda-power-tuning)。

为了优化函数性能，我们还建议部署可以利用高级矢量扩展 2 (AVX2) 的库。这样一来，您就可以处理艰巨的工作负载，如机器学习推理、媒体处理、高性能计算（HPC）、科学模拟和财务建模。有关更多信息，请参阅[使用 AVX2 创建更快的 AWS Lambda 函数](https://aws.amazon.com/blogs/compute/creating-faster-aws-lambda-functions-with-avx2/)。

**对您的 Lambda 函数进行加载测试**，确定最佳超时值。分析函数的运行时间很重要，这样更容易确定依赖关系服务是否有问题，这些问题可能导致并发函数以超出您的预期的速度增加。如果您的 Lambda 函数进行网络调用的资源无法处理 Lambda 扩缩，这就更加重要。有关对应用程序进行负载测试的更多信息，请参阅 [AWS 上的分布式负载测试](https://aws.amazon.com/solutions/implementations/distributed-load-testing-on-aws/)。

**设置 IAM policy 时使用最严格的权限。**了解您的 Lambda 函数所需的资源和操作，并限制这些权限的执行角色。有关更多信息，请参阅[在 AWS Lambda 中管理权限](lambda-permissions.md)。

**熟悉。[Lambda 配额Lambda 限额](gettingstarted-limits.md)**在确定运行时资源限制时，负载大小、文件描述符和 /tmp 空间通常会被忽略。

**删除不再使用的 Lambda 函数。**这样，未使用的函数就不会不必要地占用有限的部署程序包空间。

**如果您使用 Amazon Simple Queue Service 作为事件源**，请确保该函数的预计调用时间值不超过队列上的[可见性超时](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-visibility-timeout.html)值。这同样适用于 [CreateFunction](https://docs.aws.amazon.com/lambda/latest/api/API_CreateFunction.html) 和 [UpdateFunctionConfiguration](https://docs.aws.amazon.com/lambda/latest/api/API_UpdateFunctionConfiguration.html)。
+ 对于 **CreateFunction**，AWS Lambda 会使函数创建流程失败。
+ 对于 **UpdateFunctionConfiguration**，它可能会导致该函数的重复调用。

## 功能可扩展性
<a name="function-scalability"></a>

**熟悉您的上游和下游吞吐量限制。**虽然 Lambda 函数可随负载无缝扩展，但上游和下游依赖项可能不具有相同的吞吐量。如果您需要限制函数可以扩展的幅度，可以为函数[配置预留并发](configuration-concurrency.md)。

**内置节流容错能力：**如果同步函数因流量超过 Lambda 的扩展速率而遭遇节流，则可使用以下策略来提高节流容错能力：
+ **使用[超时、重试和抖动回退](https://aws.amazon.com/builders-library/timeouts-retries-and-backoff-with-jitter/)**：实施这些策略可以平滑重试的调用，有助于确保 Lambda 可以在几秒钟内纵向扩展，尽量减少最终用户节流。
+ **使用[预置并发](provisioned-concurrency.md)**：预置并发是 Lambda 分配给函数的预初始化执行环境的数量。Lambda 在可用时使用预置并发处理传入请求。如有必要，Lambda 还可以将函数扩展到预置并发设置之上。配置预置并发会让 AWS 账户产生额外费用。

## 指标和警报
<a name="alarming-metrics"></a>

**使用 [将 CloudWatch 指标与 Lambda 结合使用](monitoring-metrics.md) 和[ CloudWatch Alarms](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/AlarmThatSendsEmail.html)**，而不是在您的 Lambda 函数代码中创建和更新指标。追踪 Lambda 函数的运行状况是更加有效的方式，这样您就可以在早期开发过程中发现问题。例如，您可以根据 Lambda 函数调用的预计持续时间配置警报，以解决函数代码引起的瓶颈或延迟。

**使用嵌入式指标格式 (EMF) 异步发送自定义指标** 应使用 EMF 通过函数日志发送指标，而不是对 CloudWatch 进行同步 API 调用。这种方法可减小延迟并改善性能。Powertools for AWS Lambda 中的指标实用程序可自动处理 EMF 格式。有关更多信息，请参阅“Powertools for AWS Lambda”文档中的 [Python](https://docs.aws.amazon.com/powertools/python/latest/core/metrics/)、[TypeScript](https://docs.aws.amazon.com/powertools/typescript/latest/features/metrics/)、[Java](https://docs.aws.amazon.com/powertools/java/latest/core/metrics/) 或 [.NET](https://docs.aws.amazon.com/powertools/dotnet/core/metrics/) 指标实用程序。有关使用嵌入式指标格式生成指标格式日志的更多信息，请参阅《Amazon CloudWatch 用户指南》中的[使用嵌入式指标格式发布日志](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch_Embedded_Metric_Format_Generation.html)。

**使用结构化的 JSON 日志记录来提高可观测性。**结构化日志记录可以更轻松地搜索、筛选和分析函数日志。可考虑使用 Powertools for AWS Lambda 中的 Logger 实用程序，自动将日志格式化为 JSON。有关更多信息，请参阅“Powertools for AWS Lambda”文档中的 [Python](https://docs.aws.amazon.com/powertools/python/latest/core/logger/)、[TypeScript](https://docs.aws.amazon.com/powertools/typescript/latest/features/logger/)、[Java](https://docs.aws.amazon.com/powertools/java/latest/core/logging/) 或 [.NET](https://docs.aws.amazon.com/powertools/dotnet/core/logging/) Logger 实用程序。

**利用您的日志记录库和 [AWS Lambda 指标和维度](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/lam-metricscollected.html)**捕捉应用程序错误（例如，ERR、ERROR、WARNING 等） 

**使用 [AWS Cost Anomaly Detection](https://docs.aws.amazon.com/cost-management/latest/userguide/manage-ad.html)** 来检测您账户中的异常活动。Cost Anomaly Detection 使用机器学习技术来持续监控您的成本和使用情况，并尽力减少误报。Cost Anomaly Detection 使用来自 AWS Cost Explorer 的数据，该数据最长可能会延迟 24 小时。因此，发生使用后最长可能需要 24 小时才会检测到异常。要开始使用 Cost Anomaly Detection，您必须首先[注册 Cost Explorer](https://docs.aws.amazon.com/cost-management/latest/userguide/ce-enable.html)。然后[访问 Cost Anomaly Detection](https://docs.aws.amazon.com/cost-management/latest/userguide/settingup-ad.html#access-ad)。

## 处理流
<a name="stream-events"></a>

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

默认情况下，Lambda 会在记录可用时尽快调用您的函数。如果 Lambda 从事件源中读取的批处理只有一条记录，则 Lambda 将会只向该函数发送一条记录。为避免在记录数量较少的情况下调用该函数，您可以配置 *batching window*（批处理时段），让事件源缓冲最多五分钟的记录。调用函数前，Lambda 会持续从事件源中读取记录，直到收集完整批处理、批处理时段到期或批处理达到 6MB 的有效负载时为止。有关更多信息，请参阅 [批处理行为](invocation-eventsourcemapping.md#invocation-eventsourcemapping-batching)。

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

**为流处理启用部分批处理响应。**在处理来自 Kinesis 或 DynamoDB 等流的批记录时，启用部分批处理响应，以允许 Lambda 仅重试失败的记录，而非整个批次。这可以提高处理效率并减少不必要的再处理。可选择使用 Powertools for AWS Lambda 中的批处理实用程序来简化批处理模式。

**注意**  
可使用 Powertools for AWS Lambda 进行批处理。有关更多信息，请参阅：  
[Python - 批量处理](https://docs.aws.amazon.com/powertools/python/latest/utilities/batch/)
[TypeScript - 批处理](https://docs.aws.amazon.com/powertools/typescript/latest/features/batch/)
[Java - 批处理](https://docs.aws.amazon.com/powertools/java/latest/utilities/batch/)
[.NET - 批处理](https://docs.aws.amazon.com/powertools/dotnet/utilities/batch-processing/)

**通过增加分区提高 Kinesis 流处理吞吐量。**一个 Kinesis 流由一个或多个分区组成。Lambda 从 Kinesis 读取数据的速率随着分片数量的增加而线性扩展。增加分区数量会直接增加 Lambda 函数并发调用的最大数量，还可增加 Kinesis 流处理的吞吐量。有关分片和函数调用之间的更多信息，请参阅 [轮询和批处理流](with-kinesis.md#kinesis-polling-and-batching)。如果您增加 Kinesis 流中的分区数量，请确保您已为数据选择了合适的分区键（请参阅[分区键](https://docs.aws.amazon.com/streams/latest/dev/key-concepts.html#partition-key)），这样相关记录将会位于同一分区中，而且也可合理分配您的数据。

在 IteratorAge 上**使用 [Amazon CloudWatch](https://docs.aws.amazon.com/streams/latest/dev/monitoring-with-cloudwatch.html)**，确定是否正在处理您的 Kinesis 流。例如，将 CloudWatch 警报的最大值设置配置为 30000（30 秒）。

## 安全最佳实践
<a name="security-best-practices"></a>

**监控 AWS Lambda 的使用情况，因为它与使用 AWS Security Hub CSPM 的安全最佳实践有关。**Security Hub CSPM 使用安全控件来评估资源配置和安全标准，以帮助您遵守各种合规框架。有关使用 Security Hub CSPM 评估 Lambda 资源的更多信息，请参阅《AWS Security Hub CSPM 用户指南》中的 [AWS Lambda 控件](https://docs.aws.amazon.com/securityhub/latest/userguide/lambda-controls.html)。

**使用 Amazon GuardDuty Lambda Protection 监控 Lambda 网络活动日志：**在 AWS 账户 中调用 Lambda 函数时，GuardDuty Lambda Protection 可帮助识别潜在安全威胁。以某个函数查询与加密货币相关活动关联的 IP 地址为例。GuardDuty 会监控在调用 Lambda 函数时生成的网络活动日志。要了解更多信息，请参阅**《Amazon GuardDuty User Guide》中的 [Lambda Protection](https://docs.aws.amazon.com/guardduty/latest/ug/lambda-protection.html)。