The English version of quarkus.io is the official project site. Translated sites are community supported on a best-effort basis.

AWS Lambda SnapStartの設定

SnapStart は、AWS上のJava関数のコールドスタートアップ時間を大幅に短縮するスナップショット・リストアの仕組みです。このドキュメントでは、この機能を活用するためのさまざまな設定について説明します。SnapStartのリファレンスドキュメントではないので、SnapStartの動作の詳細については説明しません。

本機能はAWS Lambdaでのみ利用可能であり、すべてのリージョンで利用できるわけではありません。AWSのドキュメントをご確認の上、ご利用のAWSリージョンが該当するかご確認ください。

SnapStart最適化の有効化/無効化

Quarkus AWS Lambdaエクステンションを使用すると、SnapStartの最適化が自動的に有効になります。 ただし、以下を使用して明示的に有効化/無効化することもできます:

quarkus.snapstart.enable=true|false
Quarkusの最適化のみで、関数のSnapStartの有効/無効は設定されません。

クラスプリローディング

クラスローディングは、関数の実行時間に大きな影響を与えます。この最適化により、SnapStartのスナップショット処理中にクラスをプリロードすることができます。

プリロードするクラスは2か所に記載されています。

  1. エクステンションは、クラスのリストを生成することができます ( io.quarkus.deployment.builditem.PreloadClassBuildItem ビルドアイテムを使用します)。

  2. 以下のように、プリロードするクラスをリストアップした src/main/resources/META-INF/quarkus-preload-classes.txt ファイルを追加することができます。

com.amazonaws.services.lambda.runtime.LambdaRuntimeInternal
com.fasterxml.jackson.annotation.JsonAlias
com.fasterxml.jackson.annotation.JsonFormat$Feature
com.fasterxml.jackson.core.exc.InputCoercionException
com.fasterxml.jackson.core.exc.StreamWriteException
com.fasterxml.jackson.core.io.ContentReference
com.fasterxml.jackson.core.io.IOContext
com.fasterxml.jackson.core.io.JsonEOFException
com.fasterxml.jackson.core.io.MergedStream
com.fasterxml.jackson.core.io.NumberInput
com.fasterxml.jackson.core.io.NumberOutput
com.fasterxml.jackson.core.io.UTF32Reader
com.fasterxml.jackson.core.json.ByteSourceJsonBootstrapper
com.fasterxml.jackson.core.json.JsonReadContext
com.fasterxml.jackson.core.json.JsonWriteContext
com.fasterxml.jackson.core.json.UTF8StreamJsonParser
com.fasterxml.jackson.core.JsonEncoding
com.fasterxml.jackson.core.JsonGenerationException
com.fasterxml.jackson.core.JsonLocation
com.fasterxml.jackson.core.JsonStreamContext
com.fasterxml.jackson.core.JsonToken
...

フォーマットはシンプルで、1行に1クラスです。

クラスリストの計算

このステップは特に使い勝手が悪いため、改善を計画しています。

クラスのリストを計算するには、関数をデプロイして、環境変数 JAVA_TOOL_OPTIONS-verbose:class に設定することをお勧めします。 その後、関数を実行し、(CloudWatchで)ログを取得します。sed/awkなどのテキストエディタでクラス名を抽出することができるはずです。

アプリケーションクラス一覧

デフォルトでは、(Quarkus で生成されたクラスも含む)アプリケーションに含まれるクラスのクラスリストが生成されま す。そのため、 quarkus-preload-classes.txt ファイルでこれらを繰り返す必要はありません。

次の設定により、この機能を無効にすることができます。

quarkus.snapstart.generate-application-class-list=false

プリローディングの無効化

次の設定により、クラスのプリローディングを無効にすることができます。

quarkus.snapstart.preload-classes=false

クラス初期化のスキップ

デフォルトでは、クラスがプリロードされるときに、 初期化もされます 。これは、依存するクラスも解決することを意味します。この動作を無効にするには、次のようにします。

quarkus.snapstart.initialize-classes=false

クライアント・プライミング

クライアントの プライミング は、スナップショット処理中にクライアントを初期化し、アプリケーションの実行時にすでに完全に機能するようにする技術です。

プライミング を実現するには、2つの方法があります。

  1. static ブロックでクライアントを初期化します。これは、クラスのプリロードのおかげで、スナップショットの前に実行されることになります。

  2. 初期化を行うCRaC Resourceを登録する

(1)は以下のように実現できます:

@ApplicationScoped
public class HeroRepository {
    private static final DynamoDbClient client;

    static {
        client = DynamoDbClient.builder()
                .region(Region.US_EAST_2)
                .credentialsProvider(DefaultCredentialsProvider.create())
                .build();
        client.describeEndpoints();
    }
    // ...
}
静的ブロックを使ってプライミングを実装すると、アプリケーションのネイティブコンパイルができなくなる場合があります。ビルド時にクラスを初期化すると、クライアントの初期化でスレッドが起動したり、 ネイティブコンパイルと互換性のないコネクションが開かれたりすることがあります。

次のセクションで(2)について説明します。

リソース登録

SnapStartはCRaC APIを使用して、スナップショット前またはリストア中にアプリケーションでカスタムコードを実行できるようにします。

CRaC APIではありますが、SnapStartはCRaCではないので、他のCRaC実装では動作しないような こと を行うことができます。
package org.acme.hello;

import io.quarkus.runtime.Startup;
import org.crac.Context;
import org.crac.Core;
import org.crac.Resource;
import org.jboss.logging.Logger;

import jakarta.annotation.PostConstruct;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;

@Startup
@ApplicationScoped
public class HelloPriming implements Resource {

    @Inject
    Logger logger;

    @PostConstruct
    void init() {
        // Important - register the resource
        Core.getGlobalContext().register(this);
    }

    @Override
    public void beforeCheckpoint(Context<? extends Resource> context) throws Exception {
        logger.info("before checkout hook");
        // initialize your client here.
    }

    @Override
    public void afterRestore(Context<? extends Resource> context) throws Exception {
        logger.info("after checkout hook");
        // if there is anything to do during the restoration, do it here.
    }
}
リストアは2秒間に限られます。

TieredCompilation

また、SnapStartを使用する場合は、 階層型コンパイル を使用することをお勧めします。これを実現するには、 JAVA_TOOL_OPTIONS 環境プロパティを -XX:+TieredCompilation -XX:TieredStopAtLevel=1 に設定します。

TieredCompilation は、通常のLambda関数でも興味深いことができます。

関連コンテンツ