Reducir el tiempo de startup del SDK para AWS Lambda - AWS SDK for Java 2.x

Reducir el tiempo de startup del SDK para AWS Lambda

Uno de los objetivos del AWS SDK for Java 2.x es reducir la latencia de startup de las funciones AWS Lambda. El SDK contiene cambios que reducen el tiempo de startup, descritos al final de este tema.

En primer lugar, este tema se centra en los cambios que puede realizar para reducir los tiempos de arranque en frío. Esto incluye realizar cambios en la estructura de su código y en la configuración de los clientes del servicio.

Uso de un cliente de HTTP basado en AWS CRT

Para trabajar con AWS Lambda, recomendamos el AwsCrtHttpClient para escenarios sincrónicos y el AwsCrtAsyncHttpClient para escenarios asincrónicos.

El tema Configurar el cliente HTTP basado en CRT de AWS de esta guía describe las ventajas de usar los clientes de HTTP, cómo agregar la dependencia y cómo configurar su uso por los clientes de servicio.

Eliminar las dependencias del cliente HTTP no utilizadas

Además del uso explícito de un cliente basado en AWS CRT, puede eliminar otros clientes de HTTP que el SDK incluye de forma predeterminada. El tiempo de startup de Lambda se reduce cuando se necesita cargar menos librerías, por lo que debería eliminar cualquier artefacto no utilizado que la JVM necesite cargar.

El siguiente fragmento de código de un archivo pom.xml Maven muestra la exclusión del cliente HTTP basado en Apache y el cliente HTTP basado en Netty. (Estos clientes no son necesarios cuando se utiliza un cliente basado en AWS CRT.) En este ejemplo, se excluyen los artefactos del cliente de HTTP de la dependencia del cliente de S3 y se agrega el artefacto aws-crt-client para permitir el acceso a clientes de HTTP basados en AWS CRT.

<project> <properties> <aws.java.sdk.version>2.27.21</aws.java.sdk.version> <properties> <dependencyManagement> <dependencies> <dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>bom</artifactId> <version>${aws.java.sdk.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <dependencies> <dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>aws-crt-client</artifactId> </dependency> <dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>s3</artifactId> <exclusions> <exclusion> <groupId>software.amazon.awssdk</groupId> <artifactId>netty-nio-client</artifactId> </exclusion> <exclusion> <groupId>software.amazon.awssdk</groupId> <artifactId>apache-client</artifactId> </exclusion> </exclusions> </dependency> </dependencies> </project>
nota

Añada el elemento <exclusions> a todas las dependencias del cliente de servicio del archivo pom.xml.

Configurar los clientes de servicio para abreviar las búsquedas

Especificar una región

Cuando cree un cliente de servicio, llame al método region en el generador del cliente de servicio. Esto acorta el proceso de búsqueda de regiones predeterminado del SDK que comprueba varios lugares para obtener la información de Región de AWS.

Para mantener el código Lambda independiente de la región, utilice el siguiente código dentro del método region. Este código accede a la variable de entorno AWS_REGION establecida por el contenedor Lambda.

Region.of(System.getenv(SdkSystemSetting.AWS_REGION.environmentVariable()))
Utilizar EnvironmentVariableCredentialProvider

Al igual que el comportamiento de búsqueda predeterminado para la información de la Región, el SDK busca las credenciales en varios lugares. Si especifica el EnvironmentVariableCredentialProvider al generar un cliente de servicio, ahorrará tiempo en el proceso de búsqueda de credenciales del SDK.

nota

El uso de este proveedor de credenciales permite que el código se utilice en funciones Lambda, pero es posible que no funcione en Amazon EC2 u otros sistemas.

Si piensa utilizar Lambda SnapStart para Java en algún momento, debe confiar en la cadena de proveedores de credenciales predeterminadas para buscar credenciales. Si especifica el EnvironmentVariableCredentialsProvider, la búsqueda inicial de credenciales funciona, pero cuando se activa SnapStart, el tiempo de ejecución de Java establece las variables de entorno de las credenciales del contenedor. Tras la activación, las variables de entorno utilizadas por EnvironmentVariableCredentialsProvider (variables de entorno clave de acceso) no están disponibles en el SDK de Java.

El siguiente fragmento de código muestra un cliente de servicio S3 configurado adecuadamente para su uso en un entorno Lambda.

S3Client s3Client = S3Client.builder() .region(Region.of(System.getenv(SdkSystemSetting.AWS_REGION.environmentVariable()))) .credentialsProvider(EnvironmentVariableCredentialsProvider.create()) .httpClient(AwsCrtHttpClient.builder().build()) .build();

Inicializar el cliente de SDK fuera del controlador de la función de Lambda

Recomendamos inicializar un cliente SDK fuera del método del controlador Lambda. De esta forma, si se reutiliza el contexto de ejecución, se puede omitir la inicialización del cliente de servicio. Al reutilizar la instancia del cliente y sus conexiones, las invocaciones posteriores al método controlador se producen más rápidamente.

En el siguiente ejemplo, la instancia S3Client se inicializa en el generador mediante un método de fábrica estático. Si se reutiliza el contenedor que administra el entorno Lambda, se reutiliza la instancia S3Client inicializada.

public class App implements RequestHandler<Object, Object> { private final S3Client s3Client; public App() { s3Client = DependencyFactory.s3Client(); } @Override public Object handle Request(final Object input, final Context context) { ListBucketResponse response = s3Client.listBuckets(); // Process the response. } }

Minimizar la inyección de dependencias

Los marcos de inyección de dependencias (DI) pueden tardar más tiempo en completar el proceso de configuración. También es posible que requieran dependencias adicionales, que tardan un tiempo en cargarse.

Si se necesita un marco de DI, recomendamos usar marcos DI livianos como Dagger.

Utilizar un arquetipo de Maven orientado a AWS Lambda

El equipo del SDK de Java de AWS ha desarrollado una plantilla de arquetipo de Maven para arrancar un proyecto de Lambda con un tiempo de startup mínimo. Puede crear un proyecto de Maven a partir del arquetipo y saber que las dependencias están configuradas adecuadamente para el entorno de Lambda.

Para obtener más información sobre el arquetipo y trabajar con un ejemplo de implementación, consulte esta entrada del blog.

Considerar Lambda SnapStart para Java

Si sus requisitos de tiempo de ejecución son compatibles, AWS ofrece Lambda SnapStart para Java. Lambda SnapStart es una solución basada en infraestructura que mejora el rendimiento de startup de las funciones de Java. Cuando publica una nueva versión de una función, Lambda SnapStart la inicializa y toma una instantánea inmutable y cifrada del estado de la memoria y el disco. A continuación, SnapStart almacena en caché la instantánea para volver a utilizarla.

Cambios en la versión 2.x que afectan al tiempo de startup

Además de los cambios que haga en su código, la versión 2.x del SDK para Java incluye tres cambios principales que reducen el tiempo de startup:

  • Uso de jackson-jr, una biblioteca de serialización que mejora el tiempo de inicialización.

  • Uso de las bibliotecas java.time para los objetos de fecha y hora, parte del JDK.

  • Uso de Slf4j para una fachada de registro.

Recursos adicionales

La Guía para desarrolladores DE AWS Lambda contiene una sección sobre las mejores prácticas para desarrollar funciones de Lambda que no es específica de Java.

Para ver un ejemplo de cómo crear una aplicación nativa en la nube en Java que utilice AWS Lambda, consulte el contenido de este taller. En el taller se trata la optimización del rendimiento y otras buenas prácticas.

Puede considerar la posibilidad de utilizar imágenes estáticas que se compilen con antelación para reducir la latencia de startup. Por ejemplo, puede usar el SDK para Java 2.x y Maven para generar una imagen nativa de GraalVM.