缩短SDK启动时间 Amazon Lambda - Amazon SDK for Java 2.x
Amazon Web Services 文档中描述的 Amazon Web Services 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅 中国的 Amazon Web Services 服务入门 (PDF)

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

缩短SDK启动时间 Amazon Lambda

的目标之一 Amazon SDK for Java 2.x 是减少 Amazon Lambda 函数的启动延迟。SDK包含缩短启动时间的更改,本主题末尾将对此进行讨论。

首先,本主题重点介绍为缩短冷启动时间可以进行的更改。这包括更改代码结构和服务客户端的配置。

使用 Amazon CRT基于基础的HTTP客户端

对于使用 Amazon Lambda,我们建议在同步场景中使用,AwsCrtHttpClientAwsCrtAsyncHttpClient对于异步场景,我们建议使用。

本指南中的Amazon CRT基于配置的HTTP客户端主题描述了使用HTTP客户端的好处、如何添加依赖关系以及如何配置服务客户端对它们的使用。

移除未使用的HTTP客户端依赖关系

除了显式使用 Amazon CRT基于客户端的外,您还可以移除默认情况下SDK引入的其他HTTP客户端。当需要加载的库较少时,Lambda 的启动时间会缩短,因此您应该删除JVM需要加载的所有未使用的工件。

以下 Maven pom.xml 文件片段显示了基于 Apache 的客户端和基于 Netty 的HTTP客户端的排除情况。HTTP(当您使用 Amazon CRT基于基础的客户端时,不需要这些客户端。) 此示例将HTTP客户端对象排除在 S3 客户端依赖项之外,并添加了该aws-crt-client对象以允许访问 Amazon CRT基于这些HTTP客户端的客户端。

<project> <properties> <aws.java.sdk.version>2.27.21</aws.java.sdk.version> <properties> <dependencyManagement> <dependencies> <dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>bom</artifactId> <version>${aws.java.sdk.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <dependencies> <dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>aws-crt-client</artifactId> </dependency> <dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>s3</artifactId> <exclusions> <exclusion> <groupId>software.amazon.awssdk</groupId> <artifactId>netty-nio-client</artifactId> </exclusion> <exclusion> <groupId>software.amazon.awssdk</groupId> <artifactId>apache-client</artifactId> </exclusion> </exclusions> </dependency> </dependencies> </project>
注意

<exclusions> 元素添加到 pom.xml 文件中的所有服务客户端依赖项中。

配置服务客户端以进行快捷查找

指定区域

创建服务客户端时,在服务客户端生成器上调用 region 方法。这简化了默认SDK的区域查找过程,该过程会在多个位置检查 Amazon Web Services 区域 信息。

要使 Lambda 代码独立于区域,请在 region 方法中使用以下代码。此代码访问 Lambda 容器设置的 AWS_REGION 环境变量。

Region.of(System.getenv(SdkSystemSetting.AWS_REGION.environmentVariable()))
使用 EnvironmentVariableCredentialProvider

就像区域信息的默认查找行为一样,会在SDK多个位置查找证书。通过指定EnvironmentVariableCredentialProvider何时构建服务客户端,可以节省证书查找过程中的时间。SDK

注意

使用此凭证提供程序可以将代码用于 Lambda 函数,但可能无法在 Amazon EC2 或其他系统上运行。

如果您打算在某个时候使用 Lambd SnapStart a for Java,则应依靠默认的凭证提供程序链来查找证书。如果您指定EnvironmentVariableCredentialsProvider,则初始凭证查找起作用,但是激活后 SnapStart ,Java 运行时会设置容器凭据环境变量。激活后,由EnvironmentVariableCredentialsProvider访问密钥环境变量使用的环境变量对Java不可用。SDK

以下代码段显示了为在 Lambda 环境中使用而经过适当配置的 S3 服务客户端。

S3Client s3Client = S3Client.builder() .region(Region.of(System.getenv(SdkSystemSetting.AWS_REGION.environmentVariable()))) .credentialsProvider(EnvironmentVariableCredentialsProvider.create()) .httpClient(AwsCrtHttpClient.builder().build()) .build();

在 Lambda 函数处理程序之外初始化SDK客户端

我们建议在 Lambda 处理程序方法之外初始化SDK客户端。这样,如果重复使用执行上下文,则可以跳过服务客户端的初始化。通过重复使用客户端实例及其连接,处理程序方法的后续调用可更快进行。

在以下示例中,使用静态工厂方法在构造函数中初始化 S3Client 实例。如果重复使用由 Lambda 环境管理的容器,则会重复使用初始化的 S3Client 实例。

public class App implements RequestHandler<Object, Object> { private final S3Client s3Client; public App() { s3Client = DependencyFactory.s3Client(); } @Override public Object handle Request(final Object input, final Context context) { ListBucketResponse response = s3Client.listBuckets(); // Process the response. } }

尽量减少依赖关系注入

依赖关系注入 (DI) 框架可能需要更多时间才能完成设置过程。它们可能还需要额外的依赖项,这需要一段时间才能加载。

如果需要 DI 框架,建议使用诸如 Dagger 之类的轻量级 DI 框架。

使用 Maven Archetype 瞄准 Amazon Lambda

Amazon Java SDK 团队开发了一个 Maven Archetype 模板,可以在最短的启动时间内启动 Lambda 项目。您可以从该原型构建 Maven 项目,并知道依赖项的配置非常适合 Lambda 环境。

要了解有关原型的更多信息并完成示例部署,请参阅此博客文章

考虑一下适用于 Java 的 Lambda SnapStart

如果您的运行时要求兼容,则 Amazon 提供适用 SnapStart 于 Java 的 Lambda。Lambda SnapStart 是一种基于基础设施的解决方案,可提高 Java 函数的启动性能。当您发布新版本的函数时,Lambda 会对其进行 SnapStart 初始化,并拍摄内存和磁盘状态的不可变加密快照。 SnapStart 然后缓存快照以供重复使用。

影响启动时间的 2.x 版更改

除了您对代码所做的更改外,SDK适用于 Java 的 2.x 版本还包括三项主要更改,可缩短启动时间:

  • 使用 jackson-jr,它是一个序列化库,可以改进初始化时间

  • java.tim e 库用于日期和时间对象,这是其中的一部分 JDK

  • 对记录 facade 使用 Slf4j

其他 资源

Amazon Lambda 开发者指南中有一节介绍开发非 Java 特定的 Lambda 函数的最佳实践

有关使用 Java 构建云原生应用程序的示例 Amazon Lambda,请参阅此研讨会内容。该研讨会讨论了性能优化和其他最佳实践。

您可以考虑使用提前编译的静态映像来减少启动延迟。例如,你可以使用适用于 Java 2.x 和 Maven 的 GraalVM 原生镜像。SDK