Amazon Web Services ブログ

New – Lambda SnapStart で Lambda 関数を高速化

お客様が AWS Lambda を気に入っている理由はさまざまです。開発面では、シンプルなプログラミングモデルと、その機能が他の AWS サービスを簡単に利用できることが高く評価されています。運用面では、変化する使用パターンに迅速に対応できる強力なアプリケーションを構築できるというメリットがあります。

すでに Lambda を使用している方ならご存知かもしれませんが、関数は安全で隔離された実行環境内で実行されます。環境の各ライフサイクルは、初期化起動シャットダウンの 3 つの主要フェーズで構成されています。とりわけ、 Init フェーズは関数のランタイムをブートストラップし、関数の静的コードを実行します。多くの場合、これらの操作はミリ秒以内に完了し、フェーズがそれほど長くなることはありません。残りのケースでは、いくつかの理由でかなりの時間がかかることがあります。まず、一部の言語ではランタイムの初期化にコストがかかる場合があります。例えば、Java ランタイムのいずれかを Spring Boot Quarkus Micronaut などのフレームワークと組み合わせて使用する Lambda 関数の Init フェーズには、10 秒もかかることがあります (これには、依存性注入、関数のコードのコンパイル、クラスパスコンポーネントのスキャンが含まれます)。次に、静的コードが機械学習モデルをダウンロードしたり、参照データを事前に計算したり、他の AWS サービスへのネットワーク接続を確立したりする場合があります。

Lambda SnapStart のご紹介
Lambda をさまざまな方法で使用できるようにするため、11 月 28 日より Lambda SnapStart を導入いたします。

特定の Lambda 関数に対して Lambda SnapStart を有効にした後、新しいバージョンの関数を公開すると最適化プロセスが開始されます。このプロセスは関数を起動し、Init フェーズ全体にわたって実行します。次に、メモリとディスクの状態に関する不変の暗号化されたスナップショットを取得し、再利用できるようにキャッシュします。その後関数が呼び出されると、状態は必要に応じてキャッシュからチャンク単位で取得され、実行環境への入力に使用されます。この最適化により、新しい実行環境を作成する際に専用の Init フェーズが不要になるため、呼び出し時間が短縮され、予測しやすくなります。

現在、Corretto (java11) ランタイムを利用する Java 関数のサポートを開始しており、Spring Boot、Quarkus、Micronaut、その他の Java フレームワークを利用するアプリケーションに Lambda SnapStart がすぐに使用されるようになることを期待しています。Java 関数で Lambda SnapStart を有効にすると、追加コストなしで最大で 10 倍の速さで起動できます。

Lambda SnapStart の使用
私が最後に実際に Java に出会ったのは前世紀だったので、AWS Labs リポジトリのサーバーレス Spring Boot 2 の例を出発点として使用しました。AWS SAM CLI をインストールし、テストビルドとデプロイを行ってベースラインを確立しました。この関数を呼び出したところ、Initの所要時間が 6 秒を少し超えていることがわかりました。

次に、template.yml に 2 行追加して SnapStart プロパティを設定しました。

再構築して再デプロイし、SnapStartをセットアップする関数の最新バージョンを公開し、別のテストを実行しました。

SnapStartでは、関数の新しいバージョンを公開すると、初期化フェーズ (先ほど説明した初期化期間で表される) が発生します。SnapStart が有効になっている関数を呼び出すと、Lambda は関数ハンドラーを呼び出す前にスナップショット (復元期間で表される) を復元します。その結果、SnapStart でのコールド呼び出しの合計は、リストア時間 +所要時間になります。SnapStartは、コールドスタートの所要時間を 6 秒以上から 200 ミリ秒未満へと短縮しました。

スナップレジリエンスの強化
Lambda SnapStart は、初期化された単一のスナップショットを再利用して複数の実行環境を再開することで、アプリケーションを高速化します。これはコードにいくつか興味深い影響を及ぼします。

一意性 – SnapStart を使用する場合、一意性を維持するために、初期化中に生成されていた固有のコンテンツは、初期化後に生成する必要があります。ユーザー (または参照しているライブラリ) が疑似乱数ジェネレーターを使用している場合は、初期化フェーズで取得したシードに基づいて作成しないでください。OpenSSL の RAND_Bytes を更新して、SnapStart と組み合わせて使用したときにランダム性が確保されるようにしました。また、java.security.SecureRandom が既にスナップ復元機能を備えていることを確認しました。Amazon Linux の/dev/random /dev/urandom もスナップ復元性に優れています。

ネットワーク接続 – コードが Init フェーズでネットワークサービスへの長期接続を作成し、Invoke フェーズでそれらを使用する場合は、必要に応じて接続を再確立できることを確認してください。AWS SDK はこれを実現するために既に更新されています。

エフェメラルデータ – これは事実上、上記の項目のより一般的な形式です。Init フェーズでコードが参照情報をダウンロードまたは計算する場合は、キャッシュ期間中にコードが古くなっていないかを簡単に確認することを検討してください。

Lambda には、一意性を維持するのに役立つランタイムフック 2 つと、発生する可能性のある問題の検出に役立つスキャンツールが用意されています。

知っておくべきこと
Lambda SnapStart: について、知っておくべきことがいくつかあります。

キャッシュ – キャッシュされたスナップショットは、使用されていない状態が 14 日間続くと削除されます。スナップショットが更新またはパッチが適用されたランタイムに依存する場合、Lambda はキャッシュを自動的に更新します。

料金設定 – Lambda SnapStart の使用には追加料金はかかりません。

機能の互換性 – Lambda SnapStart は、大容量のエフェメラルストレージ、エラスティックファイルシステム、プロビジョニングされた同時実行性、または Graviton2 では使用できません。一般的に、汎用の Lambda 関数には SnapStart を使用し、レイテンシーの影響を非常に受けやすい関数のサブセットにはプロビジョニング型同時実行を使用することをお勧めします。

Firecracker – この機能はファイヤークラッカースナップショットを利用します。

リージョン – Lambda SnapStart は、米国東部 (オハイオ、バージニア北部)、米国西部 (オレゴン)、アジアパシフィック (シンガポール、シドニー、東京)、欧州 (フランクフルト、アイルランド、ストックホルム) リージョンでご利用いただけます。

Jeff;

原文はこちらです。