AWS Lambda の SDK の起動時間を短縮する - AWS SDK for Java 2.x

AWS Lambda の SDK の起動時間を短縮する

AWS SDK for Java 2.x の目標の 1 つは、AWS Lambda 関数の起動レイテンシーを短縮することです。SDK には、起動時間を短縮する変更が含まれています。これについてはこのトピックの最後で説明します。

まず、このトピックでは、コールド起動時間を短縮するためにできる変更に焦点を当てます。これには、コード構造やサービスクライアントの設定の変更が含まれます。

AWS CRT ベースの HTTP クライアントを使用する

AWS Lambda を使用する場合は、同期シナリオの場合は AwsCrtHttpClient を、非同期シナリオの場合は AwsCrtAsyncHttpClient を使用することをお勧めします。

このガイドの AWS CRT ベースの HTTP クライアントを設定する トピックでは、HTTP クライアントを使用する利点、依存関係を追加する方法、サービスクライアントによる使用を設定する方法について説明します。

未使用の HTTP クライアント依存関係を削除する

AWS CRT ベースのクライアントを明示的に使用するほかに、SDK がデフォルトで取り込む他の HTTP クライアントも削除できます。ロードする必要のあるライブラリが少ないほど、Lambda の起動時間は短くなるため、JVM がロードする必要のある未使用のアーティファクトはすべて削除する必要があります。

以下の Maven pom.xml ファイルのスニペットは、Apache ベースの HTTP クライアントと Netty ベースの HTTP クライアントが除外されていることを示しています。(AWS CRT ベースのクライアントを使用する場合、これらのクライアントは必要ありません)。この例では、HTTP クライアントのアーティファクトを S3 クライアントの依存関係から除外し、aws-crt-client アーティファクトを追加して AWS 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>
注記

pom.xml ファイル内のすべてのサービスクライアント依存関係に <exclusions> 要素を追加します。

検索をショートカットするようにサービスクライアントを設定します。

リージョンを指定する

サービスクライアントを作成したら、サービスクライアントビルダーの region メソッドを呼び出します。これにより、複数の場所で AWS リージョン 情報を確認する SDK のデフォルトのリージョン検索プロセスを短縮できます。

Lambda コードをリージョンから独立させるには、region メソッド内で以下のコードを使用します。このコードは、Lambda コンテナによって設定された AWS_REGION 環境変数にアクセスします。

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

リージョン情報のデフォルトの検索動作と同様に、SDK は複数の場所で認証情報を検索します。サービスクライアントを構築するときに EnvironmentVariableCredentialProvider を指定することで、SDK の認証情報検索処理にかかる時間を短縮できます。

注記

この認証情報プロバイダーを使用すると、コードを Lambda 関数で使用できますが、Amazon EC2 または他のシステムでは動作しない可能性があります。

どこかの時点で Lambda SnapStart 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 アーキタイプターゲティング AWS Lambda を使用する

AWS Java SDK チームは、最小限の起動時間で Lambda プロジェクトをブートストラップするための Maven Archetype テンプレートを開発しました。アーキタイプから Maven プロジェクトを構築し、依存関係が Lambda 環境に合わせて適切に設定されていることを確認できます。

アーキタイプおよびデプロイ例について知るには、このブログ記事を参照してください。

Lambda SnapStart for Java を検討する

ランタイム要件に互換性がある場合は、AWS で Lambda SnapStart for Java を使用できます。Lambda SnapStart は、Java 関数の起動パフォーマンスを向上させるインフラストラクチャベースのソリューションです。新しいバージョンの関数を発行する場合、Lambda SnapStart は初期化され、メモリとディスクの状態の変更不可能な暗号化されたスナップショットを作成します。その後、SnapStart はスナップショットをキャッシュして再利用します。

起動時間に影響するバージョン 2.x の変更点

コードに加えた変更に加えて、SDK for Java のバージョン 2.x には、起動時間を短縮する 3 つの主な変更が含まれています。

  • 初期化時間を短縮するシリアル化ライブラリである、Jackson-jr を使用します

  • JDK の一部である日付時刻オブジェクトで java.time ライブラリを使用します。

  • ログ記録ファサードの Slf4j を使用します

その他のリソース

AWS Lambda デベロッパーガイドには、Java 固有ではない Lambda 関数を開発するためのベストプラクティスに関するセクションが含まれます。

AWS Lambda を使用するクラウドネイティブアプリケーションを Java で構築する例については、この「ワークショップコンテンツ」を参照してください。ワークショップでは、パフォーマンスの最適化やその他のベストプラクティスについて説明します。

起動時のレイテンシーを短縮するために、事前にコンパイルされた静的イメージの使用を検討できます。例えば、SDK for Java 2.x および Maven を使用して GraalVM ネイティブイメージを構築できます。