Lambda 関数スナップショットの前後のコード実装 - AWS Lambda

Lambda 関数スナップショットの前後のコード実装

ランタイムフックを使用して、Lambda がスナップショットを作成する前、または Lambda がスナップショットから関数を再開した後でコードを実装できます。ランタイムフックは、オープンソースの Coordinated Restore at Checkpoint (CRaC) プロジェクトの一部として提供されています。CRaC は、Open Java Development Kit (OpenJDK) 向けに開発中です。リファレンスアプリケーションで CRaC を使用する方法の例については、GitHub にある CRaC リポジトリを参照してください。CRaC は、3 つの主要要素を使用します。

  • ResourcebeforeCheckpoint() および afterRestore() の 2 つのメソッドを持つインターフェイス。これらのメソッドを使用して、スナップショット前、および復元後に実行するコードを実装します。

  • Context <R extends Resource> – チェックポイントと復元に関する通知を受け取るには、ResourceContext に登録されている必要があります。

  • Core – 静的メソッド Core.getGlobalContext() 経由でデフォルトのグローバル Context を提供するコーディネーションサービス。

Context および Resource の詳細については、CRaC ドキュメントの「Package org.crac」を参照してください。

org.crac package を使用してランタイムフックを実装するには、以下の手順を実行します。Lambda ランタイムには、チェックポイント作成前と復元後にランタイムフックを呼び出す、カスタマイズされた CRaC コンテキスト実装が含まれています。

ステップ 1: ビルド設定を更新する

ビルド設定に org.crac 依存関係を追加します。以下の例は、Gradle を使用しています。他のビルドシステムの例については、Apache Maven ドキュメントを参照してください。

dependencies { compile group: 'com.amazonaws', name: 'aws-lambda-java-core', version: '1.2.1' # All other project dependecies go here: # ... # Then, add the org.crac dependency: implementation group: 'org.crac', name: 'crac', version: '1.4.0' }

ステップ 2: Lambda ハンドラーを更新する

Lambda 関数ハンドラーは、イベントを処理する関数コード内のメソッドです。関数が呼び出されると、Lambda はハンドラーメソッドを実行します。関数は、ハンドラーが応答を返すか、終了するか、タイムアウトするまで実行されます。

詳細については、「Java の Lambda 関数ハンドラーの定義」を参照してください。

以下のハンドラー例は、チェックポイント作成前 (beforeCheckpoint()) と復元後 (afterRestore()) にコードを実行する方法を示しています。このハンドラーは、ランタイムが管理するグローバル Context への Resource の登録も行います。

注記

Lambda がスナップショットを作成するときは、初期化コードが最大 15 分間実行される場合があります。制限時間は 130 秒、または設定されている関数のタイムアウト (最大 900 秒) のいずれか長い方です。beforeCheckpoint() ランタイムフックは初期化コードの時間制限にカウントされます。Lambda がスナップショットを復元するときは、タイムアウト制限 (10 秒) 内にランタイム (JVM) がロードされ、afterRestore() ランタイムフックが完了される必要があります。その時間を超えると、SnapStartTimeoutException が発生します。

... import org.crac.Resource; import org.crac.Core; ... public class CRaCDemo implements RequestStreamHandler, Resource { public CRaCDemo() { Core.getGlobalContext().register(this); } public String handleRequest(String name, Context context) throws IOException { System.out.println("Handler execution"); return "Hello " + name; } @Override public void beforeCheckpoint(org.crac.Context<? extends Resource> context) throws Exception { System.out.println("Before checkpoint"); } @Override public void afterRestore(org.crac.Context<? extends Resource> context) throws Exception { System.out.println("After restore");

Context は、登録されたオブジェクトへの WeakReference のみを維持します。Resource に対してガベージコレクションが行われた場合、ランタイムフックは実行されません。ランタイムフックが実行されることを保証するには、コードが Resource への強参照を維持する必要があります。

以下は、避ける必要があるパターンの 2 つの例です。

例 – 強参照がないオブジェクト
Core.getGlobalContext().register( new MyResource() );
例 – 匿名クラスのオブジェクト
Core.getGlobalContext().register( new Resource() { @Override public void afterRestore(Context<? extends Resource> context) throws Exception { // ... } @Override public void beforeCheckpoint(Context<? extends Resource> context) throws Exception { // ... } } );

これらの代わりに、強参照を維持します。以下の例では、登録されたリソースに対してガベージコレクションが行われず、ランタイムフックが一貫的に実行されます。

例 – 強参照を持つオブジェクト
Resource myResource = new MyResource(); // This reference must be maintained to prevent the registered resource from being garbage collected Core.getGlobalContext().register( myResource );