使用 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:
始终从 /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 加快启动速度。