Massimizza le prestazioni Lambda SnapStart - AWS Lambda

Le traduzioni sono generate tramite traduzione automatica. In caso di conflitto tra il contenuto di una traduzione e la versione originale in Inglese, quest'ultima prevarrà.

Massimizza le prestazioni Lambda SnapStart

Ottimizzazione prestazioni

Per massimizzare i vantaggi di SnapStart, prendi in considerazione i seguenti consigli di ottimizzazione del codice per il tuo runtime.

Nota

SnapStart funziona meglio se utilizzato con invocazioni di funzioni su larga scala. Le funzioni richiamate di rado potrebbero non presentare gli stessi miglioramenti delle prestazioni.

Per massimizzare i vantaggi di SnapStart, si consiglia di precaricare le dipendenze e inizializzare le risorse che contribuiscono alla latenza di avvio nel codice di inizializzazione anziché nel gestore delle funzioni. In questo modo la latenza associata al caricamento intensivo delle classi viene rimossa dal percorso di invocazione, ottimizzando le prestazioni di avvio con. SnapStart

Se non riesci a precaricare le dipendenze o le risorse durante l'inizializzazione, ti consigliamo di precaricarle con invocazioni fittizie. A tale scopo, aggiornate il codice del gestore delle funzioni, come illustrato nell'esempio seguente, tratto dalla funzione pet store del repository Labs. AWS GitHub

private static SpringLambdaContainerHandler<AwsProxyRequest, AwsProxyResponse> handler; static { try { handler = SpringLambdaContainerHandler.getAwsProxyHandler(PetStoreSpringAppConfig.class); // Use the onStartup method of the handler to register the custom filter handler.onStartup(servletContext -> { FilterRegistration.Dynamic registration = servletContext.addFilter("CognitoIdentityFilter", CognitoIdentityFilter.class); registration.addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST), false, "/*"); }); // Send a fake Amazon API Gateway request to the handler to load classes ahead of time ApiGatewayRequestIdentity identity = new ApiGatewayRequestIdentity(); identity.setApiKey("foo"); identity.setAccountId("foo"); identity.setAccessKey("foo"); AwsProxyRequestContext reqCtx = new AwsProxyRequestContext(); reqCtx.setPath("/pets"); reqCtx.setStage("default"); reqCtx.setAuthorizer(null); reqCtx.setIdentity(identity); AwsProxyRequest req = new AwsProxyRequest(); req.setHttpMethod("GET"); req.setPath("/pets"); req.setBody(""); req.setRequestContext(reqCtx); Context ctx = new TestContext(); handler.proxy(req, ctx); } catch (ContainerInitializationException e) { // if we fail here. We re-throw the exception to force another cold start e.printStackTrace(); throw new RuntimeException("Could not initialize Spring framework", e); } }

Per massimizzare i vantaggi di SnapStart, concentrati sull'organizzazione efficiente del codice e sulla gestione delle risorse all'interno delle tue funzioni Python. Come linea guida generale, esegui attività di calcolo complesse durante la fase di inizializzazione. Questo approccio elimina dal percorso di invocazione le operazioni che richiedono molto tempo, migliorando le prestazioni complessive delle funzioni. Per implementare questa strategia in modo efficace, consigliamo le seguenti best practice:

  • Importa le dipendenze al di fuori dell'handler della funzione.

  • Crea istanze boto3 al di fuori dell'handler.

  • Inizializza le risorse o le configurazioni statiche prima che l'handler venga richiamato.

  • Prendi in considerazione l'utilizzo di un hook di runtime prima dello snapshot per attività che richiedono molte risorse come il download di file esterni, il precaricamento di framework come Django o il caricamento di modelli di machine learning.

Esempio — Ottimizza la funzione Python per SnapStart
# Import all dependencies outside of Lambda handler from snapshot_restore_py import register_before_snapshot import boto3 import pandas import pydantic # Create S3 and SSM clients outside of Lambda handler s3_client = boto3.client("s3") # Register the function to be called before snapshot @register_before_snapshot def download_llm_models(): # Download an object from S3 and save to tmp # This files will persist in this snapshot with open('/tmp/FILE_NAME', 'wb') as f: s3_client.download_fileobj('amzn-s3-demo-bucket', 'OBJECT_NAME', f) ... def lambda_handler(event, context): ...

Per ridurre i tempi di compilazione just-in-time (JIT) e caricamento degli assiemi, prendete in considerazione la possibilità di richiamare il gestore di funzioni da un hook di runtime. RegisterBeforeCheckpoint Grazie al funzionamento della compilazione su più livelli .NET, otterrai risultati ottimali richiamando l'handler più volte, come illustrato nell'esempio seguente.

Importante

Assicurati che l'invocazione della funzione fittizia non produca effetti collaterali indesiderati, come l'avvio di transazioni commerciali.

public class Function { public Function() { Amazon.Lambda.Core.SnapshotRestore.RegisterBeforeSnapshot(FunctionWarmup); } // Warmup method that calls the function handler before snapshot to warm up the .NET code and runtime. // This speeds up future cold starts after restoring from a snapshot. private async ValueTask FunctionWarmup() { var request = new APIGatewayProxyRequest { Path = "/heathcheck", HttpMethod = "GET" }; for (var i = 0; i < 10; i++) { await FunctionHandler(request, null); } } public async Task<APIGatewayProxyResponse> FunctionHandler(APIGatewayProxyRequest request, ILambdaContext context) { // // Process HTTP request // var response = new APIGatewayProxyResponse { StatusCode = 200 }; return await Task.FromResult(response); } }

Best practice per la rete

Lo stato delle connessioni che la funzione stabilisce durante la fase di inizializzazione non è garantito quando Lambda riprende la funzione da uno snapshot. Nella maggior parte dei casi, le connessioni di rete stabilite da un AWS SDK riprendono automaticamente. Per altre connessioni, consigliamo le seguenti best practice.

Ristabilire le connessioni di rete

Ristabilisci sempre le connessioni di rete quando la funzione riprende da uno snapshot. Si consiglia di ristabilire le connessioni di rete nel gestore delle funzioni. In alternativa, puoi usare un hook di runtime dopo il ripristino.

Non utilizzare hostname come identificatore univoco dell'ambiente di esecuzione

Si consiglia di non utilizzare hostname per identificare l'ambiente di esecuzione come nodo o container univoco nelle applicazioni. Con SnapStart, una singola istantanea viene utilizzata come stato iniziale per più ambienti di esecuzione. Tutti gli ambienti di esecuzione restituiscono lo stesso valore hostname per InetAddress.getLocalHost() (Java), socket.gethostname() (Python) e Dns.GetHostName() (.NET). Per le applicazioni che richiedono un'identità dell'ambiente di esecuzione o un valore hostname univoco, si consiglia di generare un ID univoco nel gestore della funzione. Oppure, utilizza un hook di runtime dopo il ripristino per generare un ID univoco, quindi utilizza l'ID univoco come identificatore per l'ambiente di esecuzione.

Evitare di collegare connessioni a porte di origine fisse

Si consiglia di evitare di associare le connessioni di rete a porte di origine fisse. Le connessioni vengono ristabilite quando una funzione riprende da uno snapshot e le connessioni di rete legate a una porta di origine fissa potrebbero non riuscire.

Evitare di usare la cache DNS Java

Le funzioni Lambda memorizzano già nella cache le risposte DNS. Se si utilizza un'altra cache DNS con SnapStart, è possibile che si verifichino dei timeout di connessione quando la funzione riprende da un'istantanea.

La classe java.util.logging.Logger può abilitare indirettamente la cache DNS JVM. Per sovrascrivere le impostazioni predefinite, imposta networkaddress.cache.ttl su 0 prima dell'inizializzazione di logger. Esempio:

public class MyHandler { // first set TTL property static{ java.security.Security.setProperty("networkaddress.cache.ttl" , "0"); } // then instantiate logger var logger = org.apache.logging.log4j.LogManager.getLogger(MyHandler.class); }

Per evitare errori UnknownHostException nel runtime di Java 11, si consiglia di impostare networkaddress.cache.negative.ttl su 0. Nei runtime di Java 17 e successivi, questa operazione non è necessaria. È possibile impostare questa proprietà per una funzione Lambda con la variabile di ambiente AWS_LAMBDA_JAVA_NETWORKADDRESS_CACHE_NEGATIVE_TTL=0.

La disabilitazione della cache DNS JVM non disabilita la cache DNS gestita da Lambda.