使用 Lambda SnapStart 处理唯一性 - AWS Lambda

使用 Lambda SnapStart 处理唯一性

调用在 SnapStart 函数上纵向扩展时,Lambda 使用单个初始化的快照来恢复多个执行环境。如果您的初始化代码生成了快照中包含的唯一内容,则跨执行环境重复使用该内容时,该内容可能不是唯一的。若要在使用 SnapStart 时保持唯一性,则必须在初始化后生成唯一的内容。这包括唯一的 ID、唯一的密钥和用于生成伪随机性的熵。

我们推荐使用以下最佳实践来帮助您保持代码的唯一性。对于 Java 函数,Lambda 还提供了开源 SnapStart 扫描工具,以帮助检查假设唯一性的代码。如果您在初始化阶段生成唯一的数据,则可以使用运行时挂钩来还原唯一性。使用运行时挂钩,您可以在 Lambda 拍摄快照之前立即运行特定代码,也可以在 Lambda 从快照恢复函数后立即运行特定代码。

避免在初始化期间保存依赖唯一性的状态

在函数的初始化阶段,避免缓存旨在保持唯一性的数据,例如生成用于日志记录的唯一 ID 或为随机函数设置种子。相反,建议您在函数处理程序中生成唯一的数据或为随机函数设置种子 – 或使用运行时钩子

以下示例演示如何在函数处理程序中生成 UUID。

Java
例 – 在函数处理程序中生成唯一的 ID
import java.util.UUID; public class Handler implements RequestHandler<String, String> { private static UUID uniqueSandboxId = null; @Override public String handleRequest(String event, Context context) { if (uniqueSandboxId == null) uniqueSandboxId = UUID.randomUUID(); System.out.println("Unique Sandbox Id: " + uniqueSandboxId); return "Hello, World!"; } }
Python
例 – 在函数处理程序中生成唯一的 ID
import json import random import time unique_number = None def lambda_handler(event, context): seed = int(time.time() * 1000) random.seed(seed) global unique_number if not unique_number: unique_number = random.randint(1, 10000) print("Unique number: ", unique_number) return "Hello, World!"
.NET
例 – 在函数处理程序中生成唯一的 ID
namespace Example; public class SnapstartExample { private Guid _myExecutionEnvironmentGuid; public SnapstartExample() { // This GUID is set for non-restore use cases, such as testing or if SnapStart is turned off _myExecutionEnvironmentGuid = new Guid(); // Register the method which will run after each restore. You may need to update Amazon.Lambda.Core to see this Amazon.Lambda.Core.SnapshotRestore.RegisterAfterRestore(MyAfterRestore); } private ValueTask MyAfterRestore() { // After restoring this snapshot to a new execution environment, update the GUID _myExecutionEnvironmentGuid = new Guid(); return ValueTask.CompletedTask; } public string Handler() { return $"Hello World! My Execution Environment GUID is {_myExecutionEnvironmentGuid}"; } }

使用加密安全的伪随机数生成器(CSPRNG)

如果您的应用程序依赖随机性,我们建议您使用加密安全的随机数生成器(CSPRNG)。除了 OpenSSL 1.0.2 之外,Lambda 托管式运行时还包括以下内置 CSPRNG:

  • Java:java.security.SecureRandom

  • Python:SystemRandom

  • .NET:System.Security.Cryptography.RandomNumberGenerator

始终从 /dev/random/dev/urandom 获取随机数的软件也通过 SnapStart 保持随机性。

AWS 加密库会自动保持 SnapStart 的随机性,从下表中指定的最低版本开始。如果您将这些库与 Lambda 函数一起使用,请确保使用以下最低版本或更高版本:

Library 支持的最低版本(x86) 支持的最低版本(ARM)
AWS libcrypto(AWS-LC)

1.16.0

1.30.0

AWS libcrypto FIPS

2.0.13

2.0.13

如果通过以下库将上述加密库与 Lambda 函数打包为可传递依赖项,请确保使用以下最低版本或更高版本:

Library 支持的最低版本(x86) 支持的最低版本(ARM)
AWS SDK for Java 2.x

2.23.20

2.26.12

AWS Common Runtime for Java

0.29.8

0.29.25

Amazon Corretto 加密提供商

2.4.1

2.4.1
Amazon Corretto 加密提供商 FIPS

2.4.1

2.4.1

以下示例演示如何使用 CSPRNG 来保证唯一的编号序列,即使从快照中还原函数也是如此。

Java
例 – java.security.SecureRandom
import java.security.SecureRandom; public class Handler implements RequestHandler<String, String> { private static SecureRandom rng = new SecureRandom(); @Override public String handleRequest(String event, Context context) { for (int i = 0; i < 10; i++) { System.out.println(rng.next()); } return "Hello, World!"; } }
Python
例 – random.SystemRandom
import json import random secure_rng = random.SystemRandom() def lambda_handler(event, context): random_numbers = [secure_rng.random() for _ in range(10)] for number in random_numbers: print(number) return "Hello, World!"
.NET
例 – RandomNumberGenerator
using Amazon.Lambda.Core; using System.Security.Cryptography; [assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))] namespace DotnetSecureRandom; public class Function { public string FunctionHandler() { using (RandomNumberGenerator rng = RandomNumberGenerator.Create()) { byte[] randomUnsignedInteger32Bytes = new byte[4]; for (int i = 0; i < 10; i++) { rng.GetBytes(randomUnsignedInteger32Bytes); int randomInt32 = BitConverter.ToInt32(randomUnsignedInteger32Bytes, 0); Console.WriteLine("{0:G}", randomInt32); } } return "Hello World!"; } }

SnapStart 扫描工具(仅 Java)

Lambda 为 Java 提供了扫描工具,以帮助您检查假设唯一性的代码。SnapStart 扫描工具是一个开源 SpotBugs 插件,该工具根据一组规则运行静态分析。该扫描工具有助于识别可能打破有关唯一性假设的潜在代码实施。有关安装说明和扫描工具执行的检查列表,请参阅 GitHub 上的 aws-lambda-snapstart-java-rules 存储库。

要详细了解如何使用 SnapStart 处理唯一性,请参阅 AWS 计算博客上的通过 AWS Lambda SnapStart 加快启动速度