本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。
缩短 SDK 的启动时间 Amazon Lambda
的目标之一 Amazon SDK for Java 2.x 是减少 Amazon Lambda 函数的启动延迟。SDK 包含可缩短启动时间的更改,本主题末尾将对此进行讨论。
首先,本主题重点介绍为缩短冷启动时间可以进行的更改。这包括更改代码结构和服务客户端的配置。
使用 SDK 的 UrlConnectionHttpClient
对于同步 场景,适用于 Java 的 SDK 2.x 提供了 UrlConnectionHttpClient
UrlConnectionHttpClient
基于类路径中已有的类,因此无需加载额外的依赖项。
有关将 UrlConnectionHttpClient
添加到 Lambda 项目并配置其使用的信息,请参阅配置基于 URLConnection 的 HTTP 客户端。
注意
与 SDK 的 ApacheHttpClient
相比,UrlConnectionHttpClient
存在一些功能限制。ApacheHttpClient
是 SDK 中的默认异步 HTTP 客户端。例如,UrlConnectionHttpClient
不支持 HTTP PATCH 方法。
少数 Amazon API 操作需要补丁请求。这些操作的名称通常以 Update*
开头。以下是几个示例。
-
Amazon Security Hub API 中的@@ 几个
Update*
操作以及BatchUpdateFindings操作 -
所有 Amazon API Gateway API 的
Update*
操作 -
亚马逊 WorkDocs API 中的@@ 几项
Update*
操作
如果你可能使用UrlConnectionHttpClient
,请先参阅你正在使用 Amazon Web Service 的 API 参考。了解您需要的操作是否使用 PATCH 操作。
使用 SDK 的 AwsCrtAsyncHttpClient
AwsCrtAsyncHttpClient
AwsCrtAsyncHttpClient
是一个异步非阻塞 HTTP 客户端。它建立在 Amazon 公共运行时的 Java 绑定之上,该绑定是用 C 编程语言编写的。 Amazon 通用运行时开发的目标之一是快速性能。
本指南中关于配置 HTTP 客户端的部分包含有关向 Lambda 项目添加 AwsCrtAsyncHttpClient
和配置其用途的信息。
移除未使用的 HTTP 客户端依赖项
除了明确使用 UrlConnectionHttpClient
或 AwsCrtAsyncHttpClient
之外,您还可以移除 SDK 默认引入的其他 HTTP 客户端。当需要加载的库较少时,Lambda 启动时间会缩短,因此您应该移除 JVM 需要加载的所有未使用的构件。
以下 Maven pom.xml
文件片段展示了排除基于 Apache 的 HTTP 客户端和基于 Netty 的 HTTP 客户端的情况。(使用 UrlConnectionHttpClient
时不需要这些客户端。) 此示例从 S3 客户端依赖项中排除 HTTP 客户端构件,并添加了引入 UrlConnectionHttpClient
类的 url-connection-client
构件。
<project> <properties> <aws.java.sdk.version>2.17.290</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>url-connection-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>
如果您使用 AwsCrtAsyncHttpClient
,请将对 url-connection-client
的依赖项替换为对 aws-crt-client
的依赖项。
注意
将 <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 或其他系统上运行。
以下代码段显示了为在 Lambda 环境中使用而经过适当配置的 S3 服务客户端。
S3Client client = S3Client.builder() .region(Region.of(System.getenv(SdkSystemSetting.AWS_REGION.environmentVariable()))) .credentialsProvider(EnvironmentVariableCredentialsProvider.create()) .httpClient(UrlConnectionHttpClient.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
使用 Maven Archetype 瞄准 Amazon Lambda
Amazon Java SDK 团队开发了一个 Maven Archetype
要了解有关原型的更多信息并完成示例部署,请参阅此博客文章
考虑一下适用于 Java 的 Lambda SnapStart
如果您的运行时要求兼容,则 Amazon 提供适用 SnapStart 于 Java 的 Lambda。Lambda SnapStart 是一种基于基础设施的解决方案,可提高 Java 函数的启动性能。当您发布新版本的函数时,Lambda 会对其进行 SnapStart 初始化,并拍摄内存和磁盘状态的不可变加密快照。 SnapStart 然后缓存快照以供重复使用。
影响启动时间的 2.x 版更改
除了您对代码所做的更改外,适用于 Java 的 SDK 2.x 版本还包括三项可缩短启动时间的主要更改:
-
使用 jackson-jr
,它是一个序列化库,可以改进初始化时间 -
对日期和时间对象使用 java.time
库,此为 JDK 的一部分。 -
对记录 facade 使用 Slf4j
。
其他 资源
Amazon Lambda 开发者指南中有一节介绍开发非 Java 特定的 Lambda 函数的最佳实践。
有关使用 Java 构建云原生应用程序的示例 Amazon Lambda,请参阅此研讨会内容
您可以考虑使用提前编译的静态映像来减少启动延迟。例如,您可以使用适用于 Java 的 SDK 2.x 和 Maven 来构建 GraalVM 原生映像。