AWS Lambda SnapStart Configuration

SnapStart es un mecanismo de snapshot y restauración que reduce drásticamente el tiempo de arranque en frío de las funciones Java en AWS. Este documento explica las distintas configuraciones que puede utilizar para aprovechar esta característica. No es una documentación de referencia sobre SnapStart y no cubrirá en detalle cómo funciona SnapStart.

This feature is only available on AWS Lambda, and not in all regions. Please check the AWS documentation to verify the eligibility of your AWS region.

Activación y desactivación de las optimizaciones de SnapStart

Si utiliza la extensión AWS Lambda de Quarkus, las optimizaciones SnapStart se habilitan automáticamente. Sin embargo, puede habilitarlo/deshabilitarlo explícitamente utilizando:

quarkus.snapstart.enable=true|false
It does not enable/disable SnapStart for your function, only the Quarkus optimizations.

Precarga de clases

La carga de clases tiene un gran impacto en el tiempo de ejecución de las funciones. Esta optimización permite precargar clases durante el proceso de instantánea de SnapStart.

Las clases a precargar se enumeran en dos lugares:

  1. las extensiones pueden producir una lista de clases (utilizando el elemento de compilación io.quarkus.deployment.builditem.PreloadClassBuildItem)

  2. puede añadir un archivo src/main/resources/META-INF/quarkus-preload-classes.txt que enumere las clases a precargar, por ejemplo:

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
...

El formato es sencillo: una clase por línea.

Cálculo de la lista de clases

That step is particularly not user-friendly. We plan to improve it.

Para calcular la lista de clases, recomendamos desplegar su función y establecer la variable de entorno JAVA_TOOL_OPTIONS en -verbose:class. A continuación, ejecute su función y recupere el registro (en CloudWatch). Debería poder extraer los nombres de las clases utilizando sed/awk o cualquier editor de texto.

Lista de clases de aplicaciones

Por defecto, Quarkus genera la lista de clases de las clases incluidas en tu aplicación (incluyendo las clases generadas por Quarkus). Por lo tanto, no tienes que repetirlas en el archivo quarkus-preload-classes.txt.

Puede desactivar esta función mediante:

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

Desactivar la precarga

Puede desactivar la precarga de clases utilizando:

quarkus.snapstart.preload-classes=false

Omitir la inicialización de clases

Por defecto, cuando se precargan las clases, también se inicializan, lo que significa que también resuelve las clases dependientes. Puede desactivar este comportamiento utilizando:

quarkus.snapstart.initialize-classes=false

Preparación del cliente

Preparación del cliente, priming, es una técnica que permite inicializar un cliente durante el proceso de instantánea, de modo que ya es completamente funcional durante el tiempo de ejecución de la aplicación.

Hay dos formas de conseguir priming:

  1. inicializar el cliente en un bloque static que, gracias a la precarga de clases, se ejecutará antes de la instantánea

  2. registrar un Recurso CRaC que realice la inicialización

(1) puede lograrse de la siguiente manera:

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

    static {
        client = DynamoDbClient.builder()
                .region(Region.US_EAST_2)
                .credentialsProvider(DefaultCredentialsProvider.create())
                .build();
        client.describeEndpoints();
    }
    // ...
}
Implementing priming using a static block may prevent the native compilation of your application. Client initialization may start threads or open connections which are not compatible with the native compilation if the class is initialized at build time.

La siguiente sección trata de (2).

Registro de recursos

SnapStart utiliza la API CRaC para permitir que la aplicación ejecute código personalizado antes de la instantánea o durante la restauración.

While it’s the CRaC API, SnapStart is not CRaC and can do things that would not work with others CRaC implementations.
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.
    }
}
Restoration is limited to 2 seconds.

Compilación por niveles

También se recomienda utilizar la compilación por niveles al utilizar SnapStart. Para ello, establezca la propiedad de entorno JAVA_TOOL_OPTIONS en -XX:+TieredCompilation -XX:TieredStopAtLevel=1.

TieredCompilation can also be interesting for regular Lambda functions.

Related content