Actualmente estoy trabajando en una función AWS Lambda escrita en Java. Necesita obtener objetos de S3 y, por lo tanto, configuré un rol de IAM y estoy creando un cliente S3 en el controlador de Lambda:
import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.RequestHandler; import com.amazonaws.services.s3.AmazonS3; import com.amazonaws.services.s3.AmazonS3ClientBuilder; public class Example implements RequestHandler<Void, Void> { @Override public Void handleRequest(Void nothing, Context ctx) { long start = System.currentTimeMillis(); AmazonS3 amazonS3 = AmazonS3ClientBuilder.defaultClient(); ctx.getLogger().log("Creating S3 client took " + (System.currentTimeMillis() - start) + "ms"); ... return null; } } Sin embargo, el uso de AmazonS3ClientBuilder es muy lento, la declaración de registro imprime los siguientes tiempos al asignar 192 MB a la función:
Creating S3 client took 13541ms Creating S3 client took 16482ms Creating S3 client took 13617ms Creating S3 client took 16380msIncluso cuando aumenta la memoria hasta 3008 MB para obtener la máxima potencia de procesamiento (ya que AWS asigna potencia de CPU proporcional a la memoria para Lambdas), se tarda entre 1 y 2 segundos en obtener el cliente:
Creating S3 client took 1413ms Creating S3 client took 1170ms Creating S3 client took 1528ms Creating S3 client took 1394ms Estos tiempos se registraron en escenarios de arranque en frío y estoy almacenando en caché la instancia de AmazonS3 para solicitudes posteriores, pero parece bastante extremo que solo construir un cliente S3 puede llevar más de 16 segundos en un Lambda no cálido.
¿Estoy haciendo un mal uso de AmazonS3ClientBuilder , posiblemente al no anular algunos valores predeterminados, lo que genera un rendimiento deficiente? ¿Cómo se puede acelerar la inicialización del cliente?
El SDK de AWS para Java 2.0 se lanzó en noviembre. Es básicamente una reescritura de la versión 1.x y parece haber mejorado bastante el rendimiento. Migrar el código de la pregunta para usar el nuevo SDK nos daría algo similar a lo siguiente:
import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.RequestHandler; import software.amazon.awssdk.services.s3.S3Client; public class Example implements RequestHandler<Void, Void> { @Override public Void handleRequest(Void nothing, Context ctx) { long start = System.currentTimeMillis(); S3Client s3Client= S3Client.create(); ctx.getLogger().log("Creating S3 client took " + (System.currentTimeMillis() - start) + "ms"); ... return null; } }Al asignar 192 MB a la función:
Creating S3 client took 9380ms Creating S3 client took 9719ms Creating S3 client took 10098ms Creating S3 client took 9519msAl asignar 3008 MB a la función:
Creating S3 client took 884ms Creating S3 client took 873ms Creating S3 client took 886ms Creating S3 client took 877msSegún estas cifras aproximadas, el tiempo de creación del cliente S3 en escenarios de arranque en frío se ha reducido en más de un tercio cuando se usa la versión 2 del SDK.
Al ejecutar una función sin servidor, permanecerá activa (también conocida como caliente) mientras la esté ejecutando. Su contenedor se mantiene vivo, listo y esperando su ejecución.
Después de un período de inactividad, su proveedor de nube dejará caer el contenedor y su función quedará inactiva (también conocida como fría).
Un arranque en frío ocurre cuando ejecuta una función inactiva. El retraso proviene de su proveedor de nube que aprovisiona su contenedor de tiempo de ejecución seleccionado y luego ejecuta su función.
Puede solucionar esto manteniendo sus funciones 'calientes'. Una forma de hacer esto sería agregar un cronjob que haga ping a su función de vez en cuando. Hay un complemento disponible que hace exactamente eso llamado serverless-plugin-warmup , y estoy seguro de que hay muchos más como ese.
Los clientes de AWS se consideran seguros para subprocesos y pueden ser utilizados de forma segura por varias solicitudes al mismo tiempo. Debería poder crear el cliente como una variable miembro y reutilizar el mismo cliente para cada solicitud. Esto debería ahorrar un tiempo considerable, ya que el cliente predeterminado realiza algunas llamadas a AWS cada vez que se crea para buscar la región y las credenciales.