Java AWS Lambda 関数がうまく動作しません。原因は何ですか。また、Java 関数の初期化と呼び出し時間のレイテンシーを減らすにはどうすればよいですか。
簡単な説明
Java Lambda 関数のレイテンシーを増加させる原因は主に 2 つです。
Java 仮想マシン (JVM) 遅延読み込み
メモリ使用量を減らすために、ライブラリがアプリケーションで最初に呼び出されるまで、JVM が Java クラスライブラリの初期化を遅らせます。これにより、多数の入出力 (I/O) 操作が発生し、Lambda 実行環境での最初の呼び出し時間のレイテンシーが高くなります。
Java のリフレクション API
Java のリフレクション API を使用すると、Java コードが他のクラス、インタフェース、フィールド、メソッドに関する情報を検出し、その基になる値を操作できるようになります。リフレクションには動的に解決されるタイプが含まれるため、特定の JVM 最適化は実行できません。そのため、リフレクションを使用すると、リフレクションを使用しない場合よりも動作が遅くなります。
Java Lambda 関数のパフォーマンスを最適化するには、この記事で説明しているベストプラクティスのいずれか 1 つ以上を実装します。
**注意:**特定の導入事例を確認するには、AWS re: Invent 2019: AWS Lambda および Java のベストプラクティスをご参照ください。
解決方法
Lambda 関数のプロビジョニングされた同時実行を設定する
プロビジョニングされた同時実行は、要求された数の実行環境を初期化して、関数の呼び出しにすぐに応答できるようにします。関数にプロビジョニングされた同時実行を設定するには、「プロビジョニングされた同時実行を設定する」 の手順に従います。
詳細については、「Lambda 関数の同時実行数を管理する」をご参照ください。
**注意:**プロビジョニングされた同時実行を設定すると、AWS アカウントに料金が発生します。プロビジョニングされた同時実行は、関数のバージョンまたは Lambda 関数エイリアスで設定できます。
関数ハンドラーの外部で関数の静的ロジックを初期化する
Lambda 関数を初期化すると、Lambda はホスト CPU 容量のバーストを最大 10 秒間割り当てます。この CPU バーストにより、関数ハンドラーの外部で次のことを実行するのがベストプラクティスです。
- ライブラリと依存関係をインポートする
- 構成を設定する
- 他のサービスへの接続を初期化する
この静的な初期化により、これらのリソースがサンドボックスごとに一旦初期化され、その後実行環境でのすべての呼び出しに再利用することができます。
詳細については、「静的初期化を最適化する」をご参照ください。
関数ハンドラーの外部で遅延読み込みされたライブラリに対して API コールを行う
初期化中のライブラリの遅延ロードを回避するために、関数ハンドラーの外部で遅延読み込みされたライブラリに対してダミー API コールを行うことができます。このダミー呼び出しによって、ライブラリが初期化され、使用中の SDK をスタンバイさせます。
**注意:**Lambda が正常な API コールに必要な情報を持っていない場合、遅延読み込みされたライブラリへのダミーの呼び出しが失敗することがあります。呼び出しが失敗した場合は、必ずエラーをキャッチしてください。
Lambda コードのリフレクションを減らす
リフレクションを使用すると、リフレクションを使用しない場合よりも動作が遅くなります。頻繁に呼び出すコードのセクションではリフレクションを使用しないようにしてください。
アプリケーション内のクラスの数を減らす
ランタイムにデプロイパッケージのサイズを減らすと、関数の呼び出しにかかる時間が短縮されます。
詳細については、「AWS Lambda 関数を操作するためのベストプラクティス」をご参照ください。
事前に Lambda 関数の設定パラメータを設定する
事前に関数の構成パラメータを設定すると、関数の呼び出しとレイテンシーが軽減されます。コードで設定変数を指定しない場合は、Lambda が関数のデフォルト変数を検出するまでにかかる時間が増えます。
詳細については、「AWS Lambda 関数を操作するためのベストプラクティス」の「関数コード」セクションをご参照ください。
AWS Java SDK 2.0 にアップデートする
詳細については、「AWS Java SDK 2.x のチューニングによる起動時間の短縮」をご参照ください。
注意:AWS Java SDK 2.0 には、デフォルトで Java HTTP URL 接続クライアントと合わせて、Netty HTTP クライアントと Apache HTTP クライアント が含まれています。ユースケースで Apache および Netty HTTP クライアントを必要としない場合は、デプロイパッケージから削除することがベストプラクティスです。